Skip to content

convert_from_registers byteorder #2616

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
lorithai opened this issue Mar 24, 2025 · 1 comment
Closed

convert_from_registers byteorder #2616

lorithai opened this issue Mar 24, 2025 · 1 comment

Comments

@lorithai
Copy link

Hi

I am facing some issues with the new method for converting registers to float. The documention for the device i am communicating with says the word order and byte order is in the little endian format.

This example has the two registers [0xDA77, 0xFB41] which is supposed to be read as 31.43

I have been using the following method to convert registers to floats (being deprecated)

from pymodbus.payload import BinaryPayloadDecoder, BinaryPayloadBuilder
from pymodbus.constants import Endian
temperature_registers = [0xDA77, 0xFB41]  # DA 77 FB 41 (temperature)
values = {}
values["raw_value"] = [hex(val) for val in temperature_registers]
values["decoded_value"] = BinaryPayloadDecoder.fromRegisters(temperature_registers,byteorder=Endian.LITTLE, wordorder=Endian.LITTLE).decode_32bit_float()      

This has been working fine and gives the expected output of
{'raw_value': ['0xda77', '0xfb41'], 'decoded_value': 31.433521270751953}

I get a message that this method will be deprecated after version 3.9.0 so i am trying to convert to the new method of using convert_from_registers()

My attempt is as follows

from pymodbus.client.mixin import ModbusClientMixin
DATATYPE = ModbusClientMixin.DATATYPE
temperature_registers = [0xDA77, 0xFB41]  # DA 77 FB 41 (temperature)
values = {}
values["raw_value"] = [hex(val) for val in temperature_registers]
values["decoded_value"] = ModbusClientMixin.convert_from_registers(temperature_registers,data_type=DATATYPE.FLOAT32,word_order="little")

But this gives an unexpexted result
{'raw_value': ['0xda77', '0xfb41'], 'decoded_value': -1.006544287142157e+36}

Shuffling the bytes around to a reverse order (little endian byte order) and selecting word_order="big" in the following way

from pymodbus.client.mixin import ModbusClientMixin
DATATYPE = ModbusClientMixin.DATATYPE
#temperature_registers = [0xDA77, 0xFB41]  # DA 77 FB 41 (temperature)
temperature_registers = [0x41FB,0x77DA] # reverse byte order
values = {}
values["raw_value"] = [hex(val) for val in temperature_registers]
values["decoded_value"] = ModbusClientMixin.convert_from_registers(temperature_registers,data_type=DATATYPE.FLOAT32,word_order="big")

This gives the expected result
{'raw_value': ['0x41fb', '0x77da'], 'decoded_value': 31.433521270751953}

From what i can tell from the documentation of the modbus device the order needs to be reversed from A B C D (DA 77 FB 41) to D C B A (41 FB 77 DA). To me this would require a little endian word_order and little endian byte order.
Somewhat confused by the stark difference in inputs and outputs in these two methods and that the convert_from_registers doesn't seem to have byteorder option.

I guess i can create a byte order swap function for myself though.

Regards

@janiversen
Copy link
Collaborator

The modbus standard defines byte order to be big, therefore the pymodbus library only supports changing the word order.

Python have standard methods to switch the byte order, so use those.

@janiversen janiversen closed this as not planned Won't fix, can't repro, duplicate, stale Mar 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants