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'
にスリープを入れてみたので、デバイスが通話で崩壊することはありませんが、どちらの方法でも取得できます。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でトレースをアクティブにする方法がわかりません。関数は正しく、もう1つは使用していないライブラリ用です。
コードはこのように見えます
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)
私は問題を回避する方法が欲しいです、多分私が正しい答えを得るまでもう一度相談するだけです。私は試してみるのが苦手で、他の人を除いて答えがあるかもしれません。
ただし、簡単な回避策があります。まず、pymodbusバージョン2.2.0を使用していることを確認します(pip list
パスが正しく設定されている場合は、Windowsでコマンドラインターミナルを開いて入力します。それ以外の場合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仕様に従って、デフォルトのfrom socket.interCharTimeout
:を使用する代わりに、選択したボーレートでのビット時間の1.5倍に文字間隔が定義されます。
self._t0 = float((1 + 8 + 2)) / self.baudrate
self.inter_char_timeout = 1.5 * self._t0
このソリューションで問題を修正できれば、必要な28個のレジスタを一度に読み取るデバイスのオーバーヘッドを減らすことができるはずです。
問題が解決しない場合は、ハードウェアに問題がある可能性があります。コードをしばらく脇に置いて、QModMasterなどでレジスターを読み取って、ハードウェアが意図したとおりに動作していることを確認することをお勧めします。(フレームを短くするノイズや接地の問題が発生する可能性があります。前面にいくつかのポインタが必要な場合は、質問を編集して、ハードウェアの詳細(デバイスの種類と接続方法など)を含めてください)。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加