Добрый день, уважаемые читатели!
В этой статье я расскажу про то, как можно просто и легко принимать и обрабатывать данные на Arduino и ESP8266/32 от различных беспроводных устройств и датчиков, работающих на частоте 433 MHz. Про радиомодули 433MHz и их применение для связи между двумя Arduinами не писал только самый ленивый. Например такой ленивый, как ваш покорный слуга. Но в данной статье я хотел бы акцентировать ваше внимание на приеме данных, причем не от другой Arduinы или ESP, а от готовых беспроводных пультов и сенсоров, предлагаемых китайской электронной промышленностью в огромных объемах и вариантах. Это послужит основой для дальнейшего описания работы самодельного устройства охранно-пожарной сигнализации, так как в нем, помимо проводных, могут быть использованы и весьма распространенные беспроводные пульты и датчики: движения (PIR), протечки, пожарные извещатели, сигнализаторы метана и угарного газа и т.д. и т.п.
Важное замечание: в данной статье я буду рассматривать принципы передачи данных с помощью “обычных” приемников для 433 MHz. Трансиверы LoRa, LoRaWAN и LPWAN – это совершенно другие технологии связи (хотя и иногда использующие те же частоты), и они требуют отдельного рассмотрения.
Обзор LPD диапазона 433 МГц
В России (и не только) для портативных маломощных радиостанций с 2004 года решением ГКРЧ разрешен к использованию диапазон частот 433,075 МГц – 434,790 МГц, называемый также LPD (Low Power Device – маломощные радиостанции), максимальная не лицензируемая мощность в данном диапазоне составляет всего 10 мВт (максимальная – 20 мВт, но уже потребуется получить особое приглашение разрешение). Иногда этот диапазон называют как ISM-диапазон, хотя, на мой взгляд, это более широкое понятие. Диапазон LPD 433 МГц не подлежит лицензированию, т. е. не требуется получать специальное разрешение на частоту и регистрацию самого устройства. В диапазоне LPD работают многие устройства, такие как радиопульты для открытия дверей и гаражей, автомобильные радиосигнализации, различные датчики и устройства радиоуправления. Плюсы LPD диапазона в том, что помехи от промышленного производства и электролиний не оказывают на эту часть радиоспектра сильного влияния. А в условиях работы на открытой местности дальность связи существенно возрастает из-за отсутствия строений вообще. Еще один ощутимый плюс — все оборудование для LPD диапазона имеет довольно компактные размеры.
Частота 433.92 МГц выделена для работы маломощных цифровых передатчиков таких как: радиобрелки автосигнализаций, брелки управления шлагбаумами на стоянках, различные датчики и другие подобные системы. Поэтому практически по всех DIY-модулях передатчик и приемник заранее настроены на эту частоту.
Виды модуляции
Сама по себе несущая частота передатчика никакой информации не передает. Чтобы приемник получил какую-то информацию, передатчик должен эту информацию закодировать и модулировать несущую частоту этим кодом (в данной статье мы говорим только о передаче информации в цифровом виде, а не “голосом”). Этот процесс загрузки полезного сигнала для отправки в высокочастотный сигнал называется модуляцией. Разрешенный ГКРЧ класс излучения в диапазоне 433 МГц — 16K0F3E, то есть частотная модуляция с полосой не шире 16 кГц. Но на практике сплошь и рядом встречаются устройства и с другими типами модуляции, например OOK.
Родственники дядюшки Ляо производят огромное количество устройств модулей для LPD диапазона с разными типами модуляции и кодирования сигнала, часто не совместимые друг с другом. Если вы интересовались данной темой, то наверняка сталкивались с сокращениями – ASK, OOK, FSK, PSK, 16-QAM и многими другими. Если вы хорошо знаете предмет, смело крутите страницу вниз до следующей главы. Ну а для начинающих давайте кратенько разберемся, что означают виды модуляции ASK/OOK, FSK и PSK.
ASK – амплитудная модуляция
При амплитудной модуляции информация передается в в виде изменения уровня сигнала на выходе передатчика, то есть его амплитуды. При этом частота и фаза несущего сигнала остаются постоянными. Уровни сигнала на выходе оставлены на усмотрение разработчиков системы модуляции. Наглядно это можно представить так:
Амплитудные виды модуляции обеспечивает высокую эффективность использования полосы пропускания и имеют простую конструкцию приемника. Но эти методы имеют невысокую энергетическую эффективность (так как средний уровень мощности существенно меньше максимального), требуют очень высокого отношения сигнал/шум для демодуляции сигнала (это связано с тем, что шум влияет на амплитуду), особенно учитывая то, что сигналов в диапазоне LPD передаются с очень малой мощностью. Однако они достаточно просты в реализации и поэтому все ещё находят применение. Более подробно об этом виде модуляции вы можете почитать тут.
ООК – амплитудная манипуляция
Наиболее простым подвидом амплитудной модуляции сигнала ASK является амплитудная манипуляция или OOK (ON OFF Keying). Если говорить простыми словами, то при логической единице на входе передатчика последний включен и передает сигнал в эфир, при логическом ноле – выключен.
Модуляция OOK продлевает срок службы батареи, поскольку во время логического нуля несущая не передается. Следовательно, в течение этого времени передатчик может находиться в состоянии “выключено”. Как раз этот тип модуляции наиболее часто используется в системах инженерной сигнализации и охранных системах. Но модуляция ASK обеспечивает большую устойчивость к помехам по сравнению с модуляцией OOK.
FSK – частотная модуляция
FSK означает частотную манипуляцию. При частотной модуляции на выходе передатчика изменяется не амплитуда сигнала, а частота несущей. Модулированный сигнал будет иметь частоту f1, когда двоичный вход равен единице, и будет иметь частоту f2, когда двоичный вход равен нулю. Сам передатчик при этом работает всегда с постоянной мощностью и амплитудой.
К достоинствам FSK можно отнести постоянную мощность сигнала передатчика (что позволяет использовать высокоэффективные методы усиления) и более высокую помехозащищенность канала связи. Модуляция FSK работает гораздо лучше, чем OOK/ASK при наличии помех. Реализации передатчика и приемника FSK просты для приложений с низкой скоростью передачи данных. Но FSK использует большую полосу пропускания по сравнению с другими методами модуляции, такими как ASK и PSK. Следовательно, это не эффективно с точки зрения пропускной способности. Более подробно об FSK вы можете почитать тут.
PSK – фазовая модуляция
Как и следует из названия, при фазовой модуляции изменяется не частота и не амплитуда сигнала, а его фаза. На рисунке изображен тип модуляции PSK с использованием двоичной фазовой манипуляции. При этом логическая 1 представлена сменой фазы несущей на 180 градусов, а логический 0 — без сдвига фазы радиочастотной несущей.
PSK это самый энергоэффективный метод модуляции по сравнению по сравнению с ASK и FSK. Еще одним важным преимуществом является то, что PSK менее подвержен ошибкам по сравнению с модуляцией ASK и занимает ту же полосу пропускания, что и ASK. Более высокая скорость передачи данных может быть достигнута с использованием специальных подвидов PSK модуляции как QPSK, 16-QAM, 64-QAM и т. д. К недостаткам можно отнести сложность алгоритмов декодирования принятого сигнала. Более подробно об PSK вы можете почитать тут.
С видами модуляции разобрались. Если Вам будет интересно, то более глубокие сведения по данному предмету вы сможете почерпнуть здесь (на английском, гугл в помощь). Теперь чуть-чуть остановимся на популярных методах модуляции.
BPSK-двоичная фазовая манипуляция
Как уже упоминалось выше, в PSK двоичные 1 и двоичные 0 представлены разными фазами несущей, каждая из которых находится на расстоянии 180 градусов друг от друга. Самая простая схема BPSK использует две фазы для представления двух двоичных цифр и известна как двоичная фазовая манипуляция. На рисунке выше как раз проиллюстрирован данный метод. Этот метод передачи данных считается наиболее надежным методом цифровой модуляции и используется для беспроводной связи на большие расстояния, в том числе в сотовой связи. Подробнее здесь.
QPSK – квадратурная фазовая манипуляция
Это метод цифровой фазовой модуляции PSK. QPSK более эффективно использует полосу пропускания, поскольку каждая точка сигнала представляет два бита. В отличие от BPSK этот метод использует фазовые сдвиги, кратные уже 90 градусам. То есть за каждое изменение фазы сигнала мы можем передать не 1 бит, а целых два: 00, 01, 10, 11. То есть этот метод имеет вдвое большую пропускную способность, чем BPSK. Он более надежен по сравнению с другими методами модуляции, кроме BPSK. Подробнее здесь.
QAM – квадратурная амплитудная модуляция
Это метод цифровой модуляции представляет собой комбинацию методов амплитудной и фазовой модуляции. QAM использует концепцию двух частот сигнала; один, смещенный на 90 градусов относительно другого, может передаваться на той же несущей. Для QAM каждая несущая модулируется ASK/PSK. Следовательно, символы данных имеют разные амплитуды и фазы. Подробнее здесь.
Есть еще целая куча достаточно методов модуляции, но рамках данной статьи нам они будут совсем не интересны. Да даже BPSK/QPSK/QAM, в общем-то не нужны. Но если вы желаете “углубить и расширить” свои познания, можете воспользоваться тем же ресурсом, которым пользовался я, либо любым аналогичным. А мы переходим к способам кодирования информации.
Передача двоичных данных по радиоканалу
С модуляциями радиосигнала разобрались. Осталось понять, в каком виде различные устройства кодируют данные для передачи через радиоэфир.
Большинство самых простых и дешевых пультов, датчиков движения, дыма и прочая-прочая работают с использованием модуляции ASK/ООК. То есть любое передающее устройство может передавать в эфир только “единицы” (так как “нули” это и есть отсутствие передачи). В простейшем случае этого вполне достаточно: есть сигнал с датчика, значит он сработал. Нет – все тихо сидим на попе ровно. Нужно два датчика – немного изменяем частоту передатчика и добавляем еще один приемник (на другую частоту). Но когда датчиков много, это становится очень накладно – ведь приходится иметь некоторое множество приемников и передатчиков на разные частоты. Ерунда выходит.
Для того, чтобы обеспечить передачу цифровых данных от некоторого множества источников радиосигнала на одной и той же частоте применяется кодирование, а по сути еще одна модуляция. Только на этот раз не логические уровни превращаются в радиосигнал, а цифровые данные превращаются в последовательность импульсов. Кодирование реализовано достаточно просто – примерно по тому же самому принципу сканируются одномерные штрихкоды в магазине. И по тому же самому принципу работает передача данных по любым другим однопроводным шинам передачи данных, например One Wire или Single Bus.
Достигается это за счет изменения (и последующего измерения) длительности передаваемых импульсов или пауз между ними. В основном используется два формата, они оба кодируют двоичные значения (нули и единицы), но по-разному:
- PWM – широтно-импульсная модуляция (всем известный ШИМ). ШИМ кодирует данные, отправляя короткий импульс, затем длинную паузу или длинный импульс, а затем короткую паузу. В зависимости от используемого протокола одно означает единицу, другое – ноль. Обратите внимание, что общая длина каждой передачи имеют фиксированное значение, которое может изменяться в зависимости от протокола.
- PPM – позиционно-импульсная модуляция (ППМ). PPM кодирует данные, отправляя импульс фиксированной длины, затем короткую или длинную паузу перед отправкой следующего импульса: короткий период означает ноль, длинный означает единицу (или наоборот, в зависимости от используемого протокола). Обратите внимание, что длина импульса всегда постоянна, а вот паузы между ними имеют разную длину.
Но и это еще не всё! На следующем уровне, “выше” физического уровня ASK/ООК и канального уровня PWM/PPM, в дело вступают протоколы передачи данных.
Протоколы (способы) передачи данных
Протокол передачи данных описывает, каким образом должна вестись передача данных: какова форма импульсов для передачи логической единицы и ноля; с каких импульсов должна начинаться передача очередного пакета; какова общая длина пакета; в каком порядке передаются полезные данные; и так далее, и тому подобное.
Протоколов передачи данных производители разных устройств напридумывали ой как много. Даже в рамках одного и того же формата передачи данных (PWM или PPM) они могут существенно отличаться друг от друга, что делает их не всегда совместимыми друг с другом. Например погодные датчики от одной метеостанции могут не работать с другой, даже если используется та же частота и тот же формат передачи данных (вид “верхней” модуляции, назовем это так). Например просто потому, что длительность и форма импульсов выбрана другой. Различные любители зачастую тоже изобретают свои личные алгоритмы и протоколы передачи, что так же не вносит никакой ясности.
Для самых простых и популярных случаев (среди китайской продукции) протокол будет выглядеть примерно так:
- Каждый пакет данных начинается со “стартового” импульса заданной длительности, затем идет пауза для того, чтобы приемник успел приготовиться к приему данных
- “Единицы” и “ноли” кодируются импульсами разной длительности и периода следования
- После передачи пакета определенной длины обычно идет достаточно длинная пауза, а затем передача несколько повторяется для исключения ошибок
В качестве примера отлично подойдет описание протокола в довольно известной библиотеке rc-switch:
- минимальная длина передачи в миллисекундах, принимаемая за базовую условную единицу (УЕ)
- стартовый сигнал – два значения: длительность передачи и длительность паузы в УЕ
- двоичная единица – два значения: длительность передачи и длительность паузы в УЕ
- двоичный ноль – два значения: длительность передачи и длительность паузы в УЕ
- инверсия полезного сигнала (используется или нет)
Таким образом можно описать и PWM и PPM модуляцию.
Например:
{ 350, { 1, 31 }, { 1, 3 }, { 3, 1 }, false }
что означает:
- Минимальная длина импульса на выходе передатчика – 350 микросекунд
- Каждая передача начинается с импульса 1*350 мкс, затем идет пауза 31*350 мкс, общая длительность стартовой посылки ~ 32*350 = 11,2 миллисекунд
- Каждый полезный бит информации передается одним включением передатчика. Если длина передачи в три раза меньше длины паузы, то это означает, что мы приняли двоичную единичку, если наоборот – ноль.
- Инверсия данных не используется.
Из описания данного протокола можно понять, что в данном протоколе используется PWM модуляция, так как общая длительность каждого передаваемого бита не изменяется, а меняется соотношение (стартовый импульс в расчет можно не принимать). Заметьте – общая длина передачи не определена, а оставлена на усмотрение производителя оборудования. Точно так же можно описать любые другие способы двоичных данных по радиоканалу.
В рамках данной статьи я не имею никакой возможности рассматривать все протоколы, но есть отличный ресурс, где можно найти описание протокола передачи данных для нужного вам девайса: https://github.com/merbanan/rtl_433
Кодирование передаваемых данных
Ок, с принципами передачи цифровых данных через канал связи ASK/ООК мы с вами в первом приближении ознакомились. Поток сознания цифр передавать условно можем и даже так же условно можем их принять. Но что нам дают эти цифры (код)? Далее в дело вступает кодирование более высокого уровня. Здесь так же существует множество вариантов, и делается это в первую очередь не для того, чтобы усложнить нам с вами (т.е. пользователям и потребителям) жизнь, а для того, чтобы лучше защитить канал передачи данных усложнить жизнь различным кулхацкерам. Рассмотрим некоторые из самых известных:
- В самом простом случае передатчик всегда передает один и тот же фиксированный код, который “прошит” в его внутренней памяти. Либо постоянную часть кода (адрес) плюс некую переменную (данные). Так работает подавляющее большинство простейших радиопультов, датчиков протечек, дыма и т.д. В датчиках температуры вместо кода передается адрес, номер канала и данные об метеоусловиях. Но все передается “в открытом виде” – такие пакеты легко перехватить, расшифровать и “задавить” помехами с помощью другого приемника и (или) передатчика. Для брелоков управления различают версии с “прошитым” кодом-адресом и “обучаемые”, то есть адрес которых может изменить сам пользователь.
- Если требуется большая защита канала связи, то можно применить “плавающий код”. В этом случае кодовая посылка изменяется на основе предыдущего кода по определенному алгоритму, известному и передатчику, и приемнику. Но неизвестному хакеру. Но в этом случае возможна “рассинхронизация” приемника и передатчика, да и алгоритм преобразования можно подобрать, перехватив достаточно большое количество кодов. Именно поэтому на некоторых типах автосигнализаций, если приемник перестал реагировать на команды с пульта, необходимо зажать кнопку на пульте на длительное время – пульт переберет весь цикл изменений и приемник получит возможность вновь синхронизироваться.
- В ещё более сложных устройствах (например в автомобильных сигнализациях с обратной связью) может применяться диалоговый способ передачи: в этом случае и в пульте, и в автомобиле есть и приемник и передатчик; а при каждом сеансе связи они обмениваются зашифрованными данными друг с другом. В этом случае обмен данными осуществляется по всем
шпионскимправилам, с использования ключей шифрования и прочих премудростей. Зато надежно.
Как ни крути, вся эта мешанина форматов, протоколов и кодировок только усложняет нашу с вами “программистскую” работу с радиоканалами. А что делать? Не переживайте – в большинстве случаев китайская промышленность использует простые протоколы и передает код в открытом виде. Безусловно, безопасность использования таких брелоков и сенсоров в охранных системах вызывает большие сомнения. Но большинство готовых китайских GSM-сигнализаций, которые можно найти на Ali и в наших магазинах, ничтоже сумняшеся используют такие сенсоры и для охранных подсистем. Не надежно, конечно, но зато очень дешево. И ничего, очень даже пользуются спросом у населения. Обзор одной такой сигнализации есть и на моем сайте.
Эти же датчики я использовал и в своем проекте “Термостат + ОПС“, но стараюсь использовать радиоканал только для инженерных датчиков – протечки, задымления и т.д.. Конечно же, никто не запрещает использовать и пульты и датчики движения, там более что их продается много, но перехватить, подавить и подделать такие сигналы особого труда не составляет, даже воспользовавшись банальной самоделкой на arduino. А подавлять и имитировать сигналы для инженерных датчиков особого смысла как бы не имеет.
Во всех этих дешевых сенсорах может использоваться разные протоколы, но при этом формат передачи один и тот же: общая длина передачи составляет всего 24 бита, из них:
- 20 бит отведено под индивидуальный адрес передатчика
- 4 последних бита отведено под полезную нагрузку (значения от 0x00 до 0x0F), например это может быть факт срабатывания датчика, номер нажатой на брелоке кнопки или состояние батареи.
Если посчитать длительность передачи одной кодовой посылки, то для примера протокола, приведенного выше, то получим:
- стартовый бит – 32*350 мкс = 11,2 миллисекунд
- 24 бита, длительность каждого 4 * 350 мкс = 1400 мкс, что в сумме составит 33,60 миллисекунд
В сумме одна посылка составит 44,8 мс, затем следует небольшая пауза и посылка повторяется 3-5 раз. То есть на всю передачу обычно уходит от 50 до 250 мс, в зависимости от количества повторов передачи. Пульты управления (брелоки) так они вообще повторяют посылку все время, пока нажата кнопка на пульте.
Например возьмем пульт управления (брелок):
- адрес – 0x0000D3A8 (к примеру, у разных пультов они разные)
- кнопка 1 – 0x01 (последний бит)
- кнопка 2 – 0x02 (предпоследний бит)
- кнопка 3 – 0x04 (пред-предпоследний бит)
- кнопка 4 – 0x08 (пред-пред-предпоследний бит)
Как видите, этим кодом можно передать нажатие любой комбинации из 4 кнопок одновременно.
Иногда полезный сигнал кодируется сразу несколькими битами (но в пределах того же общего протокола передачи). Например вот достаточно “продвинутый” датчик движения с радиоканалом:
- адрес – 0x0003153C (к примеру)
- 0x00 (пустая посылка, только адрес) – включение датчика (вставили батарейки или нажали кнопку активации)
- 0x03 (установлено 2 бита: 0x01 и 0x02 ) – tamper или попытка вскрытия датчика
- 0x06 – обнаружено движение в зоне контроля
- 0x0D – низкий уровень заряда батарей, замените плиз
Разные производители используют разные коды команд (полезных данных), не совместимые друг с другом. В последующих статьях я постараюсь рассказать о некоторых из них, с которыми мне удалось лично пообщаться.
На этом с микро-“теорией” передачи стоит уже завязывать, и давайте уже определимся с электронной составляющей: модулями приемников.
Модули для приема радиосигналов
Для разработчиков Arduino-устройств (и ESP8266 / ESP32 конечно же) доступны достаточно большое множество готовых радиомодулей для организации беспроводной связи по различным технологиям и в различных частотных диапазонах. Для получения данных с пультов и датчиков нам интересен только модуль приемника, но очень часто они продаются комплектами, поэтому в таблице они приведены парами. Приемник обозначен символами RX, передатчик соответственно – TX. Все модули можно купить на известной китайской площадке. Вы можете кликнуть по фото для увеличения изображения.
Примечания:
- В таблице указана только небольшая часть предлагаемых в поднебесной модулей радиоприемников на 433 МГц. Я не в состоянии прошерстить весь али и впихнуть сюда все возможные варианты. При выборе ориентируйтесь в первую очередь на совместимость с вашим микроконтроллером по питанию и выходным уровням.
- Характеристики, приведенные в таблице – заявленные, то есть взяты со страниц товара. Реальные характеристики могут отличаться от заявленных.
- В таблице приведены только “чистые” модули (без встроенных кодировщиков). В этом случае все “обязанности” по кодированию и декодированию сигнала возлагаются на микроконтроллер и программиста (или библиотеку). Но можно легко приобрести модули с встроенной микросхемой кодирования / декодирования сигнала, которая будет излучать в эфир уже закодированный сигнал, и принимать, соответственно, только “свой” код.
Лично я пользовался только MX-RM-5V, RX470-4 и SYN480R. Что могу сказать из лично своего опыта.
- MX-RM-5V модуль пятивольтовый, и с ESP32/8266 работает крайне неохотно (оно и понятно, питания не хватает).
- RX470-4 отказался принимать сигнал уже в нескольких метрах от датчика (может брак попался?).
- SYN480R – у меня работают отлично, я ими очень доволен. Компактный и чувствительный модуль, в настройке не нуждается. И это при трех вольтовом питании. При должной развязке от МК ловит сигнал более чем за 100 метров от приемника (хотя на таком расстоянии иногда бывают ошибки в принимаемых данных).
Подключение приемника к микроконтроллеру
Во-первых, к любому приемнику необходимо подключить антенну к выводу, обозначенному как ANT. Для простейшей антенны типа “полуволновой вибратор” длина должна составлять 14233/433,92 = 32.9 см. Можно также сделать “четверть-волновой вибратор”, тогда его длина должна быть всего 16,5 см (но чувствительность будет несколько хуже). Провод можно скрутить в спираль.
А можно просто взять и купить готовые китайские “спиральки” на 433 МГц, иногда они идут в комплекте с самим приемником. Они довольно компактны, но зачастую плохо паяются.
Подключение к микроконтроллеру зависит от напряжения питания оного. Если напряжение питания приемника соответствует напряжению питания микроконтроллера, то ничего согласовывать не требуется. То есть в простейшем случае просто соединяем выход приемника DO / DATA / Data Out напрямую к микроконтроллеру без каких либо подтяжек и резистивных делителей.
Но если вы, например, заходите подключить пяти-вольтовый приемник к микроконтроллеру с питанием 3,3 вольта, то вам потребуется добавить резистивный делитель, чтобы поглотить излишки напряжения на входе МК. Так как в большинстве случаев на выходе приемника будут импульсы с напряжением примерно равным напряжению питания приемника. Надеюсь вы знаете, как рассчитывается простейший резистивный делитель.
А вот с питанием приемников 433 МГц все немного интереснее. Любой микроконтроллер – это источник радиопомех в довольно широком диапазоне частот. В том числе, эти помехи могут проникать на приемник и по шинам питания. То есть для достижения максимальной чувствительности нам очень желательно “развязать” по питанию микроконтроллер и приемник (простое добавление фильтрующих конденсаторов зачастую не решает проблему). Как это сделать? С помощью отдельного стабилизатора, конечно же! Если ваш приемник допускает питание 3,3В, то я рекомендую вам использовать такую вот схему:
Допустим я имею страстное желание подключить SYN480R к ESP32 или ESP8266. Поскольку SYN480R может работать при напряжении питания от 3.3 до 5.5В у меня есть три варианта:
- Схема 1. Запитать приемник с вывода 3V3 какой-нибудь платы ESP32-DevKit (при её использовании), используя тот же самый стабилизатор, от которого питается и сам микроконтроллер. Помехи имеют место быть, дальность связи снижается. Но для опытов сгодится и так.
- Схема 2. Запитать приемник от 5В, подаваемых плату ESP32-DevKit, а выход приемника подключить к ноге ESP через делитель. В этом случае приемник будет частично развязан от МК через внутренний стабилизатор платы ESP32-DevKit. Не забудьте про фильтрующие конденсаторы.
- Схема 3. Поставить на приемник “свой собственный” стабилизатор 3,3В. Поскольку ток потребления приемника весьма небольшой, достаточно будет какого-нибудь дешевого L78L33. В этом случае помехе будет еще сложнее добраться с МК до приемника.
Само собой, я в своих конструкциях предпочитаю третий вариант. Как показала практика, это позволяет вообще забыть о помехах для приемника со стороны питания. Ну я мы переходим к обсуждению программной реализации.
Программная реализация
Как вы наверное уже поняли из всей этой вышеизложенной ереси, что для того, чтобы получить какие-либо данные из радиоканала, нам придется программно измерять длительности принимаемых импульсов. Или пауз, если это PPM, не суть важно, но желательно с максимальной точностью. Справедливости ради нужно сказать, что существуют модули приемников со встроенными микросхемами-декодировщиками, но в рамках данной статьи они нас не интересуют (прим. авт.).
Если вы создаете свое устройство на базе Arduino – микроконтроллеров или ESP8266, то проще всего воспользоваться уже готовой и проверенной библиотекой rc-switch. На данный момент она поддерживает 12 протоколов передачи данных. Последовательность работы с ней очень проста:
- Настраиваем прием функцией .enableReceive() (один раз в программе).
- В каждом цикле проверяем, если данные в радиоканале с помощью .available().
- Если данные есть – их можно считать с помощью .getReceivedValue() и других подобных методов.
- После считывания данных необходимо очистить внутренние переменные библиотеки с помощью .resetAvailable() – библиотека готова к приему следуюещего кода.
Примеры использования есть на github:
#include <RCSwitch> RCSwitch mySwitch = RCSwitch(); void setup() { Serial.begin(9600); mySwitch.enableReceive(0); // Receiver on interrupt 0 => that is pin #2 } void loop() { if (mySwitch.available()) { Serial.print("Received "); Serial.print( mySwitch.getReceivedValue() ); Serial.print(" / "); Serial.print( mySwitch.getReceivedBitlength() ); Serial.print("bit "); Serial.print("Protocol: "); Serial.println( mySwitch.getReceivedProtocol() ); mySwitch.resetAvailable(); } }
Формально, описанная выше библиотека должна нормально работать и на ESP32 c фремворком Arduino32 (но я давно не проверял).
Для ESP32 и ESP-IDF она не совсем подходит, и я немного переделал её реализацию под ESP-IDF (ссылка кликабельна, можете пользоваться совершенно бесплатно). Моя версия полностью адаптирована под ESP32, но только для ESP-IDF, так как для настройки GPIO и прерываний используются специфичные для ESP-IDF функции, как и для измерения интервалов времени. Кроме того, внесено и существенное изменение в обработку полученных кодовых посылок: после получения данных библиотека сама отправляет принятый код в некую “входящую” очередь (указанную при инициализаwии библиотеки) через вызов xQueueSendFromISR(), а так же автоматически выполняет сброс через rx433_ResetAvailable().
Дабы был немного понятен механизм, приведу часть кода описываемой библиотеки, который, собственно и выполняет указанные действия (его не нужно вставлять в ваш код – как работать с библиотекой указано ниже):
if (rxDetectProtocol(i, cntChanges)) { // receive succeeded for protocol i, post data to external queue QueueHandle_t queueProc = (QueueHandle_t)arg; if (queueProc) { input_data_t data; data.source = IDS_RX433; data.rx433.protocol = i; data.rx433.value = rx433_GetReceivedValue(); data.count = rx433_GetReceivedBitLength(); // reset recieved value rx433_ResetAvailable(); // we have not woken a task at the start of the ISR BaseType_t xHigherPriorityTaskWoken = pdFALSE; // post data xQueueSendFromISR(queueProc, &data, &xHigherPriorityTaskWoken); // now the buffer is empty we can switch context if necessary. if (xHigherPriorityTaskWoken) { portYIELD_FROM_ISR(); }; } else { // reset recieved value rx433_ResetAvailable(); };
В очередь будут отправлены следующий пакет данных:
- source = IDS_RX433 – указывает на то, что данные получены по радиоканалу
- rx433.protocol – здесь будет сохранен условный номер протокола передачи данных (в рамках библиотеки)
- rx433.value – здесь будет сохранены собственно сами полезные данные (кодовая посылка)
- count – длина кодовой посылки в битах (например 24)
После этого любая ваша другая задача, которая “занимается” обработкой входных данных по радиоканалу, получает этот пакет данных из очереди и обрабатывает его.
PS: Можно было бы отправлять полученный код не в очередь, а в цикл событий, но есть одно “но” – из обработчика прерываний в цикл событий нельзя отправить ничего длиннее 4 байт. А тогда нам придется потерять данные о протоколе и длине посылки. Поэтому пришлось сделать так как есть.
Как этим пользоваться?
Вначале настраиваем и запускаем библиотеку, например так:
// Здесь объявлена структура input_data_t #include "rTypes.h" // Собственно сама библиотека #include "reRx433.h" .... // Создаем очередь для приема данных static QueueHandle_t rxQueue = NULL; rxQueue = xQueueCreate(32, sizeof(input_data_t)); .... // Инициализируем библиотеку: передаем ей номер вывода, к которому подключен приемник и указатель на входящую очередь rx433_Init(CONFIG_GPIO_RX433, rxQueue); rx433_Enable();
На этом всё, настройка в общем-то закончена.
Затем, где-то в глубинах космоса другой задаче ждем этих данные из очереди:
input_data_t data; if (xQueueReceive(rxQueue, &data, portMAX_DELAY) == pdPASS) { ... обрабатываем полученные данные ... };
Все получилось даже проще “стандартной” библиотеки и в полном соответствии с принципами FreeRTOS.
Примечания:
1. Если вы не желаете “тянуть” rTypes в свой проект – объявите структуру в любом другом Вам удобном месте. У меня она вынесена в отдельный модуль, так как используется и в других библиотеках, формируя один общий поток ввода данных извне. Выглядит она так:
/** * Data packet from receiver RX433 :: 40 bit * */ typedef struct { uint8_t protocol; uint32_t value; } rx433_data_t; /** * Data in mixed input stream :: 40+8+16 = 64 bit * */ typedef struct { source_type_t source; union { gpio_data_t gpio; rx433_data_t rx433; ext_data_t ext; }; uint16_t count; } input_data_t;
2. Если не хотите использовать библиотеку reLog, вызовы rlog_x легко заменить на стандартные ESP_LOGX – буквально “поиском и заменой” по коду.
3. От библиотеки reLed также можно легко избавиться без ущерба для здоровья.
Ну а на этом, пожалуй стоит завершить данное повествование. В дальнейшем планирую сделать мини-обзор беспроводных датчиков и брелоков, которые подходят под описание в данной статье. Разрешите откланяться, ваш Александр aka kotyara12. До следующих встреч на сайте и на telegram-канале!
💠 Полный архив статей вы найдете здесь
Пожалуйста, оцените статью:
А что за переменная “i”? Где ее объявлять? Какого она типа должна быть?
Заранее спасибо за ответ.
Это просто кусок кода для демонстрации определенных моментов работы библиотеки. В тексте чуть есть ссылка на репозиторий – вы можете посмотреть весь код сразу.
Доброго!
А под Arduino IDE можно библиотеку сделать?
Нужно запустить SYN480R под FreeRTOS на ESP32.
Спасибо!
Доброго! Можете использовать и эту же. В принципе, должно работать. Но – подключить ее через интерфейс не сможете, только вручную.
Благодарю!
Подключаю вручную и начинается квест 🙂 Найди rTypes.h, найди reLed.h …
А есть страничка со всеми Вашими библиотеками в одном месте?
Все библиотеки есть на GitHub. Полностью одним архивом есть там же в готовых проектах – термостат, алкогометр.
Но!
Совсем не обязательно использовать мои библиотеки точно в том виде, как они лежат на GitHub. Все-таки это не отдельные либы, а скорее одна целая прошивка. Поэтому, если вам не хочется тянуть все это в свой проект, их достаточно легко “доработать напильником” под себя. Например:
– rTypes в данном конкретном случае нужен только для объявления структурированного типа данных, который будет отправляется во входящую очередь. Этот тип вы можете объявить где угодно и как угодно и исключить этот модуль вообще.
– reLed нужен только для мигания светодиодом при приеме сигнала – если вам не нужно это, можно легко исключить
– rLog можно очень легко заменить на стандартный esp_log.h, нужно только rlog_X заменить на ESP_LOGX поиском и заменой
Ну и т.д.
Скомпилировал в Arduino IDE2, залил в Wemos Lolin 32 Lite
При запуске rx433_Init(PORT_SYN480R, rxQueue); возникает ошибка:
10:18:16.431 -> E (1019) gpio: gpio_isr_handler_add(467): GPIO isr service is not installed, call gpio_install_isr_service() first
10:18:16.431 -> 00:00:01 [E] {reRx433.cpp:258 rx433_Init()} RX433 :: Failed to set ISR handler: #259 ESP_ERR_INVALID_STATE
Не подскажите, как исправить? Предварительно запустить gpio_install_isr_service() ? А с каким параметром?
Советую почитать статью про обработку прерываний GPIO. Там про это написано
Спасибо добрый человек!
Все заработало.
А то уже было отчаялся найти реализацию 433MHz приемника под FreeRTOS.