Die vollständige Antwort, die über RS-485 von einem Modbus-Gerät übernimmt, kann nicht gelesen werdenPython

Python-Programme
Anonymous
 Die vollständige Antwort, die über RS-485 von einem Modbus-Gerät übernimmt, kann nicht gelesen werden

Post by Anonymous »

Ich habe versucht, mit einem I-7000 IO-Modulgerät zu kommunizieren, das Modbus unterstützt. Im Allgemeinen kann ich erfolgreich Befehle wie das Schreiben an eine Spule oder das Lesen einer Spule senden, aber ich muss mit einem Problem konfrontiert werden - ich kann die Antwort aus dem IO -Modulgerät nicht lesen, zumindest nicht jedes Mal. Ich verwende pyserial und erwarte 6 Bytes, die mit einer bestimmten Bestellung zurückgegeben wurden, aber die Nachricht nicht richtig lese. Jede Meldung verfügt am Ende über eine Geräte -ID, einen Funktionscode, eine Spulenadresse, einen Wert und eine CRC -Nachricht. Meistens kann ich die CRC -Nachricht am Ende nur lesen und manchmal kann ich einige der anderen Bytes vorher lesen. Selten kann ich die gesamte Nachricht lesen.

Code: Select all

import serial
import time
import crcmod.predefined

# Function to calculate Modbus RTU CRC
def calculate_rs_485_crc(message):
crc16 = crcmod.predefined.mkCrcFun("modbus")
return crc16(message)

port = "/dev/ttyS0"
baudrate = 115200
timeout = 1

ser = serial.Serial(
port,
baudrate,
timeout=timeout,
parity=serial.PARITY_NONE,
)

# Construct Modbus RTU command
message = "020100060001"
command = bytes.fromhex(message)
crc = calculate_rs_485_crc(command)
command_with_crc = command + crc.to_bytes(2, "little")

print(f"Sent: {command_with_crc.hex()}")
ser.write(command_with_crc)

byteData = ser.read_until(b"\xcc")

print(f"byteData: {byteData}")

ser.close()
< /code>
Ich habe Baudrate und den Port überprüft, sie sind in Ordnung. Was auch immer ich mir vorstellen, das Ergebnis ist das gleiche. Ich habe versucht, eine Zeit zu setzen. Wenn ich zumindest keine Schlafzeit habe, erhalten Sie einige Teile der Nachricht. < /P>
Dies ist mein Terminal, an dem ich sehe, was gedruckt wird. Manchmal empfangen Sie das Ende der Nachricht (CRC -Bytes):

Sent: 0201000600011df8< /code>

byteData: b'Q\xcc'

Und manchmal kann ich die tatsächlich erwartete Nachricht sehen. Oder manchmal auch etwas dazwischen.

Code: Select all

Sent: 0201000600011df8< /code>

byteData: b'\x02\x01\x01\x00Q\xcc'

Außerdem können Sie im Code Read_until verwenden, aber ich habe versucht, Readline zu verwenden und einfach zu lesen, indem ich die Anzahl der Bytes angibt, die ich zu lesen habe, aber keine davon geholfen hat. Gleiches Ergebnis. Ich bin mir nicht sicher, warum diese Inkonsistenz geschieht. Die meisten meiner Online -Lese -Online -Probleme zeigen Zeitprobleme oder Hardwareprobleme, aber es sind definitiv keine Hardwareprobleme, da ich einige andere Tools verwendet habe, die vom Hersteller bereitgestellt werden, um mit diesem Gerät zu sprechen, und es hat gut funktioniert. Wenn es sich um ein Timing -Problem handelt, verstehe ich nicht, wie es so ist, denn wenn ich etwas Zeit in den Schlaf stelle, um sicherzustellen, dass jedes Stück der Nachricht eingetroffen ist, bekomme ich nichts.
Ich hoffe, Sie können mir helfen.

Code: Select all

user@localhost:~$ sudo mbpoll -m rtu -b 115200 -d 8 -s 1 -p none /dev/ttyS0 -a 2 -r 1 -1 -t 0
mbpoll 1.0-0 - FieldTalk(tm) Modbus(R) Master Simulator
Copyright © 2015-2019 Pascal JEAN, https://github.com/epsilonrt/mbpoll
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions; type 'mbpoll -w' for details.

Protocol configuration: Modbus RTU
Slave configuration...: address = [2]
start reference = 1, count = 1
Communication.........: /dev/ttyS0,     115200-8E1
t/o 1.00 s, poll rate 1000 ms
Data type.............: discrete output (coil)

-- Polling slave 2...
Read discrete output (coil) failed: Connection timed out
< /code>
Bearbeiten #2: Importierte eine Funktion < /p>
Ich habe diesen anderen Code, der so gut wie dasselbe tut, nur in einer Funktion. Ich habe diese Funktion in meinem Code genannt, den Sie oben sehen können, und dann funktioniert alles in Ordnung. Ich bin mir nicht wirklich sicher warum.  Aber das ist immer noch keine gute Lösung, da ich zwei serielle Portinstanzen erstelle und beide schreiben und lesen: < /p>
import serial
import time
import logging
import os
import crcmod.predefined

logger = logging.getLogger(__name__)

def send_over_rs485(message: str, max_attempts=3):
attempts = 0
while attempts < max_attempts:
try:
ser = serial.Serial("/dev/ttyS0", 115200, timeout=0.3)

command = bytes.fromhex(message)
crc = calculate_rs_485_crc(command)
command_with_crc = command + crc.to_bytes(2, "little")

ser.write(command_with_crc)

time.sleep(0.2)

if ser.in_waiting:
response = ser.readline()
return response.hex()
else:
# print("No response available in rs-485 serial buffer.")
logging.debug("No response available rs-485 in serial buffer.")

except serial.SerialException as e:
logging.error(f"Serial communication error: {e}")
except OSError as e:
logging.error(f"OS-level communication error: {e}")
except Exception as e:
logging.error(f"Unexpected error: {e}")
finally:
if "ser" in locals() and ser.is_open:
ser.close()
attempts += 1

logging.warning(f"Reached maximum attempts without success: {attempts}")
return None

# Function to calculate Modbus RTU CRC
def calculate_rs_485_crc(message):
crc16 = crcmod.predefined.mkCrcFun("modbus")
return crc16(message)
< /code>
Dieser Funktion importiere und rufe meinen Code so an: < /p>
import serial
import time
import crcmod.predefined
# NOTE: IMPORTED FUNCTION HERE
from serial_protocol import send_over_rs485 # NOTE: it worked only because of this

# Function to calculate Modbus RTU CRC
def calculate_rs_485_crc(message):
crc16 = crcmod.predefined.mkCrcFun("modbus")
return crc16(message)

port = "/dev/ttyS0"
baudrate = 115200
timeout = 1

ser = serial.Serial(
port,
baudrate,
timeout=timeout,
parity=serial.PARITY_NONE,
)

# Construct Modbus RTU command
message = "020100060001"
# NOTE: CALLED FUNCTION HERE
# NOTE: This somehow makes it work:
send_over_rs485(message)

command = bytes.fromhex(message)
crc = calculate_rs_485_crc(command)
command_with_crc = command + crc.to_bytes(2, "little")

print(f"Sent: {command_with_crc.hex()}")
ser.write(command_with_crc)

byteData = ser.read_until(b"\xcc")

print(f"byteData: {byteData}")

ser.close()
< /code>
Mit dieser Änderung, die ich nicht verstehe, erhalte ich die vollständige Antwort. Hoffentlich können Sie mir helfen, zu verstehen, warum. < /P>
Antwort: < /p>
Sent: 0201000600011df8
in waiting false 0
byteData: b'\x02\x01\x01\x00Q\xcc'
< /code>
Bearbeiten Nr. 3: Eigentlich war es nicht die Send_Over_rs485, die es möglich ermöglichte, zu arbeiten, aber ich konnte es funktionieren, wenn ich den Socket erstelle, dann lesen, dann den Socket schließen, dann den Socket erstellen und schreiben und erneut lesen und dann funktioniert es. Das zweite Mal. Ich verstehe nicht warum.  Hier ist der aktualisierte Code: < /p>
import serial
import time
import crcmod.predefined

# Function to calculate Modbus RTU CRC
def calculate_rs_485_crc(message):
crc16 = crcmod.predefined.mkCrcFun("modbus")
return crc16(message)

def setup_serial_port() -> serial.Serial:

port = "/dev/ttyS0"
baudrate = 115200
timeout = 0.3

ser = serial.Serial(
port=port,
baudrate=baudrate ,
bytesize=serial.EIGHTBITS,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
timeout=timeout
)

return ser

# Construct Modbus RTU command
message = "020100060001"

command = bytes.fromhex(message)
crc = calculate_rs_485_crc(command)
command_with_crc = command + crc.to_bytes(2, "little")

ser = setup_serial_port()

print(f"Sent: {command_with_crc}")
ser.write(command_with_crc)
time.sleep(0.2)
byteData = ser.read(6)
print(f"byteData: {byteData}")

ser.close()

ser = setup_serial_port()

print(f"Sent: {command_with_crc}")
ser.write(command_with_crc)
time.sleep(0.5)  # Short delay to ensure the response is available

if ser.in_waiting:
print(f"in waiting {ser.in_waiting}")
else:
print(f"in waiting false {ser.in_waiting}")
byteData = ser.read(6)

print(f"byteData: {byteData}")

ser.close()

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post