Search code examples
pythonmodbusmodbus-tcppymodbuspymodbustcp

PyModbusTCP reading different values than actual ModBus values?


I am trying to read from registers 40001 to 40004 through PyModbusTCP, when reading value 40001 on PyModbusTCP I am not reading the same value that is shown on the screen of the equipment and the one that is read through Open ModScan (which is the same value as the one shown on my equipment). I don't know if this has something to do with zero based addressing or if it's simply because the value that is supposed to be read is like -1000 which doesn't make sense (the sensor is faulty but still outputting).

The Modbus Addresses are: 40001 -> Present Val, 40003 -> Working Set Point, 40004 -> Current Output Percentage. All of these are padded by *10.

What I have tried:

print(c.read_holding_registers(0, 4))

Output of that line was: 55532, 0, 100, 100 (two last values match what is on screen)

Output on ModScan at the same time was: 40001 -> -10003, 40002 -> 0, 40003 -> 100, 40004 -> 100.


Solution

  • The people who added comments to my question we're correct, it's a signed integer vs. unsigned integer problem. To fix this I converted the integer back to a binary number of 16 chars (16 bits = 2 bytes), and then got the integer value based on the 2's complement/unsigned conversion to decimal values.

    import sys
    
    def twos(val_str, bytes):
        val = int(val_str, 2)
        b = val.to_bytes(bytes, byteorder=sys.byteorder, signed=False)    
                                                              
        return int.from_bytes(b, byteorder=sys.byteorder, signed=True)
    
    
    def misread_correction(decimal):
        binary = bin(decimal & 0xffff)[2:].zfill(16) 
        corrected = twos(binary,2)
        corrected /= 10
        return corrected