Безумный радиошлюз для контроля освещения и многого другого

В одной из предыдущих статей рассматривались самодельные сенсорные выключатели на основе радиореле. Вот только тогда все их возможности не были показаны. В этой статье раскроем их на полную, спроектировав шлюз для управления из умного дома и по присутствию людей (много технарской мути под катом, залетайте!).
Как уже было упомянуто в статье, «сенсорность» не то чтобы нужна этим выключателям, так что все сенсоры были заменены на кнопки. Это позитивно отразилось и на эстетике, и на удобстве использования, а число ложных срабатываний снизилось до нуля. Но основная часть выключателя осталась почти незадействована — радиореле.

Проект
Именно радиореле позволяет интегрировать освещение (и другие устройства) в умный дом. Для этого существуют коммерческие модели радиоволновых шлюзов с управлением по защищенному радиоканалу, которые позволяют пересылать управляющие коды прямиком от пользователя. Однако стоят подобные девайсы, на мой взгляд, дороговато, имеют кучу ограничений и компромиссов и, вообще говоря, нуждаются в доработке.

Да и заведены на удаленный сервер. А я привык к локальному управлению через сервер HomeAssistant, так что буду делать свой с нуля!
Для этого я решил воспользоваться возможностями ESPHome. Данная прошивка позволяет конфигурировать широкий диапазон микроконтроллеров с WiFi модулем, что дает защищенный радиоканал (по крайней мере до самого шлюза). А огромный набор компонентов позволяет не морочиться с написанием кода. Да и управляется локально.

Поскольку с прошивкой уже понятно, смотрим, что надо по железу. Для управления устройствами хватит и дешевого китайского передатчика 433 FS1000A — это будут «руки» нашего устройства.

Но раз уж есть передача, пусть будет и прием — можно будет, например, интегрировать в умный дом различные радиокнопки и пульты, да и в отладочных целях такая прослушка не помешает. Для этого есть столь же дешевый приемник — назовем это «ушами».

Чтобы управлять светом, необходимо «увидеть», кто находится в помещении. «Глазами» выступит LD2420 — 25 ГГц микроволновый датчик присутствия. Довольно полезный модуль, который, ко всему позволяет определить расстояние до ближайшего объекта. и стоит около 130 рублей за штуку.

Есть модули и подороже, с их помощью можно даже отслеживать несколько объектов сразу в реальном времени. Но стоят не сто рублей, так что пока оставим их в сторонке.

Мозгом шлюза выступит дешевый модуль D1 Mini на основе ESP8266, который я недавно брал по 100 рублей с АлиЭкспресс. Несмотря на дешевизну он совсем не немощный, и легко заткнет за пояс обычную «ардуинку» по возможностям.

Хотя после недавней скидки в ДНС я бы не назвал его таким уж дешевым — там я накупил полноценных умных лампочек на ESPHome-совместимом контроллере CB2S. За 80 рублей в них еще и корпус, и светодиоды, и питание… О приключениях с этими штуками я расскажу чуть попозже.

Итак, вернемся к нашим баранам. У нас есть «глаза», «уши», «руки», «мозг». Казалось бы, уродец готов! Но нет, ему необходимо «сердце», а им выступит блок питания на 5V от какой-то ненужной уже зарядки.

По основным компонентам все, но не совать же это дело как есть в распределительную коробку? Удерживать внутренности вместе будет корпус одного из радиореле, сходного с тем, что я использовал для сенсорных выключателей. Само реле я применил в другом месте, а корпус оставил. Вот он и пригодился.

Далее устройство я запланировал разместить в распределительной коробке — она подходит по высоте для микроволнового датчика, и в ней полно места.

С компонентами разобрались — переходим к пайке. Для соединения модулей (с малым потреблением тока) и антенн я использую провода IDE шлейфов. В свое время я не придумал, куда их применить. Теперь же не могу представить, что бы я без них делал!

Радиомодули соединяются тремя проводами — земля, плюс питания и сигнал (у приемника пин дублируется). Еще один провод длиной 17.3см (для 433 МГц; для 315 МГц нужен 23см), скрученный в катушку, используется как антенна. Можно антенну не паять, но дальность и качество приема не будет радовать.

Для датчика LD2420 необходимо минимум 3 провода, хотя можно подсоединить хоть 5. Два провода отвечают за питание 3.3В, два за общение модуля по UART и дополнительный бинарный вывод датчика (есть присутствие или нет). Таким образом, датчик может быть единожды откалиброван по UART даже без микроконтроллера, а затем приспособлен к реле и уже самостоятельно управлять освещением. Однако такой подход подходит скорее для уличного света, он не очень точен.


Я решил использовать постоянное подключение по UART для получения значения расстояния до объекта и возможности калибровки «на лету». Да и для статистики в умном доме может пригодиться.
Можно также подключить все 5 проводов, но в прошивке использовать только бинарный вывод. В этом на самом деле тоже есть смысл. Датчик достаточно серьезно нагружает контроллер и, если в устройстве много сложной периферии, для стабильности лучше оставить бинарный выход, а по мере надобности конфигурировать LD2420 по UART.
Модуль D1 Mini уже оснащен всей необходимой периферией и просто подключается к остальным и к питанию. Общую схему прилагаю.

В корпусе модули распихал по углам и приклеил двусторонним скотчем. Главное в этом деле хорошо изолировать высоковольтную часть блока питания от низковольтной электроники. Делается это с помощью того же двустороннего скотча и воздушной прослойки. Но можно заморочиться и применить термоусадку. Я этого делать не стал.

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

Установка шлюза довольно простая — я просто прилепил его на двустороннюю ленту к крышке распределительной коробки. Провода соединил через клеммную колодку Подключаем питание и… Поехали!

Правда, поедем недалеко. Устройство появилось в сети, но еще ничего не умеет. Добавляем в конфигурацию радиоприемник и передатчик, а также датчик присутствия.
esphome:
name: rf-bridge
friendly_name: "RF Bridge"
# --- Платформа: подправьте под своё устройство (esp8266/esp32)
esp8266:
board: D1 Mini
# --- Сеть: заполните свои данные
wifi:
ssid: "YOUR_SSID"
password: "YOUR_PASSWORD"
# (опционально) static_ip, ap и т.п.
logger:
level: DEBUG
api:
ota:
# --- Remote receiver (приёмник)
remote_receiver:
- id: rf_rx
pin:
number: D3
inverted: true
mode:
input: true
pullup: true
dump: [rc_switch, raw, pronto] # дамп в логи (DEBUG)
tolerance: 60%
filter: 4us
idle: 4ms
# автоматически вызывается при декодировании RCSwitch
on_rc_switch:
- lambda: |-
// Логируем сырые данные
ESP_LOGI("rc_switch", "Received RCSwitch protocol=%d data='%s'", x.protocol, x.data.c_str());
// публикуем в текстовый сенсор для отображения в HA
id(last_rf).publish_state(x.data);
// если 24 бита — пометим как EV1527-подобное (по описанию EV1527 часто 24 бита)
if (x.data.size() == 24) {
ESP_LOGI("rc_switch", "EV1527-like 24-bit code detected: %s", x.data.c_str());
}
# --- Remote transmitter (передатчик)
remote_transmitter:
pin: D4
carrier_duty_percent: 100% # для 433MHz модулей ставят 100%
# --- Текстовый сенсор: последний принятый код
text_sensor:
- platform: template
name: "Last RF Code"
id: last_rf
uart:
- id: ld2420_uart
tx_pin: D2# LD2420 TX -> ESP RX
rx_pin: D1# LD2420 RX <- ESP TX
baud_rate: 115200 # или 256000 для старых прошивок
parity: NONE
stop_bits: 1
# --- Компонент LD2420
ld2420:
# Версия прошивки (текстовый сенсор)
text_sensor:
- platform: ld2420
fw_version:
name: "LD2420 FW Version"
# Наличие цели (presence)
binary_sensor:
- platform: ld2420
has_target:
name: "LD2420 Presence"
id: ld_presence
# Расстояние до движущейся цели (приблизительно, в шагах по 0.7 м)
sensor:
- platform: ld2420
moving_distance:
name: "LD2420 Moving Distance"
id: ld_distance
# Параметры/калибровка (удобно менять из UI)
select:
- platform: ld2420
operating_mode:
name: "LD2420 Mode"
number:
- platform: ld2420
presence_timeout:
name: "LD2420 Presence Timeout"
button:
- platform: ld2420
apply_config:
name: "LD2420 Apply Config"
factory_reset:
name: "LD2420 Factory Reset"
restart_module:
name: "LD2420 Restart Module"
А теперь собственно, суть дела. У меня три радиореле на первом этаже, а также люстра с двойным управляемым освещением (теплое и холодное) и еще одно радиореле на втором.
Реле будут управляться двумя сигналами — один на включение, один на выключение. Использование одного сигнала для вкл/выкл может привести к неприятным ситуациям. Скажем, сигнал на выключение не дошел (обратной связи-то нет) и свет будет считаться выключенным, а потом, когда его надо будет включить, сигнал его выключит. В общем, сделано это, чтобы сервер не гадал, что будет делать лампочка при передаче сигнала. На люстре, к сожалению, такой опции нет.
Поскольку все реле имеют режим сопряжения, я просто сгенерировал 10 24-битовых последовательностей, используя сайт (4 пары для реле с вкл-выкл сигналами, и 2 одиночных для люстры). Потом можно будет привязать их к соответствующим устройствам.

Далее необходимо занести это в прошивку с помощью шаблонных кнопок, при нажатии которых будет задействован передатчик.
button:
- platform: template
name: "1F Relay 1 ON"
on_press:
- remote_transmitter.transmit_rc_switch_raw:
code: '0110001011010100011010100' # исходный + '0'
protocol: 1
repeat:
times: 10
wait_time: 10ms
- platform: template
name: "1F Relay 1 OFF"
on_press:
- remote_transmitter.transmit_rc_switch_raw:
code: '0001100000011101000110100'
protocol: 1
repeat:
times: 10
wait_time: 10ms
- platform: template
name: "1F Relay 2 ON"
on_press:
- remote_transmitter.transmit_rc_switch_raw:
code: '1010001000111001100100000'
protocol: 1
repeat:
times: 10
wait_time: 10ms
- platform: template
name: "1F Relay 2 OFF"
on_press:
- remote_transmitter.transmit_rc_switch_raw:
code: '1001011100111100100111000'
protocol: 1
repeat:
times: 10
wait_time: 10ms
- platform: template
name: "1F Relay 3 ON"
on_press:
- remote_transmitter.transmit_rc_switch_raw:
code: '0110101001000000001011000'
protocol: 1
repeat:
times: 10
wait_time: 10ms
- platform: template
name: "1F Relay 3 OFF"
on_press:
- remote_transmitter.transmit_rc_switch_raw:
code: '1000001111011111110101100'
protocol: 1
repeat:
times: 10
wait_time: 10ms
- platform: template
name: "2F Relay ON"
on_press:
- remote_transmitter.transmit_rc_switch_raw:
code: '0011010000110000010111100'
protocol: 1
repeat:
times: 10
wait_time: 10ms
- platform: template
name: "2F Relay OFF"
on_press:
- remote_transmitter.transmit_rc_switch_raw:
code: '1001101101100110000111010'
protocol: 1
repeat:
times: 10
wait_time: 10ms
- platform: template
name: "Chandelier Warm"
on_press:
- remote_transmitter.transmit_rc_switch_raw:
code: '1101110100101001001100100'
protocol: 1
repeat:
times: 10
wait_time: 10ms
- platform: template
name: "Chandelier Cold"
on_press:
- remote_transmitter.transmit_rc_switch_raw:
code: '1111111001011101010001010'
protocol: 1
repeat:
times: 10
wait_time: 10ms
Знаю, что это не совсем «шлюз», ведь они зашиты в устройство. Но мне не нужно будет часто менять эти значения, потому что выключатели уже на местах, а ремонт не планируется. Можно, конечно, напрячься и сделать управление напрямую по строке, которую отсылает HomeAssistant, но это просто усложнит прошивку. Кроме того, зашитые коды могут быть использованы в локальных скриптах, если сервер, например, упадет.
Крайне внимательный читатель мог заметить, что коды, которые я вставил в прошивку со сгенерированными не совпадают. А совсем дотошный мог бы посчитать, что они 25-значные, а на конце каждого ноль. Но зачем?
Путем научного тыка было выявлено, что при передаче «честного» 24-битного сигнала устройство почему-то шлет 23 бита. А реле не понимает 23 бита, и никак не реагирует. Можете себе представить, сколько я ломал голову, перебирал приемники и передатчики, уверенный, что китаец подсунул мне брак...
Причем обнаружилось случайно, когда я как раз увидел отладочный вывод в консоли с приемника того же устройства, с которого отправлял. Этот баг я направил разработчику, но, видимо, у них там и так багов выше крыши, за несколько месяцев мне даже никто не ответил.
В итоге я просто решил добавлять «костыль» в виде дополнительного знака в каждый код. И это, как ни странно, сработало!
Теперь дело осталось за малым — сделать автоматизацию для включения-выключения света в прихожей. Тут как раз пригодилась информация о расстоянии. Это позволило включать свет только если человек в прихожей, а не в смежном туалете, куда датчик тоже частично «добивает».
- id: ld2420_turn_on_light
alias: "Включение света — LD2420 (distance < 400 1s)"
description: "Включить свет, когда distance < 400 в течение 1 секунды"
trigger:
- platform: numeric_state
entity_id: sensor.ld2420_moving_distance
below: 400
for: '1s'
condition:
- condition: state
entity_id: light.hallway # <- ЗАМЕНИТЕ на ваш entity_id
state: 'off'
action:
- service: light.turn_on
target:
entity_id: light.hallway
mode: single
- id: ld2420_turn_off_light
alias: "Выключение света — LD2420 (presence off 5s)"
description: "Выключить свет, когда датчик присутствия выключен 5 секунд"
trigger:
- platform: state
entity_id: binary_sensor.ld2420_presence
to: 'off'
for: '5s'
condition:
- condition: state
entity_id: light.hallway # <- ЗАМЕНИТЕ на ваш entity_id
state: 'on'
action:
- service: light.turn_off
target:
entity_id: light.hallway
mode: single
В результате управлять светом теперь можно тремя способами — рукой, через умный дом и через различные радиопульты. Это дает гибкость и широкие возможности автоматизации. При этом частичный отказ системы (падение сервера, отказ роутера) не отрезает пользователя от управления, а сервер умного дома позволяет реализовать сценарии разной сложности, от управления по присутствию до сложных пользовательских пресетов. Ну и конечно из любого места локальной сети можно управлять всеми выключателями или с помощью телеграм-бота.

Из недостатков можно разве что отметить, что в текущей реализации управления по присутствию выключатели бесполезны — внешний сигнал все равно главнее действий пользователя. Ну и если у вас маленькие дети — лучше от них кнопки закрыть. Эти кнопки могут привязывать радиореле к кодам или стирать сопряжение. А значит если молодой исследователь их натыкает, то они перестанут работать как надо с умным домом.
По итогу этот проект показал, что «умный» функционал не обязательно должен быть дорогим, закрытым и завязанным на облачные сервисы. Простая комбинация ESP12 с прошивкой ESPHome, дешёвых 433-МГц модулей и микроволнового датчика LD2420 позволила на практике получить локальный шлюз, который одновременно остаётся дешевым, ремонтопригодным и гибким. Архитектура, основанная на взаимодействии более простых slave-устройств с одним шлюзом также неплохо удешевляет всю конструкцию. Есть потенциал для улучшения как вширь так и вглубь, последовательно улучшая интуитивность добавлением сценариев. Хотя конкретная реализация имеет недостатки, общая идея, на мой взгляд, имеет право на существование. Спасибо за чтение — буду признателен за ваше мнение и впечатления. Пишите в комментариях, что понравилось и что стоило бы сделать иначе.
+34 |
1280
41
|
+67 |
4775
177
|
+52 |
2950
86
|
+212 |
5039
78
|
Если что, LD2412S очень хорошо эксплуатировать вместе с Esp32S2 mini — можно шлёпать прямо поверх платки, с вайваем не интерферирует, по ширине совпадает, ноги у S2 можно как угодно переназначать, удобный контроллер.
Устройства на основе Zigbee стоят дешево, нужен только один шлюз — usb свисток к HA