Modbus RTU Drexel & Weiss <> openHAB

I’m not an OH2 user, but I see a lot of frustration about its habit of caching configurations and using “older versions”. I suspect an OH restart is needed when tinkering with configs.

Reading with a length of 4 ought to work, we ought to get to the bottom of that.

Note that 32-bit write is problematic, if thats what you are attempting later

1 Like

Re caching : even restart might not be enough. Consult this post for more details how to clear the cache : Modbus RTU openHAB binding Error

Best
Sami

@ssalonen ty! your link helped clearing cache!

as for my “read/write” item:

modbus.cfg:

serial.slave3.connection=/dev/ttyAMA0:9600:8:none:1:rtu
serial.slave3.id=1
serial.slave3.type=holding
serial.slave3.start=5016
serial.slave3.length=2
serial.slave3.valuetype=int32

item:

Number Raum_MB_Soll "Raumtemperatur SOLL raw" (Modbus) {modbus="slave3:0"}

events.log (when changing temp. on heating system display)

2017-05-10 22:06:24.936 [ItemStateChangedEvent     ] - Raum_MB_Soll changed from 22500 to 22300

and this happens when i try to write: events.log

2017-05-10 22:09:13.895 [ItemCommandEvent          ] - Item 'Raum_MB_Soll' received command 22800
2017-05-10 22:09:14.278 [ItemStateChangedEvent     ] - Raum_MB_Soll changed from 22300 to 22800

it doesn’t relly change…

but i get this in openhab.log:

2017-05-10 22:09:13.985 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - Last request: 01 10 13 98 00 01 02 59 10 a3 15
2017-05-10 22:09:13.986 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - failed to read: CRC Error in received frame: 0 bytes:
2017-05-10 22:09:13.988 [ERROR] [pi.modbus.io.ModbusSerialTransaction] - execute try 1/3 error: I/O exception - failed to read. Request: net.wimpi.modbus.msg.WriteMultipleRegistersRequest@1c7ccc2 (unit id 1 & transaction 49). Serial parameters: SerialParameters@1eaaaaf[portName=/dev/ttyAMA0,baudRate=9600,flowControlIn=none,flowControlOut=none,databits=8,stopbits=1,parity=none,encoding=rtu,echo=false,receiveTimeoutMillis=1500]
2017-05-10 22:09:14.117 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - Last request: 01 10 13 98 00 01 02 59 10 a3 15
2017-05-10 22:09:14.118 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - failed to read: CRC Error in received frame: 0 bytes:
2017-05-10 22:09:14.120 [ERROR] [pi.modbus.io.ModbusSerialTransaction] - execute try 2/3 error: I/O exception - failed to read. Request: net.wimpi.modbus.msg.WriteMultipleRegistersRequest@1c7ccc2 (unit id 1 & transaction 49). Serial parameters: SerialParameters@1eaaaaf[portName=/dev/ttyAMA0,baudRate=9600,flowControlIn=none,flowControlOut=none,databits=8,stopbits=1,parity=none,encoding=rtu,echo=false,receiveTimeoutMillis=1500]
2017-05-10 22:09:14.229 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - Last request: 01 10 13 98 00 01 02 59 10 a3 15
2017-05-10 22:09:14.230 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - failed to read: CRC Error in received frame: 0 bytes:
2017-05-10 22:09:14.232 [ERROR] [pi.modbus.io.ModbusSerialTransaction] - execute try 3/3 error: I/O exception - failed to read. Request: net.wimpi.modbus.msg.WriteMultipleRegistersRequest@1c7ccc2 (unit id 1 & transaction 49). Serial parameters: SerialParameters@1eaaaaf[portName=/dev/ttyAMA0,baudRate=9600,flowControlIn=none,flowControlOut=none,databits=8,stopbits=1,parity=none,encoding=rtu,echo=false,receiveTimeoutMillis=1500]
2017-05-10 22:09:14.233 [ERROR] [pi.modbus.io.ModbusSerialTransaction] - execute reached max tries 3, throwing last error: I/O exception - failed to read. Request: net.wimpi.modbus.msg.WriteMultipleRegistersRequest@1c7ccc2. Serial parameters: SerialParameters@1eaaaaf[portName=/dev/ttyAMA0,baudRate=9600,flowControlIn=none,flowControlOut=none,databits=8,stopbits=1,parity=none,encoding=rtu,echo=false,receiveTimeoutMillis=1500]
2017-05-10 22:09:14.235 [ERROR] [.binding.modbus.internal.ModbusSlave] - ModbusSlave (slave3): error when executing write request (net.wimpi.modbus.msg.WriteMultipleRegistersRequest@1c7ccc2): I/O exception - failed to read

does this help?

From the binding WIKI

Note: The way Decimal commands are handled currently means that it is probably not useful to try to use Decimal commands with non-16bit valuetypes.

You cannot simply write 32-bit at present.

We’ll have to try to hack it with two 16-bit Items. It gets complicated because of the sign.

This is untested -

modbus.cfg to deal with this register pair as 16-bits, important note - Unsigned

writemultipleregisters = true

...
serial.slave3.type=holding
serial.slave3.start=5016
serial.slave3.length=2
serial.slave3.valuetype=uint16

Items to handle 32-bit data in 16-bit chunks

// a virtual item for incoming reading
Number Raum_MB_Soll "Raumtemperatur SOLL raw" (Modbus) {autoupdate="false"}
// a pair of modbus registers for 16-bit read/write
Number Raum_MB_Soll_Hi "Raumtemperatur high byte" (Modbus) {modbus="slave3:0", autoupdate="false"}
Number Raum_MB_Soll_Lo "Raumtemperatur low byte" (Modbus) {modbus="slave3:1", autoupdate="false"}

Rules to do the magic

rule  "process incoming words"
when
   Item Raum_MB_Soll_Lo changed    
then
  Thread::sleep(100)   // _Hi should have changed already, wait a little to be sure
   var int hiraw = (Raum_MB_Soll_Hi.state as DecimalType).intValue   // get word
   var int loraw = (Raum_MB_Soll_Lo.state as DecimalType).intValue
   var int result = (hiraw * 65535) + loraw
   if (hiraw > 32767 ) {
         // oh dear it is signed, weird maths to follow
      result =  result - 4294967296    // think this extracts twos complement to signed ?!
   } 
   Raum_MB_Soll.postUpdate(result)    // to virtual item
end

rule "process outgoing value"
when
   Item Raum_MB_Soll received command    // from UI or rule
then
   var int raw32 = (receivedCommand as DecimalType).intValue
   if (raw32 < 0) {
      logInfo("mbconvert","negative numbers not supported")    // I chickened out of twos complement maths
   } else {
      var int hival = raw32 / 65535
      var int loval = raw32.bitwiseAnd(65535)    // mask with FFFF
      Raum_MB_Soll_Hi.sendCommand(hival)
      Raum_MB_Soll_Lo.sendcommand(loval)
   }
end

I do not know if this idea will work at all, if the OH binding sends the two halves of the 32-bit pair separately the slave might reject it.


This is where you would want autoupdate=“false” in your Item config to ensure that the value in OH reflects what is in the real modbus device (at the next read poll), otherwise when you send the Item a command from UI or rule the autoupdate feature changes the Item value.

Thanks @rossko57 for pitching in. I fear that even that might not work since the default behavior is to write single register. The value written will be the decimal value rounded to 16bit integer, and function code will be 6 or 16 depending on the config.

Perhaps this slave refuses to respond with single register writes?

Best
Sami

That is my suspicion too, likely the reason that it only supports FC16

should i ask the manufacturer something?

error for rule:

2017-05-11 13:45:25.258 [ERROR] [.script.engine.ScriptExecutionThread] - Rule 'process outgoing value': An error occured during the script execution: The name '<XFeatureCallImplCustom>.sendcommand(<XFeatureCallImplCustom>)' cannot be resolved to an item or type.

Check Item(s) exist.
Does the read part work? twos complement stuff scares me.

items exist - i used your input 1:1
read part seems to work!

2017-05-11 15:34:40.584 [ItemStateChangedEvent     ] - Raum_MB_Soll_Lo changed from 22500 to 22000
2017-05-11 15:34:40.744 [ItemStateChangedEvent     ] - Raum_MB_Soll changed from 22500 to 22000

There is a funny pratfall using primitive variables like int, but I thought it did not apply to item.sendCommand method.

nevertheless, try instead

      var Number hival = (raw32 / 65535).intValue
      var Number loval = raw32.bitwiseAnd(65535)    // mask with FFFF
      Raum_MB_Soll_Hi.sendCommand(hival)
      Raum_MB_Soll_Lo.sendcommand(loval)

I’m still expecting to see a Modbus failure in the end though

Still a problem with rule:

2017-05-11 21:59:22.106 [ERROR] [.script.engine.ScriptExecutionThread] - Rule 'process outgoing value': An error occured during the script execution: The name '<XFeatureCallImplCustom>.sendcommand(<XFeatureCallImplCustom>)' cannot be resolved to an item or type.
2017-05-11 21:59:22.188 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - Last request: 01 10 13 98 00 01 02 00 00 98 89
2017-05-11 21:59:22.189 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - failed to read: CRC Error in received frame: 0 bytes:
2017-05-11 21:59:22.190 [ERROR] [pi.modbus.io.ModbusSerialTransaction] - execute try 1/3 error: I/O exception - failed to read. Request: net.wimpi.modbus.msg.WriteMultipleRegistersRequest@13dbc24 (unit id 1 & transaction 1146). Serial parameters: SerialParameters@5f0110[portName=/dev/ttyAMA0,baudRate=9600,flowControlIn=none,flowControlOut=none,databits=8,stopbits=1,parity=none,encoding=rtu,echo=false,receiveTimeoutMillis=1500]
2017-05-11 21:59:22.296 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - Last request: 01 10 13 98 00 01 02 00 00 98 89
2017-05-11 21:59:22.298 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - failed to read: CRC Error in received frame: 0 bytes:
2017-05-11 21:59:22.300 [ERROR] [pi.modbus.io.ModbusSerialTransaction] - execute try 2/3 error: I/O exception - failed to read. Request: net.wimpi.modbus.msg.WriteMultipleRegistersRequest@13dbc24 (unit id 1 & transaction 1146). Serial parameters: SerialParameters@5f0110[portName=/dev/ttyAMA0,baudRate=9600,flowControlIn=none,flowControlOut=none,databits=8,stopbits=1,parity=none,encoding=rtu,echo=false,receiveTimeoutMillis=1500]
2017-05-11 21:59:22.418 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - Last request: 01 10 13 98 00 01 02 00 00 98 89
2017-05-11 21:59:22.420 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - failed to read: CRC Error in received frame: 0 bytes:
2017-05-11 21:59:22.422 [ERROR] [pi.modbus.io.ModbusSerialTransaction] - execute try 3/3 error: I/O exception - failed to read. Request: net.wimpi.modbus.msg.WriteMultipleRegistersRequest@13dbc24 (unit id 1 & transaction 1146). Serial parameters: SerialParameters@5f0110[portName=/dev/ttyAMA0,baudRate=9600,flowControlIn=none,flowControlOut=none,databits=8,stopbits=1,parity=none,encoding=rtu,echo=false,receiveTimeoutMillis=1500]
2017-05-11 21:59:22.426 [ERROR] [pi.modbus.io.ModbusSerialTransaction] - execute reached max tries 3, throwing last error: I/O exception - failed to read. Request: net.wimpi.modbus.msg.WriteMultipleRegistersRequest@13dbc24. Serial parameters: SerialParameters@5f0110[portName=/dev/ttyAMA0,baudRate=9600,flowControlIn=none,flowControlOut=none,databits=8,stopbits=1,parity=none,encoding=rtu,echo=false,receiveTimeoutMillis=1500]
2017-05-11 21:59:22.430 [ERROR] [.binding.modbus.internal.ModbusSlave] - ModbusSlave (slave3): error when executing write request (net.wimpi.modbus.msg.WriteMultipleRegistersRequest@13dbc24): I/O exception - failed to read

this is rules:

rule  "process incoming words"
when
   Item Raum_MB_Soll_Lo changed    
then
  Thread::sleep(100)   // _Hi should have changed already, wait a little to be sure
   var int hiraw = (Raum_MB_Soll_Hi.state as DecimalType).intValue   // get word
   var int loraw = (Raum_MB_Soll_Lo.state as DecimalType).intValue
   var int result = (hiraw * 65535) + loraw
   if (hiraw > 32767 ) {
         // oh dear it is signed, weird maths to follow
      result =  result - 4294967296    // think this extracts twos complement to signed ?!
   } 
   Raum_MB_Soll.postUpdate(result)    // to virtual item
end

rule "process outgoing value"
when
   Item Raum_MB_Soll received command    // from UI or rule
then
   var int raw32 = (receivedCommand as DecimalType).intValue
   if (raw32 < 0) {
      logInfo("mbconvert","negative numbers not supported")    // I chickened out of twos complement maths
   } else {
      var Number hival = (raw32 / 65535).intValue
      var Number loval = raw32.bitwiseAnd(65535)    // mask with FFFF
      Raum_MB_Soll_Hi.sendCommand(hival)
      Raum_MB_Soll_Lo.sendcommand(loval)
   }
end

You don’t happen to have Items called hival or loval, by chance? Change the var names in the rule to avoid a clash.

I fear the Modbus error is terminal for this whole idea though. It appears this slave insists on a pair of registers being written together - fair enough for a 32-bit target. The current OH binding simply will not do that, it writes one at a time. (selecting writemultipleregisters only chooses write mode FC16, it actually still writes one at a time just using a different Modbus command).

Your only hope is for ‘someone’ to implement 32-bit writes, whcih may not be as easy as it sounds.

there’s defInitely no item called hival or loval.
what does this mean?

The name '<XFeatureCallImplCustom>.sendcommand(<XFeatureCallImplCustom>)' cannot be resolved to an item or type.

i had the same error on a completely different rule… (playsound()) …

ahh it’s a test you see … you copy/pasted my sendcommand/sendCommand typo :blush:

copy/paste is all i do here :relaxed: since this last posts are all beyond my understanding…

Raum_MB_Soll_Lo.sendcommand(loval)

should be

Raum_MB_Soll_Lo.sendCommand(loval)

and that’s it? or did you hide more typos?

okay, the rule error doesn’t pop up anymore… still, doesn’t seem to work:

2017-05-12 20:35:58.446 [ItemCommandEvent          ] - Item 'Raum_MB_Soll' received command 23500
2017-05-12 20:35:58.471 [ItemCommandEvent          ] - Item 'Raum_MB_Soll_Hi' received command 0
2017-05-12 20:35:58.482 [ItemCommandEvent          ] - Item 'Raum_MB_Soll_Lo' received command 23500
2017-05-12 20:35:58.573 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - Last request: 01 10 13 98 00 01 02 00 00 98 89
2017-05-12 20:35:58.575 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - failed to read: CRC Error in received frame: 0 bytes:
2017-05-12 20:35:58.576 [ERROR] [pi.modbus.io.ModbusSerialTransaction] - execute try 1/3 error: I/O exception - failed to read. Request: net.wimpi.modbus.msg.WriteMultipleRegistersRequest@1188266 (unit id 1 & transaction 3065). Serial parameters: SerialParameters@14caf0d[portName=/dev/ttyAMA0,baudRate=9600,flowControlIn=none,flowControlOut=none,databits=8,stopbits=1,parity=none,encoding=rtu,echo=false,receiveTimeoutMillis=1500]
2017-05-12 20:35:58.683 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - Last request: 01 10 13 98 00 01 02 00 00 98 89
2017-05-12 20:35:58.684 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - failed to read: CRC Error in received frame: 0 bytes:
2017-05-12 20:35:58.686 [ERROR] [pi.modbus.io.ModbusSerialTransaction] - execute try 2/3 error: I/O exception - failed to read. Request: net.wimpi.modbus.msg.WriteMultipleRegistersRequest@1188266 (unit id 1 & transaction 3065). Serial parameters: SerialParameters@14caf0d[portName=/dev/ttyAMA0,baudRate=9600,flowControlIn=none,flowControlOut=none,databits=8,stopbits=1,parity=none,encoding=rtu,echo=false,receiveTimeoutMillis=1500]
2017-05-12 20:35:58.797 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - Last request: 01 10 13 98 00 01 02 00 00 98 89
2017-05-12 20:35:58.798 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - failed to read: CRC Error in received frame: 0 bytes:
2017-05-12 20:35:58.800 [ERROR] [pi.modbus.io.ModbusSerialTransaction] - execute try 3/3 error: I/O exception - failed to read. Request: net.wimpi.modbus.msg.WriteMultipleRegistersRequest@1188266 (unit id 1 & transaction 3065). Serial parameters: SerialParameters@14caf0d[portName=/dev/ttyAMA0,baudRate=9600,flowControlIn=none,flowControlOut=none,databits=8,stopbits=1,parity=none,encoding=rtu,echo=false,receiveTimeoutMillis=1500]
2017-05-12 20:35:58.801 [ERROR] [pi.modbus.io.ModbusSerialTransaction] - execute reached max tries 3, throwing last error: I/O exception - failed to read. Request: net.wimpi.modbus.msg.WriteMultipleRegistersRequest@1188266. Serial parameters: SerialParameters@14caf0d[portName=/dev/ttyAMA0,baudRate=9600,flowControlIn=none,flowControlOut=none,databits=8,stopbits=1,parity=none,encoding=rtu,echo=false,receiveTimeoutMillis=1500]
2017-05-12 20:35:58.802 [ERROR] [.binding.modbus.internal.ModbusSlave] - ModbusSlave (slave3): error when executing write request (net.wimpi.modbus.msg.WriteMultipleRegistersRequest@1188266): I/O exception - failed to read
2017-05-12 20:35:58.930 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - Last request: 01 10 13 99 00 01 02 5b cc a2 3d
2017-05-12 20:35:58.932 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - failed to read: CRC Error in received frame: 0 bytes:
2017-05-12 20:35:58.934 [ERROR] [pi.modbus.io.ModbusSerialTransaction] - execute try 1/3 error: I/O exception - failed to read. Request: net.wimpi.modbus.msg.WriteMultipleRegistersRequest@f8024f (unit id 1 & transaction 3066). Serial parameters: SerialParameters@185c155[portName=/dev/ttyAMA0,baudRate=9600,flowControlIn=none,flowControlOut=none,databits=8,stopbits=1,parity=none,encoding=rtu,echo=false,receiveTimeoutMillis=1500]
2017-05-12 20:35:59.041 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - Last request: 01 10 13 99 00 01 02 5b cc a2 3d
2017-05-12 20:35:59.042 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - failed to read: CRC Error in received frame: 0 bytes:
2017-05-12 20:35:59.044 [ERROR] [pi.modbus.io.ModbusSerialTransaction] - execute try 2/3 error: I/O exception - failed to read. Request: net.wimpi.modbus.msg.WriteMultipleRegistersRequest@f8024f (unit id 1 & transaction 3066). Serial parameters: SerialParameters@185c155[portName=/dev/ttyAMA0,baudRate=9600,flowControlIn=none,flowControlOut=none,databits=8,stopbits=1,parity=none,encoding=rtu,echo=false,receiveTimeoutMillis=1500]
2017-05-12 20:35:59.157 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - Last request: 01 10 13 99 00 01 02 5b cc a2 3d
2017-05-12 20:35:59.158 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - failed to read: CRC Error in received frame: 0 bytes:
2017-05-12 20:35:59.160 [ERROR] [pi.modbus.io.ModbusSerialTransaction] - execute try 3/3 error: I/O exception - failed to read. Request: net.wimpi.modbus.msg.WriteMultipleRegistersRequest@f8024f (unit id 1 & transaction 3066). Serial parameters: SerialParameters@185c155[portName=/dev/ttyAMA0,baudRate=9600,flowControlIn=none,flowControlOut=none,databits=8,stopbits=1,parity=none,encoding=rtu,echo=false,receiveTimeoutMillis=1500]
2017-05-12 20:35:59.161 [ERROR] [pi.modbus.io.ModbusSerialTransaction] - execute reached max tries 3, throwing last error: I/O exception - failed to read. Request: net.wimpi.modbus.msg.WriteMultipleRegistersRequest@f8024f. Serial parameters: SerialParameters@185c155[portName=/dev/ttyAMA0,baudRate=9600,flowControlIn=none,flowControlOut=none,databits=8,stopbits=1,parity=none,encoding=rtu,echo=false,receiveTimeoutMillis=1500]
2017-05-12 20:35:59.162 [ERROR] [.binding.modbus.internal.ModbusSlave] - ModbusSlave (slave3): error when executing write request (net.wimpi.modbus.msg.WriteMultipleRegistersRequest@f8024f): I/O exception - failed to read

That is OH Modbus binding attempting to write registers 5016 and 5017 (hex 1398,1399) consecutively, using FC16.
The D&W slave doesn’t like it.

and that’s nothing we could fix with more infos from d&w?
the seller has good connection to the manufacturer… :neutral_face:

The problem is only partly with D&W.

Modbus specification happily allows writing of individual registers. Modbus spec knows nothing about 32-bit paired registers. It’s just a way of interpreting two lumps transported over Modbus, which only knows 16-bit registers…
So in theory any writable register should be writable individually.

In practice however, many real world Modbus devices do pair up standard registers to be handled as 32-bit units, a de facto addition to the spec.
Clearly it would be a Bad Thing to write half ofsuch a unit at a time.
Modbus spec does allow to write several registers at a time - so it is a reasonable design decision by D&W to insist that happens and so avoid the two halves of your 32-bit unit getting out of step.

You could argue that D&W should strictly adhere to Modbus spec, but there is a good technical reason why they do not.
They are not alone - hardly any real world Modbus devices do implement the spec exactly, there is a lot of variation. For any example, a lot of devices will NOT accept the multi-write we want here.

The real solution here (and probably in other situations as well) would be to have the OH binding write 32-bit units (which OH does know about from your config) in multi-register write mode in one operation.

I’ve opened an enhancement request on your behalf, as your heating system is unusable with OH

But any effort put into that might be better spent developing a real OH2 version Modbus binding. That would I guess be a way off though. How desperate are you?. Which would you prioritise?