Arduino 2 серводвигателя джойстик для управления. Делаем еще один джойстик (геймпад) на Arduino

Инструкция

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

Подключим джойстик по приведённой схеме. Аналоговые выходы X и Y джойстика подключим к аналоговым входам A1 и A2 Arduino, выход кнопки SW - к цифровому входу 8. Питание джойстика осуществляется напряжением +5 В.

Для того чтобы наглядно увидеть, как работает джойстик, напишем такой скетч. Объявим пины, зададим им режимы работы. Обратите внимание, в процедуре setup() мы подали на вход switchPin высокий уровень. Этим мы включили встроенный подтягивающий резистор на этом порту. Если его не включить, то, когда кнопка джойстика не нажата, 8-ой порт Arduino будет висеть в воздухе и ловить наводки. Это повлечёт за собой нежелательные хаотичные ложные срабатывания.

В процедуре loop() мы постоянно опрашиваем состояние кнопки и отображаем его с помощью светодиода на выходе 13. Из-за того, что вход switchPin подтянут к питанию, светодиод постоянно горит, а при нажатии кнопки гаснет, а не наоборот.

Далее мы считываем показания двух потенциометров джойстика - выхода осей X и Y. Arduino имеет 10-разрядные АЦП, поэтому значения, снимаемые с джойстика, лежат в диапазоне от 0 до 1023. В среднем положении джойстика, как видно на иллюстрации, снимаются значения в районе 500 - примерно середина диапазона.

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

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

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

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

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

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

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

Является модулем ввода данных. С его помощью можно управлять роботами, манипуляторами, станками, различными моделями (машинки, танки, самолёты, вертолёты, квадрокоптеры, лодки и т.д.), а также использовать для создания игровых приставок, выбора пунктов меню на дисплеях и индикаторах, ввода значений, и т.д. Джойстик можно не только перемещать по осям X и Y, но и нажимать на него.

Видео:

Спецификация:

  • Напряжение питания: 5 В / 3,3 В (оба напряжения входят в диапазон допустимых значений).
  • Потребляемый ток: < 10 мА
  • Габариты: 30x30 мм

Все модули линейки "Trema" выполнены в одном формате

Подключение:

  • Выводы «X» и «Y» модуля подключается к любым аналоговым входам Arduino . Значения, считываемые с этих выводов, растут при перемещении джойстика слева на право и снизу вверх.
  • Вывод «K» является цифровым и подключается к любому выводу Arduino . В обычном состоянии на нём уровень логического «0», а при нажатии на джойстик, он меняется на логическую «1».
  • Выводы «V» и «G» являются выводами питания.

Модуль удобно подключать 3 способами, в зависимости от ситуации:

Способ - 1: Используя проводной шлейф и Piranha UNO

Используя провода «Папа - Мама », подключаем напрямую к контроллеру Piranha UNO


Способ - 2: Используя Trema Set Shield

Модуль можно подключить к любому из аналоговых входов Trema Set Shield.


Способ - 3: Используя проводной шлейф и Shield

Используя 5-и проводной шлейф, к Trema Shield, Trema-Power Shield, Motor Shield, Trema Shield NANO и тд.


Питание:

Входное напряжение 5 В или 3,3 В постоянного тока, подаётся на выводы Vcc (V) и GND (G).

Подробнее о модуле:

Данные модуля считываются с двух потенциометров и тактовой кнопки, механически связанных с рычагом джойстика. Кнопка подключена в разрыв питания Vcc и выхода «K», который прижат к GND через резистор. Следовательно, на выходе «K» может устанавливаться только два состояния: логический «0» (кнопка отпущена) или «1» (кнопка нажата). Выводы координат «X» и «Y» являются аналоговыми выходами модуля, они подключены к потенциометрам так, что напряжение снимаемое между этими выводами и GND растет при перемещении джойстика слева на право и снизу вверх.

Примеры:

Определение положения джойстика и включение светодиода по нажатию кнопки

const int8_t Xaxis = A0; // Определяем номер вывода, к которому подключен контакт оси Х джойстика const int8_t Yaxis = A1; // Определяем номер вывода, к которому подключен контакт оси У джойстика const int8_t Button = 2; // Определяем номер вывода, к которому подключен контакт кнопки джойстика const int8_t LED = 7; // Определяем номер вывода, к которому подключен светодиод uint16_t XborderMIN = 505; // Задаём границу значений, НИЖЕ которой будет считаться, что джойстик отклонён по оси Х влево uint16_t XborderMAX = 515; // Задаём границу значений, ВЫШЕ которой будет считаться, что джойстик отклонён по оси Х вправо uint16_t YborderMIN = 505; // Задаём границу значений, НИЖЕ которой будет считаться, что джойстик отклонён по оси У вниз uint16_t YborderMAX = 515; // Задаём границу значений, ВЫШЕ которой будет считаться, что джойстик отклонён по оси У вверх uint16_t Xvol = 0, Yvol = 0; // Задаём переменные, которые будут принимать значения, считанные с осей джойстика void setup() { Serial.begin(9600); // Инициируем передачу данных в монитор последовательного порта pinMode(LED, OUTPUT); // Настраиваем вывод LED на работу в режиме выхода pinMode(Button, INPUT); // Настраиваем вывод Button на работу в режиме входа } void loop() { Xvol = analogRead(Xaxis); // Считываем значения оси Х Yvol = analogRead(Yaxis); // Считываем значения оси У if (Xvol < XborderMIN) { // Проверяем, полученное значение Х меньше нижней границы центрального положения или нет. Если да, то if (Yvol < YborderMIN) { // проверяем, полученное значение У меньше нижней границы центрального положения или нет. Если да, то Serial.println("Left-Down"); // значит джойстик находится в положении ВЛЕВО-ВНИЗ } else if (Yvol > YborderMAX) { // Если же полученное значение У больше верхней границы центрального положения, то Serial.println("Left-Up"); // значит джойстик находится в положении ВЛЕВО-ВВЕРХ } else { Serial.println("Left"); // Если же полученное значение У входит в границы центрального положения по оси У, значит джойстик отклонён ВЛЕВО } } else if (Xvol > XborderMAX) { // Проверяем, полученное значение Х больше верхней границы центрального положения или нет. Если да, то if (Yvol < YborderMIN) { // проверяем, полученное значение У меньше нижней границы центрального положения или нет. Если да, то Serial.println("Right-Down"); // значит джойстик находится в положении ВПРАВО-ВНИЗ } else if (Yvol > YborderMAX) { // Если же полученное значение У больше верхней границы центрального положения, то Serial.println("Right-Up"); // значит джойстик находится в положении ВПРАВО-ВВЕРХ } else { Serial.println("Right"); // Если же полученное значение У входит в границы центрального положения по оси У, значит джойстик отклонён ВПРАВО } } else { // Если полученное значение Х входит в границы центрального положения по оси Х, значит if (Yvol < YborderMIN) { // проверяем, полученное значение У меньше нижней границы центрального положения или нет. Если да, то Serial.println("Down"); // значит джойстик находится в положении ВНИЗ } else if (Yvol > YborderMAX) { // Если же полученное значение У больше верхней границы центрального положения, то Serial.println("Up"); // значит джойстик находится в положении ВВЕРХ } else { Serial.println("Center"); // Если же полученное значение У входит в границы центрального положения по оси У, значит джойстик находится в центре. } } if (digitalRead(Button)) { // Проверяем, нажата ли кнопка delay(1); // Если кнопка была нажата, то подавляем дребезг digitalWrite(LED, !digitalRead(LED)); // и меняем состояние на выходе светодиода Serial.println("Button click!"); // Выводим текст о том, что кнопка была нажата while (digitalRead(Button)) {} // Если кнопка удерживается, то ничего не делаем delay(10); // Если кнопка отпускается, то подавляем дребезг } }

В мониторе последовательного порта вы увидите.

Шла обычная пятница, ничто не предвещало беды…

Но червь «нужно что-то сделать» уже начал свою работу. После прочтения статьи я вспомнил, что у меня в барахле лет 15, если не больше, валяется сеговский геймпад. Забрал я его с твердым намерением сделать геймпад на процессоре AVR (про ардуино я тогда и не слышал, но пару небольших проектов на AVR сделал).

Еще больше утвердила мое намерение статья про MSX , и в пятницу я решил - делаю!


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

В качестве контроллера я решил использовать Beetle , так как он был заказан мной когда-то, но пока не испробован, да и не очень понравился «малым количеством портов».

И тут меня ждало разочарование - портов 6, кнопок 10. Горю моему не было предела, но мозг таки нашел решение, для начала я решил попробовать собрать прототип из 2-х кнопок, так как я решил использовать фокус с диодом, чтобы опрашивать 10 кнопок с помощью 6 выводов. Практически окрыленный, я засел за проверку… И тут случилась следующая неприятность - кнопок на джойстике больше, чем 10! В общем это был тот момент, когда нужно было смотреть в документацию, хотя идей было много - например припаять (ага, моим паяльником, который накрывает почти все ножки с одной стороны микросхемы), или поискать просветления в интернете.
Документация же четко сказала, что портов у Beetle на самом деле не 6, а 10, что сделало дальнейший процесс скучным (так я думал). (Использование 8 выводов дает возможность опрашивать 2 * 6 = 12 кнопок, что мне и было нужно)

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

Схема получившегося геймпада:

Быстро накидав пример я убедился что он не работает… Не понял?! Пример то простейший. Подумав, сообразил, что цифровому пину не хватает того сопротивления, что дают резиновые токопроводящие кнопки, немного изменил схему, теперь читается аналоговый сигнал и сравнивается с половиной максимума. Перепаиваю контакты, переписываю программу и… ничего не работает, совсем. Контроллер не определяется, все пропало. Код проверен, и перепроверен, все должно работать! А контроллер не видится ни в какую. Мотивация падает, делаем перерыв.

Через некоторое время безуспешно поигравшись с Beetle, ну все, убил контроллер своим паяльником, с сожалением достаю из закромов Arduino Micro, прошиваю прошивку и снова тишина! Становится понятно, что-то не так с кодом, в конце концов нахожу банальную причину - бесконечный цикл в loop(), исправляю, но зашить то не могу! Оказывается проблема, когда контроллер не видится решается нажатием на резет во время прошивания (или замыканием пинов в моем случае)

В итоге получился сеговский геймпад, проверен, работает, я счастлив: поиграл в Metal Gear, Felix The Cat, Super Mario.





P. S. «Трюк со светодиодом». Конечно не обязательно использовать светодиод, обычный диод лучше подходит, суть простая, вместо двух выводов использовать один, соединенный с разными кнопками через 2 диода:

Новые статьи

● Проект 18: Обрабатываем данные от джойстика. Управление Pan/Tilt Bracket с помощью джойстика

В этом эксперименте мы рассмотрим подключение к Arduino двухосевого аналогового джойстика.

Необходимые компоненты:

Для управления каким-либо устройством на основе Arduino, перемещающимся в двухмерной системе координат, отлично подойдет джойстик. Для плат Arduino существуют модули аналогового джойстика, имеющие ось X, Y (потенциометры 10 кОм) и дополнительную кнопку - ось Z. Джойстик позволяет плавно и точно отслеживать степень отклонения от нулевой точки. Сам джойстик подпружиненный, поэтому он будет возвращаться в центральное состояние после его отпускания из определенной позиции.
Контакты Vcc и GND между всеми тремя группами контактов соединены. Таким образом, для подключения нужно 5 проводов: ось X, ось Y, кнопка Z, питание Vcc и общий GND. Джойстики - пассивные модули и не потребляют какую-либо энергию от платы Arduino. Выводы VERT и HORZ подключаются к аналоговым входам A0 и A1 Arduino, SEL - к цифровому входу D2. Схема подключения показана на рис. 18.1.

Рис. 18.1. Схема подключения платы джойстика к Arduino

Напишем скетч считывания данных джойстика и вывода значений в монитор последовательного порта Arduino IDE. Содержимое скетча показано в листинге 18.1.

Const int axisX=A0 // ось Х подключена к A0 const int axisY=A1 // ось Y подключена к A1 const int axisZ=2 // ось Z (кнопка джойстика) подключена к D2 int valX, valY, valZ = 0 ; void setup () { pinMode(axis_Z, INPUT_PULLUP); // конфигурируем D2 как INPUT с включением // подтягивающего резистора внутри процессора Serial.begin(9600 ); } void loop () { valX = analogRead(axisX); // значение оси Х valY = analogRead(axisY); // значение оси Y valZ = 1 -digitalRead(axisZ); // значение оси Z (кнопка) // выводим значения в монитор Serial.print("X:" );Serial.print(valX, DEC); Serial.print(" | Y:" );Serial.print(valY, DEC) Serial.print(" | Z: " );Serial.println(valZ, DEC); delay(500 ); // пауза перед следующим считыванием данных }
Порядок подключения:

1. Подключаем джойстик к плате Arduino по схеме на рис. 18.2.
2. Загружаем в плату Arduino скетч из листинга 18.1.
3. Смотрим в мониторе последовательного порта Arduino IDE вывод значений смещения по осям X и Y и состояние кнопки (ось Z).

Рис. 18.2. Схема подключения платы джойстика и Pan/Title Bracket к Arduino


Создадим более понятный пример использования джойстика для управления положением кронштейна Pan/Titl Bracket с двумя сервоприводами, на котором можно разместить, например, камеру и менять положение камеры влево/вправо и вниз/вверх с помощью джойстика. Схема соединений для данного эксперимента показана на рис. 18.2.
Перемещением джойстика по оси X мы будем управлять поворотом нижнего сервопривода (влево/вправо), перемещением джойстика по оси Y будем управлять поворотом верхнего сервопривода (вверх/вниз). Среднее нейтральное положение джойтика по каждой оси (при аналоговом значении 512) соответствует углу поворота сервопривода на угол 90°. Содержимое скетча показано в листинге 18.2.

#include // подключение библиотеки Servo Servo servo1, servo2; const int pinServo1=8 ; // Пин для подключения 1 сервопривода const int pinServo2=9 ; // Пин для подключения 2 сервопривода // переменные для хранения углов поворота сервоприводов int angleServo1,angleServo2 = 0 ; const int axisX=A0; // ось Х подключена к A0 const int axisY=A1; // ось Y подключена к A1 int valX, valY = 0 ; // переменные для хранения значений осей void setup () { // подключить переменную servo1 к выводу pinServo1 servo1.attach(pinServo1); // подключить переменную servo2 к выводу pinServo2 Servo2.attach(pinServo2); } void loop () { valX = analogRead(axisX); // значение оси Х valY = analogRead(axisY); // значение оси Y // масштабируем значение к интервалу 0-180 angleServo1=map (valX,0 ,1023 ,0 ,180 ); angleServo2=map (valY,0 ,1023 ,0 ,180 ); // поворот сервоприводов на полученный угол servo1.write(angleServo1); servo2.write(angleServo2); delay(15 ); // пауза для ожидания поворота сервоприводов }
Порядок подключения:

1. Собираем Pan/Title Bracket и сервоприводы.
2. Подключаем джойстик и Pan/Title Bracket к плате Arduino по схеме на рис. 18.2.
3. Загружаем в плату Arduino скетч из листинга 18.2.
4. Управляем положением Pan/Title Bracket перемещением джойстика по осям X и Y.

Листинги программ

Подключение джойстика к Arduino позволит сделать дистанционное управление с помощью джойстика машинкой или роботом на Ардуино. Рассмотрим в статье, как подключить джойстик шилд самостоятельно и сделать управление сервоприводом с помощью джойстика на Ардуино. Представим несколько скетчей и дадим схему подключения джойстика к микроконтроллеру Arduino Nano или Arduino Uno.

Джойстик схема подключения к Ардуино

Аналоговый джойстик представляет собой ручку, которая крепится на шарнире с двумя потенциометрами, определяющими положение джойстика по оси X и Y, и кнопкой Z. Наклон ручки вращает потенциометры и изменяет выходное напряжение, позволяя отследить степень отклонения ручки от центральной точки. При отпускании ручки джойстика, она плавно возвращается в центральное (нулевое) положение.

Как подключить джойстик к Arduino Nano и Arduino Uno

У модуля джойстика KY-023 есть свои недостатки. Дело в том, что ручка джойстика не всегда точно возвращается в центральное положение, поэтому следует учитывать в программе центральное положение ручки, как некоторый диапазон значений, а не точное значение. То есть, при положении ручки джойстика в центре, значение X и Y координат может находиться в диапазоне от 490 до 530, вместо 512.

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

Для занятия нам понадобятся следующие детали:

  • плата Arduino Uno / Arduino Nano / Arduino Mega;
  • модуль джойстика ky-023;
  • 2 светодиода и 2 резистора;
  • макетная плата;
  • провода «папа-мама», «папа-папа».
Схема подключения аналогового джойстика к Ардуино Уно

После подключения к Ардуино джойстика, загрузите следующий скетч. В данном примере на монитор порта будут выводиться данные с джойстика, а при нажатии кнопки будет выключаться светодиод на плате, подключенный параллельно к Pin 13. Соберите схему с джойстиком, как показано на схеме выше, загрузите скетч и откройте монитор порта программы Arduino IDE.

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

#define pinX A2 // ось X джойстика #define pinY A1 // ось Y джойстика #define swPin 2 // кнопка джойстика #define ledPin 13 // светодиод на Pin 13 void setup () { Serial .begin (9600); pinMode (ledPin, OUTPUT ); pinMode (pinX, INPUT ); pinMode (pinY, INPUT ); pinMode (swPin, INPUT ); digitalWrite (swPin, HIGH ); } void loop () { boolean ledState = digitalRead (swPin); // вкл./выкл. светодиод // считываем значение оси Х // считываем значение оси Y Serial .print (X); // выводим в Serial Monitor Serial .print ("\t" ); // табуляция Serial .println (Y); }

Скетч. Управление джойстиком светодиодами

Теперь можно усложнить схему, сделав плавное включение светодиода , управляемое от джойстика. Для этого подключите два светодиода через резистор к аналоговым портам 5 и 6. В следующем скетче, с помощью функции map() , переменные X и Y преобразуются из диапазона чисел от 0 до 1023 в диапазон чисел от 0 до 255. Подключите светодиоды к пинам 5 и 6 Ардуино и загрузите следующий скетч.

#define pinX A2 // ось X джойстика #define pinY A1 // ось Y джойстика #define swPin 2 // кнопка джойстика #define ledPin 13 // светодиод на Pin 13 #define ledX 5 // светодиод на Pin 5 #define ledY 6 // светодиод на Pin 6 void setup () { pinMode (ledX, OUTPUT ); pinMode (ledY, OUTPUT ); pinMode (ledPin, OUTPUT ); pinMode (pinX, INPUT ); pinMode (pinY, INPUT ); pinMode (swPin, INPUT ); digitalWrite (swPin, HIGH ); } void loop () { boolean ledState = digitalRead (swPin); // считываем состояние кнопки digitalWrite (ledPin, ledState); // вкл./выкл. светодиод int X = analogRead (pinX); // считываем значение оси Х int Y = analogRead (pinY); // считываем значение оси Y X = map (X, 0, 1023, 0, 255); // преобразуем значение X в другой диапазон Y = map (Y, 0, 1023, 0, 255); // преобразуем значение Y в другой диапазон analogWrite (ledX, X); // включаем светодиоды с разной яркостью analogWrite (ledY, Y); }

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

  1. с помощью функции map() можно задать любой, в том числе, обратный диапазон чисел. Также можно использовать отрицательные значения.
Поделиться