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

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

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

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

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

Она имеет 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 с плюсом аккумуляторной батареи. По-умолчанию в прошивке идет расчет уровня заряда для 2-х последовательно соединенных 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]; //Нужна для вывода температуры на ЖК

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

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

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;
}

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

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;
}

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

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

Нажатие кнопки определяется следующим образом. Первым делом с помощью АЦП получаем значение напряжения на выводе, к которому подключены кнопки. Далее, происходит сравнение с переменной, в которой хранятся «эталонные» данные. Сравнение происходит в цикле, и если произошло совпадение, то легко узнать, какие кнопки нажаты. Для этого достаточно перевести число «проходов» цикла в двоичный код. Биты установленные в «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-биты как они были в «чистом» МК, лишь выберите тактирование от встроенного генератора на 8МГц.

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

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

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

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

Вид платы.

 

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

 

 

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

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

 

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

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

Следующая статья: 


Список радиоэлементовОбозначение
Тип
Номинал
Количество
ПримечаниеМагазинМой блокнот

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

Скачать список элементов (PDF)

Прикрепленные файлы:

Добавить комментарий

Ваш адрес email не будет опубликован.