ESPHome и Modbus RS485: no response received

Ошибка no response received - removed from send queue в логах ESPHome означает, что устройство не ответило на запрос по Modbus через RS485 - последовательную линию связи. Сначала проверьте проводку между ESP и преобразователем RS485 и управление направлением передачи. Если вы только связываете ESP32 с Home Assistant, посмотрите общий гайд по ESPHome и ESP32.

Как выглядит проблема

В трех ветках форума пользователи описали такие симптомы:

  • датчик уровня воды QDY30A по RS485 не отдает показания, в логах только запросы без ответов;
  • ESP32 с модулем MAX485 не получает ответ по Modbus от инвертора Growatt SPF 5000 ES, и значения не попадают в Home Assistant;
  • плата реле не отвечает на запросы, бинарные входы не меняют состояние.

Строки из отладочного лога modbus_controller выглядят так:

Modbus command to device=1 register=0x04 countdown=0 no response received - removed from send queue
[D][modbus_controller:040]: Modbus command to device=255 register=0x00 no response received - removed from send queue
[14:55:57.604][D][modbus_controller:039]: Modbus command to device=1 register=0x40D no response received - removed from send queue

Причины

Пользователи форума связывали отсутствие ответа с управлением направлением передачи, перепутанными проводами и лишним пакетом переключателя. Каждую причину указали в одной ветке.

ПричинаКак проверитьЧто сделать
У MAX485 не настроено управление направлением передачи DE/REПроверить настройку flow_control_pin - пина переключения направленияНастроить flow_control_pin с учетом поддержки этой опции в UART
GPIO16 и GPIO17 подключены к модулю MAX485 наоборотПереставить провода TX и RX местамиСобрать схему так, чтобы GPIO16 шел на RO, а GPIO17 на DI
Modbus-переключатель отправлял штатный пакет вдобавок к пакету, собранному в write_lambdaВключить отладку UART и посмотреть, какие пакеты уходят в линиюУбрать write_lambda и перейти на coil-выходы - бинарные выходы Modbus - с переключателями platform: output

Что помогло

Больше всего подтверждений у проверки проводки между ESP и преобразователем RS485.

Проверить подключение TX и RX

Проверка подключения помогла пользователям форума в двух ветках - три сообщения об успехе, ни одного о неудаче. В одной ветке помогла перестановка TX и RX местами, в другой - прямое соединение TX к TX и RX к RX с учетом маркировки модуля. На плате MAX485 в итоге GPIO16 шел на RO, а GPIO17 на DI. Рабочий конфиг из ветки:

uart:
  id: mod_bus
  tx_pin: 17
  rx_pin: 16
  baud_rate: 9600
  stop_bits: 1
 
modbus:
  id: modbus1
  flow_control_pin: 4 #for use when you use a rs485 board without auto flow control. Like the rs485 max board.

modbus_controller:
  - id: ${modbus_controller_id}
    address: 0x1
    modbus_id: modbus1
    setup_priority: -10
    update_interval: ${modbus_update_interval}

Добавить flow_control_pin

Платам на MAX485 без автопереключения нужен пин направления DE/RE. В документации Modbus в ESPHome опция описана как полезная для RS485-приемопередатчиков без автоматического переключения направления, обычный MAX485 приведен там как пример. В той же документации сказано, что если сам UART поддерживает flow_control_pin, пин настраивают в блоке uart. В одной ветке это изменение вернуло ответы:

modbus:
  id: modbus1
  uart_id: mod_bus
  flow_control_pin: GPIO35

Читать восемь входов одним запросом

У пользователя форума в одной ветке бинарные входы платы реле заработали после чтения восьми входов одним запросом и разбора байта data[0] по битовым маскам. Состояния публиковались в отдельные сущности. В старых версиях для этого использовали custom_command:

modbus_controller:
- id: modbus_device
  address: 0xFF   ## address of the Modbus slave device on the bus
  modbus_id: modbus1
  setup_priority: -10
  update_interval: 1s


binary_sensor:
- platform: modbus_controller
  modbus_controller_id: modbus_device
  id: inp1
    #                   FF    02    00    00    00    08    6C    12”
  custom_command: [ 0xFF, 0x02, 0x00, 0x00, 0x00, 0x08, 0x6C, 0x12]
  name: "I1"
  lambda: |-
      if (0x02 & data[0]) {
        id(inp2).publish_state(true);
      }
      else {
        id(inp2).publish_state(false);
      }
      return (0x01 & data[0]);

- platform: template
  id: inp2
  name: "I2"

Заменить write_lambda на coil-выходы

В одной ветке форума отказ от write_lambda помог плате реле, у которой Modbus-переключатель дублировал пакеты. Для каждого реле объявили coil-выход с битовой маской, а переключатели построили на platform: output. Раздел output у modbus_controller подтверждает, что такая запись создает бинарный выход. Конфиг из этой ветки:

switch:
  - platform: output
    name: "Relé 1"
    output: 'r1o'
    id: r1
  - platform: output
    name: "Relé 2"
    output: 'r2o'
    id: r2   

output:
  - platform: modbus_controller
    modbus_controller_id: modbus_device
    address: 0x0000
    register_type: coil
    bitmask: 0xFF00
    id: r1o
  - platform: modbus_controller
    modbus_controller_id: modbus_device
    address: 0x0001
    register_type: coil
    bitmask: 0xFF00
    id: r2o      

Если не помогло

Посмотрите отправленные запросы через отладку UART. Такой способ диагностики предлагали в одной ветке форума, но результат остался неизвестен - сообщений об успехе или неудаче нет. Если ESPHome ругается уже на сам конфиг, посмотрите разбор ошибки remove the platform key.

Частые вопросы

Помогли ли другие варианты подключения?

Соединение DE и RE с GND и смена контактов разъема инвертора не помогли - по одному сообщению о неудаче в каждой из двух веток форума. В первом случае пробовали постоянный прием на MAX485. Во втором подключались к контактам 7 и 8 RS485-разъема Growatt вместо 1 и 2, меняя порядок проводов в обоих вариантах.

Стоит ли ставить register_count: 8?

У пользователя форума в одной ветке установка register_count: 8 у бинарного сенсора не сработала, как и сокращение конфигурации до одного датчика. Для каждого приема есть одно сообщение о неудаче. В документации ESPHome опции register_count и force_new_range объявлены устаревшими с удалением в 2027.3.0. Сейчас описаны reuse_previous_range и response_size.

Чем закончились попытки с лямбдами?

Отправка пакетов управления реле через write_lambda и чтение входов с разбором data[3] дали частичный результат в одной ветке форума. Полного успеха или неудачи для этих попыток пользователи не сообщили. Лямбда здесь - фрагмент кода для обработки команды или ответа. По документации ESPHome write_lambda выполняется до создания команды записи Modbus, а лямбда при пользовательской команде позволяет обработать ответ.

Андрей Ковалев, редактор. Собирает решения из веток форума Home Assistant и сверяет команды и настройки с официальной документацией.