Problems with integrating DfRobot 4in1 Soil sensor

Hello everybody! I need your help!

My intended goal: Integration of DfRobot 4in1 soil sensor RS485 IP68 Soil Temperature Moisture pH And EC Meter for Precision Agriculture & Irrigation Solutions into home assistant by using a T-CAN485 – LILYGO® board.

Problem: I have managed to connect the T-Cab485 to HA, however the sensor is not responding... I have tried different things like swapping A and B or connecting the VCC of the sensor to the + Pin of the board's power supply, but nothing helped.


I have chosen a 12V 3A power supply because the sensor needs 5-30V and the board 5-12V.

Here is my yaml:

esphome:
  name: tcan485-soil-sensor
  friendly_name: T-CAN485 Soil Sensor
  on_boot:
    priority: 100
    then:
      - output.turn_on: enable_5v_pin
      - output.turn_on: rs485_en
      - output.turn_on: rs485_se

esp32:
  board: esp32dev
  framework:
    type: esp-idf

wifi:
  ssid: "********"
  password: "*********"
  ap:
    ssid: "TCAN485Soil Fallback"

ota:
  platform: esphome

web_server:
  port: 80

logger:
  level: DEBUG
  logs:
    modbus: WARN
    modbus_controller: WARN
    uart: WARN

output:
  - platform: gpio
    id: enable_5v_pin
    pin: GPIO16
    inverted: true
  - platform: gpio
    id: rs485_en
    pin: GPIO17
    inverted: true
  - platform: gpio
    id: rs485_se
    pin: GPIO19
    inverted: true

mqtt:
  broker: 192.168.1.104
  port: 1883
  discovery: true
  discovery_retain: false

uart:
  id: uart_bus
  tx_pin: GPIO22
  rx_pin: GPIO21
  baud_rate: 9600
  parity: NONE
  stop_bits: 1

modbus:
  id: modbus_bus
  uart_id: uart_bus

modbus_controller:
  id: soil_controller
  address: 0x02
  modbus_id: modbus_bus
  update_interval: 60s

sensor:
  - platform: modbus_controller
    name: "Soil Humidity"
    address: 0x0000
    unit_of_measurement: "%RH"
    register_type: holding
    value_type: U_WORD
    accuracy_decimals: 1
    lambda: "return (x / 10.0);"
  - platform: modbus_controller
    name: "Soil Temperature"
    address: 0x0001
    unit_of_measurement: "°C"
    register_type: holding
    value_type: U_WORD
    accuracy_decimals: 1
    lambda: "return (x / 10.0);"
  - platform: modbus_controller
    name: "Soil EC"
    address: 0x0002
    unit_of_measurement: "µS/cm"
    register_type: holding
    value_type: U_WORD
    accuracy_decimals: 0
  - platform: modbus_controller
    name: "Soil pH"
    address: 0x0003
    unit_of_measurement: ""
    register_type: holding
    value_type: U_WORD
    accuracy_decimals: 1
    lambda: "return (x / 10.0);"

Here are logs:
[09:43:26][W][modbus:064]: Stop waiting for response from 1 274ms after last send

Can someone help me fix that?

Why are they inverted? I suspect you need to drive those pins high..

These normally come with address 0x01

Good question. Ai suggested that:
"The LilyGo T-CAN485 uses NPN transistors as level-shifters between the ESP32 GPIOs and the RS485 chip's enable pins. The RS485 chip's enable pins are active-low — they need to see LOW to turn on.

So the circuit works like this:

ESP32 GPIO17 (HIGH) → NPN transistor conducts → RS485 pin pulled LOW → RS485 enabledESP32 GPIO17 (LOW) → NPN transistor off → RS485 pin pulled HIGH → RS485 disabled

With inverted: true, ESPHome flips the logic:

• output.turn_on → actually outputs LOW → RS485 chip activates :white_check_mark:
• output.turn_off → actually outputs HIGH → RS485 chip deactivates"

This is why you have to be careful trusting AI (and most things on the Internet and the world)

This is what the sample code does:

    pinMode(ME2107_EN, OUTPUT);
    digitalWrite(ME2107_EN, HIGH);

    pinMode(RS485_CALLBACK, OUTPUT);
    pinMode(RS485_EN, OUTPUT);
    digitalWrite(RS485_EN, HIGH);
    digitalWrite(RS485_CALLBACK, HIGH); 

AI is great, except when it is not. If you don't know which is which, it can be very frustrating.

And this is another T-CAN485 example:

 // enable boost power chip
    pinMode(BOOST_ENABLE_PIN, OUTPUT);
    digitalWrite(BOOST_ENABLE_PIN, HIGH);

    pinMode(RS485_RE_PIN, OUTPUT);  
    pinMode(RS485_SHUTDOWN_PIN, OUTPUT);  

    digitalWrite(RS485_SHUTDOWN_PIN, HIGH); // Shutdown Disable , 1:Enable RS485 , 0:Disable RS485
    digitalWrite(RS485_RE_PIN, HIGH);       // Receive Enable