TIA s7-1500 und Modbus over TCP

vollmi

Level-3
Beiträge
5.435
Reaktionspunkte
1.409
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi

Ich versuche grade eine Modbusverbindung zu mehreren Servern aufzubauen.
Die S7-1500 bringt ja einen Modbustreiber mit. Mit dem habe ich auch schon erfolgreich eine Verbinung zu EINEM Server aufgebaut. Jetzt habe ich aber deren 5 und wollte das einfach für jeden Server Instanzieren.
Das hat aber nicht so wirklich geklappt, der Erste hat die Daten immer gebracht die Nächsten blieben einfach auf 0.

Dann habe ich es jetzt so gemacht dass ich nur einen Treiber Starte und die Verbindung nach done oder error kappe und zum nächsten aufbaue. Macht aber die ganze Sache unnötig komplex.

Hat schonmal jemand mehrere Instanzen des MB_Client paralell erfolgreich laufen lassen?
Mich irritiert etwas die Aussage in der Hilfe.

REQ schrieb:
Kommunikationsanfrage mit dem Modbus TCP-ServerDer Paramter REQ ist pegelgesteuert. Das heißt, solange der Eingang gesetzt ist (REQ=true), sendet die Anweisung Kommunikationsanfragen.

  • Mit der Kommunikationsanfrage wird der Instanz-DB für andere Clients gesperrt.
  • Änderungen an den Eingangsparametern wirken sich erst aus, wenn eine Antwort des Servers erfolgt ist oder eine Fehlermeldung ausgegeben wurde.
  • Wird während einer laufenden Modbus-Anfrage der Parameter REQ erneut gesetzt, wird im Anschluss keine weitere Übertragung durchgeführt.

Heisst das ich muss mit den anderen Instanzen auswerten ob schon eine fremdinstanz aktiv ist und mit dem Req warten? Das wird ja richtig übel wenn man dann diverse aktive Verbindungen gegeneinander verriegeln muss und mit einer Statemaschine jede einzelne Kommunikationsanfrage ankicken muss.
Wozu dann überhaupt mehrere Verbindungen projektieren. Dann kann man sie auch ab und aufbauen.

Ich hätte gerne mehrere MB_Clienten Instanziert und nur für sich abgearbeitet. Das heisst es laufen mehrere IDs paralell.
Halt wie wenn man BSEND/BRECV auf mehreren Verbindungen laufen lässt. Die laufen ja auch paralell gleichzeitig ohne gegeneinander verriegelt zu sein.

mfG René
 
Hallo René,

ich kenne mich da nicht aus, doch aus der Beschreibung des MB_Client entnehme ich, daß man für jede Verbindung eine eigene Instanz des MB_Client braucht, wobei der MB_Client offenbar nicht multiinstanzfähig ist, sondern einen eigenen IDB braucht. Weiters braucht man für jede Verbindung eine eigene Verbindungsbeschreibungs-Struktur an CONNECT mit eindeutiger/verschiedener Verbindungs-ID.
V13.0 Systemhandbuch schrieb:
Bei einzelnen Client-Verbindungen müssen Sie folgende Regeln beachten:
● Jede "MB_CLIENT"-Verbindung muss einen eindeutigen Instanz-DB verwenden.
● Für jede "MB_CLIENT"-Verbindung muss eine eindeutige IP-Adresse des Servers
spezifiziert sein.
● Jede "MB_CLIENT"-Verbindung benötigt eine eindeutige Verbindungs-ID.
Die einzelne Verbindungs-ID muss jeweils für jeden einzelnen Instanz-DB der Anweisung
verwendet werden. Verbindungs-ID und Instanz-DB gehören jeweils paarweise zusammen
und müssen für jede Verbindung eindeutig sein.

Harald
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Dann muss ich das mit zwei instanzen nochmal ausprobieren. Ich hab den MB_Client nämlich in einer eigenen Instanz laufen lassen. Aber zusammen sind sie dann trotzdem nicht gelaufen.

mfg René
 
So hab noch etwas rumprobiert.
Das ist mal ein erster Wurf. Diesen Baustein habe ich 5 mal instanziert in einer Multiinstanz eines optimierten FBs.
Der FB selbst ist ja nicht optimiert (wegen AT Überlagerung)

Code:
FUNCTION_BLOCK "Modbus_Diris"{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
   VAR_INPUT 
      ID : Word;
   END_VAR


   VAR_OUTPUT 
      Energy { S7_HMI_Accessible := 'False'; S7_HMI_Visible := 'False'} : "DirisA41_C550_Table";
   END_VAR


   VAR 
      MB_CLIENT {OriginalPartName := 'MB_CLIENT_FB_1084_S71500'; LibVersion := '4.0'} : MB_CLIENT;
      LDB_Config {OriginalPartName := 'TCON_Configured'; LibVersion := '1.0'} : TCON_Configured;
      Req : Bool;
      Disconnect : Bool;
      IEC_Timer_0_Instance {OriginalPartName := 'IEC_TIMER'; LibVersion := '1.0'} : TON_TIME;
      IEC_Timer_0_Instance_1 {OriginalPartName := 'IEC_TIMER'; LibVersion := '1.0'} : TON_TIME;
      Zaehler : Int;
      F_TRIG_Instance {OriginalPartName := 'F_TRIG_1500'; LibVersion := '1.0'} : F_TRIG;
      R_TRIG_error {OriginalPartName := 'R_TRIG_1500'; LibVersion := '1.0'} : R_TRIG;
      R_TRIG_Done {OriginalPartName := 'R_TRIG_1500'; LibVersion := '1.0'} : R_TRIG;
      AktuellerLDB : Int;
      Status_Save : Word;
      Config_Save {OriginalPartName := 'TCON_Configured'; LibVersion := '1.0'} : Array[0..100] of TCON_Configured;
      ReqTrigger {OriginalPartName := 'R_TRIG_1500'; LibVersion := '1.0'} : R_TRIG;
      Daten : Array[0..50] of Int;
      strDaten { S7_HMI_Accessible := 'False'; S7_HMI_Visible := 'False'} AT Daten : "DirisA41_C550_Table";
   END_VAR


   VAR_TEMP 
      index : Int;
      RET_val : Int;
   END_VAR


   VAR CONSTANT 
      Datenlänge : UInt := 20;
   END_VAR




BEGIN
	        #LDB_Config.ConnectionType := 254;
	        #LDB_Config.InterfaceId := 100;
	        #LDB_Config.ID := #ID;
	        
	#MB_CLIENT(REQ := #Req,
	           DISCONNECT := false,
	           MB_MODE := 0,
	           MB_DATA_ADDR := 40001,
	           MB_DATA_LEN := #Datenlänge,
	           MB_DATA_PTR := #Daten,
	           CONNECT := #LDB_Config);
	
	#Energy := #strDaten;
	
	
	
	#Req := true;
	 
	#R_TRIG_error(CLK:=#MB_CLIENT.ERROR);
	#R_TRIG_Done(CLK:=#MB_CLIENT.DONE);
	
	
	
	IF #R_TRIG_Done.Q OR #R_TRIG_error.Q OR #IEC_Timer_0_Instance.Q THEN
	    #Req := false;
	END_IF;
	
	#IEC_Timer_0_Instance(IN:=#Req,
	                      PT:=t#10s);
	
	IF #IEC_Timer_0_Instance.Q THEN
	        #Req := false;
	END_IF;
	
	IF #MB_CLIENT.ERROR THEN
	    #Status_Save := #MB_CLIENT.STATUS;
	    
	END_IF;
END_FUNCTION_BLOCK

Ich schreibe die Daten also erstmal in einen Statischen Bereich der eigenen Instanz und kopiere sie dann auf die Schnittstelle.

In der Hilfe zum modbus Baustein steht aber das es zwingend ein globaler DB mit optimiertem Zugrif sein muss. Funktioniert aber auch mit einem nicht optimierten Zugriff in einer Instanz.

Zeiger auf das Modbus-Datenregister: Das Register ist ein Puffer für die vom Modbus-Server empfangenen oder zum Modbus-Server zu sendenden Daten. Der Zeiger muss auf einen globalen Datenbaustein mit optimiertem Zugriff verweisen.
Die Anzahl der Bits, die adressiert werden, muss durch 8 teilbar sein.

Da sieht man mal wieder, die Bausteine programmiert sicher jemand der noch nie ein Wort mit dem Dokuschreiber gesprochen bzw gemailt hat. Ich bezweifle auch dass die dieselbe Sprache sprechen.

mfG René
 
In der Hilfe zum modbus Baustein steht aber das es zwingend ein globaler DB mit optimiertem Zugrif sein muss. Funktioniert aber auch mit einem nicht optimierten Zugriff in einer Instanz.
Oh, interessant.

Hatte mich nämlich auch schon gefragt wie man am vernünftig (blockweise) von einem optimierten Array_of_WORD des Empfangspuffers in einen optimierten Struct im Zieldatenbereich kopieren soll? Dafür geht keiner der MOVE-Befehle. Nicht optimiert ginge der zumindest SFC20 oder AT.
 
Zuletzt bearbeitet:
Zurück
Oben