ESPHome (ESP8266/ESP32) Modbus TCP to RTU Bridge

I have successfully installed modbus bridge, i have defined RX/TX pins and connected them to Ouman H23 RTU slave pins. With CAS modbus scanner i can connect to the esp, but im just receiving connection timeouts on every register. I have tried to reverse RX/TX pins, no change.
in esphome logs i see:

[17:59:08.144][W][modbus_bridge:886]: Modbus timeout: no response received (no first byte) client_id=1

any ideas ?

I also tried to configure it to homeassistant:

Ouman H23 modbus doc:

name_tr="Outdoor temp." pointtype="6" registertype="Holding" addressformat="S32" addressindex="201" categorytype="2" unit="°C" decimals="1" scaling="10" readacceslevel="5" writeacceslevel="1" min="-50" max="130" type="0" iotype="1" />

configuration.yaml:

  - name: ouman
    type: tcp
    timeout: 5
    host: !secret ouman_host
    port: 502
    sensors:
      - name: "Ouman Ulkolämpötila"
        unique_id: ouman_outdoor_temp_201
        address: 200
        input_type: holding
        data_type: int32
        scale: 0.1
        precision: 1
        unit_of_measurement: "°C"
        scan_interval: 60

Esphome config:

esphome:
  name: esphome-web-0cd233
  friendly_name: Modbus bridge
  min_version: 2025.9.0
  name_add_mac_suffix: false

esp8266:
  board: esp01_1m
  
external_components:
  - source:
      type: git
      url: https://github.com/rosenrot00/esphome_modbus_bridge
    components: [modbus_bridge]

uart:
  id: uart_bus
  tx_pin: GPIO01
  rx_pin: GPIO03
  baud_rate: 9600
  stop_bits: 1
  rx_buffer_size: 256  # minimum 256 recommended; increase for long RTU responses

  # Modbus bridge configuration
modbus_bridge:
  id: mb_bridge
  uart_id: uart_bus
  tcp_port: 502                # TCP port to listen on
  tcp_poll_interval: 50        # ms between TCP polls
  tcp_client_timeout: 60000    # ms of inactivity before client is disconnected
  tcp_allowed_clients: 4       # number of simultaneous TCP clients (min 1)
  rtu_response_timeout: 3000   # ms, internally clamped to >=10 ms
  #flow_control_pin: GPIO18     # optional: RS-485 DE/RE pin

  on_tcp_clients_changed:
    then:
      - lambda: |-
          id(tcp_clients) = count;
      - logger.log:
          format: "TCP clients connected: %d"
          args: ['count']
    # Other available events (use similarly):
    # on_rtu_send:       # (function_code, address) – triggered for every RTU command sent
    # on_rtu_receive:    # (function_code, address) – triggered for every valid RTU response
    # on_rtu_timeout:    # (function_code, address) – triggered for RTU timeouts
    # on_tcp_started:    # () – triggered when TCP server successfully starts
    # on_tcp_stopped:    # () – triggered when TCP server stops or IP is lost

# Output and LED for visual feedback
output:
  - platform: gpio
    id: output_led_status
    pin: GPIO2

light:
  - platform: binary
    id: led_status
    name: "Status LED"
    output: output_led_status

# Global variable to hold number of connected TCP clients
globals:
  - id: tcp_clients
    type: int
    restore_value: no
    initial_value: '0'

# Every 3 s: blink LED as many times as connected TCP clients (100 ms per blink)
interval:
  - interval: 3s
    then:
      - if:
          condition:
            lambda: 'return id(tcp_clients) > 0;'
          then:
            - repeat:
                count: !lambda 'return id(tcp_clients);'
                then:
                  - light.turn_on: led_status
                  - delay: 100ms
                  - light.turn_off: led_status
                  - delay: 100ms  # short pause between blinks

# Debug switch for enabling verbose Modbus logging
switch:
  - platform: template
    name: "Modbus Bridge Debug"
    id: modbus_debug_switch
    restore_mode: RESTORE_DEFAULT_OFF
    turn_on_action:
      - lambda: |-
          id(mb_bridge).set_debug(true);
          id(modbus_debug_switch).publish_state(true);
    turn_off_action:
      - lambda: |-
          id(mb_bridge).set_debug(false);
          id(modbus_debug_switch).publish_state(false);

          
# Enable logging
logger:
  baud_rate: 0
  
# Enable Home Assistant API
api:

# Allow Over-The-Air updates
ota:
- platform: esphome

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

Yeah well, have misunderstood whole project, i need ttl rs485 converter too, no wonder it wouldnt work :smiley:

And maybe even new Esp…

What it wont work with old ones ? ;D

Generally yes, but serial port has to be intact.