tjhowse / modbus4mqtt

Modbus TCP <-> MQTT glue. YAML configuration. Robust.
Other
74 stars 33 forks source link

Scan batching and modbus start address #55

Open toml55 opened 3 months ago

toml55 commented 3 months ago

Hi,

I got the following issue with my solar inverter: scan batching causes the first modbus read address to start at a boundary that is a multiple of scan batching value. I have a SMA tripower solar inverter that is somewhat picky on the modbus side: It has 32 bit modbus registers that need to be read within one single modbus command, so I have to set scan_batching=2. However the starting address some registers is an odd value (e.g. 30843 for battery current). So if I set scan_batching = 2 or 4, the script always changes the starting address to an even value (e.g.. 30842). Because this register does not exist, the solar inverter aborts the read command. scan_batching=1 does also not work because the 32 bits must be read within one command. Workaround is to change line 128 of modbus_read.py in order not to allow to reduce the starting address: group = int(k) # - int(k) % self._scan_batching I did not understand the reason why the starting address is reduced to a boundary of scan_batching multiples. Is this somewhere required in the modbus spec or is there another reason to do this?

tjhowse commented 3 months ago

That's a real doozie. Another creative implementation of the modbus protocol.

See if you can set the address_offset setting to 1 such that the two-register scan sweeps both registers in one read command.

toml55 commented 3 months ago

Thank you for your answer. I know modbus is so old and there are many quirks in some implementations but I did not expect such strange things in a new and current product like my solar inverter. Luckily good tools like wireshark exist to find out what´s going on in detail. I tried address_offset=1, but this only causes the first address read to be incremented, so instead of desired register "30843" now the register "30844" is read. If I change the register value to "30842" with address_offset=1 still applied, then register "30842" is read, but never "30843". I looked into the code and found that the address_offset is only applied to the register address in the config, but does not change the behaviour of the modbus read command. This is like a 32 bit variable starting at an odd address which works but should be avoided on x86 processors due to performance.