Pymodbus:响应字节数错误

Pymodbus : Wrong byte count in response

我们正在请求来自 RS485 设备的 14 个响应,有时我们得到的响应没有设置的 9 个字节。那是因为它有时会在 3 个参数中回复。

Normal: 
CALL->     01 04 00 00 00 02 71 CB 
RESPONSE-> 01 04 04 43 59 E6 66 F4 59


Error:
CALL->      01 04 00 00 00 02 71 CB 
RESPONSE -> 01 04 04 43
            59 CC CD AA 86 

发生错误时,我从 pymodbus 收到此消息:

DEBUG:pymodbus.transaction: Incomplete message received, Expected 9 bytes Recieved 4 bytes !!!!
DEBUG:pymodbus.transaction:Changing transaction state from 'WAITING FOR REPLY' to 'PROCESSING REPLY'
DEBUG:pymodbus.transaction:RECV: 0x1 0x4 0x4 0x3e
DEBUG:pymodbus.framer.rtu_framer:Frame check failed, ignoring!!
DEBUG:pymodbus.framer.rtu_framer:Resetting frame - Current Frame in buffer - 0x1 0x4 0x4 0x3e
DEBUG:pymodbus.transaction:Getting transaction 1
DEBUG:pymodbus.transaction:Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'

我试过让 for 进入休眠状态,这样它就不会因通话而使设备崩溃,但无论如何我都能接到电话。我也读过 https://wingpath.co.uk/docs/modtest/troubleshoot.html 他们这样说:

"Wrong byte count in response: XXX when expecting XXX"

The byte count in the response sent by the slave is not what was expected for the count that ModTest sent in the request.

Turn on tracing to get more information.

Check that your slave is functioning correctly.

If you want ModTest to accept the response even though it is incorrect, you could deselect Strict Checking.

但我不知道如何在 PYMODBUS 上进行主动跟踪,功能是正确的,另一个是我认为我没有使用的库

代码看起来像这样

from __future__ import division
import pymodbus
import serial
from pymodbus.pdu import ModbusRequest
from pymodbus.client.sync import ModbusSerialClient as ModbusClient #initialize a serial RTU client instance
from pymodbus.transaction import ModbusRtuFramer
from time import sleep
from pymodbus.constants import Endian              # Nodig voor 32-bit float getallen (2 registers / 4 bytes)
from pymodbus.payload import BinaryPayloadDecoder  # Nodig voor 32-bit float getallen (2 registers / 4 bytes)
from pymodbus.payload import BinaryPayloadBuilder  # Nodig om 32-bit floats te schrijven naar register

import logging
logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.DEBUG)

#
method = "rtu"
port = "COM1"
baudrate = 2400
stopbits = 1
bytesize = 8
parity = "N"
timeout = 10 # I SET THIS TO 10 MAYBE IT WOULD HELP BUT DIDN'T
retries = 5  # SAME THING WITH THIS ONE
#
try:
    client = ModbusClient(method = method, port = port, stopbits = stopbits, bytesize = bytesize, parity = parity, baudrate = baudrate, timeout = timeout, retries = retries)
    connection = client.connect()
    print (connection)
except:
    print ("Modbus connectie error")
#
def 420 (y):
    variables = [0,6,12,18,24,30,36,70,72,74,76,78,342,344]
    labels = ["Voltage","Corriente","Potencia_Activa","Potencia_Aparente","Potencia_Reactiva","Factor_Potencia","Angulo_Fase","Frecuencia","Potencial_Activa_Consumida","Potencia_Activa_Inyectada","Potencia_Reactiva_Consumida","Potencia_Reactiva_Inyectada","Energia_Activa_Total","Energia_Reactiva_Total"]
    unidades = ["V","A","W","VA","VAr","%","Grados","HZ","kWh","kWh","kVArh","kVArh","kWh","kVArh"]
    LISTA = []
    h = 0
    hh = 0
    for xx in variables:
        try:
            data = client.read_input_registers(xx, 2, unit=1)
            decoder = BinaryPayloadDecoder.fromRegisters(data.registers, Endian.Big)
            eastron = round(decoder.decode_32bit_float(), 3)
            weaito = str(labels[h]) + " = " + str(eastron) + " " + str(unidades[hh])
            LISTA.append(weaito)
            h = h + 1
            hh = hh + 1
            sleep(0.5)
        except:
            print ("PICO")
            sleep(1)
    print(LISTA)

我很想找到解决问题的方法,也许只是再次咨询,直到我得到正确的答案。我不擅长尝试,除了那些也许有答案。

您似乎遇到了已知的 issue 字符间距问题。

虽然有一个简单的解决方法。首先,确保你使用的是 pymodbus 版本 2.2.0(如果你的路径设置正确,你可以在 Windows 上打开命令行终端并输入 pip list ,否则你必须移动到您的脚本 Python 文件夹,其中存储 pip.exe

然后更改您的代码以添加声明为 Falsestrict 参数:

....
client = ModbusClient(method = method, port = port, stopbits = stopbits, bytesize = bytesize, parity = parity, baudrate = baudrate, timeout = timeout, retries = retries)
client.strict = False    #Use Modbus interchar spacing as timeout to prevent missing data for low baudrates
connection = client.connect()
...

这将根据 Modbus 规范定义字符间距,在所选波特率下为位时间的 1.5 倍,而不是使用 socket.interCharTimeout:

中的默认值
self._t0 = float((1 + 8 + 2)) / self.baudrate
self.inter_char_timeout = 1.5 * self._t0

如果您可以使用此解决方案解决您的问题,您应该能够减少设备一次性读取所需的 28 个寄存器的开销。

如果您的问题没有得到解决,我认为您可能遇到了硬件问题。我建议您暂时搁置您的代码并尝试使用 QModMaster 或类似的东西读取寄存器,以确保您的硬件按预期运行。 (您可能会遇到噪音或接地问题,从而缩短您的帧数,如果您想在这方面得到一些指示,请编辑您的问题以包含有关您的硬件的更多详细信息,即:设备类型以及您如何连接它们)。