pythonmodbus-tcppymodbuspymodbustcp

Pymodbus write_registers : Working with bytes vs words


When writing to multiple registers using Pymodbus it seems that the encode method on the class WriteMultipleRegistersRequest creates a word to add to the packet from the list of values using this packet += struct.pack('>H', value)

I have registers mapped to an IO Link master where I want to be able to assign each byte with the following:

0x00, 0x01, 0x64, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x04, 0x38

Since Pymodbus is encoding my input as words I end up with an output like the below which then incorrectly maps to the io link as it is padding each hexadecimal value with 0x00 due to the H flag on the struct on the encode method:

0x0 0x1 0x0 0x64 0x0 0x0 0x0 0x0 0x0 0x1 0x0 0x1 0x0 0x1 0x0 0x0 0x0 0x0 0x0 0x1 0x0 0x0 0x0 0x1 0x0 0x0 0x0 0x4 0x0 0x38

If I build my own hex array and send it down the socket it works fine as I am able to assign each byte rather than the word that is created by pymodbus.

As far as I can see there isn't a way in pymodbus to specify if I want to encode in words or single bytes and I would still like to take advantage of other aspects of the package and avoid having to build my packets manually for each call.

Anyone have any advise on how to best approach this?


Solution

  • Modbus is a word-oriented protocol and byte ordering is "BigEndian".
    If your IO-Link payload always have an even length, the solution is simple: you have to combine two bytes into one word. There are many ways to do that and the simplest (IMO) is:

    wordArray=[]
    for i in range( 0, len(byteArray), 2):
        wordArray.append( (byteArray[i]<<8) + byteArray[i+1]
    

    If the mapping to IO-Link is incorrect, you have to swap bytes by moving the <<8 to the other byte.