Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to store signed 16bit value in pymodbus register

I am trying to implement a pymodbus server. I am using ModbusSparseDataBlocks in the ModbusSlaveContext. This works so far. The client can write and read vales from every register instantiated.

But I have problems with negative values. The client needs 16bit signed integer format and he can not interpret my negative values.

This is how I fill the register with values:

#write positive value (100) to IR[0x10] --> client interprets this correctly
context[0x00].setValues(4, 0x10, 100)
#write negative value (-100) to IR[0x10] --> client can't read this, throws failure
context[0x00].setValues(4, 0x10, -100)

How can I write a valid 16bit signed integer to the register?

(I am using python 2.7 and pymodbus version 1.2.0)

like image 235
wewa Avatar asked Nov 15 '25 11:11

wewa


2 Answers

It looks like your library only understands unsigned 16-bit numbers. If you bitwise-AND the signed value with 0xFFFF (a 16-bit mask) in Python, you'll get the same result:

What you're doing:

>>> import struct
>>> struct.unpack('<H',struct.pack('<h',-100))[0]
65436

Bitwise-AND:

>>> -100 & 0xFFFF
65436

So you can do:

context[0x00].setValues(4, 0x10, -100 & 0xFFFF)

Positive values will be unaffected, and negative values result in the unsigned 16-bit 2's complement value.

To convert an unsigned 2's complement 16-bit value back to signed, test for the sign bit (215) and subtract 216 if present:

value = value-2**16 if value & 2**15 else value

or equivalently:

value = value-0x10000 if value & 0x8000 else value
like image 146
Mark Tolonen Avatar answered Nov 18 '25 19:11

Mark Tolonen


I found out that following works for me, but I don't know if this is the correct and safe way.

import struct

def signed(value):
    packval = struct.pack('<h',value)
    return struct.unpack('<H',packval)[0]

#write positive value (100) to IR[0x10] --> client interprets this correctly
context[0x00].setValues(4, 0x10, signed(100))
#write negative value (-100) to IR[0x10] --> client interprets this correctly
context[0x00].setValues(4, 0x10, signed(-100))
like image 43
wewa Avatar answered Nov 18 '25 20:11

wewa



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!