![](https://habrastorage.org/webt/0u/mm/oy/0ummoy-fn9wqwmngehdcra0awii.jpeg)
Эта идея появилась у меня достаточно давно, и наконец-то дошли руки её частично реализовать. А именно: хотелось попробовать сделать средство общения с помощью известного радиопередатчика NRF24L01+PA+LNA.
В качестве способа общения на данном этапе подразумевается обмен текстовыми сообщениями, а на втором этапе — доделаю захват и передачу голоса и, может быть, даже файлов. На данном этапе написан код и протестирована в теории сама концепция. Итак…
▍ Вводная часть
Сначала небольшое отступление: многие недолюбливают эти передатчики из-за того, что их достаточно сложно запустить, так как они имеют свои особенности, о которых я уже говорил в прошлой статье.
![](https://habrastorage.org/getpro/habr/post_images/329/097/c0e/329097c0ecefa6049c6d962729464f2c.webp)
![](https://habrastorage.org/getpro/habr/post_images/b53/2e2/9c5/b532e29c547940e3ff434cf324db4c36.webp)
Тем не менее, вкратце повторю их основные проблемы и как с этим бороться. Главной проблемой, с которой сталкивается любой строитель системы на таких передатчиках, является то, что для их стабильной работы необходима большая сила тока, чем та, которую могут обеспечить пины питания микроконтроллеров Arduino, esp32.
То есть, если вы просто подключите передатчик к этим пинам и будете пытаться его запустить, то, с большой долей вероятности, ничего не получится, либо передача будет работать нестабильно с постоянными разрывами связи и потерями пакетов.
Кроме того, нужно учитывать, что в момент передачи данных энергопотребление скачкообразно возрастает и, таким образом, если даже в состоянии покоя передатчик как-то работал, то в момент передачи резко происходит сбой.
Но даже если у вас с каким-то чудом передатчик заработал, то, с большой долей вероятности, могут начаться проблемы с потерями пакетов, так как радиотракт этого передатчика очень чувствителен к внешним помехам.
Казалось бы, всё выглядит достаточно печально, и нет возможности это исправить?
А вот и нет, всё это исправляется весьма легко и непринуждённо, после чего передатчик будет радовать вас стабильной высокоскоростной связью, которая, к тому же, обладает свойством весьма быстро восстанавливаться в случае потери: например, я достаточно много работал с wi-fi esp32, и, поэтому, мне есть с чем сравнить — при нажатии на кнопку перезагрузки esp32, восстановление wi-fi-связи происходит за период вплоть до 4 секунд (в самых запущенных случаях, но, обычно, конечно быстрее, но, тем не менее, не менее 1-2 секунд). В то же время как при нажатии на кнопку перезагрузки esp32, к которой подключён NRF24L01+PA+LNA, — восстановление связи происходит практически мгновенно. Точное время я не замерял, но визуально, это примерно 1/5 секунды и менее. Такое быстрое восстановление связи может быть важным в ряде применений, например, при удалённом управлении некими движущимися устройствами.
Итак, вкратце, что нужно для стабильной работы передатчика NRF:
- стабилизированный источник питания (я не стал мудрить и использовал родной, имеющий, к тому же, разъём для подключения передатчика, что достаточно удобно);
- параллельно пинам питания припаивается конденсатор, роль которого заключается в обеспечении стабильного питания, в пиковые моменты — я использовал на 63V, 100мкФ;
- плата передатчика обматывается бумажным малярным скотчем или просто бумажкой (я специально не использовал изоленту или обычный скотч, чтобы они не оставляли после себя липкий слой на плате) — для того, чтобы не замкнуть контакты. После этого, прямо поверх малярного скотча плата обматывается парой-тройкой витков кулинарной фольги или даже просто металлизированного блестящего фантика от конфеты (пробовал, отлично работает). Поверх всего, плата обматывается ещё одним слоем малярного скотча (чтобы защитить фольгу от повреждений). Суть этой процедуры с обматыванием заключается в защите радиотракта от внешних помех, — это позволит избежать потери пакетов;
- так как мы используем микроконтроллер, для управления этим передатчиком и для прошивки его будем использовать Arduino IDE, нужна будет правильная библиотека, умеющая работать с этим передатчиком.
При соблюдении всех перечисленных выше требований, радиопередатчик работает отлично и без каких-либо проблем (что учитывая его цену в 200 с небольшим рублей и скорости передачи – весьма заманчиво).
Но есть ряд небольших нюансов, которые я перечислил ниже.
Например, я отметил для себя, что в коде необходимо предусмотреть возможность восстановления связи при разрыве, так как на данном этапе код этого не предусматривает. То есть, если связь разорвётся, она так и останется в таком состоянии.
Раньше, в той статье, ссылку на которую я давал выше, и где я строил систему радиоуправления для самолётов, там поддержание стабильной связи осуществлялась с помощью того, что передатчик постоянно отсылал данные, даже в состоянии покоя. В случае отсутствия данных от передатчика в течение некоторого времени, приёмник считал, что произошёл разрыв и принудительно перезагружал esp32 приёмника (командой ESP.restart).
Здесь следует реализовать нечто подобное, однако следует подумать, что передавать и с какой периодичностью (чтобы и батареи сильно не сажать, если система предусматривает автономную работу, и, в то же время, чтобы система отличала фоновый сигнал для поддержания связи и полезные текстовые данные). Я специально не стал это реализовывать, так как вопрос дискуссионный и может быть решён по-разному.
Ещё одной специфической проблемой при построении системы явилось то, что на каком-то этапе экспериментов у меня отпаялась одна ножка конденсатора, и то периодически касалась контакта, то отклеивалась от него, удерживаясь на расстоянии от него в каких-то микронных долях. Результатом этого явилось то, что я чуть с ума не сошёл, пытаясь понять, почему всё правильно, но «иногда работает, а иногда не работает»:-)))
То есть, как я уже и говорил, система очень зависима от хорошего питания, поэтому, при пропадании контакта на одной из ножек конденсатора, передатчик наотрез отказывался работать. Так что, проверяйте контакты, это важно…
Кстати, ещё пару слов о контактах: я заметил, что даже просто лежащая соединённая проводами (известные DuPont перемычки) система, со временем начинает сбоить на ровном месте — пропадает контакт в произвольных местах, в произвольное время (что, впрочем, для любого строителя arduino-систем не является откровением).
Поэтому, если вам нужна стабильно работающая система — пайка и только пайка. Единственная оговорка здесь — разъём стабилизированного источника питания для радиопередатчика не сбоил у меня ни разу, за что ему плюс. Что, однако, не исключает такой возможности в будущем…
И, напоследок, ещё немного про питание: в коде ниже можно будет увидеть, что радиопередатчик может работать на разных скоростях передачи и на разных мощностях. В ходе экспериментов я пробовал запитывать всю систему просто от USB кабелей, которыми микроконтроллеры esp32 были подключены к компьютеру.
Всё работало довольно неплохо ровно до того момента, как я решил изменить мощность передатчика с минимальной (выставленной у меня по умолчанию), — на максимальную. Если до этого передача шла стабильно и всё работало хорошо, то на максимальной мощности сразу произошёл отказ и восстановить работу мне не удавалось, пока не подключил в качестве источника питания дополнительную аккумуляторную батарею на 4,5V. Вот после этого всё стало сверхстабильно и на любых мощностях. Так что, питание эта штука любит, надо иметь это в виду…
▍ Пробуем запускать
Итак, перейдём к делу… Планируется вот такая система:
![](https://habrastorage.org/webt/f-/3m/vy/f-3mvyeh8gpu_f8w7h26zuqkkd0.jpeg)
Для начала, соберём всю систему, где схема соединений будет выглядеть следующим образом:
![](https://habrastorage.org/webt/aq/ea/qm/aqeaqmkehkhh9gsjxn9avnachvu.jpeg)
Наверху, на схеме, — показаны соединения для одной платы. Я же собрал сразу две, чтобы они могли общаться между собой:
![](https://habrastorage.org/webt/3p/yf/rf/3pyfrf-siv3xvjqgbqctjwlrrle.jpeg)
Для первого теста я изменю код из своей статьи выше, где передатчик будет постоянно посылать цифры 5 и 6. Это удобно в том смысле, что можно проверять, всё ли подключено, не отвалился ли где контакт? Когда всё подключено правильно, у вас в мониторе порта приёмника должны отображаться бесконечно отправляемые цифры 5 и 6 (кликабельно):
![](https://habrastorage.org/webt/2w/fq/51/2wfq51a-oeowewlrstsizmycg40.jpeg)
Код этого первого варианта я приложил здесь.
Для вариантов кода здесь и ниже, хочу отметить, что весь код я достаточно подробно прокомментировал в самом коде, поэтому здесь его приводить и разбирать я не буду.
Однако, это всего лишь демонстратор, поэтому, попробуем несколько изменить код и осуществить передачу ввода в монитор порта. В этом и следующих вариантах мы также сохраним расположение условного передатчика и приёмника — слева на экране будет передатчик, а справа — приёмник. Вводим для теста одну букву «п» в левом мониторе порта и отправляем (кликабельно):
![](https://habrastorage.org/webt/9n/pv/ke/9npvke0oo-njdpckbklioyhtptu.jpeg)
Как мы видим, передача то осуществляется, но в мониторе порта отображаются какие-то цифры. А дело здесь вот чем: так как сама Arduino IDE работает в кодировке utf-8, а монитор порта в win-1251, — то если мы просто отправим туда шрифт на кириллице — то будут «кракозябры» (латиницу то он понимает).
Полный код этого варианта можно найти здесь.
Поэтому выше показан пример с отправкой байтов, таким образом мы хотя бы узнаем, как выглядят передаваемые данные в байтовом виде (потому что смотреть на «кракозябры» нет смысла). Исходя из этого, мы и дальше будем продолжать работать в utf-8, специально распознавая шрифт, перед выводом его в монитор порта.
Таблицу с разными кодировками можно найти вот здесь, откуда мы будем использовать только второй столбик.
Из этой таблицы мы можем увидеть, что латинский шрифт и символы кодируются одним числом (т.е. одним байтом — если посмотреть значение этой цифры в бинарном варианте), в то время как кириллица кодируется двумя цифрами (т.е. двумя байтами). Числа о которых я говорю – тёмно-зелёные, первые слева в столбике:
![](https://habrastorage.org/webt/fv/ia/r4/fviar4ua7vkr-g1vpiiwusawc58.jpeg)
В примере выше мы увидели, что буква «п» приходит в виде двух чисел, кроме которых приходит ещё какое то число 10. Это число представляет собой символ перевода строки. Таким образом, по приходу этого числа мы можем судить, что необходимо осуществить переход на новую строку.
Модифицируем приведённый код выше, так как он сейчас представляет собой только разрозненные две части: только передатчика и только приёмника, для того чтобы каждый из них мог и передавать, и принимать данные.
Здесь только отмечу, что, как можно заметить в ходе, каждая «труба» (Pipe) и у приёмника, и у передатчика имеет уникальный ID (попарно, чтобы и у передатчика, и у приёмника совпадали), и таким образом, как и во многих других устройствах связанных с передачей данных, идёт передача на приёмник (TX-RX), только здесь это названо «трубами» и имеет попарно разные ID.
Кроме того, я написал пример обработчика приходящих текстовых данных, который вы можете дополнить до полного алфавита и набора символов, так как в данном случае происходит только распознавание слов «привет», «privet».
Попробуем теперь послать данные, всё распознаётся и корректно выводится на обоих мониторах порта (слева — передатчика, справа — приёмника, кликабельно):
![](https://habrastorage.org/webt/_5/pv/lb/_5pvlbqvp-tyryqipsa6_8slyei.jpeg)
Можно попробовать послать текст и в обратном направлении — всё так же корректно распознаётся.
Полный код этого варианта можно найти здесь. В качестве комментария к коду замечу только, что там я показал и разбор латинского шрифта тоже (хотя он и так хорошо отображается в мониторе порта). Сделано это просто для примера. Вы же можете этот блок удалить и слать данные латинского шрифта/символов — напрямую в монитор порта.
Но это всё касается только случая, когда общение ведётся в варианте с компьютера на компьютер.
А представим теперь ситуацию, что на поясе человека висит некая коробочка, которая и осуществляет дальнюю связь, а мы бы с ней связывались через смартфон и отправляли со смартфона текстовые данные. Как можно было бы это сделать? По возможности нужно учесть, что такая связь должна быть как можно менее энергозатратной и для этих целей как раз хорошо подходит Bluetooth.
Поэтому мы скачиваем программку под Android — Serial Bluetooth Monitor (есть ли она под iPhone не знаю, так как у меня Android).
Подробное описание настройки этой программы и код Bluetooth-части мы возьмём вот отсюда.
Кстати говоря, если вы захотите проапгрейдить всю систему, и перевести с обычного Bluetooth на Bluetooth BLE, то там же есть и такой вариант.
После того как весь код написан и запущен, включим Bluetooth на своём смартфоне и спарим esp32 с ним, после чего, запустим программу Serial Bluetooth Monitor и соединимся с нашей esp32:
![](https://habrastorage.org/webt/2o/ya/3f/2oya3fr--atdpy18l775gyixgrs.jpeg)
Как видим по сообщению, соединение осуществлено. Но нам требуется ещё произвести кое-какие манипуляции, так как по умолчанию в этой программе эти моменты настроены иначе. А именно: включаем кодировку utf-8, а также при приёме и передаче включаем настройку, чтобы в качестве конца строки передавался символ LF (или цифра 10, о которой мы говорили выше), картинки кликабельны:
![](https://habrastorage.org/webt/2o/eq/i-/2oeqi-6nlpfmr3skpr57ugbh9ka.jpeg)
![](https://habrastorage.org/webt/iu/cw/34/iucw34jdu7qxf4-jm2l_avguyys.jpeg)
![](https://habrastorage.org/webt/tx/wu/ny/txwuny4gkin-why7ilynzkef9xe.jpeg)
Вот и всё! Теперь, если мы отправим слово «привет» или «privet» — с любого из трёх устройств: двух NRF24L01+PA+LNA или смартфона — оно отобразится на всех трёх устройствах сразу (кликабельно):
![](https://habrastorage.org/webt/uh/po/w5/uhpow5r2qmy8smiscej3koawns0.jpeg)
Полный код от этого варианта, можно найти вот здесь. Так же, как и в предыдущих вариантах — он состоит из частей А и Б (side_A, side_B). По большому счёту, вам side_B не нужен — он урезанный, просто чтобы протестить работу кода. Можно использовать только side_A, соответственно только предварительно «спарив» трубы (pipe) у абонентов попарно (чтобы ID у труб были соответственно одинаковы — посмотрите, как я сделал в приложенном коде и можете сделать так же). Код не оптимален, но — работает.
Вот примерно таким образом, можно расширить возможности смартфона по осуществлению радиосвязи между членами группы в удалённых местах, где не ловит сотовая связь. Правда, понятно, что такой способ будет уступать рациям по дальности (если не использовать дополнительные чипы LoRa), но, у него есть свои интересные моменты. Например, для смартфона можно написать некое приложение, через которое можно будет осуществлять голосовую/текстовую связь, передавая данные микроконтроллеру, а тот, в свою очередь, — передавая их через радиопередатчик. Таким образом, человек будет общаться привычным ему образом, используя тот же самый смартфон, что по-своему любопытно.
Итак, подытоживая, хотел бы сказать, что здесь я продемонстрировал своеобразный «Range Extender», то бишь увеличитель радиуса связи, в тех условиях, где мобильная связь недоступна: например, чтобы общение происходило между клиентами, где мобильный телефон или компьютер передаёт сообщение через радиосвязь между двумя NRF24L01+PA+LNA. Да, знающие наверняка скажут, что, а не лучше ли использовать «LoRa»-связь?
Но мне кажется, что здесь разные варианты имеют место быть, где одним из преимуществ связи между NRF24L01+PA+LNA является потенциально доступная высокая скорость передачи (до 2 Мбит в секунду, — в зависимости от расстояния, наличия преград и т.д., но всё же).
То есть, здесь я постарался продемонстрировать потенциально возможный вариант такой связи. И, например, всю систему можно было бы проапгрейдить следующим образом: постоянно тестируется радиоканал на доступность и скорость. Если в данный момент клиент находится в зоне действия высокоскоростной связи — то ему предлагается общение голосом, файлами или в текстовом варианте. Если же он находится за пределами высокоскоростной зоны, — связь с ним осуществляется через дополнительно установленный чип LoRa, только текстовыми сообщениями.
В случае осуществления голосовой связи видится достаточно интересным то, что голосовой трафик не является общедоступным (без специального оборудования), как в случае обычных раций и будет отличаться относительно чистой передачей голоса, без помех в виде других участников эфира.
Да, сама рабочая частота передатчика не подразумевает поражающие воображение дальности связи, но, как знают старожилы интернета — прослушивание голосового трафика вполне возможно даже на 36,6 кбит/с, скажем автор этой статьи примерно на такой скорости и слушал в своё время онлайн радиостанции:-). В то время как у радиопередатчика NRF24L01+PA+LNA заявляется скорость передачи порядка 250 кбит/с на дистанции в километр, что является более чем достаточным для передачи голосового трафика.
Так как в коде выше я уже реализовал побайтную передачу данных, вы можете попробовать самостоятельно реализовать голосовую передачу, подключив микрофон и считывая данные с помощью функции analogRead().
Кстати, тут же хочу отметить пару полезных моментов: так как взаимодействие с передатчиком требует использования библиотеки RF24, то вот здесь вы можете найти подробное описание API, где можно найти много интересного.
Например, я для себя обнаружил возможность подтверждения (acknowledge) приёма данных клиентом, уже реализованную в библиотеке, так как мне всегда было интересно, «а может я тут зря сижу, жду, а никто ничего и не получал?» Этих вариантов подтверждения там имеется некоторое количество, так что можете с ними ознакомиться.
Теперь насчёт возможности голосовой передачи: если мы обратимся к описанию функции openWritingPipe(), то мы увидим, однозначное подтверждение того, что с помощью этой библиотеки полнодуплексная (чтобы говорить и слушать одновременно) передача невозможна:
там говорится о том, что перед началом передачи необходимо остановить прослушивание входящих данных (stopListening() ), а после окончания передачи необходимо возобновить прослушивание (startListening()).
Печаль… Однако решить этот вопрос можно рядом способов:
- как на рациях, установить кнопку, нажимая на которую говоришь, а отпуская — слушаешь;
- установить на каждую абонентскую «рацию» сразу две NRF24L01+PA+LNA: одна из которых работает только в качестве передатчика, а другая — только в качестве приёмника;
- Некий вариант с буферизацией и попеременным приёмом/передачей байтов (один приняли, один передали и т.д. и т.п.).
В любом случае теперь у читателей есть некий объём информации и исходные коды для собственных экспериментов и разработок, о которых будет интересно услышать;-)
Этот вариант радиосвязи не претендует на «лучший из лучших и самый оптимальный», скорее просто ещё один вариант, со своими плюсами и минусами.
Скидки, итоги розыгрышей и новости о спутнике RUVDS — в нашем Telegram-канале ?
![](https://habrastorage.org/webt/4g/dr/oa/4gdroaajo7o0zzvwwx5__rlzhwi.png)