我正在尝试通过 pymodbus 控制 EX-PS 5080 电源。我正在尝试读取远程状态。 Modbus 地址 = 402;功能码 = 01 读取线圈;数据类型 = uint(16);数据长度(以字节为单位)= 2;寄存器数量 = 1
这是一个简化的代码:
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: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"
输出中没有任何返回。 我注意到“RECV:0x0 0x1 0x2 0x0 0x0 0x84”的长度不正确。 CRC 中似乎缺少一个字节。
EA PS5000还有一个官方软件,可以检查原始代码。这里我发送了
[TX] 0x0 0x1 0x1 0x92 0x0 0x1 0x5c 0xa
我有
[RX] 0x0 0x1 0x2 0x0 0x0 0x84 0x3c
我尝试在 pymodbus 中检查 CRC:
from pymodbus.utilities import computeCRC, checkCRC
crc = computeCRC(b'\x00\x01\x01\x92\x00\x01\x5c\x0a')
print(hex(crc))
返回的是 0x0,我期望的是 0x84 0x3c
为什么 CRC 计算会给出意想不到的结果?
从屏幕截图和代码记录的差异来看,您似乎没有收到最终字节(3C),导致 pymodbus 无法解码消息。
也许串行总线的参数不正确(奇偶校验、停止位)?
在您的 CRC 计算中,您似乎误解了 CRC 的计算和添加位置: CRC 是根据您发送的消息计算的,并附加为最后 2 个字节:
>>> crc = computeCRC(b'\x00\x01\x01\x92\x00\x01')
>>> print(hex(crc))
0x5c0a
因此总消息变为:
0x0 0x1 0x1 0x92 0x0 0x1 0x5c 0xa
由于一些时髦的数学计算,(再次)附加 CRC 的消息的 CRC 将始终为 0。
收到消息的 CRC 确实是 0x84 0x3C,计算公式为:
>>> crc = computeCRC(b'\x00\x01\x02\x00\x00')
>>> print (hex(crc))
0x843c