ESPHOME configuration for AEM1000 (Environmental monitoring box from ASAIR)

Hi,
Has anyone came across AEM1000 (Environmental monitoring box from ASAIR)? This is basically a environmental monitoring box capable of sensing temperature, humidity, VOC, CO2 and PM2.5. The datasheet states communication through RS485/UART based on standard Modbus RTU. However, the direct UART is not available buy default I think. So, I tried to connect through RS485 transceiver module following esphome Modbus controller guide. But was not able to make it work. Is there any thing I am missing? Any help is greatly appreciated. Below is my current configuration.

---
###################################################
# Substitutions variables
###################################################
substitutions:
  devicename: aem1000
  friendly_name: Aem1000 Test
  device_description: "Senses Indoor Environment"
  project_version: "1.0.0"
  loglevel: DEBUG

###################################################
# Board Configuration
###################################################
esphome:
  name: ${devicename}
  friendly_name: ${friendly_name}
  min_version: 2024.7.0
  name_add_mac_suffix: true
  project:
    name: esphome.AEM1000
    version: "${project_version}"
  on_boot:
      priority: 240
      then:
        - wait_until:
            condition:
              wifi.connected:
            timeout: 60s

esp8266:
  board: d1_mini
  restore_from_flash: true
  framework:
    version: recommended

# Enable logging
logger:
  level: ${loglevel} # Default logging level
  baud_rate: 0  # Disable logging over UART

api:
  reboot_timeout: 0s
  encryption:
    key: !secret api_encryption_key

wifi:
  networks:
    - ssid: !secret wifi_ssid
      password: !secret wifi_password
  # manual_ip:
    # static_ip: 192.168.0.59
    # gateway: 192.168.0.1
    # subnet: 255.255.255.0
# Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "${devicename}"
# The captive portal is a fallback mechanism for when connecting to the configured WiFi fails.

# https://esphome.io/components/captive_portal.html
captive_portal:

# Allow provisioning WiFi via serial
# improv_serial:

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

safe_mode:
  reboot_timeout: 10min
  num_attempts: 5

# To have a "next url" for improv serial
# web_server:

# RTC time update
time:
  - platform: homeassistant

button:
  - platform: restart
    name: "Restart - ${friendly_name}"
    id: reboot_trigger
    entity_category: config

###################################################
# UART configuration for AEM1000
###################################################

uart:
  id: uart_bus
  tx_pin: TX
  rx_pin: RX
  baud_rate: 9600

modbus:
  uart_id: uart_bus
  id: modbus1

modbus_controller:
- id: modbus_device
  address: 0x01   ## address of the Modbus slave device on the bus
  modbus_id: modbus1
  setup_priority: -10

# Sensor definitions
sensor:
  - platform: modbus_controller
    modbus_controller_id: modbus_device
    register_type: read
    address: 0x0000
    value_type: U_WORD
    id: aem1000_temperature
    name: "AEM1000 Temperature"
    unit_of_measurement: "°C"
    accuracy_decimals: 1
    # filters:
    #   - lambda: |-
    #       return x * 0.1;

  - platform: modbus_controller
    modbus_controller_id: modbus_device
    register_type: read
    address: 0x0001
    value_type: U_WORD
    id: aem1000_humidity
    name: "AEM1000 Humidity"
    unit_of_measurement: "%"
    accuracy_decimals: 1
    # filters:
    #   - lambda: |-
    #       return x * 0.1;

  - platform: modbus_controller
    modbus_controller_id: modbus_device
    register_type: read
    address: 0x0002
    value_type: U_WORD
    id: aem1000_voc
    name: "AEM1000 VOC"
    unit_of_measurement: "ppm"
    accuracy_decimals: 1

  - platform: modbus_controller
    modbus_controller_id: modbus_device
    register_type: read
    address: 0x0003
    value_type: U_WORD
    id: aem1000_co2
    name: "AEM1000 CO2"
    unit_of_measurement: "ppm"
    accuracy_decimals: 1

  - platform: modbus_controller
    modbus_controller_id: modbus_device
    register_type: read
    address: 0x0004
    value_type: U_WORD
    id: aem1000_pm25
    name: "AEM1000 PM2.5"
    unit_of_measurement: "µg/m³"
    accuracy_decimals: 1

Can you post the modbus protocol (addresses) of that device.

As per the the datasheet (link) it is 0x01 and the Modbus RTU communication register definition are

Ok.
Register_type is wrong, should be holding.
If that doesn’t resolve, post your wiring scheme.
If you have Esp32 devboard available , you reduce odds by 90%

I tried with holding but with no success. Here is my wiring is it okay?

aem1000 RS485B ->> RS485 to TTL board B-
aem1000 RS485A ->> RS485 to TTL board A+
aem1000 5V ->> D1 Mini 5V
aem1000 GND ->> D1 Mini GND

RS485 to TTL board RXD ->> D1 Mini TX
RS485 to TTL board TXD ->> D1 Mini RX
RS485 to TTL board VCC ->> D1 Mini 3V3
RS485 to TTL board GND ->> D1 Mini GND

Image

Register_type: holding is the correct one.

In case your rs485 converter has automatic flow control (no DE/RE pins), wiring sounds correct .

Anyway, many D1 mini boards don’t have Uart working on pins Gpio1 and 3.
Uart can be mapped to tx_pin: GPIO15 and rx_pin: GPIO13 but if that rs485-module has pullups on data pins, your Esp goes to wrong boot mode at startup. Try.
Then only option is to use softwareserial through general pins like GPIO4 and 5. At baudrate 9600 it should work anyway.

Do you have long wiring?
Try also with termination resistor set with jumper P5. Rs485 standard calls termination resistor on both ends but for short distances it’s often not needed.

For my experience, half of the issues on modbus communication are coming from flimsy wiring. Make sure all wires are good and connections are solid.

What is your output in log?