sourceperl / pyModbusTCP

A simple Modbus/TCP library for Python
MIT License
293 stars 102 forks source link

Reading holding registers with negative values #29

Closed briantilburgs closed 2 years ago

briantilburgs commented 4 years ago

Hi,

Today I hava installed a EMU Modbus TCP power meter for my solat energy. I thried to measure the returned energy but thet seems to be [65535, 65432] I think that should be a negative value, how should I correct that?

emu = ModbusClient(host=emu_dev["ip"], port=emu_dev["port"], auto_open=True) emu.read_holding_registers(4524, 4)

Thanks,

Brian

sourceperl commented 4 years ago

Hi, yes it's probably "two’s complement" negative value.

See at https://pymodbustcp.readthedocs.io/en/latest/quickstart/index.html#utils-module-modbus-data-mangling for how to deal with this.

solanu commented 4 years ago

Same here but writing negative int32 (long).

I have transformed negative int (-250) to word list using long_list_to_word function and I get [65286, -1] when it should be [65286, 65535]

sourceperl commented 3 years ago

Not sure if this is still useful for you, but the behavior you report in july matches the "historical" use of get_2comp. That is to say, he could translate data received via modbus and convert them. But it can not do it in the other way with negative python int.

Quickstart extract with historical usage:

from pyModbusTCP import utils
list_16_bits = [0x0000, 0xFFFF, 0x00FF, 0x8001]

# display "[0, -1, 255, -32767]"
print(utils.get_list_2comp(list_16_bits, 16))

# display "-1"
print(utils.get_2comp(list_16_bits[1], 16))

Since commit 644ed80359b2166f377cfe691c626cc5773709f0 get_2comp deal with negative python int also.

So now:

from pyModbusTCP.utils import get_2comp, long_list_to_word

# return [65286, 65535]
print(long_list_to_word([get_2comp(-250, 32)], big_endian=False))