Радиоуправление на ATmega8 и радиомодулях NRF24L01+PA+LNA. Передатчик

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

Это первый фактор, который сподвигнул меня на «отчаянный шаг» — разработку собственной схемы радиоуправления. Второй фактор заключается в том, что подавляющее большинство конструкций не имеет обратной связи. А так как в моем случае необходимо управлять моделью подводной лодки, то необходимо контролировать как минимум два параметра на стороне модели: уровень заряда аккумулятора и наличие воды внутри корпуса модели. Третий же фактор — знакомство с беспроводными модулями NRF24L01+, а так же с их усиленной версией (дальность «стандартной» — около 10 метров) NRF24L01+PA+LNA, которая позволяет «пробить» на целых 1.1 км, в условиях прямой видимости и при скорости передачи 250 кб/с. Ну и конечно, при разработке схемы «с нуля» гораздо проще изначально ее ориентировать на свои нужды.

Что в итоге получилось вы узнаете из данного «цикла» статей. Он состоит из двух публикаций — текущей, в которой описан передатчик а так же следующей, в которой будет описан приемник.

Итак, немного общих сведений о данной системе радиоуправления.

Она имеет 4 цифровых (дискретных) и 4 аналоговых каналов, что позволяет ее использовать для управления моделью любого типа: воздушной, наземной или водной. Кроме того,  имеется обратная связь, что особенно удобно при управлении воздушной или водной моделью (на дисплей пульта выводится информация о состоянии заряда батарей, уровне сигнала, наличии воды в корпусе и температуре двигателя). Для отображения информации используется дисплей от телефонов Siemens LPH8731-3C. При разрешении 101х80 пикселей, его вполне хватает для решения поставленных задач.

Решено было использовать NRF24L01+PA+LNA (на AliExpress), дальность связи которых составляет 1,1 км, как упоминалось ранее (против NRF24L01+ , у которых всего 10-15 метров). Цоколевки обоих модулей абсолютно идентичны.

После небольшой вводной, можно приступить непосредственно к теме этой статьи — пульту управления. 

«Сердцем» устройства является микроконтроллер ATmega8. Вообще-то на этапе проектирования предполагалось использование микроконтроллера ATmega48, но как выяснилось, написанный код для него был слишком объемным, и впоследствии он был заменен на ATmega8. 

Принципиальная схема устройства представлена ниже:

Схема

Немного о схеме.

Внимание! На схеме не обозначен интегральный стабилизатор напряжения LM1117-3.3! Он монтируется либо на внешней плате, либо непосредственно на плате пульта. К примеру, я его расположил на свободном от деталей участке платы, и залил термоклеем. 

Разъем J1 используется для подключения радио-модуля NRF24L01+. Разъемы J4 и J5 предназначены для упрощения подачи питающего напряжения на какие-либо внешние устройства. J4 подключен к плюсу питания (3.3V), а J5 — к минусу (общему). Кроме того, к этим разъемам так же подключается и стабилизатор LM1117-3.3. 

J2 предназначен для измерения уровня заряда аккумуляторов. Для этого, необходимо соединить его контакт №1 с плюсом аккумуляторной батареи. По-умолчанию в прошивке идет расчет уровня заряда для двух последовательно соединенных Li-Ion аккумуляторов (максимальный уровень напряжения 8.4В). Если у вас используется другой тип аккумуляторов, то необходимо внести изменения в прошивку, а так же возможно придется пересчитать делитель напряжения на резисторах R7 и R8, но об это несколько позже. Как вы видите, в схеме имеется еще один неиспользуемый делитель — его предполагалось использовать для контроля напряжения каждой банки в аккумуляторной батарее. В данной версии прошивки он не используется, но может пригодиться, если вы планируете применить в своей конструкции аккумуляторы другого типа. Например, Ni-Mh, Ni-Cd и т.д. , с меньшим напряжением банки и как правило, большим количеством банок в батарее. Правда, для этого придется опять-таки немного модифицировать прошивку.

К разъему J2 подсоединен ЖК дисплей. На принципиальной схеме контактам разъема соответствуют одноименные контакты дисплея (контакт №1 на разъеме совпадает с контактом №1 на дисплее). На практике выглядит так:

Схема подключения ЖК дисплея

Переменные резисторы RV1 — RV4 служат для установки положения исполнительных механизмов, подключенных к приемнику (сервомашинки, регуляторы оборотов двигателя и т.д.).

Кнопки предназначены для дискретного управления нагрузкой, подключенной к отдельному разъему приемника. Они настроены на работу без фиксации.

Программа для микроконтроллера написана на C под AVR-GCC (WinAVR). Кроме стандартных библиотек использовались модифицированные варианты библиотек для дисплея от телефона Siemens A65 (LPH8731-3C.h), и для работы с радиомодулем NRF24L01+. Они присутствуют в прикрепленном файле.

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

Кратко о переменных:

 const unsigned char mux[][3] = {  //Применяется для переключения входа АЦП    {0,0,0},{0,0,1},{0,1,0},    {0,1,1},{1,0,0},{1,0,1},    {1,1,0},{1,1,1} };  unsigned char control[4];  //Массив, содержащий значения, соответствующие положению ручек переменных резисторов unsigned char rx_array[8];  //Массив, в который записываются данные для передачи unsigned char tx_array[8];  //Аналогично предыдущему, но для приема unsigned char rx_address[5] = {0xD7,0xD7,0xD7,0xD7,0xD7};  //Адрес устройства, прием unsigned char tx_address[5] = {0xE7,0xE7,0xE7,0xE7,0xE7};  //Аналогично предыдущему, передача unsigned int button_push[16] = {1021, 339, 509, 256, 696, 294, 413, 229, 837, 317, 460, 242, 606, 276, 380, 217};  //Численное значение АЦП для различных комбинаций кнопок   volatile unsigned char counter_rx, action;  //Отвечают за обновление данных на ЖК volatile unsigned char water, water_old, water_set;  //"Водные" переменные. В первую записывается текущее состояние (0 - 1), вторая отвечает за определение изменения. Третья - счетчик. volatile unsigned char button;  //Используется для хранения текущего состояния кнопок volatile unsigned int battery_mod, battery_ctrl, signal_level;  //Ответственные за отображение уровня батарей и сигнала volatile int ds18temp;  //Температура char string[6];  //Нужна для вывода температуры на ЖК

Следующий пункт — реализация контроля двух банок аккумуляторов (либо двух аккумуляторных батарей).

В программе за контроль напряжения батареи пульта отвечает следующая функция:

 unsigned char get_battery_control(void) {    volatile unsigned char a;     battery_ctrl = adc_read(7, 0);    //    if (battery_ctrl < 204) a = 0;    else if (battery_ctrl < 223) a = 1;    else if (battery_ctrl < 235) a = 2;    else a = 3;    //       return a; }

Для мониторинга двух банок ее необходимо изменить следующим образом:

 unsigned char get_battery_control(void) {    unsigned char data[][3] = {{204, 223, 235},{102, 111, 117}};    volatile unsigned char d, e;    volatile unsigned int a, b, c;    a = adc_read(6, 0); //Задаем канал и разрешение (0 - 10бит, 1 - 8бит).    b = adc_read(7, 0);    if (b < a)     { 	 d = 1;   	 c = a;      }    else     { 	 d = 0; 	 c = b;      }    //    if (c < data[d][0]) e = 0;    else if (c < data[d][1]) e = 1;    else if (c < data[d][2]) e = 2;    else e = 3;    //       return e; }

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

И еще одна остановочка, последняя. Это касается кнопок.

Нажатие кнопки определяется следующим образом. Первым делом с помощью АЦП получаем значение напряжения на выводе, к которому подключены кнопки. Далее, происходит сравнение с переменной, в которой хранятся «эталонные» данные. Сравнение происходит в цикле, и если произошло совпадение, то легко узнать, какие кнопки нажаты. Для этого достаточно перевести число «проходов» цикла в двоичный код. Биты установленные в «1» и есть нажатые кнопки.

 unsigned int button_push[16] = {1021, 339, 509, 256, 696, 294, 413, 229, 837, 317, 460, 242, 606, 276, 380, 217};  //Численное значение АЦП для различных комбинаций кнопок .....  void get_button(void) {   volatile unsigned char a, i;   volatile unsigned int c, e[3];    for (i = 0;i < 3;i++)   {    e[i] = adc_read(4, 0);   }   c = (e[0] + e[1] + e[2])/3;  //Считаем среднее значение за 3 измерения    for (a = 0;a < 16;a++)  //Необходимо прокрутить цикл 16 (так как у нас 4 кнопки)   {    if (c > 1000) button = 0;    else if ((c > (button_push[a] - 10))&&(c < (button_push[a] + 10))) button = a; //Проверяем на совпадение. Если в районе +/- 10 ед. , то считаем верным.   } }

Для прошивки микроконтроллера в моем случае использовался программатор USBasp в паре с программой Khazama AVR Programmer. Fuse-биты микроконтроллера необходимо выставить следующим образом:

Fuse-биты

Если вы используете другую программу для прошивки микроконтроллера, то оставляйте все fuse-биты как они были в «чистом» МК, только выберите тактирование от встроенного генератора на 8МГц.

Теперь немного о печатной плате и сборке устройства. Печатная плата выполнена на одностороннем фольгированном материале (текстолит, гетинакс), и имеет размеры 45х55 мм. Топология печатной платы представлена ниже:

Печатная плата

Проводники, обозначенные синим цветом — это перемычки. Их можно выполнить, например, из телефонного одножильного кабеля.

Переменные резисторы можно применить любого типа, с сопротивлением 6,8 — 33 кОм. Микроконтроллер в теории можно заменить на ATmega168 или 328, так как они отличаются только объемом памяти программ. ЖК дисплей заменить нельзя, для этого придется использовать другую библиотеку для работы с ним. В качестве интегрального стабилизатора напряжения можно использовать любой линейный или импульсный, рассчитанный на выходное напряжение 3.3 вольта. Это может быть, например, LM1117-3.3. Резисторы R7 — R10 желательно брать презиционные, в противном случае возможно нечеткое определение нажатых кнопок.

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

Вид платы.

 

НА этом фото показано как был «установлен» стабилизатор LM1117-3.3. Джампер стоит для подачи 5 вольт на МК, минуя стабилизатор (для программирования).

 

 

Это фото сделано не просто так. Внимание! Если у вас есть желание не возиться с модулями NRF24L01+, вопрошая «Почему не передает …. ?», то установите непосредственно на платку параллельно питанию два конденсатора: на 47мкФ и 100нФ. Почему и как, вопрос, но без них стабильная работа практически не возможна.

Вид устройства в сборе.

 

Отображение данных на ЖК дисплее (приемник отключен).

Спасибо за внимание к этой статье! Удачной вам сборки ваших устройств!

Следующая статья: Радиоуправление на ATmega8 и радиомодулях NRF24L01+PA+LNA. Приемник

Список радиоэлементов

Обозначение Тип Номинал Количество Примечание Магазин Мой блокнот
U1 МК AVR 8-бит ATmega8 1
U2 Линейный стабилизатор LM1117-3.3 1 За пределами платы
U3 Радиомодуль NRF24L01+ 1 Или его модификация NRF24L01+LNA+PA
LCD1 LCD-дисплей LPH8731-3C 1
C1 Конденсатор 1000 мкФ 1 6.3В
C2 Конденсатор 100 нФ 1 0805
R1, R4 Резистор 2.2 кОм 2 0805
R2, R8, R10 Резистор 10 кОм 3 0805
R3 Резистор 4.7 кОм 1 0805
R5, R6 Резистор 240 Ом 2 0805
R7, R9, R11 Резистор 1.1 кОм 3 0805
RV1 — RV4 Переменный резистор 10к 4 СП-1
J1 — J5 Разъем PLS-40 1
SA1 — SA4 Переключатели МП-1 4 Любые