Search code examples
modbusrs485pymodbus

rtu Pymodbus trouble reading slave device


I have been trying to connect to a device using a serial port and RTU Modbus. The device is a variable frequency controller:

enter image description here

Which is connected to my laptop via the following RS485 to USB converter:

https://www.amazon.co.uk/gp/product/B01E8JRL6O/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1

The instructions with the device I'm connected to provide a usage example for reading data with Modbus, as shown below: enter image description here

With the above, provided, I have tried to perform a read request with the below code:

from pymodbus.client.sync import ModbusSerialClient as ModbusClient
modbus = ModbusClient(method='rtu', port='/dev/tty.usbserial-AQ00BYCR', baudrate=9600, timeout=1)
modbus.connect()
test = modbus.read_holding_registers(1, 1, unit=1)
print (test)

Where I assume, above, that the line:

test = modbus.read_holding_registers(1, 1, unit=1)

means that register address 1 is read, for 1 reading frame, and for device ID 1. To my understanding, this request corresponds to the instruction example shown above. Unfortunately, however, I consistently get the error message:

Modbus Error: [Input/Output] Modbus Error: [Invalid Message] Incomplete message received, expected at least 2 bytes (1 received)

Does anyone know why I am getting this error? And, secondly, is the CRC calculated on-the-fly by the pymodbus? Or am I supposed to some how calculate this and include it?

Any help is much appreciated!


Solution

  • As discussed in the comments you are facing a strange issue.

    To sum up:

    -Your PID controller supports Modbus RTU over RS485.

    -Wiring is correct: T/R+ on the USB converter goes to T/R(A) on the controller and T/R- to T/R(B).

    -The USB converter seems to be good and supports Modbus (RS485 half-duplex).

    -Your code should work.

    -Baud rate and parity are correct. (EDIT: this was actually the problem according to the comment below, oftentimes the baud rate the manual claims to be the default was changed in a new revision of the firmware or by somebody else manipulating the device for their own needs).

    To have more details you can add debugging/logging as follows:

    from pymodbus.client.sync import ModbusSerialClient as ModbusClient
    
    import logging
    FORMAT = ('%(asctime)-15s %(threadName)-15s '
              '%(levelname)-8s %(module)-15s:%(lineno)-8s %(message)s')
    logging.basicConfig(format=FORMAT)
    log = logging.getLogger()
    log.setLevel(logging.DEBUG)
    
    
    modbus = ModbusClient(method='rtu', port='/dev/tty.usbserial-AQ00BYCR', baudrate=9600, timeout=1)
    modbus.connect()
    test = modbus.read_holding_registers(1, 1, unit=1)
    print(test.registers)
    

    Try that and you'll convince yourself that pymodbus is indeed writing the following bytes on the port:

    0x01 0x03 0x00 0x01 0x00 0x01 0xD5 0xCA
    

    Looking at the log (it should be similar to mine but in your you'll see the answer from the device too):

    2019-12-03 18:24:45,262 MainThread      DEBUG    transaction    :111      Current transaction state - IDLE
    2019-12-03 18:24:45,262 MainThread      DEBUG    transaction    :116      Running transaction 1
    2019-12-03 18:24:45,262 MainThread      DEBUG    transaction    :215      SEND: 0x1 0x3 0x0 0x1 0x0 0x1 0xd5 0xca
    2019-12-03 18:24:45,262 MainThread      DEBUG    sync           :73       New Transaction state 'SENDING'
    2019-12-03 18:24:45,262 MainThread      DEBUG    transaction    :224      Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
    2019-12-03 18:24:46,264 MainThread      DEBUG    transaction    :234      Transaction failed. (Modbus Error: [Invalid Message] Incomplete message received, expected at least 2 bytes (0 received)) 
    2019-12-03 18:24:46,265 MainThread      DEBUG    rtu_framer     :235      Frame - [] not ready
    2019-12-03 18:24:46,265 MainThread      DEBUG    transaction    :390      Getting transaction 1
    2019-12-03 18:24:46,265 MainThread      DEBUG    transaction    :189      Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
    

    At this point, all I end up with are extremely far-fetched theories (if you are running on a very very old version of pymodbus, the endianness of the CRC was wrong, and you would see 0xca 0xd5 instead).