Хочу сразу оговориться:

1. Статься из разряда «how to…». Пишу только потому что просили и чтоб не выглядеть голословным.

2. Мне столь простое устройство не нужно. Поэтому корпусом и подбором компонентов не заморачиваюсь. Делаем в виде прототипа.

3. Платформа Arduino. Ее уровень абстракции является наиболее подходящим для изучения школьниками (класса с 6-го). Собственно из моего учебного курса и взята большая часть описываемых примеров.

4. Статья скорее как затравка к изучению этой темы. Я не буду сильно углубляться и рассказывать все с азов. Это будет слишком объемно и не влезет в рамки статьи. В конце дам список ресурсов для самостоятельного изучения.

 

Постановка задачи

Хотим получить электронную начинку 4-х канального пульта пропорционального радиоуправления для… каждый сам решает для чего.

Формализуем наше «хочу»:

Вход – два двухосевых джойстика.

Выход – PPM сигнал для подключения к вч-модулю (или к компьютеру для симулятора).

 

Введение

Сердцем нашей конструкции будет микроконтроллер семейства mega фирмы Atmel, помещенный на плату с минимальной обвязкой и с зашитым в него специальным загрузчиком для программирования по последовательному порту. Собственно это и есть Arduino. Подробно можно почитать на официальном сайте проекта Arduino.cc или на его русскоязычном клоне Arduino.ru. Там желающие найдут всю необходимую информацию о том, какие бывают разновидности Arduino, как заливать прошивку, познакомятся с основами языка, смогут свободно скачать среду программирования… Там все по-русски и без затей. Никаких заумных инсталляторов, никаких сложных сред. Небольшое меню и две-три кнопки на тулбаре – все что нужно для того чтобы начать.

Джойстик. В его конструкции за прошедшие ндцать лет кардинально ничего не изменилось. Два потенциометра с перпендикулярными осями – вот и весь джойстик. Перемещение ручки по некоторой оси приводит к перемещению скользящего контакта соответствующего переменного резистора. Подключим их по следующей схеме(левый рисунок). Получится ни что иное как обыкновенный делитель напряжения(схема справа). Так для каждого положения ручки управления R1 и R2 будут свои. При этом R1 + R2 = const (номинал резистора). Т.е. для каждого положения ручки на оси на входе микроконтроллера будет свое напряжение в интервале от 0 до VCC(напряжения питания).

В джойстиках используются обычно резисторы номиналом в 5Ком. Но точность номинала при таком подключении не особо важна. Это может быть и 4, и 6 и 10Ком.

Где взять джойстики? Ну как-то так сложилось, что все самое интересное и нужное можно найти в пультах Nintendo Wii. Нет, можно конечно сделать самому... Но на сегодня, как мне кажется, самый простой и дешевый вариант – купить джойстики управления для Turnigy 9XR прямо тут на Паркфлаере. Лично я закупил их с десяток для различных поделок и экспериментов.

Левый стик управления в сборе - для передатчика Turnigy 9XR, (Mode 2)

Правый стик управления в сборе - для передатчика Turnigy 9XR, (Mode 2)

Где взять Arduino и какую выбрать для данной задачи? Поскольку задача крайне проста, плату можно брать любую. Самая маленькая и дешевая – Arduino Mini с atmega168 на борту. Правда к ней надо еще взять USB-to-TTL для программирования или Kingduino USB to serial UART interface Я взял Arduino Nano c atmega328 (потому что под руку подвернулась именно она) и шилд типа такого для удобства подключения периферии.

 

Получение положения джойстиков

Подключаем каждый из четырех резисторов джойстиков по выше указанной схеме. При этом у Arduino задействуем контакты A0-A3. Эти контакты подключены к АЦП микроконтроллера и могут быть запрограммированы как аналоговые входы. Более менее подробно о программировании аналоговых входов я писал тут. Повторяться не буду.

Пишем прошивку. Я предумышленно разбил код на три файла:

TX.ino – основной файл. Он содержит главные точки входа – функции setup() и loop().

Config.h – в этом файле в дефайнсах определяется подключение периферии

Analog.ino - собственно код работы с АЦП.

Принцип простой. Настраиваем регистры микроконтроллера так, чтобы АЦП непрерывно выполнял преобразования. По завершении каждого преобразования срабатывает прерывание ISR(ADC_vect) и выполняется соответствующий код. Нам остается только переключать входы к АЦП и запоминать результат в массиве. Время на одно преобразование порядка 26мкс. Если Вы внимательно посмотрите на мой код, то заметите, что я беру результат каждого второго преобразования. Все дело в том, что АЦП работает независимо от центрального ядра. Пока выполняется код в прерывании и переключаются входы АЦП уже делает следующее преобразование. Как следствие – недостоверный результат. Поэтому я и беру каждое второе… В итоге получим массив из четырех элементов, значения которых должны изменяться пропорционально движению джойстиков в интервале от 0 до 1023. Вот архив (TX1.rar) с кодом примера.

 

Формируем выходной сигнал

Теперь нам надо сформировать массив канальных импульсов. Сделаем для этого такую функцию:

void UpdateChannels()

{

for (uint8_t i = 0; i<CHANNELS_COUNT; i++)

{

Channels[i] = map(AnalogValues[i], 0, 1023, 1000, 2000);

}

}

Здесь мы заполняем массив значений каналов попутно приводя полученные с АЦП значения к интервалу 1000-2000мкс. Это будут наши канальные импульсы. Осталось по этому массиву сформировать выходной сигнал. Для этого воспользуемся таймером.

У 168-ой /328-ой меги есть три таймера/счетчика, работающих от основного задающего генератора. Два из них имеют разрядность 16 и один – 8. Будем использовать один из 16-ти разрядных таймеров.

Сначала его надо настроить. Во-первых при частоте 16МГц установим делитель на 8, чтоб таймер отсчитывал половинки микросекунд:

TCCR1B |= (1<<CS11);

Каждый из таймеров имеет два компаратора и может генерить прерывания по совпадению значений. Разрешим эти прерывания для нашего таймера:

TIMSK1 = (1<<OCIE1A) | (1<<OCIE1B);

Компаратор А настроим на длину фрейма – 20мс

OCR1A = 100000;

Компаратор В будем использовать для формирования канальных импульсов.

Выводить импульсы будем на 13-й вывод Arduino.

В прерывании компаратора А напишем код инициализации нового канального фрейма:

ISR (TIMER1_COMPA_vect)

{

ppm_cur = 0;

OCR1B = PPM_PAUSE;

TCNT1 = 0;

PPM_on;

}

Фрейм начинается с паузы. Ее длину мы и запишем в соответствующий регистр компаратора В.

В прерывании компаратора В будет следующий код:

ISR (TIMER1_COMPB_vect)

{

if (PPM_0){

PPM_off;

OCR1B = TCNT1 + PPM_PAUSE;

ppm_cur++;

}

else {

PPM_on;

if(ppm_cur <= CHANNELS_COUNT)

OCR1B = TCNT1 + (Channels[ppm_cur-1]<<1);

else {

OCR1B = 0;

}

}

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

Если на выходе была пауза, то установим на выходе сигнал. А в регистр таймера запишем его длину. Если это синхропауза, то длина будет до конца фрейма и в регистр запишем 0.

Вроде бы как все. Загружаем в контроллер, подключаем к вч-модулю, на выход приемника вешаем серы… Работает!

Вот только есть одно НО. Сервы работают не в полном диапазоне. В чем проблема?

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

И сопротивления R1 и R4 как раз и дают эту погрешность. Ну да не проблема. Введем калибровку. Для этого подключим кнопку. Алгоритм будет примитивный:

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

Первый джойстик вправо вверх, держать, нажать кнопку.

Второй джойстик влево вниз, держать, нажать кнопку.

Второй джойстик вправо вверх, держать, нажать кнопку.

Так мы заполним два массива минимальных и максимальных значений для каждого аналогового входа. Вот только каждый раз калибровать – как-то неудобно. Ок. У нашего контроллера есть энергонезависимая память – запишем туда.

Теперь все работает как надо. Код по ссылке (TX2.rar) .

Так же не сложно увидеть, что число каналов легко увеличить до восьми, добавив еще органы управления – «крутилки» (резисторы) и тумблеры. Далее можно усложнить функцию UpdateChannels() - добавить туда микшеры. Можно подключить дисплей и написать меню сервисных функций… Итог – пульт а-ля Turnigy 9XR своими руками. Если не будет хватать выводов или памяти контроллера – возьмите по-мощнее. Atmega 2560 сможет реализовать практически все Ваши идеи и фантазии.

В заключении обещанные ссылки:

1. Arduino.cc – официальный сайт платформы

2. Arduino.ru – русскоязычный сайт платформы

3. http://rc-master.ucoz.ru/publ/20-1-0-85 - достаточно неплохой справочник по микроконтроллерам Atmel

4. Улли Соммер - Программирование микроконтроллерных плат ArduinoFreeduino – 2012

5. Arduino. Блокнот программиста. Brian W. Evans – справочник языка. Есть русский перевод.

6. Гололобов В. - С чего начинаются роботы. О проекте Arduino для школьников (и не только) – 2011

Будут вопросы – задавайте. Постараюсь ответить.

Делать фотографии и снимать видео ради всего этого не вижу смысла - времени нет, да и лениво.

Оборудование, на котором тестировал(за исключением компьютера):