Modbus unable to write to register, function code 0x10 used to write to multiple registers

I’ve successfully been able to read out a whole bunch of registries from my SAJ solar inverter using the vendor’s Modbus communication protocol (https://www.solartoday.nl/wp-content/uploads/saj-plus-series-inverter-modbus-protocal.pdf)

uart:
  id: uart_bus
  tx_pin: ${tx_pin}
  rx_pin: ${rx_pin}
  baud_rate: 115200
  stop_bits: 1
  data_bits: 8
  parity: NONE
  #debug:
  #  direction: BOTH

modbus:
  id: modbus0
  uart_id: uart_bus

modbus_controller:
  - id: saj
    ## the modbus device addr
    address: 0x1
    modbus_id: modbus0
    setup_priority: -10
    update_interval: 5s

....
sensor:
  - platform: modbus_controller
    modbus_controller_id: saj
    name: "PV1 voltage"
    id: solar_inverter_pv1volt
    address: 0x0107
    register_type: holding
    value_type: U_WORD
    device_class: "voltage"
    unit_of_measurement: "V"
    state_class: "measurement"
    accuracy_decimals: 1
    filters:
      - multiply: 0.1
...

However, of all the registeres available for reading, only 2 special registries are meant for writing to.
I’m particularly interested in writing to register “801FH” (at the bottom of the pdf) which would allow me to send a percentage to limit the power output.
Was thinking of using a Number Slider to configure that.

Easy! I thought…

number:
  - platform: modbus_controller
    modbus_controller_id: saj
    name: "Limit Power"
    id: solar_inverter_powerlimit
    address: 0x801F
    register_type: holding
    mode: slider
    use_write_multiple: true
    step: 10
    min_value: 0
    max_value: 100
    value_type: U_WORD
    device_class: "power"
    unit_of_measurement: "%"

Unfortunately, I get an error from that:

[15:08:12][V][modbus_controller:047]: Sending next modbus command to device 1 register 0x801F count 1
[15:08:12][V][modbus:199]: Modbus write: 01.03.80.1F.00.01.9C.0C (8)
[15:08:12][V][modbus_controller:509]: Command sent 3 0x801F 1
[15:08:12][V][modbus:042]: Modbus received Byte  1 (0X1)
[15:08:12][V][modbus:042]: Modbus received Byte  131 (0X83)
[15:08:12][V][modbus:042]: Modbus received Byte  2 (0X2)
[15:08:12][V][modbus:042]: Modbus received Byte  192 (0Xc0)
[15:08:12][V][modbus:042]: Modbus received Byte  241 (0Xf1)
[15:08:12][D][modbus:119]: Modbus error function code: 0x83 exception: 2
[15:08:12][E][modbus_controller:091]: Modbus error function code: 0x3 exception: 2 
[15:08:12][E][modbus_controller:100]: Modbus error - last command: function code=0x3  register address = 0x801F  registers count=1 payload size=0

It uses 01.03 —> device 1, function 0x03 which is the command to read. According to the vendor’s spec, 10 should be used.
I’m under the impression that I need to do something a bit more complicated than that. Any suggestions?

Does it work if you use the modbus.write_registry service via dev tools?

If so, you could create a number helper and have an automation that triggers when this value changes and call the write registry service.

I managed to get it to somewhat work:

number:
  - platform: modbus_controller
    modbus_controller_id: saj
    name: "Limit Power"
    id: solar_inverter_powerlimit
    address: 0x801F
    register_type: holding
    value_type: U_WORD
    mode: slider
    use_write_multiple: true
    step: 1
    min_value: 0
    max_value: 100
    multiply: 10.0

When I change the slider to 0%, I see the invertor still outputting ~61W, but to be honest, that might just be a limitation of the invertor itself.

So from a functional point of view, this seems to work. The register expects an integer multiplied by 10 to get the percentage.
So 50% → 500, 100% → 1000.

I do get an error in the logs:

[10:45:42][E][modbus_controller:091]: Modbus error function code: 0x3 exception: 2 
[10:45:42][E][modbus_controller:100]: Modbus error - last command: function code=0x3  register address = 0x801F  registers count=1 payload size=0

Not sure how to get rid of that, but I think maybe that’s because the SAJ modbus implementation expects a different function number to be called for submitting multiple values than the ESPHome implementation uses?