Modbus Kommunikation

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Bonze
User
Beiträge: 2
Registriert: Donnerstag 20. November 2014, 19:22

Hallo,

ich versuche mit Hilfe der http://mblogic.sourceforge.net/mblibs/simpleclient.html Modbus Lib eine verbindung zu meiner Beckhoff BC9100 PLC herzustellen. Diese unterstützt das Modbus TCP Protokoll schon von Haus aus.
Das Anfragen der Inputs/outputs gelingt schon sehr gut, somit kann ich zumindest schonmal den Status lesen.

Code: Alles auswählen

host = '192.168.178.24'
port = 502
timeout = 10.5
TransID = 1
UnitID = 1 #wird ignoriert, uebernimmt TCP/IP'
FunctionCode = 3 #1 gesetze Outs, 2 belegte INs, 3 PEW/PAW +MW (Read), 4 PEW read, 5 PAW write (1Byte only!), 15 write Outs,
Addr = 0 #start adresse
Qty = 2
client = Modbus.ModbusTCPSimpleClient(host, port, timeout) ##verbindung oeffnen
client.SendRequest(TransID, UnitID, FunctionCode, Addr, Qty)
ergebnis = client.ReceiveResponse()
print("IP ",host," Funktion ", FunctionCode," Adresse ", Addr, " ByteAnzahl", Qty)
Jedoch würde ich gerne auch ausgänge schreiben, doch das funktioniert nicht richtig- bzw. gar nicht.

Code: Alles auswählen

daten = (255,255,255)
senden = Utilities.intlist2bin(daten)
client = Modbus.ModbusTCPSimpleClient(host, port, timeout) ##verbindung oeffnen
#                                 Funktion, Adresse, Laenge, Daten
client.SendRequest(TransID, UnitID, 15 ,     0,       3,    senden)
lasse ich mir den Request ausgeben, erhalte ich das hier.
b'\x00\x01\x00\x00\x00\r\x00\x01\x00\x0f\x00\x00\x00\x03\x00\x06\x00\xff\x00\xff\x00\xff'
das r duerfte darin eigentlich gar nicht vorkommen, der rest der Daten stimmt.

hiermit wird der Code erzeugt.

Code: Alles auswählen

	########################################################
	def MBRequest(self, TransID, UnitID, FunctionCode, Addr, Qty, MsgData=None):
		"""Make a modbus client request message.
        Parameters:
            TransID (integer) = Transaction ID.
            UnitID (integer) = Unit ID.
            FunctionCode (integer) = Function code.
            Addr (integer) = Data address.
            Qty (integer) = Number of addresses to read or write.
            MsgData (binary string) = Data in Modbus binary string
                format. Valid data is required for functions
                5, 6, 15, and 16. For 1, 2, 3, and 4, this
                parameter is optional.
        If the function code is not supported, a ParamError exception will be
            returned. Invalid data will cause an exception to be raised.
        Returns (string) = A packed binary string of bytes containing the
            Modbus/TCP message.
        """

		# Read coils or registers. MBAP length is fixed at 6.
		if FunctionCode in (1, 2, 3, 4):
			return struct.pack('>HHHBBHH', TransID, 0, 6, UnitID,
							   FunctionCode, Addr, Qty)

		# Write single coil or register. MBAP length is fixed at 6.
		elif FunctionCode in (5, 6):
			# Construct message.
			return struct.pack('>HHHBBH2s', TransID, 0, 6, UnitID,
							   FunctionCode, Addr, MsgData)

		# Write multiple coils or registers. MBAP length is variable.
		elif FunctionCode in (15, 16):
			# Construct message.
			count = len(MsgData)
			# MBAP length parameter is size of PDU plus unitid.
			return struct.pack('>HHHHHHHH %ds' % count, TransID, 0, count + 7, UnitID,
							   FunctionCode, Addr, Qty, count, MsgData)

		# Function code is not supported.
		else:
			raise ParamError  # ,'Function code not supported'

BlackJack

@Bonze: Warum dürfte '\r' darin nicht vorkommen? Dir ist klar dass das ein Byte mit dem Wert 13 (0x0d in Hexadezimal) ist?
Bonze
User
Beiträge: 2
Registriert: Donnerstag 20. November 2014, 19:22

mhh :D
das kann natuerlich sein :D
das Problem welches ich habe ist, dass die PLC immer eine Fehlermeldung zurueckgibt , welche besagt das die Adresse nicht stimmen wuerde;
eigentlich kann das nicht sein, da ich mich an die Angaben des Hersteller bei den Adressen halte.
Deshalb denke ich, dass der Sendesyntax nen Fehler enthaelt.

Hier die Angaben des Herstellers bzw. NachrichtenKopf
ModbusTCP-Protokoll
Byte Name Beschreibung
0 Transaction identifier wird vom Slave zurückgesendet
1 Transaction identifier wird vom Slave zurückgesendet
2 Protocol identifier immer 0
3 Protocol identifier immer 0
4 Length field 0 (wenn die Nachricht kleiner 256 Byte ist)
5 Length field Anzahl der folgenden Bytes
6 UNIT identtifier wird vom Slave zurückgegeben
7 Modbus es folgt das Modbus-Protokoll beginnend mit der Funktion
+
8 Functionscode
? Nachricht
Antworten