Problem with Modbus component on ESPHome

Hello to all, I come here to post in the hope someone might assist with my problem.

I have a weird and annoying problem with following number component of the modbus_controller:

number:
  - platform: modbus_controller
    modbus_controller_id: modbus_dantherm
    name: "Set Temperature"
    id: temp_set
    device_class: temperature
    register_type: holding
    address: 1017    ## address of the register inside the Modbus slave device
    unit_of_measurement: "°C"
    value_type: U_WORD
    min_value: 0
    max_value: 36

The sensor component allows values from 0 to 36, and the slider appears normally in GUI, however, when I set this value to x, it actually sets it to x + 5. This happens for all values I set between 0 and 28. When I set a value from 29 to 36, it always returns 34. Seems like its on a mission to wind me up.

Here is a log of when I set the component:

[11:55:44][D][number:054]: 'Set Temperature' - Setting number value
[11:55:44][D][number:113]:   New number value: 13.000000
[11:55:44][D][modbus.number:061]: Updating register: connected Sensor=Set Temperature start address=0x3E9 register count=1 new value=13.00 (val=13.00)
[11:55:44][D][number:012]: 'Set Temperature': Sending state 13.000000
[11:55:44][D][uart_debug:114]: >>> 01:06:03:F9:00:0D:98:7A
[11:55:44][D][number:012]: 'Set Temperature': Sending state 13.000000
[11:55:45][D][uart_debug:114]: <<< 01:06:03:F9:00:0D:98:7A

This the value that it returns when it updates every minute or so:

[11:56:32][D][modbus.number:023]: Number new state : 18.00
[11:56:32][D][number:012]: 'Set Temperature': Sending state 18.000000

Any help in understanding the problem would be much appreciated.

Sounds weird.
Also, why it’s telling start address 0x3E9 at first? And why it’s sending twice?

[11:55:44][D][modbus.number:061]: Updating register: connected Sensor=Set Temperature start address=0x3E9 register count=1 new value=13.00 (val=13.00)
[11:55:44][D][number:012]: ‘Set Temperature’: Sending state 13.000000
[11:55:44][D][uart_debug:114]: >>> 01:06:03:F9:00:0D:98:7A
[11:55:44][D][number:012]: ‘Set Temperature’: Sending state 13.000000
[11:55:45][D][uart_debug:114]: <<< 01:06:03:F9:00:0D:98:7A

Can you post the whole yaml.

Hello, and thanks for assisting.

I think it mentions start address because 1001 or 03E9 in hex is the first register in the list of sensors.
I have pasted below the whole yaml file:

esphome:
  name: esp-dantherm-modbus
  friendly_name: ESP Dantherm Modbus

esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:
  baud_rate: 0

# Enable Home Assistant API
api:
  encryption:
    key: !secret esphome_key

ota:
  - platform: esphome
    password: !secret ota_password

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



uart:
  tx_pin: GPIO17
  rx_pin: GPIO16
  baud_rate: 115200
  parity: none
  data_bits: 8
  stop_bits: 1
  debug:

modbus:
  id: modbus_1
  send_wait_time: 200ms
  role: client
  flow_control_pin: GPIO2

modbus_controller:
  - id: modbus_dantherm
    address: 0x1
    modbus_id: modbus_1

binary_sensor:
- platform: modbus_controller
  modbus_controller_id: modbus_dantherm
  name: "Compressor State"
  device_class: running
  id: comp_state
  register_type: holding
  address: 1001    ## address of the register inside the Modbus slave device

- platform: modbus_controller
  modbus_controller_id: modbus_dantherm
  name: "Fan State"
  device_class: running
  id: fan_state
  register_type: holding
  address: 1002    ## address of the register inside the Modbus slave device

- platform: modbus_controller
  modbus_controller_id: modbus_dantherm
  name: "Solenoid State"
  device_class: running
  id: sole_state
  register_type: holding
  address: 1003    ## address of the register inside the Modbus slave device

- platform: modbus_controller
  modbus_controller_id: modbus_dantherm
  name: "Exhaust Fan State"
  device_class: running
  id: exfan_state
  register_type: holding
  address: 1004    ## address of the register inside the Modbus slave device

- platform: modbus_controller
  modbus_controller_id: modbus_dantherm
  name: "Heater 1 State"
  device_class: running
  id: heat1_state
  register_type: holding
  address: 1005    ## address of the register inside the Modbus slave device

- platform: modbus_controller
  modbus_controller_id: modbus_dantherm
  name: "Heater 2 State"
  device_class: running
  id: heat2_state
  register_type: holding
  address: 1006    ## address of the register inside the Modbus slave device

- platform: modbus_controller
  modbus_controller_id: modbus_dantherm
  name: "Running Normally"
  id: alarm1_state
  register_type: holding
  address: 1007

- platform: modbus_controller
  modbus_controller_id: modbus_dantherm
  name: "Alarm"
  device_class: problem
  id: alarm2_state
  register_type: holding
  address: 1008

- platform: modbus_controller
  modbus_controller_id: modbus_dantherm
  name: "Failed to Start"
  device_class: problem
  id: fail_start
  register_type: holding
  address: 1018    ## address of the register inside the Modbus slave device

- platform: modbus_controller
  modbus_controller_id: modbus_dantherm
  name: "Standby Mode"
  device_class: running
  id: sb_mode
  register_type: holding
  address: 1019    ## address of the register inside the Modbus slave device

- platform: modbus_controller
  modbus_controller_id: modbus_dantherm
  name: "Dehumidification Active"
  device_class: running
  id: deh_mode
  register_type: holding
  address: 1020    ## address of the register inside the Modbus slave device

- platform: modbus_controller
  modbus_controller_id: modbus_dantherm
  name: "De-Icing Active"
  device_class: running
  id: ice_mode
  register_type: holding
  address: 1021    ## address of the register inside the Modbus slave device

- platform: modbus_controller
  modbus_controller_id: modbus_dantherm
  name: "Low Pressure Fail Mode"
  device_class: problem
  id: lp_mode
  register_type: holding
  address: 1022    ## address of the register inside the Modbus slave device

- platform: modbus_controller
  modbus_controller_id: modbus_dantherm
  name: "Sensor Fail Mode"
  device_class: problem
  id: sens_mode
  register_type: holding
  address: 1023    ## address of the register inside the Modbus slave device

- platform: modbus_controller
  modbus_controller_id: modbus_dantherm
  name: "High Pressure Fail Mode"
  device_class: problem
  id: hp_mode
  register_type: holding
  address: 1024    ## address of the register inside the Modbus slave device

- platform: modbus_controller
  modbus_controller_id: modbus_dantherm
  name: "Ambient Fail Mode"
  device_class: problem
  id: amb_mode
  register_type: holding
  address: 1029    ## address of the register inside the Modbus slave device

- platform: modbus_controller
  modbus_controller_id: modbus_dantherm
  name: "Ambient Temp out of range Mode"
  device_class: problem
  id: ambt_mode
  register_type: holding
  address: 1030    ## address of the register inside the Modbus slave device

- platform: modbus_controller
  modbus_controller_id: modbus_dantherm
  name: "Ambient RH out of range Mode"
  device_class: problem
  id: ambrh_mode
  register_type: holding
  address: 1031    ## address of the register inside the Modbus slave device

sensor:
- platform: modbus_controller
  modbus_controller_id: modbus_dantherm
  name: "Evaporator 1 Temperature"
  id: evap_temp1
  device_class: temperature
  state_class: measurement
  register_type: holding
  address: 1009    ## address of the register inside the Modbus slave device
  unit_of_measurement: "°C"
  value_type: U_WORD
  filters:
    - multiply: 0.1

- platform: modbus_controller
  modbus_controller_id: modbus_dantherm
  name: "Evaporator 2 Temperature"
  id: evap_temp2
  device_class: temperature
  state_class: measurement
  register_type: holding
  address: 1010    ## address of the register inside the Modbus slave device
  unit_of_measurement: "°C"
  value_type: U_WORD
  filters:
    - multiply: 0.1

- platform: modbus_controller
  modbus_controller_id: modbus_dantherm
  name: "Condenser Temperature"
  id: cond_temp1
  device_class: temperature
  state_class: measurement
  register_type: holding
  address: 1011    ## address of the register inside the Modbus slave device
  unit_of_measurement: "°C"
  value_type: U_WORD
  filters:
    - multiply: 0.1

- platform: modbus_controller
  modbus_controller_id: modbus_dantherm
  name: "Aux Temperature Sensor"
  id: aux_temp
  device_class: temperature
  state_class: measurement
  register_type: holding
  address: 1012    ## address of the register inside the Modbus slave device
  unit_of_measurement: "°C"
  value_type: U_WORD
  filters:
    - multiply: 0.1

- platform: modbus_controller
  modbus_controller_id: modbus_dantherm
  name: "Ambiant Temperature"
  id: amb_temp
  device_class: temperature
  state_class: measurement
  register_type: holding
  address: 1013    ## address of the register inside the Modbus slave device
  unit_of_measurement: "°C"
  value_type: U_WORD
  accuracy_decimals: 1
  filters:
    - multiply: 0.1

- platform: modbus_controller
  modbus_controller_id: modbus_dantherm
  name: "Ambiant Humidity"
  id: amb_hum
  device_class: humidity
  state_class: measurement
  register_type: holding
  address: 1014    ## address of the register inside the Modbus slave device
  unit_of_measurement: "%"
  value_type: U_WORD
  filters:
    - multiply: 0.1


number:
  - platform: modbus_controller
    modbus_controller_id: modbus_dantherm
    name: "Set Relative Humidity"
    id: rh_set
    device_class: humidity
    register_type: holding
    address: 1015    ## address of the register inside the Modbus slave device
    unit_of_measurement: "%"
    value_type: U_WORD
    min_value: 40
    max_value: 95

  - platform: modbus_controller
    modbus_controller_id: modbus_dantherm
    name: "Set RH Value for ExFan Start"
    id: rh_fan
    device_class: humidity
    register_type: holding
    address: 1016    ## address of the register inside the Modbus slave device
    unit_of_measurement: "%"
    value_type: U_WORD
    min_value: 40
    max_value: 95

  - platform: modbus_controller
    modbus_controller_id: modbus_dantherm
    name: "Set Temperature"
    id: temp_set
    device_class: temperature
    register_type: holding
    address: 1017    ## address of the register inside the Modbus slave device
    unit_of_measurement: "°C"
    value_type: U_WORD
    min_value: 0
    max_value: 36

rh_set and rh_fan work normally?
Also +5 is not really matching with anything here.

yes rh_set and rh_fan work as expected. Only temp_set is problematic

Some bug?
Try without device class and min/max.

I have deleted device class and min/max from the yaml, but issue remains:

[11:29:14][D][number:054]: 'Set Temperature' - Setting number value
[11:29:14][D][number:113]:   New number value: 2.000000
[11:29:14][D][modbus.number:061]: Updating register: connected Sensor=Set Temperature start address=0x3E9 register count=1 new value=2.00 (val=2.00)
[11:29:14][D][number:012]: 'Set Temperature': Sending state 2.000000
[11:29:14][D][uart_debug:114]: >>> 01:06:03:F9:00:02:D8:7E
[11:29:14][D][number:012]: 'Set Temperature': Sending state 2.000000
[11:29:14][D][uart_debug:114]: <<< 01:06:03:F9:00:02:D8:7E
[11:29:59][D][uart_debug:114]: >>> 01:03:03:E9:00:18:94:70
[11:29:59][D][modbus_controller.sensor:025]: Sensor new state: 121.00
[11:29:59][D][sensor:094]: 'Evaporator 1 Temperature': Sending state 12.10000 °C with 0 decimals of accuracy
[11:29:59][D][modbus_controller.sensor:025]: Sensor new state: 65136.00
[11:29:59][D][sensor:094]: 'Evaporator 2 Temperature': Sending state 6513.60010 °C with 0 decimals of accuracy
[11:29:59][D][modbus_controller.sensor:025]: Sensor new state: 156.00
[11:29:59][D][sensor:094]: 'Condenser Temperature': Sending state 15.60000 °C with 0 decimals of accuracy
[11:29:59][D][modbus_controller.sensor:025]: Sensor new state: 65136.00
[11:29:59][D][sensor:094]: 'Aux Temperature Sensor': Sending state 6513.60010 °C with 0 decimals of accuracy
[11:29:59][D][modbus_controller.sensor:025]: Sensor new state: 178.00
[11:29:59][D][sensor:094]: 'Ambiant Temperature': Sending state 17.80000 °C with 1 decimals of accuracy
[11:29:59][D][modbus_controller.sensor:025]: Sensor new state: 540.00
[11:29:59][D][sensor:094]: 'Ambiant Humidity': Sending state 54.00000 % with 0 decimals of accuracy
[11:29:59][D][modbus.number:023]: Number new state : 56.00
[11:29:59][D][number:012]: 'Set Relative Humidity': Sending state 56.000000
[11:29:59][D][modbus.number:023]: Number new state : 40.00
[11:29:59][D][number:012]: 'Set RH Value for ExFan Start': Sending state 40.000000
[11:29:59][D][modbus.number:023]: Number new state : 7.00
[11:29:59][D][number:012]: 'Set Temperature': Sending state 7.000000
[11:29:59][W][component:237]: Component modbus_controller took a long time for an operation (59 ms).
[11:29:59][W][component:238]: Components should block for at most 30 ms.
[11:29:59][D][uart_debug:114]: <<< 01:03:30:00:00:00:00:00:00:00:00:00:00:00:00:00:01:00:00:00:79:FE:70:00:9C:FE:70:00:B2:02:1C:00:38:00:28:00:07:00:00:00:01:00:00:00:00:00:00:00:00:00:00:DF:B5
[11:29:59][D][uart_debug:114]: >>> 01:03:04:05:00:03:14:FA
[11:29:59][D][uart_debug:114]: <<< 01:03:06:00:00:00:00:00:00:21:75

Hex 00:38:00:28:00:07 is 56:40:7 in dec.
So it looks like your slave is adding to that register. And Esphome reads that and update the number.
Some calibration offset maybe?
What is that slave device by the way?

The slave device is a wall-mounted dehumidifier, which is mounted with an optionnal heating element. I have asked the manufacturer whether they can explain this behaviour. I note the modbus documention is wrong as it indicates min/max values of 0/36, whereas the user manual indicates 5/34. This however doesnt explain why it offsets by 5. Perhaps I can use a lambda to -5 the value I send in the command. Need to look that up as I have never managed to make lambdas work.

Modbus number has option:
write_lambda (Optional, lambda): Lambda called before send. Lambda is evaluated before the modbus write command is created.

There is example on documentation.

But the question is what is the correct temperature? The one you set or the +5 one? Is it some factory calibration offset? Maybe there is a register for that offset, did you read all the registers?
If the correct value is what you were setting, then just ignore the +5 offset your slave reports.
You could use template number to set the temp and automation to set the modbus number. Then just use that template number and ignore what you have on modbus number (set option internal: true).

I hate R/W registers, you never know how they behave…