DTWONDER DT-R008 на ESP32: https://alii.pub/72hzt9?erid=2SDnjbxfcGK
Данные платы на 8 реле и поддерживают как modbus, так и CAN шину. Тут установлен контроллер ESP32 и выведены пины для перепрошивки устройства.
Будет работать не только на плате DT-R008, но и на платах DT-R002, DT-R004, DT-R016, DT-R032
И можно было бы конечно просто прошить ESPHome и пины задать и можно было на этом остановиться. Но интереснее именно modbus, причем чтоб один модуль DT-R008 подключался к другому модулю DT-R008 по Modbus.
Схема работы будет следующая. Один модуль DT-R008 будет подключаться к другому модулю DT-R008 по шине Modbus. К ним будут подключаться выключатели. Одно устройство будет мастером, а второе слейвом.
При такой схеме у нас выключатели будут работать, даже если Home Assistant сломается. А автономность – это не маловажно.
Код Master modbus для ESPHome:
substitutions:
devicename: dt-r008_dost_1
upper_devicename: DT-R008_DOST_1
friendly_name: DT-R008_DOST_1
key: !secret api_key
ota: !secret api_key
# IP: !secret IP_dt-r008
fallback_pass: !secret wifi_ap_password
# http://10.50.50.42/
esphome:
name: dt-r008-dost-1
friendly_name: DT-R008-dost-1
esp32:
board: esp32dev
framework:
type: arduino
external_components:
- source: github://kecajtop/dtr0xx_io@master
refresh: 60s
components:
- dtr0xx_io
- source: github://epiclabs-io/esphome-modbus-server@master
refresh: 60s
components:
- modbus_server
# Enable logging
logger:
level: INFO
baud_rate: 0
# Enable Home Assistant API
api:
encryption:
key: $key
reboot_timeout: 172800s
# ota:
# password: $ota
wifi:
#ethernet:
# type: JL1101
# mdc_pin: 23
# mdio_pin: 18
# clk_mode: GPIO17_OUT
# power_pin: 0
# phy_addr: 1
ssid: !secret wifi_ssid
password: !secret wifi_password
reboot_timeout: 172800s
# use_address: $IP
# use_address: 192.168.0.8
# manual_ip:
# static_ip: 192.168.0.8
# gateway: 192.168.0.1
# subnet: 255.255.255.0
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: ${friendly_name} Fallback Hotspot
password: $fallback_pass
captive_portal:
web_server:
port: 80
time:
- platform: sntp
id: my_time
uart:
id: mod_bus
tx_pin: 1
rx_pin: 3
baud_rate: 57600
stop_bits: 1
modbus:
flow_control_pin: 33
id: modbus1
modbus_controller:
- id: dist_2
address: 1 ## address of the Modbus slave device on the bus
modbus_id: modbus1
setup_priority: -10
update_interval: 100ms
allow_duplicate_commands: true
dtr0xx_io:
- id: dtr0xx_io_hub
dingtian_clk_pin: 14
dingtian_q7_pin: 16
dingtian_sdi_pin: 13
dingtian_pl_pin: 32
dingtian_rck_pin: 15
binary_sensor:
- platform: gpio
id: input_1
name: ${friendly_name} Input 1
pin:
dtr0xx_io: dtr0xx_io_hub
number: 7
inverted: true
allow_other_uses: true
filters:
- delayed_on: 10ms
- delayed_off: 10ms
on_press:
then:
switch.toggle: relay_1
- platform: gpio
id: input_2
name: ${friendly_name} Input 2
pin:
dtr0xx_io: dtr0xx_io_hub
number: 6
inverted: true
allow_other_uses: true
filters:
- delayed_on: 10ms
- delayed_off: 10ms
on_press:
then:
switch.toggle: relay_2
- platform: gpio
id: input_3
name: ${friendly_name} Input 3
pin:
dtr0xx_io: dtr0xx_io_hub
number: 5
inverted: true
allow_other_uses: true
filters:
- delayed_on: 10ms
- delayed_off: 10ms
on_press:
then:
switch.toggle: relay_3
- platform: gpio
id: input_4
name: ${friendly_name} Input 4
pin:
dtr0xx_io: dtr0xx_io_hub
number: 4
inverted: true
allow_other_uses: true
filters:
- delayed_on: 10ms
- delayed_off: 10ms
on_press:
then:
switch.toggle: relay_4
- platform: gpio
id: input_5
name: ${friendly_name} Input 5
pin:
dtr0xx_io: dtr0xx_io_hub
number: 3
inverted: true
allow_other_uses: true
filters:
- delayed_on: 10ms
- delayed_off: 10ms
on_press:
then:
switch.toggle: relay_5
- platform: gpio
id: input_6
name: ${friendly_name} Input 6
pin:
dtr0xx_io: dtr0xx_io_hub
number: 2
inverted: true
allow_other_uses: true
filters:
- delayed_on: 10ms
- delayed_off: 10ms
on_press:
then:
switch.toggle: relay_6
- platform: gpio
id: input_7
name: ${friendly_name} Input 7
pin:
dtr0xx_io: dtr0xx_io_hub
number: 1
inverted: true
allow_other_uses: true
filters:
- delayed_on: 10ms
- delayed_off: 10ms
on_press:
then:
switch.toggle: relay_7
- platform: gpio
id: input_8
name: ${friendly_name} Input 8
pin:
dtr0xx_io: dtr0xx_io_hub
number: 0
inverted: true
allow_other_uses: true
filters:
- delayed_on: 10ms
- delayed_off: 10ms
on_press:
then:
switch.toggle: relay_8
- platform: modbus_controller
modbus_controller_id: dist_2
id: input_9
name: ${friendly_name} Input 9
register_type: holding
address: 301
internal: false
on_multi_click:
- timing:
- ON for at most 1s
- OFF for at most 1s
- ON for at most 1s
- OFF for at least 0.2s
then:
- logger.log: "Double Clicked"
- switch.toggle: relay_9
- timing:
- ON for 1s to 3s
- OFF for at least 0.5s
then:
- logger.log: "Single Long Clicked"
- switch.toggle: relay_10
- timing:
- ON for at most 1s
- OFF for at least 0.5s
then:
- logger.log: "Single Short Clicked"
- switch.toggle: relay_11
- platform: modbus_controller
modbus_controller_id: dist_2
id: input_10
name: ${friendly_name} Input 10
register_type: holding
address: 302
internal: false
on_press:
then:
switch.toggle: relay_10
- platform: modbus_controller
modbus_controller_id: dist_2
id: input_11
name: ${friendly_name} Input 11
register_type: holding
address: 303
internal: false
on_press:
then:
switch.toggle: relay_11
- platform: modbus_controller
modbus_controller_id: dist_2
id: input_12
name: ${friendly_name} Input 12
register_type: holding
address: 304
internal: false
on_press:
then:
switch.toggle: relay_12
- platform: modbus_controller
modbus_controller_id: dist_2
id: input_13
name: ${friendly_name} Input 13
register_type: holding
address: 305
internal: false
on_press:
then:
switch.toggle: relay_13
- platform: modbus_controller
modbus_controller_id: dist_2
id: input_14
name: ${friendly_name} Input 14
register_type: holding
address: 306
internal: false
filters:
- delayed_on: 10ms
- delayed_off: 10ms
on_press:
then:
switch.toggle: relay_14
- platform: modbus_controller
modbus_controller_id: dist_2
id: input_15
name: ${friendly_name} Input 15
register_type: holding
address: 307
internal: false
filters:
- delayed_on: 10ms
- delayed_off: 10ms
on_press:
then:
switch.toggle: relay_15
- platform: modbus_controller
modbus_controller_id: dist_2
id: input_16
name: ${friendly_name} Input 16
register_type: holding
address: 308
internal: false
filters:
- delayed_on: 10ms
- delayed_off: 10ms
on_press:
then:
switch.toggle: relay_16
switch:
- platform: gpio
name: ${friendly_name} Relay 1
id: relay_1
restore_mode: ALWAYS_OFF
pin:
dtr0xx_io: dtr0xx_io_hub
number: 7
inverted: false
allow_other_uses: true
- platform: gpio
name: ${friendly_name} Relay 2
id: relay_2
restore_mode: ALWAYS_OFF
pin:
dtr0xx_io: dtr0xx_io_hub
number: 6
inverted: false
allow_other_uses: true
- platform: gpio
name: ${friendly_name} Relay 3
id: relay_3
restore_mode: ALWAYS_OFF
pin:
dtr0xx_io: dtr0xx_io_hub
number: 5
inverted: false
allow_other_uses: true
- platform: gpio
name: ${friendly_name} Relay 4
id: relay_4
restore_mode: ALWAYS_OFF
pin:
dtr0xx_io: dtr0xx_io_hub
number: 4
inverted: false
allow_other_uses: true
- platform: gpio
name: ${friendly_name} Relay 5
id: relay_5
restore_mode: ALWAYS_OFF
pin:
dtr0xx_io: dtr0xx_io_hub
number: 3
inverted: false
allow_other_uses: true
- platform: gpio
name: ${friendly_name} Relay 6
id: relay_6
restore_mode: ALWAYS_OFF
pin:
dtr0xx_io: dtr0xx_io_hub
number: 2
inverted: false
allow_other_uses: true
- platform: gpio
name: ${friendly_name} Relay 7
id: relay_7
restore_mode: ALWAYS_OFF
pin:
dtr0xx_io: dtr0xx_io_hub
number: 1
inverted: false
allow_other_uses: true
- platform: gpio
name: ${friendly_name} Relay 8
id: relay_8
restore_mode: ALWAYS_OFF
pin:
dtr0xx_io: dtr0xx_io_hub
number: 0
inverted: false
allow_other_uses: true
- platform: modbus_controller
modbus_controller_id: dist_2
name: ${friendly_name} Relay 9
id: relay_9
register_type: holding
address: 201
bitmask: 1
- platform: modbus_controller
modbus_controller_id: dist_2
name: ${friendly_name} Relay 10
id: relay_10
register_type: holding
address: 202
bitmask: 1
- platform: modbus_controller
modbus_controller_id: dist_2
name: ${friendly_name} Relay 11
id: relay_11
register_type: holding
address: 203
bitmask: 1
- platform: modbus_controller
modbus_controller_id: dist_2
name: ${friendly_name} Relay 12
id: relay_12
register_type: holding
address: 204
bitmask: 1
- platform: modbus_controller
modbus_controller_id: dist_2
name: ${friendly_name} Relay 13
id: relay_13
register_type: holding
address: 205
bitmask: 1
- platform: modbus_controller
modbus_controller_id: dist_2
name: ${friendly_name} Relay 14
id: relay_14
register_type: holding
address: 206
bitmask: 1
- platform: modbus_controller
modbus_controller_id: dist_2
name: ${friendly_name} Relay 15
id: relay_15
register_type: holding
address: 207
bitmask: 1
- platform: modbus_controller
modbus_controller_id: dist_2
name: ${friendly_name} Relay 16
id: relay_16
register_type: holding
address: 208
bitmask: 1
Скачать файл с кодом можно тут: https://disk.yandex.ru/d/fEuDVjGwqi5h8A
Обратите внимание, что тут еще реализованы интересные моменты с одиночным, двойным и долгим удержанием клавиши выключателя. Тем самым можно на одну клавишу много всего навесить. Даже есть пример с нажатием на несколько секунд и это отличается от долгого нажатия и удержания.
А вот пример Slave modus платы:
substitutions:
devicename: dt-r008_dost_2
upper_devicename: DT-R008_DOST_2
friendly_name: DT-R008_DOST_2
key: !secret api_key
ota: !secret api_key
# IP: !secret IP_dt-r008
fallback_pass: !secret wifi_ap_password
# http://10.50.50.42/
esphome:
name: dt-r008-dost-2
friendly_name: DT-R008-dost-2
esp32:
board: esp32dev
framework:
type: arduino
external_components:
- source: github://kecajtop/dtr0xx_io@master
refresh: 60s
components:
- dtr0xx_io
- source: github://aj-nagrom/esphome-modbus-server@master
refresh: 60s
components:
- modbus_server
# Enable logging
logger:
level: INFO
baud_rate: 0
# Enable Home Assistant API
api:
encryption:
key: $key
reboot_timeout: 172800s
# ota:
# password: $ota
wifi:
#ethernet:
# type: JL1101
# mdc_pin: 23
# mdio_pin: 18
# clk_mode: GPIO17_OUT
# power_pin: 0
# phy_addr: 1
ssid: !secret wifi_ssid
password: !secret wifi_password
reboot_timeout: 172800s
# use_address: $IP
# use_address: 192.168.0.8
manual_ip:
static_ip: 10.50.50.43
gateway: 10.50.50.1
subnet: 255.255.255.0
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: ${friendly_name} Fallback Hotspot
password: $fallback_pass
captive_portal:
web_server:
port: 80
time:
- platform: sntp
id: my_time
uart:
id: mod_bus
tx_pin: 1
rx_pin: 3
baud_rate: 57600
stop_bits: 1
data_bits: 8
parity: NONE
debug:
direction: BOTH
modbus_server:
- id: modbuserver
uart_id: mod_bus
address: 1 # slave address
de_pin: 33 # optional
holding_registers:
- start_address: 201
number: 8
on_write: |
//ESP_LOGI("ON_WRITE", "This is 201. address=%d, value=%d", address, value);
switch(address) {
case 201:
if(value)
id(relay_1)->turn_on();
else
id(relay_1)->turn_off();
return id(relay_1).state;
case 202:
if(value)
id(relay_2)->turn_on();
else
id(relay_2)->turn_off();
return id(relay_2).state;
case 203:
if(value)
id(relay_3)->turn_on();
else
id(relay_3)->turn_off();
return id(relay_3).state;
case 204:
if(value)
id(relay_4)->turn_on();
else
id(relay_4)->turn_off();
return id(relay_4).state;
case 205:
if(value)
id(relay_5)->turn_on();
else
id(relay_5)->turn_off();
return id(relay_5).state;
case 206:
if(value)
id(relay_6)->turn_on();
else
id(relay_6)->turn_off();
return id(relay_6).state;
case 207:
if(value)
id(relay_7)->turn_on();
else
id(relay_7)->turn_off();
return id(relay_7).state;
case 208:
if(value)
id(relay_8)->turn_on();
else
id(relay_8)->turn_off();
return id(relay_8).state;
}
return 0;
on_read: |
//ESP_LOGI("ON_READ", "This is a lambda. address=%d", address);
switch (address) {
case 201:
return id(relay_1).state;
case 202:
return id(relay_2).state;
case 203:
return id(relay_3).state;
case 204:
return id(relay_4).state;
case 205:
return id(relay_5).state;
case 206:
return id(relay_6).state;
case 207:
return id(relay_7).state;
case 208:
return id(relay_8).state;
}
return 0;
- start_address: 301
number: 8
on_read: |
//ESP_LOGI("ON_READ", "This is a lambda. address=%d", address);
switch (address) {
case 301:
return id(input_1).state;
case 302:
return id(input_2).state;
case 303:
return id(input_3).state;
case 304:
return id(input_4).state;
case 305:
return id(input_5).state;
case 306:
return id(input_6).state;
case 307:
return id(input_7).state;
case 308:
return id(input_8).state;
}
return 0;
dtr0xx_io:
- id: dtr0xx_io_hub
dingtian_clk_pin: 14
dingtian_q7_pin: 16
dingtian_sdi_pin: 13
dingtian_pl_pin: 32
dingtian_rck_pin: 15
binary_sensor:
- platform: gpio
id: input_1
name: ${friendly_name} Input 1
pin:
dtr0xx_io: dtr0xx_io_hub
number: 7
inverted: true
allow_other_uses: true
filters:
- delayed_on: 10ms
- delayed_off: 10ms
- platform: gpio
id: input_2
name: ${friendly_name} Input 2
pin:
dtr0xx_io: dtr0xx_io_hub
number: 6
inverted: true
allow_other_uses: true
filters:
- delayed_on: 10ms
- delayed_off: 10ms
- platform: gpio
id: input_3
name: ${friendly_name} Input 3
pin:
dtr0xx_io: dtr0xx_io_hub
number: 5
inverted: true
allow_other_uses: true
filters:
- delayed_on: 10ms
- delayed_off: 10ms
- platform: gpio
id: input_4
name: ${friendly_name} Input 4
pin:
dtr0xx_io: dtr0xx_io_hub
number: 4
inverted: true
allow_other_uses: true
filters:
- delayed_on: 10ms
- delayed_off: 10ms
- platform: gpio
id: input_5
name: ${friendly_name} Input 5
pin:
dtr0xx_io: dtr0xx_io_hub
number: 3
inverted: true
allow_other_uses: true
filters:
- delayed_on: 10ms
- delayed_off: 10ms
- platform: gpio
id: input_6
name: ${friendly_name} Input 6
pin:
dtr0xx_io: dtr0xx_io_hub
number: 2
inverted: true
allow_other_uses: true
filters:
- delayed_on: 10ms
- delayed_off: 10ms
- platform: gpio
id: input_7
name: ${friendly_name} Input 7
pin:
dtr0xx_io: dtr0xx_io_hub
number: 1
inverted: true
allow_other_uses: true
filters:
- delayed_on: 10ms
- delayed_off: 10ms
- platform: gpio
id: input_8
name: ${friendly_name} Input 8
pin:
dtr0xx_io: dtr0xx_io_hub
number: 0
inverted: true
allow_other_uses: true
filters:
- delayed_on: 10ms
- delayed_off: 10ms
switch:
- platform: gpio
name: ${friendly_name} Relay 1
id: relay_1
restore_mode: ALWAYS_OFF
pin:
dtr0xx_io: dtr0xx_io_hub
number: 7
inverted: false
allow_other_uses: true
- platform: gpio
name: ${friendly_name} Relay 2
id: relay_2
restore_mode: ALWAYS_OFF
pin:
dtr0xx_io: dtr0xx_io_hub
number: 6
inverted: false
allow_other_uses: true
- platform: gpio
name: ${friendly_name} Relay 3
id: relay_3
restore_mode: ALWAYS_OFF
pin:
dtr0xx_io: dtr0xx_io_hub
number: 5
inverted: false
allow_other_uses: true
- platform: gpio
name: ${friendly_name} Relay 4
id: relay_4
restore_mode: ALWAYS_OFF
pin:
dtr0xx_io: dtr0xx_io_hub
number: 4
inverted: false
allow_other_uses: true
- platform: gpio
name: ${friendly_name} Relay 5
id: relay_5
restore_mode: ALWAYS_OFF
pin:
dtr0xx_io: dtr0xx_io_hub
number: 3
inverted: false
allow_other_uses: true
- platform: gpio
name: ${friendly_name} Relay 6
id: relay_6
restore_mode: ALWAYS_OFF
pin:
dtr0xx_io: dtr0xx_io_hub
number: 2
inverted: false
allow_other_uses: true
- platform: gpio
name: ${friendly_name} Relay 7
id: relay_7
restore_mode: ALWAYS_OFF
pin:
dtr0xx_io: dtr0xx_io_hub
number: 1
inverted: false
allow_other_uses: true
- platform: gpio
name: ${friendly_name} Relay 8
id: relay_8
restore_mode: ALWAYS_OFF
pin:
dtr0xx_io: dtr0xx_io_hub
number: 0
inverted: false
allow_other_uses: true
Скачать код можно по ссылке: https://disk.yandex.ru/d/Yk_hbBnm61khiQ
Данная плата тоже подключается по wifi к Home Assistant, но так-же может работать и без него. Общаясь исключительно по rs485 шине.
А вот пример из этого дела, чтоб сделать мастер выключатель. Собственно в основном ради этой фишки и затевался modus, чтоб этот мастер выключатель работал в случае отсутствия Home Assistant в сети.
Код:
binary_sensor:
- platform: gpio
id: input_1
name: ${friendly_name} Input 1 Koridor/Master
pin:
dtr0xx_io: dtr0xx_io_hub
number: 7
inverted: true
allow_other_uses: true
filters:
- delayed_on: 10ms
- delayed_off: 10ms
on_multi_click:
- timing:
- ON for 1s to 5s
- OFF for at least 0.5s
then:
#Выключаем весь свет когда уходим
- logger.log: "AWAY"
- switch.turn_off: relay_1
- switch.turn_off: relay_2
- switch.turn_off: relay_3
- switch.turn_off: relay_4
- switch.turn_off: relay_5
- switch.turn_off: relay_6
- switch.turn_off: relay_7
- switch.turn_off: relay_8
- switch.turn_off: relay_9
- switch.turn_off: relay_10
- switch.turn_off: relay_11
- switch.turn_off: relay_12
- switch.turn_off: relay_13
- switch.turn_off: relay_14
- switch.turn_off: relay_15
- timing:
- ON for at least 8s
#- OFF for at least 0.5s
then:
#Выкл/вкл контактор - все кроме холодильника и УД - режим "Отпуск"
- logger.log: "Master OFF"
- switch.toggle: relay_16
- timing:
- ON for at most 1s
- OFF for at least 0.25s
then:
#Вкл/выкл света в коридоре
- logger.log: "Light Koridor"
- switch.toggle: relay_1