pymodbus read_coils return missing 1byte CRC

61 views Asked by At

I am trying to control a EX-PS 5080 power source via pymodbus. I am trying to read the remote status. Modbus address = 402; functioncode = 01 read coils; datatype = uint(16); datalenght in bytes = 2; number of register = 1

Here is a simplified code:

from pymodbus.client import ModbusSerialClient
import pymodbus
import logging
from pymodbus.constants import Endian

logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.DEBUG)

COM = ModbusSerialClient(method='rtu',port='com4',baudrate=9600, timeout= 5, parity= 'N', stopbits=1, bytesize=8)
COM.connect()
output =  COM.read_coils(address = 402, bit = 2000, count = 1, slave =0)
COM.close()

Debug output is

DEBUG:pymodbus.logging:Current transaction state - IDLE
DEBUG:pymodbus.logging:Running transaction 1
DEBUG:pymodbus.logging:SEND: 0x0 0x1 0x1 0x92 0x0 0x1 0x5c 0xa
DEBUG:pymodbus.logging:Resetting frame - Current Frame in buffer - 
DEBUG:pymodbus.logging:New Transaction state "SENDING"
DEBUG:pymodbus.logging:Changing transaction state from "SENDING" to "WAITING FOR REPLY"
DEBUG:pymodbus.logging:Changing transaction state from "WAITING FOR REPLY" to "PROCESSING REPLY"
DEBUG:pymodbus.logging:RECV: 0x0 0x1 0x2 0x0 0x0 0x84
DEBUG:pymodbus.logging:Processing: 0x0 0x1 0x2 0x0 0x0 0x84
DEBUG:pymodbus.logging:Frame - not ready
DEBUG:pymodbus.logging:Getting transaction 0
DEBUG:pymodbus.logging:Changing transaction state from "PROCESSING REPLY" to "TRANSACTION_COMPLETE"

There is nothing return in the output. I notice "RECV: 0x0 0x1 0x2 0x0 0x0 0x84" is not correct length. It seems missing a byte in CRC.

EA PS5000 also has a official software, where one can inspect the raw code. Here I sent [TX] 0x0 0x1 0x1 0x92 0x0 0x1 0x5c 0xa I got [RX] 0x0 0x1 0x2 0x0 0x0 0x84 0x3c

enter image description here

I tried to check CRC in pymodbus:


from pymodbus.utilities import computeCRC, checkCRC
crc = computeCRC(b'\x00\x01\x01\x92\x00\x01\x5c\x0a')
print(hex(crc))

The return is 0x0, where I expect to be 0x84 0x3c

Why CRC calcualtion gives unexpect result?

1

There are 1 answers

1
Pelle On

From the difference in the logging of the screenshot and your code, it looks like you are not receiving the final byte (3C) causing pymodbus to fail to decode the message.

Maybe the parameters for the serial bus are incorrect (parity, stopbits)?

In your CRC calculation you seem to misunderstand where the CRC is calculated and added: The CRC is calculated over the message you send, and appended as the last 2 bytes:

>>> crc = computeCRC(b'\x00\x01\x01\x92\x00\x01')
>>> print(hex(crc))
0x5c0a

So the total message becomes:

0x0 0x1 0x1 0x92 0x0 0x1 0x5c 0xa

Taking the CRC (again) of a message with its CRC appended will always be 0 due to some funky math.

The CRC of the received message is indeed 0x84 0x3C, as calculated by:

>>> crc = computeCRC(b'\x00\x01\x02\x00\x00')
>>> print (hex(crc))
0x843c