1

我们从 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)

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

4

1 回答 1

1

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

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

然后更改您的代码以将strict声明的参数添加到False

....
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 倍,而不是使用默认值 from socket.interCharTimeout

self._t0 = float((1 + 8 + 2)) / self.baudrate
self.inter_char_timeout = 1.5 * self._t0

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

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

于 2019-06-19T05:43:45.790 回答