Джойстик. урок 18. ардуино

Содержание

Настраиваем игру

Код игры написан в стиле «single header». Для импорта библиотеки включим в игру oisdevice.h.

В едином файле CPP, прежде чем выполнять #include заголовка, напишем #define OIS_DEVICE_IMPL и #define OIS_SERIALPORT_IMPL — это добавит в файл CPP исходный код классов. Если у вас есть собственные утверждения, логгинг, строки или векторы, то существует несколько других макросов OIS_*, которые можно определить перед импортом заголовка, чтобы воспользоваться возможностями движка.

Для перечисления COM-портов и создания соединения с конкретным устройством можно использовать такой код:

Получив экземпляр OisDevice, нужно регулярно вызывать его функцию-член Poll (например, в каждом кадре), можно получать текущее состояние вывода контроллера с помощью DeviceOutputs(), использовать события устройства с помощью PopEvents() и отправлять устройству значения с помощью SetInput().

Пример приложения, делающего всё это, можно найти здесь: example_ois2vjoy/main.cpp.

Игра на Ардуино с джойстиками и моторами

Для этого проекта нам потребуется:

  • плата Arduino Uno / Arduino Nano / Arduino Mega;
  • 2 мотора с редукторами;
  • мотор шилд LD239;
  • 2 джойстика KY-023;
  • УЗ датчик расстояния;
  • светодиоды и резисторы;
  • фанера или другой листовой материал;
  • столярный клей, провода, изолента, паяльник и т.д.


Схема сборки электрической схемы для проекта

Используйте провода достаточной длины для подключения джойстиков к плате. Для крепления передней крышки корпуса можно использовать магниты, чтобы легко снять крышку при необходимости. Внутри корпуса находится наклонная поверхность, по которой шарик скатывается в одну сторону. Для регистрации наличия шарика в корпусе устанавливается датчик HC-SR04 — УЗ сенсор расстояния Ардуино.

Скетч для игры с джойстиками и моторами

#include "AFMotor.h"        // библиотека для мотор шилда
AF_DCMotor motor1(3);  // подключаем 1 мотор к клеммнику M3
AF_DCMotor motor2(4);  // подключаем 2 мотор к клеммнику M4

#include <Ultrasonic.h>            // библиотека для уз сенсора
Ultrasonic ultrasonic(A3, A4);  // пины trig и echo

void setup() {
   pinMode(A1, INPUT);      // пины для джойстиков
   pinMode(A2, INPUT);
   pinMode(A0, OUTPUT);  // пины для светодиодов
   pinMode(A5, OUTPUT);

   Serial.begin(9600);

   motor1.setSpeed(250); // задаем макс. скорость моторам
   motor2.setSpeed(250);
   motor1.run(RELEASE);   // останавливаем моторы
   motor2.run(RELEASE);
}

void loop() {
   // получаем информацию с джойстиков
   int d1 = analogRead(A1);
   int d2 = analogRead(A2);
   // выводим информацию на монитор
   Serial.print(d1);
   Serial.print(" - ");
   Serial.println(d2);
  
   if (d1 > 800) {
      motor1.run(FORWARD);  // задаем направление
      motor1.setSpeed(250);   // задаем скорость
   }
   if (d1 run(BACKWARD);  // задаем направление
      motor1.setSpeed(250);      // задаем скорость
   }
   if (d1 > 200 && d1 run(RELEASE); }  // останавливаем мотор

   if (d2 > 800) {
      motor2.run(FORWARD);  // задаем направление
      motor1.setSpeed(250);   // задаем скорость
   }
   if (d2 run(BACKWARD);  // задаем направление
      motor2.setSpeed(250);     // задаем скорость
   }
   if (d2 > 200 && d2 run(RELEASE); }  // останавливаем мотор

   // узнаем информацию с уз датчика
   int cm = ultrasonic.Ranging(CM);
   Serial.println(cm);

   // включаем/выключаем светодиоды
   if (cm digitalWrite(A0, HIGH); digitalWrite(A5, LOW); }
   if (cm > 5) { digitalWrite(A0, LOW); digitalWrite(A5, HIGH); }
}

Пояснения к коду:

  1. скорость вращения моторов можно поменять, уменьшив значение ;
  2. светодиоды с подсветкой подключены к аналоговым портам с АЦП — A0 и A5, которые работают в режиме OUTPUT.

Этапы сборки настольной игры на Ардуино

1. соберите электрическую схему игры, как на картинке выше;

Для подключения УЗ датчика, джойстиков и светодиодов через Motor Shield придется припаивать провода или коннекторы к аналоговым портам A0-A5 платы расширения.

2. загрузите в микроконтроллер скетч, размещенный ниже;

Так как цифровые пины используются для управления шилдом, УЗ датчик и светодиоды подключены к аналоговым пинам, которые используются, как цифровые.


Сборка электрической схемы настольной игры Ардуино

3. протестируйте правильную работу джойстиков и моторов;

При необходимости поменяйте полярность у моторов, чтобы они вращались в нужную сторону. Помните, что без редукторов моторы не смогут поднять груз.

5. закрепите моторы и редукторы на внутренней стороне крышки;

Здесь вам потребуется термоклей для крепления моторов на крышке. Для быстрого крепления самой крышки на корпусе можно использовать магниты.

6. надежно закрепите нитки на шкиве и подъемнике.

Используйте супер клей или момент для крепления ниток. Шкивы можно распечатать на 3D принтере или использовать подручные материалы.


Установка шкивов с нитками на моторы с редукторами

Заключение. Данный проект игры на Ардуино с джойстиками имеет простой код программы, однако чтобы собрать корпус и электрическую схему потребуется немало усилий. Проект с моторами на Arduino можно повесить на стене, а для питания можно использовать обычную зарядку от телефона. Теперь остается только установить шарик от пинг-понга в подъемнике и протестировать работу игры на Ардуино.

Схема соединения

Для передачи данных от пульта к роботу я использую радио модули NRF24L01. Они передают каждый раз массив значений. Чем меньше вес этого массива, тем быстрее будет передан сигнал и тем меньшую скорость передачи данных мы можем задать модулю, что уменьшит его энергопотребление. Поэтому данные с джойстика управления будем записывать в 2 ячейки массива типа byte.

Теперь рассмотрим как считываются данные с джойстика на пульте. VCC модуля соединяем с 5V Ардуино, GND с GND, потенциометр горизонтальной оси с A0, вертикальной с A1, кнопку не подключаем, так как задействовать не будем. Схема приведена ниже. Вид модуля может отличаться, но пины будут такими же (кроме случаев с отдельным подводом VCC и GND к каждому потенциометру и кнопке).

Считав данные с джойстика функциями analogRead(A0) (можно заменить А0 на horizontalSticPin ) и analogRead(A1) (можно заменить А1 на verticalSticPin ) получим следующие диапазоны значений. Вперед на вертикальной оси, назад 1023 на вертикальной оси, резкий поворот вправо на горизонтальной оси, резкий разворот влево 1023 на горизонтальной оси. Значения между ними будут давать градации поворотов: положение 0,0 даст плавный правый поворот вперед, а значение 1023,1023 даст плавный левый поворот назад.

4 Управление яркостью и цветом светодиодас помощью аналогового джойстика и Arduino

Обычно джойстик используют для управления электродвигателями. Но почему бы не использовать его, например, для управления яркостью светодиода? Давайте подключим по приведённой схеме RGB светодиод (или три обычных светодиода) к цифровым портам 9, 10 и 11 Arduino, не забывая, конечно, о резисторах.

Подключение RGB светодиода и джойстика к Arduino

Будем менять яркость соответствующих цветов при изменении положения джойстика по осям, как показано на рисунке.

Из-за того, что джойстик может быть не точно отцентрирован производителем и иметь середину шкалы не на отметке 512, а варьироваться в диапазоне примерно от 490 до 525, то светодиод может слегка светиться даже когда джойстик находится в нейтральном положении. Если вы хотите, чтобы он был полностью выключен, то внесите в программу соответствующие поправки.

Диаграмма распределения яркости красного, синего и зелёного каналов светодиода в зависимости от положения ручки джойстика

Ориентируясь на приведённую диаграмму, напишем скетч управления Arduino яркостью RGB светодиода с помощью джойстика.

const int pinRed    = 9;
const int pinGreen  = 10;
const int pinBlue   = 11;
const int swPin = 8; 
const int pinX      = A1; // X 
const int pinY      = A2; // Y 
const int ledPin    = 13;
boolean ledOn = false;  // текущее состояние кнопки
boolean prevSw = false; // предыдущее состояние кнопки

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(pinRed, OUTPUT);
  pinMode(pinGreen, OUTPUT);
  pinMode(pinBlue, OUTPUT);
  pinMode(pinX, INPUT);
  pinMode(pinY, INPUT);
  pinMode(swPin, INPUT);  
  digitalWrite(swPin, HIGH); // включаем встроенный подтягивающий резистор
}

void loop() {
  if (isLedOn()) freeMode(); // если нажата кнопка и горит светодиод на пине 13, включаем режим "фонарик"
  else discoMode(); // иначе включаем "цветомузыку"
}

boolean isLedOn() { // Определяем нажатие кнопки
  if (digitalRead(swPin) == HIGH && prevSw == LOW) {
    ledOn = !ledOn;
    prevSw = HIGH;
  }
  else  prevSw = digitalRead(swPin); 
  digitalWrite(ledPin, ledOn); // включаем светодиод на пине 13
  return ledOn;
}

void freeMode() { // Режим "фонарик"
  int X = analogRead(pinX); // считываем положение джойстика
  int Y = analogRead(pinY);
  int RED = map(Y, 512, 1023, 0, 255); // маппинг значений
  int GREEN = map(X, 512, 1023, 0, 255);
  int BLUE = map(X, 511, 0, 0, 255);
  analogWrite(pinRed, RED);     // включение каналов R,G,B
  analogWrite(pinGreen, GREEN);
  analogWrite(pinBlue, BLUE);
}

void discoMode() { // Режим "цветомузыка"
    for (int i=0; i }

Сначала объявим соответствие пинов и две переменные – ledOn и prevSw – для работы с кнопкой. В процедуре setup() назначим пинам функции и подключим к пину кнопки подтягивающий резистор командой digitalWrite(swPin, HIGH).

В цикле loop() определяем нажатие кнопки джойстика. При нажатии на кнопку переключаем режимы работы между режимом «фонарика» и режимом «цветомузыки».

В режиме freeMode() управляем яркостью светодиодов с помощью наклона джойстика в разные стороны: чем сильнее наклон по оси, тем ярче светит соответствующий цвет. Причём преобразование значений берёт на себя функция map(значение, отНижнего, отВерхнего, кНижнему, кВерхнему).

Функция map() очень полезна и удобна в применении. Она переносит измеренные значения (отНижнего, отВерхнего) по осям джойстика в желаемый диапазон яркости (кНижнему, кВерхнему). Можно то же самое сделать обычными арифметическими действиями, но запись с помощью функции map() существенно короче.

В режиме discoMode() три цвета попеременно набирают яркость и гаснут. Чтобы можно было выйти из цикла при нажатии кнопки, каждую итерацию проверяем, не была ли нажата кнопка.

В результате получился фонарик из трёхцветного RGB светодиода, яркость свечения каждого цвета которого задаётся с помощью джойстика. А при нажатии на кнопку происходит включение режима «цветомузыка». Я сделал специальную печатную плату с Arduino Pro Mini и джойстиком, и у меня он используется в качестве ночника для ребёнка 🙂

Управление яркостью и цветом RGB светодиода с помощью аналогового джойстика, подключённого к Arduino

Таким образом, мы научились подключать к Arduino аналоговый двухосевой джойстик с кнопкой и считывать с него показания. Вы можете придумать и реализовать более интересное применение джойстику, чем наш пример.

Подключение джойстика к ардуино

Подключение джойстика к Arduino Uno выполняется по схеме, приведенной ниже.

На модуле имеется 5 выходов – Vcc, Gnd, X, Y и Key (обозначения могут различаться в зависимости от устройства).

Данные по оси X выводятся на вход А0, по оси Y – на А1. Для визуального контроля нажатия кнопки также можно подключить светодиод D11. Питание осуществляется напряжением 5 Вольт. Пин GND присоединяется к такому же пину на плате Ардуино. Контакт SW можно подсоединить к любому цифровому пину.

Как видим, подключение модуля джойстика не сложно. Если устройство не работает после подключения, проверьте, правильно ли вы подсоединили все пины.

Принципиальная схема джойстика KY-023

Модуль двухосевого джойстика состоит из двух потенциометров на 10 кОм, определяющие положение осей X и Y изменение сопротивления осуществляется рычагом. Средняя нога каждого потенциометра выведены на контакты VRX и VRY, а вторая и третья нога подключена к питанию и массе. Дополнительно установлена тактовая кнопка, показания снимаются с контакта SW, так-же предусмотрено посадочное место для подтягивающего резистора (R1).

Для считывания данных с выводов VRX (ось X) и VRY (ось Y) необходимо использовать аналоговые порт Arduino. (значение от 0 до 5В или от 0 до 1023), а для считывания данных с вывода RW используем цифровой порт (значение 0В и 5В или 0 и 1). Так-как один вывод тактовой кнопки подключен к земле и при нажатии на джойстик вниз, происходит замыкание цепи, но возможно ложные срабатывания (наводки). Для получения стабильных показаний, вывод RW необходимо подтянуть к питанию +5В, через подтягивающий резистор R1 или использовать встроенный подтягивающий резистор.

Как отследить текущее направление джойстика?

Очень полезный кусок кода. На основании значений положений X и Y мы можем определить, находится ли джойстик по центу или он смещен в одном из восьми направлений (вверх, вправо-вверх, вправо, вправо-вниз, вниз, влево-вниз, влево, влево-вверх).

Так как значения в каждом из направлений будет в диапазоне от 0 до 1023, можно предположить, что центр будет находиться в диапазоне 511-512. Но это не совсем так. Настолько точно текущее значение мы не получим. И если мы определим неверное значение, можем получить информацию о движении джойстика, хотя он стоял по центру и не двигался.

Для этого мы введем диапазон значений и будем считать, что любое значение в этом диапазоне будет считаться центром:

|—|—|—|

0 505 515 1023

Этот диапазон не является «истиной последней инстанции». Вам надо его подстроить под ваш джойстик, так. Эти значения вводятся в код в виде констант:

const int X_THRESHOLD_LOW = 505;

const int X_THRESHOLD_HIGH = 515;

const int Y_THRESHOLD_LOW = 500;

const int Y_THRESHOLD_HIGH = 510;

Теперь мы преобразуем каждую координату из диапазона от 0 до 1023 в диапазон от -1 до 1. Для координаты Х – 1 значит перемещение влево, 0 означает отсутствие перемещения, а 1 – перемещение вправо. Для направления Y -1 означает перемещение вниз, 0 означает отсутствие перемещения, а 1 – перемещение вверх.

Мы начнем с установки значения в каждом направлении 0 («центр»). После этого мы используем выражения if/else для проверки, принимает ли значение положения в любом из направлений большее или меньшее значение чем наш диапазон:

x_direction = 0;

y_direction = 0;

x_position = analogRead(PIN_ANALOG_X);

y_position = analogRead(PIN_ANALOG_Y);

if (x_position > X_THRESHOLD_HIGH) {

x_direction = 1;

} else if (x_position

x_direction = -1;

}

if (y_position > Y_THRESHOLD_HIGH) {

y_direction = 1;

} else if (y_position

y_direction = -1;

}

В Arduino IDE есть функция map(), которую, теоретически могли бы использовать вместо if/else, но в данном случае метод усложняется из-за вопросов центрирования, так что применять здесь map мы не будем.

В примере, который представлен ниже, вы увидите, что в дальнейшем if/else используются для отображения направления – вы можете спокойно изменить этот пример под ваши задачи:

const byte PIN_ANALOG_X = 0;

const byte PIN_ANALOG_Y = 1;

const int X_THRESHOLD_LOW = 505;

const int X_THRESHOLD_HIGH = 515;

const int Y_THRESHOLD_LOW = 500;

const int Y_THRESHOLD_HIGH = 510;

int x_position;

int y_position;

int x_direction;

int y_direction;

void setup() {

Serial.begin(9600);

}

void loop () {

x_direction = 0;

y_direction = 0;

x_position = analogRead(PIN_ANALOG_X);

y_position = analogRead(PIN_ANALOG_Y);

if (x_position > X_THRESHOLD_HIGH) {

x_direction = 1;

} else if (x_position

x_direction = -1;

}

if (y_position > Y_THRESHOLD_HIGH) {

y_direction = 1;

} else if (y_position

y_direction = -1;

}

if (x_direction == -1) {

if (y_direction == -1) {

Serial.println(«left-down»);

} else if (y_direction == 0) {

Serial.println(«left»);

} else {

// y_direction == 1

Serial.println(«left-up»);

}

} else if (x_direction == 0) {

if (y_direction == -1) {

Serial.println(«down»);

} else if (y_direction == 0) {

Serial.println(«centered»);

} else {

// y_direction == 1

Serial.println(«up»);

}

} else {

// x_direction == 1

if (y_direction == -1) {

Serial.println(«right-down»);

} else if (y_direction == 0) {

Serial.println(«right»);

} else {

// y_direction == 1

Serial.println(«right-up»);

}

}

Подрулевое управление: за и против

Подрулевое управление магнитолой – это своеобразная опция, предложенная владельцам Рено в качестве варианта доступа к функциям медиасистемы. Аналогичные приспособления как рулевая панель – уже привычный девайс. В данном случае он реализован как периферийное устройство. Опытные автомобилисты владельцы Renault говорят о том, что внешние кнопки для проигрывания музыки действительно очень удобны.

Джойстик

В плане затрат и трудоемкости установки – это действительно более приемлемый и доступный вариант по сравнению с опциями, которые предлагаются для медиасистем. Фактически речь идет об отдельном устройстве с минимальными требованиями к установке. Вам нужно подсоединить адаптер к соответствующему разъему и прикрепить в подрулевом пространстве.

Данная опция доступна для машин Renault Лагуна, Лачетти. Само устройство производится фирмой Pioneer, что уже является гарантией качества и продуманной эргономики.

Джойстик

Преимущества, которые дает переключатель подрулевой управления магнитолой:

  • удобная и недорогая установка при выполнении функции дистанционного доступа;
  • невысокая стоимость девайса;
  • простая конструкция и схема работы;
  • через время действие становится рефлекторным, что очень удобно и позволяет отказаться от дистанционного доступа.

Нужно сказать, что джойстики довольно популярны у производителей. В продаже можно встретить различные приспособления для тюнинга. Например, переключатель для зеркала, навигации, бортового компьютера. Данные опции часто в входят в пакеты расширения вместе с навигаторами, автомобильным ТВ, музыкальным чейнджером и другими устройствами.

Джойстик установленный под рулем

Идея заимствована из спортивных автомобилей и концепт-каров, где реализуется так называемый «интуитивный» дизайн. Данные приспособления Pioneer отлично подходят для автомобилистов, любящих экстремальное вождение, и людей, совершающих на автомобиле дальние путешествия.

Подводные камни в работе геймпада

Как и с любое устройство, джойстики не лишены недостатков.  В первую очередь, наличие пружины не позволяет ручке точно вернуться в центральное положение из-за трения в механических деталях. Это приводит к тому, что приходится программно определять центральное положение, вернее диапазон значений, в которых любая точка будет условно считаться серединой.

Второй проблемой можно назвать наличие так называемых мертвых зон. Два крайних значения при наибольших отклонениях должно быть равным 0 В и напряжению питания. В действительности эти значения могут различаться, так как не используется весь электрический диапазон изменения сопротивления. Для решения этой проблемы крайние точки могут соответствовать значениям 1 кОм и 9 кОм.

Geek каналы

★ Моя партнёрка с Aliexpress ★

★ Получай 10.5% скидку с любой покупки на Aliexpress! ★

★ Полезное браузерное приложение для кэшбэка  ★

Распиновка самых популярных плат ардуино Arduino board pinmaping

В посте собраны практически все платы ардуино с распиновкой в хорошем качестве !

Arduino – это эффективное средство разработки программируемых электронных устройств, которые, в отличие от персональных компьютеров, ориентированы на тесное взаимодействие с окружающим миром. Ардуино – это открытая программируемая аппаратная платформа для работы с различными физическими объектами и представляет собой простую плату с микроконтроллером, а также специальную среду разработки для написания программного обеспечения микроконтроллера.

Ардуино может использоваться для разработки интерактивных систем, управляемых различными датчиками и переключателями. Такие системы, в свою очередь, могут управлять работой различных индикаторов, двигателей и других устройств. Проекты Ардуино могут быть как самостоятельными, так и взаимодействовать с программным обеспечением, работающем на персональном компьютере (например, приложениями Flash, Processing, MaxMSP). Любую плату Ардуино можно собрать вручную или же купить готовое устройство; среда разработки для программирования такой платы имеет открытый исходный код и полностью бесплатна.

Язык программирования Ардуино является реализацией похожей аппаратной платформы “Wiring”, основанной на среде программирования мультимедиа “Processing”.

Теги: Подключение геймпада, джойстика к Arduino, беспроводной джойстик 2.4, dualshock от PS2 к ардуино, джойстик к ардуино, беспроводной джойстик подключение, контроллер подключение, пульт к ардуино, ps2 gamepade arduino, денис, гиик, китайчик, клуб, ардуино, клуб_ардуино, обзоры, алиэкспресс, denis_geek, denis, geek, chinagreat, club_arduino, arduino, club, aliexpress, денис гиик

Алгоритм

Исходя из вышеописанного составляем алгоритм, преобразующий показания горизонтальной и вертикальной осей джойстика в две «вертикальные» оси скорости двигателей.

Вот его принцип:

Вводим следующие константы: — verticalSticCenter – значения, соответствующие центральному положению джойстика в вертикальной оси (средняя скорость робота равна ); — horizontalSticPin – значения, соответствующие центральному положению джойстика в горизонтальной оси (скорость разворота равна ) — k – коэффициент отклонения, от центральных положений, позволяет исключить влияния «шумов» на показания в положении полной остановки робота) Считываем показания вертикальной оси потенциометра в переменную speed , хранящую значение средней скорости. Считанные значения нужно перевести в диапазон типа byte , разделив на 4 (можно использовать функцию map ), в таком случае средняя скорость будет изменяться от 255 до 0. Затем вычесть из них значение verticalSticCenter , теперь средняя скорость изменяется от 128 до -128

Но для удобства расчетов хотелось бы видеть изменения скорости в диапазоне от -128 до 128 (тогда центральное положение будет давать 0, что очень важно), для этого делим показания на единицу. Смотрим, если значения относительной скорости отличаются от 0 менее чем на k (джойстик находиться в центральном положении по вертикальной оси), то приравниваем ее к 0

Считываем значения горизонтальной оси в переменную horizontal_value так же приведя к диапазону byte , будем называть их скоростью поворота. Если значения скорости поворота отклонились более, чем на k от центра в право, то скорость левого двигателя приравниваем к сумме средней скорости и величине отклонения в угловой скорости от условного 0 (вычитаем значения скорости поворота из значений ее центра), а скорость правого к их разности. Если значения скорости поворота отклонились более, чем на k от центра влево, то скорость левого двигателя приравниваем к разности средней скорости и величине отклонения от условного центра (из скорости поворота вычитаем значения условного 0), а правого к их сумме. Не выполнение условий пунктов 5 и 6 говорит о том, что значения скорости поворота лежат в пределах центра (условного 0), в этом случае приравниваем скорости обоих двигателей к средней скорости. Теперь необходимо ограничить полученные значения скоростей, что бы по модулю они не выходили за половину максимального значения типа byte для предотвращения переполнения переменных в пункте 9. Просто сравним значения с константно-объявленной границей, и если они больше, то приравняем их к ней. Сейчас скорости двигателей лежат в диапазоне от -128 до 128, но мы хотим хранить их в массиве типа byte , который не может хранить отрицательные числа, поэтому «зашифруем их»: — элемент массива data будет хранить скорость левого двигателя, а 1 скорость второго. — Если скорость будет отрицательной, мы положим в data ее модуль, а если положительной, то прибавим к ней половину диапазона значений типа byte . Таким образом значения от 0 до 128 хранят скорость вращения назад, а значения от 128 до 255 вперед.

Объяснение программы для Arduino

Полный код программы приведен в конце статьи, здесь же мы обсудим его наиболее важные фрагменты.

В следующем фрагменте кода мы инициализируем аналоговые контакты Arduino A0 и A1 чтобы отслеживать перемещение джойстика по осям X и Y соответственно.

Arduino

#define joyX A0
#define joyY A1

1
2

#define joyX A0
#define joyY A1

Далее мы инициализируем контакт PIN 2 (к нему подключена кнопка джойстика) и определим начальные значения переменных buttonstate и buttonstate1.

Arduino

int button=2;
int buttonState = 0;
int buttonState1 = 0;

1
2
3

intbutton=2;

intbuttonState=;

intbuttonState1=;

В следующем фрагменте кода мы инициализируем последовательный порт связи для работы на скорости 9600 бод/с и зададим режим работы контактов: Pin 7 – на вывод данных, контакт, к которому подключена кнопка – на ввод данных.

Arduino

void setup() {
pinMode(7,OUTPUT);
pinMode(button,INPUT);
digitalWrite(button, HIGH);
Serial.begin(9600);
}

1
2
3
4
5
6

voidsetup(){

pinMode(7,OUTPUT);

pinMode(button,INPUT);

digitalWrite(button,HIGH);

Serial.begin(9600);

}

Далее в программе мы считываем значения с аналоговых входов A0 и A1 и передаем их в окно монитора последовательной связи.

Arduino

int xValue = analogRead(joyX);
int yValue = analogRead(joyY);

Serial.print(xValue);
Serial.print(«\t»);
Serial.println(yValue);

1
2
3
4
5
6

intxValue=analogRead(joyX);

intyValue=analogRead(joyY);

Serial.print(xValue);

Serial.print(«\t»);

Serial.println(yValue);

Затем мы должны прописать в программе условия включения и выключения светодиодов в зависимости от перемещений оси джойстика. На следующем рисунке представлены диапазоны возможных изменений значений на выходах АЦП контактов A0 и A1 в зависимости от перемещения оси джойстика.

Условие для перемещения оси джойстика в направлении -Y:

Arduino

if (xValue>=0 && yValue<=10){
digitalWrite(10, HIGH);
}
else{digitalWrite(10, LOW);}

1
2
3
4

if(xValue>=&&yValue<=10){

digitalWrite(10,HIGH);

}

else{digitalWrite(10,LOW);}

Условие для перемещения оси джойстика в направлении -X:

Arduino

if (xValue<=10 && yValue>=500){
digitalWrite(11, HIGH);
}
else{digitalWrite(11, LOW);}

1
2
3
4

if(xValue<=10&&yValue>=500){

digitalWrite(11,HIGH);

}

else{digitalWrite(11,LOW);}

Условие для перемещения оси джойстика в направлении +X:

Arduino

if (xValue>=1020 && yValue>=500){
digitalWrite(9, HIGH);
}
else{digitalWrite(9, LOW);}

1
2
3
4

if(xValue>=1020&&yValue>=500){

digitalWrite(9,HIGH);

}

else{digitalWrite(9,LOW);}

Условие для перемещения оси джойстика в направлении +Y:

Arduino

if (xValue>=500 && yValue>=1020){
digitalWrite(8, HIGH);
}
else{digitalWrite(8, LOW);}

1
2
3
4

if(xValue>=500&&yValue>=1020){

digitalWrite(8,HIGH);

}

else{digitalWrite(8,LOW);}

Но если мы переместим джойстик по диагонали, то значения с выходов АЦП по осям X и Y будут 1023 и 1023 соответственно. И, поскольку, в этом случае будут выполнены сразу два из вышеперечисленных условий, то должны зажечься светодиоды, подключенные к контактам Pin 9 и Pin 8. Чтобы устранить это несоответствие, мы добавим еще условие – если оба значения (X, Y) будут равны (1023, 1023), тогда оба светодиода будут в выключенном состоянии.

Arduino

if (xValue>=1020 && yValue>=1020) {
digitalWrite(9, LOW);
digitalWrite(8, LOW);
}

1
2
3
4

if(xValue>=1020&&yValue>=1020){

digitalWrite(9,LOW);

digitalWrite(8,LOW);

}

И в заключение нам осталось одно условие для кнопки джойстика – при ее нажатии будет загораться светодиод и гореть до тех пор пока мы не отпустим кнопку.

Arduino

if (buttonState == LOW) {
Serial.println(«Switch = High»);
digitalWrite(7, HIGH);
}
else{digitalWrite(7, LOW);}

1
2
3
4
5

if(buttonState==LOW){

Serial.println(«Switch = High»);

digitalWrite(7,HIGH);

}

else{digitalWrite(7,LOW);}

Работа схемы

Схема устройства приведена на следующем рисунке.

Напряжение на выходных контактах джойстика не является полностью линейным – оно зашумлено. Для фильтрации этого шума устанавливаются конденсаторы как показано на схеме.

Также на схеме мы имеем 4 светодиода. Каждый светодиод будет отображать соответствующее направление движения джойстика. Перед тем как двигаться дальше остановимся немного на принципах работы АЦП микроконтроллера ATmega8.

Аналого-цифровой преобразователь (АЦП) микроконтроллера ATmega8 может быть использован на любом из четырех каналов PORTC – мы выберем канал 0 (PIN0) PORTC.

В микроконтроллере ATmega8 АЦП имеет разрешение (разрешающую способность) 10 бит, таким образом микроконтроллер способен реализовать чувствительность равную Vref/2^10, то есть если опорное напряжение (Vref) равно 5В мы получим цифровой инкремент на выходе 5/2^10 = 5мВ. Таким образом, на каждое приращение напряжения на 5 мВ мы будем получать один дополнительный инкремент цифрового выхода АЦП.

Для обеспечения работы схемы мы должны установить значения регистров АЦП следующим образом:

  1. Сначала мы должны активировать АЦП микроконтроллера.
  2. Затем необходимо установить максимальное входное напряжение для АЦП равное 5В. Это можно сделать путем установки значения опорного напряжения АЦП равного 5В.
  3. АЦП микроконтроллера в нашей схеме будет начинать действовать при внешнем воздействии (не от действий пользователя), поэтому нам следует установить его в режим непрерывного преобразования (free running mode): в этом режиме запуск преобразований выполняется непрерывно через определенные интервалы времени.
  4. В любом АЦП частота преобразования аналогового значения в цифровое и точность цифрового выхода обратно пропорциональны. То есть для лучшей точности цифрового выхода мы должны выбрать меньшую частоту. Для этого мы должны установить коэффициент деления предделителя АЦП в максимальное значение (2). Поскольку мы используем внутреннюю частоту микроконтроллера 1 МГц, то значение частоты преобразования АЦП будет равно 1000000/2.

Четыре основных принципа работы с АЦП микроконтроллера мы рассмотрели, теперь нам нужно установить правильные значения в двух регистрах АЦП.

RED (красный, ADEN): этот бит устанавливается чтобы задействовать функции АЦП в ATmega8.

BLUE (синий, REFS1, REFS0): эти два бита используются для установки опорного напряжения (максимального входного напряжения, которое мы собираемся обрабатывать). Поскольку мы будем использовать опорное напряжение равное 5В, бит REFS0  необходимо выставить в соответствии с приведенной таблицей.

LIGHT GREEN (светло зеленый, ADATE): этот бит должен быть установлен чтобы АЦП работал непрерывно (в режиме непрерывного преобразования).

PINK (розовый, MUX0-MUX4): эти 5 бит используются чтобы задать входной канал. Поскольку мы будем использовать ADC0 (PIN0) то, как следует из ниже приведенной таблицы, нам нет необходимости устанавливать все эти биты.

BROWN (коричневый, ADPS0-ADPS2): эти три бита используются для установки коэффициент деления предделителя АЦП. Поскольку мы используем коэффициент деления предделителя 2, мы должны установить только один из этих битов.

DARK GREEN (темно-зеленый, ADSC): этот бит необходимо установить для того чтобы АЦП начал осуществлять преобразование. Далее в программе мы можем его сбросить (в 0) если нам нужно будет остановить процесс аналого-цифрового преобразования.