Pymodbus: неправильное количество байтов в ответе

Мы запрашиваем 14 ответов от устройства RS485, и иногда ответ, который мы получили, не имеет 9 байтов, которые он устанавливает. Это потому, что иногда он отвечает тремя аргументами.

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)

Мне бы хотелось решить проблему, может быть, просто проконсультироваться еще раз, пока я не получу правильный ответ. Я не очень хорошо разбираюсь в попытках, и, кроме тех, может быть, есть ответ.


person Cristobal Rencoret    schedule 19.06.2019    source источник
comment
Вам нужно заполнить очередь полученными байтами и проанализировать ответ только после того, как вы получите достаточно байтов для полного сообщения. Вы имеете дело с двумя асинхронными устройствами, взаимодействующими друг с другом, и иногда вы не получите полное сообщение за одно чтение. Вам нужно дать устройству достаточно времени, чтобы закончить ответ.   -  person flakes    schedule 19.06.2019
comment
Да, это подойдет, но дело в том, как это закодировать, я действительно не знаю, есть ли у Pymodbus такая конфигурация.   -  person Cristobal Rencoret    schedule 19.06.2019


Ответы (1)


Похоже, вы столкнулись с известной проблемой с межсимвольным интервалом.

Однако есть простой обходной путь. Во-первых, убедитесь, что вы используете pymodbus версии 2.2.0 (вы можете сделать это, открыв терминал командной строки в Windows и набрав pip list, если у вас правильно настроен путь, в противном случае вам придется перейти в папку Python со сценариями, где хранится pip.exe ).

Затем измените свой код, чтобы добавить аргумент 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 раза больше времени передачи данных при выбранной скорости передачи вместо использования значения по умолчанию от socket.interCharTimeout:

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

Если вы сможете решить свою проблему с помощью этого решения, вы сможете уменьшить накладные расходы на ваше устройство, читая 28 регистров, которые вы хотите за один раз.

Если ваша проблема не решена, я думаю, у вас может быть аппаратная проблема. Я бы посоветовал вам отложить ваш код на некоторое время и попробовать читать регистры с помощью QModMaster или чего-то подобного чтобы убедиться, что ваше оборудование работает должным образом. (у вас могут быть проблемы с шумом или заземлением, которые сокращают ваши кадры, если вам нужны некоторые указатели на этом фронте, отредактируйте свой вопрос, включив в него более подробную информацию о вашем оборудовании, то есть: тип устройств и способ их подключения).

person Marcos G.    schedule 19.06.2019
comment
Это лучшие исправления, всего одна строчка! Я рад, что это сработало. - person Marcos G.; 19.06.2019
comment
У меня было много проблем, очень похожих на эту, но это решение не помогло. Затем я наткнулся на похожее решение, которое сработало для меня, в комментарии к багтрекеру PyModbus. - мне только пришлось использовать другой тайм-аут между символами: client.inter_char_timeout = 0.05 - person fsteff; 24.11.2020