Modbus TCP swap bytes

I’m using Ignition 7.9.9 and I have a Modbus TCP device that holds a 16 bit INT in HR2. I know that the value in HR2 should be -32768 or 0000000000000001 in binary. However in Ignition I’m getting 128 or 0000000100000000 in binary.

Is there a version of the Modbus TCP driver that allows you to swap High/Low bytes in 16 bit integers the same way you can swap High/Low words in 32 bit integers?

If not, I could make an expression tag that uses binEnc(getBit{[default]Tagpath},8),getBit(Tagpath,9…)) and so on and manually place each bit in the right spot, but I’m really hoping there’s a built in feature in the driver that I’m just missing.

Modbus protocols leave a lot to the implementer, but not that. (ps, you threw me off showing your binary backwards…)

1 Like

The devices are some scales that offer several ways of sending the data via Modbus (standard, byte swap, word swap, and double word swap), but unfortunately to be compatible with another device they have to use this byte swapping option. I’ll have to jump over to the feature request site and see if we can’t get some of the odder Modbus options thrown in there as I run into this kind of thing frequently on fringe devices, like power quality meters or scales.

Ha ha, yeah I threw myself off for a minute after posting the binary in little endian, I spend too much time in Allen-Bradley PLCs. Fortunately after I made a test tag I found that the binEnc function in Ignition also packs them little endian.

For anyone else who comes across this thread having the same issue here was my work around. I made an OPC tag that looked at the appropriate Modbus address and got the data jumbled. Then I made an expression tag that used the following code to manually perform the byte swap:

binEnc(
getBit({[default]TagPath},8)
,getBit({[default]TagPath},9)
,getBit({[default]TagPath},10)
,getBit({[default]TagPath},11)
,getBit({[default]TagPath},12)
,getBit({[default]TagPath},13)
,getBit({[default]TagPath},14)
,getBit({[default]TagPath},15)
,getBit({[default]TagPath},0)
,getBit({[default]TagPath},1)
,getBit({[default]TagPath},2)
,getBit({[default]TagPath},3)
,getBit({[default]TagPath},4)
,getBit({[default]TagPath},5)
,getBit({[default]TagPath},6)
,getBit({[default]TagPath},7)
)
1 Like

This would probably run faster:

(({[default]TagPath} & 0xff00) >> 8) | (({[default]TagPath} & 0xff) << 8)
2 Likes

Sounds like a device whose functionality needs to be replaced (with Ignition, perhaps). That's the kind of grief that makes systems unmaintainable.

That’s the ticket! I went in thinking about shifting and then immediately became distracted. Thanks, Phil!

Thanks to you both for this. Ran into the same issue with WEG Soft Starters. You would think they would know better... :expressionless:

Now you’re gonna make me put this into my new Modbus driver. (Client & Server & a few other goodies.) I had talked myself out of it a couple weeks ago. /:

Sorry to disappoint, but I decided to not implement byte swapping for integers. There's many things in the Modbus spec that have been left to implementers, but this one wasn't. Sorry. Lots of other goodies, there, though: