- Джойстик Ардуино – подключение и скетч
- Принцип работы джойстика
- Подключение джойстика к ардуино
- Как отслеживать текущее положение или направление джойстика
- Определение направления движения джойстиком
- Подводные камни в работе геймпада
- Плата расширения JoyStick shield
- Заключение
- Тема: Управление Android при помощи Arduino Leonardo и подрулевого джойстика от Reno
- Управление Android при помощи Arduino Leonardo и подрулевого джойстика от Reno
- Создаём собственный игровой контроллер
- Источник вдохновения
- Основные компоненты
- Рекомендуемые инструменты
- Программное обеспечение
- Предупреждение
- Часть 1. Собираем контроллер!
- Работаем с переключателями без документации.
- Простая двухконтактная кнопка/переключатель
- Подключаем переключатель к Arduino
- Другие переключатели почти без документации.
- Светодиодный переключатель с тремя контактами
- Подключаем переключатель к Arduino
- Проблемы этого решения
- Подключаем этот переключатель к Arduino правильно
- Подсказки по сборке
- Часть 2. Превращаем устройство в игровой контроллер!
- Часть 3. Интегрируем устройство с собственной игрой!
- Настраиваем Arduino
- Настраиваем игру
- Часть 4. Что если я хочу части 2 и 3 одновременно?
- Часть 5. Завершение
Джойстик Ардуино – подключение и скетч
Использование джойстика – это один из способов обмена информацией между человеком и устройством (компьютер, микроконтроллер) на основе Arduino. Чаще всего их используют для управления механизмами или роботами. По аналогии с привычным игровым миром джойстики также часто называют геймпадами. Геймпад прост и удобен в использовании. Сегодня существует большое количество видов джойстиков по количеству степеней свободы, частоте считывания информации и используемой технологии. В данной статье мы рассмотрим наиболее популярный вариант, научимся управлению джойстиком и узнаем, как его подключать.
Принцип работы джойстика
Аналоговый джойстик выглядит как ручка, которая закрепляется на шарнире с двумя потенциометрами, определяющими оси X и Y, и кнопкой Z. Наклон или поворот ручки вращает специальный подвижный контакт, из-за чего изменяется выходное напряжение. Сам геймпад оснащен пружиной, благодаря которой плавно возвращается в первоначальное центральное состояние после отпускания его с какой-либо позиции. Устройство позволяет более плавно отследить степень отклонения от центральной (нулевой) точки.
Подключение джойстика к ардуино
Подключение джойстика к Arduino Uno выполняется по схеме, приведенной ниже.
На модуле имеется 5 выходов – Vcc, Gnd, X, Y и Key (обозначения могут различаться в зависимости от устройства).
Данные по оси X выводятся на вход А0, по оси Y – на А1. Для визуального контроля нажатия кнопки также можно подключить светодиод D11. Питание осуществляется напряжением 5 Вольт. Пин GND присоединяется к такому же пину на плате Ардуино. Контакт SW можно подсоединить к любому цифровому пину.
Как видим, подключение модуля джойстика не сложно. Если устройство не работает после подключения, проверьте, правильно ли вы подсоединили все пины.
Как отслеживать текущее положение или направление джойстика
Для использования джойстка в реальном проекте нам понадобится написать скетч, чтобы обрабатывать данные, которые отправляет джойстик во время своей работы.
Узнать, в каком положении в текущий момент находится устройство, можно в зависимости от значений потенциометров. Перемещение происходит по направлению находящихся перпендикулярно осей X и Y. Считывание информации с геймпада происходит с помощью функции analogRead() – она показывает значения в диапазоне от 0 до 1023. В качестве аргументов ей поступают номера пинов, к которым произведено подключение джойстика:
Serial.println(analogRead(A0)); // показывает положение X координаты
Serial.println(analogRead(A1)); // показывает положение Y координаты
Для удобства советуется использовать константы, чтобы уменьшить и упростить итоговый код. Аналоговые пины как раз можно объявить постоянными:
const byte PIN_ANALOG_X = A0; // постоянная для координаты Х
const byte PIN_ANALOG_Y = A1; // постоянная для координаты Y
Определение направления движения джойстиком
Управление с помощью джойстика подразумевает собой то, что мы должны узнать направление движения ручки джойстика. Для этого нам придется получить и интерпретировать данные по всем осям.
По значению положений осей X и Y можно узнать, находится ли джойстик в центре или произошло смещение. Значения во всех направлениях находятся в диапазоне от 0 до 1023, как говорилось ранее. В первую очередь приходит мысль, что центральная точка будет находиться примерно в значении 511-512. Это заключение не совсем правильно, так как абсолютно точное положение определить нельзя.
Неверное определение центрального значения может привести к тому, что будет получена ошибочная информация о движении джойстика, если он будет находиться в неподвижном состоянии. Для этого следует выбрать числовой диапазон и условно считать, что любое значение в нем будет центральной точкой. Значения нужно подстраивать под каждый вид джойстика, но примерно оно будет в диапазоне 505-518. Полученные значения записываются в код в виде постоянных:
const int X_THRESHOLD_LOW = 505;
const int X_THRESHOLD_HIGH = 518;
const int Y_THRESHOLD_LOW = 500;
const int Y_THRESHOLD_HIGH = 510;
Следующим шагом будет преобразование координат в диапазон от -1 до 1. Для X -1 – это перемещение влево, 0 – нет движения, 1 – вправо. По Y -1 – движение вниз, 0 – центральное значение, 1 – вверх. Изначально устанавливаем все значения в центр 0. Для проверки, происходит ли перемещение, используем выражения if/else.
Подводные камни в работе геймпада
Как и с любое устройство, джойстики не лишены недостатков. В первую очередь, наличие пружины не позволяет ручке точно вернуться в центральное положение из-за трения в механических деталях. Это приводит к тому, что приходится программно определять центральное положение, вернее диапазон значений, в которых любая точка будет условно считаться серединой.
Второй проблемой можно назвать наличие так называемых мертвых зон. Два крайних значения при наибольших отклонениях должно быть равным 0 В и напряжению питания. В действительности эти значения могут различаться, так как не используется весь электрический диапазон изменения сопротивления. Для решения этой проблемы крайние точки могут соответствовать значениям 1 кОм и 9 кОм.
Плата расширения JoyStick shield
Для управления роботами или другими механизмами иногда требуется использовать джойстик к кнопками и средствами коммуникаций. Для того, чтобы не придумывать каждый раз новые конструкции, рекомендуется купить готовую плату расширения ардуино для джойстика, в которой все необходимые элементы будут спаяны.
Рассмотрим, что представляет собой этот шилд от известного в мире ардуино производителя Sparkfun. Данный геймпад работает исправно и стоит относительно недорого. Устройство может поставляться в немного разобранном виде, так что сначала его нужно собрать.
Шилд содержит несколько стандартных кнопок (4 обычных сбоку и кнопка выбора). В зависимости от модели, на плате могут быть добавлены разъемы для подключения модулей bluetooth или wifi. Традиционно, с помощью выходов пинов и гребенки можно подключать внешние устройства.
Заключение
Джойстик ардуино – незаменимая вещь во моих проектах. Благодаря этому виду датчиков вы можете добавить в свое устройство удобные и современные средства управления. В некоторых ситуациях без джойстика вообще обойтись практически невозможно: джойстик ардуино используется для управления роботами, умными машинами, сервоприводами, громкостью музыкой и яркостью подсветки на мониторе, как навигация в различных играх и во многих других проектах.
Подключение готового модуля не сложно, так же весьма доступным является и сам управляющий скетч. Чаще всего, джойстик используется в месте с кнопками и в паре с беспроводными интерфейсами, потому то управлять джойстиком на проводе быстро перемещающимися устройствами практически невозможно. Поэтому рекомендуется для работы использовать готовые шилды, в которых есть все необходимое.
Источник
Тема: Управление Android при помощи Arduino Leonardo и подрулевого джойстика от Reno
Опции темы
Поиск по теме
Отображение
Управление Android при помощи Arduino Leonardo и подрулевого джойстика от Reno
Пытаясь осуществить CarPc из Nexus 7 2013 у себя в машине наткнулся на одну интересную вещь — Leonardo с возможностью HID keyboard.
До этого думал ставить просто контроллер для управлением включения-отключения планшета и переферии. Было просто.
Но я задумал облегчить управление планшетом в движении и для этого купил подрулевой джойстик от ам Renault.
То, что я находил из скетчей под Ардуино, были либо под UNO либо на резистивное управление магнитолой.
// alpine
#define alpinePin 13
#define cmdPower 0x09
#define cmdSource 0x0A
#define cmdBand 0x0D
#define cmdVolumeDown 0x15
#define cmdVolumeUp 0x14
#define cmdUp 0x0E
#define cmdDown 0x0F
#define cmdLeft 0x13
#define cmdRight 0x12
#define cmdPlay 0x07
#define cmdAProc 0x06
#define cmdMute 0x16
#define cmdAngleUp 0x4C
#define cmdAngleDown 0x4B
#define cmdCDChange 0x03
/////////////////////////////////////////////////////////////////
// джойстик
#define rows 3
#define cols 2
// номера кнопок в соответствии со схемой
const byte keys [ rows ][ cols ] =
<
< 1 , 4 >,
< 2 , 5 >,
< 6 , 3 >
>;
// состояния направлений енкодера
const byte encoderdirection [ 3 ][ 3 ] = // 0 — на месте, 1 — вниз, 2 — вверх
<
< 0 , 1 , 2 >, // 0
< 2 , 0 , 1 >, // 1
< 1 , 2 , 0 >// 2
>;
// номера пинов
const byte rowPins [ rows ] = < 8 , 6 , 9 >; // строки (желтый, зеленый, голубой)
const byte colPins [ cols ] = < 1 , 0 >; // столбцы (черный, красный)
#define encoderPin 2 // пин енкодера (коричневый)
byte encodervalue ;
// маски для клавиш
#define MaskMediaButton 1
#define MaskRadioButton 2
#define MaskVolumeUpButton 4
#define MaskVolumeDownButton 8
#define MaskOkButton 16
#define MaskMuteButton 32
#define MaskScrollDown 64
#define MaskScrollUp 128
void setup ()
<
int i ;
// строки — на выход
for ( i = 0 ; i rows ; ++ i )
<
pinMode ( rowPins [ i ], OUTPUT );
>
// столбцы — на вход
for ( i = 0 ; i cols ; ++ i )
<
pinMode ( colPins [ i ], INPUT );
digitalWrite ( colPins [ i ], HIGH ); // включаем подтягивающий резистор
>
// столбец для енкодера
pinMode ( encoderPin , INPUT );
digitalWrite ( encoderPin , HIGH ); // включаем подтягивающий резистор
Serial . begin ( 9600 );
// initialize mouse control:
Mouse . begin ();
Keyboard . begin ();
>
// сканирование джойстика
byte scan ( void )
<
int i , j ;
byte code = 0 ;
for ( i = 0 ; i rows ; ++ i )
<
digitalWrite ( rowPins [ i ], LOW );
// кнопки
for ( j = 0 ; j cols ; ++ j )
<
if( digitalRead ( colPins [ j ]) == false )
<
code |= 1 keys [ i ][ j ] — 1 );
>
>
// енкодер
if ( digitalRead ( encoderPin ) == false )
<
int oldencodervalue = encodervalue ;
encodervalue = i ;
switch ( encoderdirection [ oldencodervalue ][ encodervalue ])
<
case 1 : // вниз
code |= 64 ;
break;
case 2 : // вверх
code |= 128 ;
break;
>
>
digitalWrite ( rowPins [ i ], HIGH );
>
// отправка байта
void SendByte ( byte data )
<
for ( int i = 0 ; i 8 ; ++ i )
<
digitalWrite ( alpinePin , HIGH );
delayMicroseconds ( 560 );
digitalWrite ( alpinePin , LOW );
// отправка команды
void Send ( byte command )
<
digitalWrite ( alpinePin , HIGH );
delayMicroseconds ( 9000 );
digitalWrite ( alpinePin , LOW );
delayMicroseconds ( 4500 );
SendByte ( 0x86 );
SendByte ( 0x72 );
SendByte ( command );
SendByte (
digitalWrite ( alpinePin , HIGH );
delayMicroseconds ( 560 );
digitalWrite ( alpinePin , LOW );
>
// цикл программы
void loop ( void )
<
byte code ;
Протестировав этот скетч на нажатия кнопок я попытался написать скетч под свои нужды.
С управлением питания планшета и переферии я разобрался, а с джойстиком, увы нет.
По этому проблема сейчас встала в управлении андроид планшетом с этого подрулевого джойстика как с HID клавиатуры с короткими и длинными нажатиями на кнопки + энкодер.
Так как я в програмирование залез только сейчас, прошу вашей помощи в реализации проекта. В долгу не останусь, т.е. Ваш труд будет оплачен по договорености.
Жду ваших предложений, можно в личку.
Последний раз редактировалось Stray; 10.10.2014 в 13:32 .
Источник
Создаём собственный игровой контроллер
Источник вдохновения
На игровых выставках разработчики Objects in Space показывали демо своей игры с контроллером на кокпите огромного космического корабля. Он был дополнен загорающимися кнопками, аналоговыми приборами, световыми индикаторами состояния, переключателями и т.д… Это сильно влияет на погружение в игру:
На сайте игры выложен туториал по Arduino с описанием коммуникационного протокола для подобных контроллеров.
Я хочу создать то же самое для своей игры
В этом примере я потрачу примерно 40 долларов, чтобы добавить красивые, большие и тяжёлые переключатели на кокпит симулятора гонок. Основные затраты связаны с этими самыми переключателями — если бы я использовал простые переключатели/кнопки, то цена была в два раза ниже! Это настоящее оборудование, способное выдерживать 240 Вт мощности, а я буду пускать по ним только примерно 0,03 Вт.
Предупреждение: я решил сэкономить, поэтому оставляю ссылку на дешёвый китайский веб-сайт, где закупаю кучу разных компонентов/инструментов. Один из недостатков покупки компонентов по дешёвке заключается в том, что часто у них нет никакой документации, поэтому в статье я решу и эту проблему.
Основные компоненты
Рекомендуемые инструменты
Программное обеспечение
Предупреждение
Я изучал электронику в старшей школе, научился пользоваться паяльником, узнал, что красные провода нужно соединять с красными, а чёрные с чёрными… Вольты, амперы, сопротивление и связывающие их уравнения — вот и всё, чем исчерпывалось моё формальное обучение электронике.
Для меня это был обучающий проект, поэтому в нём могут быть плохие советы или ошибки!
Часть 1. Собираем контроллер!
Работаем с переключателями без документации.
Как сказано выше, я покупаю дешёвые детали у розничного продавца с низкой маржей, поэтому первым делом нужно разобраться, как работают эти переключатели/кнопки.
Простая двухконтактная кнопка/переключатель
С кнопкой всё просто — в ней нет светодиодов и всего два контакта. Переключаем мультиметр в режим непрерывности/прозвонки () и касаемся щупами разных контактов — на экране будет отображаться OL (open loop, разомкнутая цепь): это означает, что между двумя щупами нет соединения. Затем нажимаем на кнопку, по-прежнему касаясь щупами контактов — на экране теперь должно отобразиться что-то типа 0.1Ω и мультиметр начнёт пищать (сообщая о том, что между щупами присутствует очень низкое сопротивление — замкнутая цепь).
Теперь мы знаем, что при нажатии кнопки цепь замыкается, а при отжатии — размыкается. На схеме это можно обозначить как простой выключатель:
Подключаем переключатель к Arduino
Найдите на плате Arduino два контакта: помеченный GND и помеченный «2» (или любым другим произвольным числом — это контакты ввода-вывода общего назначения, которыми мы можем управлять через ПО).
Если мы подключим переключатель таким образом, а потом прикажем Arduino сконфигурировать контакт «2» как контакт INPUT, то получим цепь, показанную слева (на рисунке ниже). При нажатии кнопки контакт 2 будет напрямую соединяться с землёй / 0V, а при отжатии контакт 2 не будет соединён ни с чем. Это состояние (ни с чем не соединён) называется «floating» (состояние с высоким импедансом) и, к сожалению, это не очень хорошее состояние для наших целей. Когда мы считываем данные с контакта в ПО (с помощью digitalRead(2)), получаем LOW, если контакт заземлён, и непредсказуемый результат (LOW или HIGH), если контакт находится в состоянии floating!
Чтобы исправить это, мы можем сконфигурировать контакт так, чтобы он находился в режиме INPUT_PULLUP, который соединяется с резистором внутри процессора и создаёт схему, показанную справа. В этой цепи при разомкнутом переключателе контакт 2 имеет путь к +5V, поэтому при его считывании результатом всегда будет HIGH. При замыкании переключателя у контакта по-прежнему будет путь с высоким сопротивлением к +5V, а также путь без сопротивления к земле / 0V, который «побеждает», благодаря чему при считывании контакта мы получаем LOW.
Разработчикам ПО порядок может показаться обратным — при нажатии кнопки мы считываем false / LOW, а при отжатии — true / HIGH.
Можно сделать и наоборот, но у процессора есть только встроенные подтягивающие резисторы и нет утягивающих вниз резисторов, поэтому мы будем придерживаться этой модели.
Простейшая программа для Arduino, которая считывает состояние переключателя и сообщает PC о его состоянии, выглядит примерно так, как показано ниже. Вы можете нажать кнопку загрузки в Arduino IDE, а затем открыть Serial Monitor (в меню Tools), чтобы увидеть результаты.
Другие переключатели почти без документации.
Светодиодный переключатель с тремя контактами
К счастью, на основных переключателях моей панели есть пометки трёх контактов:
Я не полностью уверен, как он работает, поэтому мы снова переключим мультиметр в режим непрерывности и коснёмся всех пар контактов при включенном и отключенном переключателе… однако на этот раз мультиметр вообще не пищит, когда мы касаемся щупами [GND] и [+] при «включенном» переключателе! Единственная конфигурация, при которой мультиметр пищит (обнаруживает соединение) — когда переключатель «включен», а щупы находятся на [+] и [lamp].
Светодиод внутри переключателя блокирует измерения непрерывности, поэтому из проведённых выше проверок мы можем предположить, что LED подключен непосредственно к контакту [GND], а не к контактам [+] и [lamp]. Далее мы переключим мультиметр в режим проверки диодов (символ ) и снова проверим пары контактов, но на этот раз важна полярность (красный и чёрный щуп). Теперь если мы соединим красный щуп с [lamp], а чёрный — с [GND], то светодиод загорится, а на мультиметре отобразится 2.25V. Это прямое напряжение диода, или минимальное напряжение, необходимое для его включения. Вне зависимости от положения переключателя, 2.25V от [lamp] к [GND] заставляет LED загореться. Если мы соединим красный щуп с [+], а чёрный — с [GND], то светодиод загорится только при включённом переключателе.
Из этих показаний мы можем предположить, что внутренности этого переключателя выглядят примерно как на схеме ниже:
- [+] и [lamp] замыкаются накоротко, когда переключатель включен/замкнут.
- Положительное напряжение от [lamp] к [GND] всегда зажигает светодиод.
- Положительное напряжение от [+] к [GND] зажигает светодиод только при включенном/замкнутом переключателе.
Честно говоря, о присутствии резистора здесь можно только догадываться. Светодиод должен быть соединён с соответствующим резистором, чтобы ограничивать подаваемый на него ток, или он сгорит. Мой не сгорел и похоже, что работает правильно. На форуме веб-сайта продавца я нашёл пост, в котором говорится об установленном резисторе, поддерживающем работу до 12 В, и это сэкономило мне время на проверку/вычисления подходящего резистора.
Подключаем переключатель к Arduino
Проще всего использовать переключатель с Arduino, проигнорировав контакт [lamp]: подключить [GND] к GND в Arduino и соединить [+] с одним из пронумерованных контактов Arduino, например 3.
Если мы сконфигурируем контакт 3 как INPUT_PULLUP (так же, как и для предыдущей кнопки), то придём к показанному ниже результату. Слева вверху показано значение, которое мы будем получать, выполнив «digitalRead(3)» в коде Arduino.
Когда переключатель включен/замкнут, мы считываем LOW и светодиод загорается! Для использования такого переключателя в данной конфигурации мы можем использовать тот же код Arduino, что и в примере с кнопкой.
Проблемы этого решения
После подключения к Arduino полная цепь выглядит так:
Однако здесь мы можем увидеть, что при замыкании переключателя кроме небольшого ограничивающего ток резистора перед LED (я предполагаю, что его сопротивление 100 Ом) есть и ещё и подтягивающий резистор на 20 кОм, который ещё больше снижает величину тока, текущего через светодиод. Это означает, что хотя цепь и работает, светодиод будет не очень ярким.
Ещё один недостаток этой схемы в том, что у нас нет программного контроля над LED — он включён, когда включён переключатель, и отключен в противоположном случае.
Можно посмотреть, что случится, если мы подключим контакт [lamp] или к 0V, или к +5V.
Если [lamp] подключен к 0V, то светодиод постоянно отключен (вне зависимости от позиции переключателя), а распознавание позиции Arduino всё равно выполняется. Это позволяет нам при желании программно отключать LED!
Если [lamp] подключен к +5V, то светодиод постоянно включен (вне зависимости от позиции переключателя), однако распознавание позиции Arduino поломано — с контакта всегда будет считываться HIGH.
Подключаем этот переключатель к Arduino правильно
Мы можем преодолеть описанные выше ограничения (низкий ток/яркость светодиода и отсутствие программного контроля над светодиодом), написав больше кода! Чтобы разрешить конфликт между возможностью управления светодиодом и сломанным из-за него распознаванием позиции, мы можем разделить две задачи по времени, то есть временно отключать LED при считывании контакта датчика (3).
Сначала подключим контакт [lamp] к ещё одному контакту Arduino общего назначения, например, к 4, чтобы можно было управлять lamp.
Чтобы создать программу, которая будет правильно считывать позицию переключателя и управлять светодиодом (мы заставим его мигать), нам достаточно просто отключать светодиод перед считыванием состояния переключателя. Светодиод будет отключаться всего на доли миллисекунд, поэтому мерцание не должно быть заметно:
В Arduino Mega контакты 2-13 и 44-46 могут использовать функцию analogWrite, которая на самом деле не создаёт напряжения от 0V до +5V, а аппроксимирует его при помощи прямоугольной волны. При желании можно использовать её для управления яркостью светодиода! Этот код заставит свет пульсировать, а не просто мерцать:
Подсказки по сборке
Пост и так уже довольно большой, так что я не буду добавлять ещё и туториал по пайке, можете его загуглить!
Однако приведу самые базовые советы:
- При соединении проводов с большими металлическим контактами сначала убедитесь, что паяльник нагрелся и какое-то время нагревайте и металлический контакт. Смысл пайки заключается в образовании постоянного соединения созданием сплава, но если горячей является только одна часть соединения, то у вас запросто может получиться «холодное соединение», которое выглядит как соединение, но на самом деле не соединено.
- При соединении двух проводов наденьте сначала на один из них кусок термоусадочной трубки — после соединения трубку надеть будет нельзя. Это кажется очевидным, но я постоянно это забываю и мне приходится использовать вместо трубки изоленту… Протяните термоусадочную трубку подальше от соединения, чтобы она не нагрелась раньше времени. Проверив паянное соединение сдвиньте на него трубку и нагрейте её.
- Тонкие маленькие соединительные провода, которые я упоминал в начале, хорошо подходят для соединений без пайки (например, при подключении к Arduino!), но довольно хрупкие. После пайки используйте для их закрепления клеевой пистолет и устраните из самого соединения все напряжения. Например, красные провода на показанном ниже снимке при работе можно случайно потянуть, поэтому после пайки я зафиксировал их каплей горячего клея:
Часть 2. Превращаем устройство в игровой контроллер!
Чтобы ОС распознала устройство как игровой USB-контроллер, нужен достаточно простой код, но, к сожалению, также необходимо заменить firmware USB-чипа Arduino другим, которое можно взять здесь: https://github.com/harlequin-tech/arduino-usb.
Но после заливки этого firmware в Arduino устройство становится USB-джойстиком и перестаёт быть Arduino. Поэтому чтобы перепрограммировать его, нужно заново перепрошить исходную firmware Arduino. Эти итерации довольно мучительны — загружаем код Arduino, прошиваем firmware джойстика, тестируем, прошиваем firmware arduino, повторяем…
Пример программы для Arduino, которую можно использовать с этим firmware, показан ниже — он конфигурирует три кнопки в качестве вводов, считывает их значения, копирует значения в структуру данных, ожидаемую этим firmware, а затем отправляет данные. Смыть, намылить, повторить.
Часть 3. Интегрируем устройство с собственной игрой!
Если у вас есть контроль над игрой, с которой должно взаимодействовать устройство, то в качестве альтернативы можно общаться с контроллером напрямую — нет необходимости делать его видимым для ОС как джойстик! В начале поста я упомянул Objects In Space; именно такой подход использовали её разработчики. Они создали простой коммуникационный ASCII-протокол, позволяющий контроллеру и игре общаться друг с другом. Достаточно просто перечислить последовательные порты системы (они же COM-порты в Windows; кстати, посмотрите, как ужасно это выглядит на C), найти порт, к которому подключено устройство с названием «Arduino», и начать считывать/записывать ASCII по этой ссылке.
На стороне Arduino мы просто используем функции Serial.print, которые применялись в показанных выше примерах.
В начале этого поста я также упоминал мою библиотеку для решения этой задачи: https://github.com/hodgman/ois_protocol.
Она содержит код на C++, который можно интегрировать в игру и использовать её в качестве «сервера», и код Arduino, который можно выполнять в контроллере, чтобы использовать его в качестве «клиента».
Настраиваем Arduino
В example_hardware.h я создал классы, чтобы абстрагировать отдельные кнопки/переключатели; например, «Switch» — это простая кнопка из первого примера., а «LedSwitch2Pin» — переключатель с управляемым светодиодом из второго примера.
Код примера для моей панели кнопок находится в example.ino.
В качестве небольшого примера давайте допустим, что у нас есть единственная кнопка, которую нужно отправлять в игру, и один управляемый игрой светодиод. Необходимый код Arduino выглядит так:
Настраиваем игру
Код игры написан в стиле «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.
Часть 4. Что если я хочу части 2 и 3 одновременно?
Чтобы контроллер мог работать в других играх (часть 2), нужно установить собственное firmware и одну программу Arduino, но чтобы контроллер полностью программировался игрой, мы использовали стандартное firmware Arduino и другую программу Arduino. Но что если мы хотим иметь обе возможности одновременно?
Пример приложения, на который я давал ссылку выше (ois2vjoy), решает эту проблему.
Это приложение общается с OIS-устройством (программа из части 3), а затем на PC преобразует эти данные в обычные данные контроллера/джойстика, которые потом передаются в виртуальное устройство контроллера/джойстика. Это означает, что можно позволить своему контроллеру постоянно использовать библиотеку OIS (другое firmware не требуется), а если мы захотим использовать его как обычный контроллер/джойстик, то просто запустим на PC приложение ois2vjoy, выполняющее преобразование.
Часть 5. Завершение
Надеюсь, кому-то эта статья показалась полезной или интересной. Спасибо, что дочитали до конца!
Если вам стало любопытно, то я приглашаю вас поучаствовать в развитии библиотеки ois_protocol! Думаю, будет здорово разработать единый протокол для поддержки всевозможных самодельных контроллеров в играх и стимулировать игры к прямой поддержке самодельных контроллеров!
Источник