How to write one value to multiple registers simultaneously

Hi,

i have a rule for my wallbox that sets the maximum current the car can charge with. The Modbus thing of that looks like this:

Bridge modbus:tcp:ebox [ host="192.168.0.99", port=502 ]  {
   Bridge poller holdingRegisters [ start=1012, length=17, refresh=5000, type="holding" ] {
      Thing data maxCurrentP1 [ readStart="1012", readValueType="float32", writeStart="1012", writeValueType="float32", writeType="holding" ]
      Thing data maxCurrentP2 [ readStart="1014", readValueType="float32", writeStart="1014", writeValueType="float32", writeType="holding" ]
      Thing data maxCurrentP3 [ readStart="1016", readValueType="float32", writeStart="1016", writeValueType="float32", writeType="holding" ]
   }

   Bridge poller inputRegisters [ start=1006, length=6, type="input", refresh=5500] {
      Thing data currentP1 [ readStart="1006", readValueType="float32" ]
      Thing data currentP2 [ readStart="1008", readValueType="float32" ]
      Thing data currentP3 [ readStart="1010", readValueType="float32" ]
   }
}

I want to set maxCurrent for P1-P3 simultaniously. When i try to set them seperately strange things happen, guess due to parallell writing of values. So i want to set them all with one transaction.

I think i saw a property related to that: writeMultipleEvenWithSingleRegisterOrCoil but i’m not sure how to use it.

For example in my rule i want to call this:

maxCurrent.sendCommand(12); // set max current to 12A

If i call

maxCurrentP1.sendCommand(12)
maxCurrentP2.sendCommand(12)
maxCurrentP3.sendCommand(12)

the above mentioned strange things happen, so how can i do it, that i write those 3 registers in one go?

Thanks in advance!

Samuel

I don’t know if you can enforce that but I doubt it.
But this is an XY problem. It is highly unlikely that whatever you see is happening because of single-writes (vulgo: that it would disappear when you did in parallel).
Of course there’s an impact on P2 and P3 when you set P1 - that’s inherent to the electrics involved.
Possibly you are using a wrong parameter that is not intended for this purpose. Or you have to wait a couple of seconds for the box to sort command impacts out.

1 Like

If I send them all individually it works, but if I send them too often or all 3 at once I get timeouts on console, so my assumption is that the modbus communication is busy somehow.

I saw in a python script that people send multiple register in one go so I thought it was possible here too.

Fairly new to modbus so I do not know all the limitations yet.

Each command to a Modbus channel fires off a write cycle, there is no way to batch up openHAB commands.

The binding will already be implementing ‘multiple write’ (i.e. using Modbus FC16) because a 32-bit value comprises multiple standard 16-bit registers.

There isn’t a writeValueType="float96" or anything that currently allows bigger blocks to be written by this binding.
But as Markus says, probably not the fix anyway.

Maybe the mystery device docs offer a clue. Are you supposed to halt it before changing these? Or does changing one cause a halt, so that it won’t accept another for a while?

The obvious thing to do is a little rule that imitates that, with time delay.

rule "my demo"
when
   Item MasterMaxCurrent received command
then
   val newValue = receivedCommand as Number
   maxCurrentP1.sendCommand(newValue)
   createTimer(now.plusSeconds(5)) [ maxCurrentP2.sendCommand(newValue) ]
   createTimer(now.plusSeconds(10)) [ maxCurrentP3.sendCommand(newValue) ]
end
1 Like

Actually the device takes the lowest of the three currents. So if P1 is 6A, P2/P3 are 16A, it will set 6A on all phases, even if P2/P3 are still on 16A. So no need to set all phases (except for the looks). I just learned that, so the timeout workaround could also be a solution i can take. But i guess i will just set one phase only and leave the others if there is no real need to change them.

I was just wondering about the many timeouts like this:

2021-08-26 23:21:55.839 [ERROR] [ing.ModbusSlaveConnectionFactoryImpl] - re-connect reached max tries 1, throwing last error: Connection refused (Connection refused). Connection TCPMasterConnection@
1ea786f[socket=Socket[unconnected]]. Endpoint ModbusTCPSlaveEndpoint@f576f7[address=192.168.0.99,port=502]
2021-08-26 23:21:55.839 [ERROR] [ing.ModbusSlaveConnectionFactoryImpl] - Error connecting connection TCPMasterConnection@1ea786f[socket=Socket[unconnected]] for endpoint ModbusTCPSlaveEndpoint@f576f
7[address=192.168.0.99,port=502]: Connection refused (Connection refused)

I also get them when i have for example two pollers with refresh=5000. So i was wondering if i did something wrong and that is why i wanted to send all 3 registers in one go. But it seems there is another underlying problem with those timeouts.

1 Like

The binding docs tell you howto get DEBUG logging for further diagnostics.
But I don’t think there’s much more to see with “Connection refused”.

Modbus slaves are entitled to say “Nope, I’m busy, go away”. There are neater ways to say that, but many Modbus slave implementations are uhhh crude and dirty.
If that’s the problem, there’s little you can apart from tuning your retry strategy perhaps.

But just as likely is that the slave is sluggish handling rapid TCP
connect/reconnect requests.
Recommended reading -

It is actually possible to write bulk of registers with single request using the “json write” functionality. It will be quite clunky, as the functionality is only available as a transformation so you would need a proxy String item glueing the P1 & P2 & P3 values together.

Probably worth investigating the reason for the connection issue(s) as advices above. Do you really need to write them at once or is the actual issue the connection issues you are seeing?