Modbuskommunikation zwischen 2 Wago Steuerungen

MW22

Level-1
Beiträge
40
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,

ich versuche gerade, eine Modbuskommunikation zwischen 2 CPU zu verstehen / realisieren. Leider habe ich keine
Wago Controller um dies zu testen.
Ich würde gerne Daten vom Typ: Time/real/bool/int von den jeweiligen Steuerungen lesen können.
Mein Ansatz ist:
Auf der CPUA (Master) habe ich den Ethernet_modbusmaster_tcp erstellt.

VAR

fbMaster_schreiben :ETHERNET_MODBUSMASTER_TCP;
xVerbinden_Schreiben : BOOL:=TRUE;
strIP_SPS_UPS_A : STRING := '192.168.2.12';
typMasterAnSlaveSchreiben: arComCPU;
dwadrText: DWORD;
xSendTrigger: BOOL; (*geht automatisch auf False wenn fertig*)
tWarteZeit: TIME := t#100ms;
fbZyklischAbfragen: TON;
xIstVerbunden: BOOL;
wError: WORD;
bID: BYTE;

END_VAR

1650371292984.png
Dazu habe ich ein Struct erstellt:

TYPE arComCPU :
STRUCT



xBatteryRelayA :BOOL ;
xBatteryRelayB :BOOL ;

xDCDBRelayA :BOOL ; (* Rückmeldebit *)
xDCDBRelayB :BOOL ; (* Rückmeldebit *)


rChargerVoltage_A :REAL ;
rChargerVoltage_B :REAL ;
rLoadCurrent_A :REAL ;
rLoadCurrent_B :REAL ;

xNextBatteryChange :BOOL ;

END_STRUCT
END_TYPE

Wenn ich nun auf der Slave Seite das gleiche Struct erstelle kommunizieren die dann schon miteinander?

Die Structvariablen habe ich einerseits auf der A und andererseits auf der B eine feste Adresse gegeben (MX x.y / MD x ).

MfG

MW22
 
Hallo MW22
bitte beim nächsten mal Controller & Software angeben.
Ich denke mal es handelt sich um Codesys 2.3 und ein 750-8xx Controller.
Wenn ich nun auf der Slave Seite das gleiche Struct erstelle kommunizieren die dann schon miteinander?
Dem Master ist es völlig Wurst ob im Slave ein Struct definiert ist.
Dein Programm schreibt in den Slave ab Adresse %MW0 - 9 Worte an Daten aus der VAriable "typMasterAnSlaveSchreiben"
.
PS:
ich würde die einzelnen Bool in einem Wort zusammenfassen.
PSS: die Zyklische Abfrage mit xSendTrigger funktioniert so nicht. Die Variable soll vom FB auf False gesetzt werden um das Ende der Funktion zu kennzeichnen. In deinem Programm schreibst du die Variable im nächsten Zyklus auf False.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich denke mal es handelt sich um Codesys 2.3 und ein 750-8xx Controller.
Ja genau. codesys 2.3 und 750-890
Dem Master ist es völlig Wurst ob im Slave ein Struct definiert ist.
Dein Programm schreibt in den Slave ab Adresse %MW0 - 9 Worte an Daten aus der VAriable "typMasterAnSlaveSchreiben"
.
Das heist:
Wenn ich im master struct zb xBatteryRelayA :BOOL ; drin habe.
xBatteryRelayA habe ich mit AT %MX81.0 Definiert.
Dann kann ich am Slave unter MX81.0 den wert auslesen? Habe ich das richtig verstanden?
PSS: die Zyklische Abfrage mit xSendTrigger funktioniert so nicht. Die Variable soll vom FB auf False gesetzt werden um das Ende der Funktion zu kennzeichnen. In deinem Programm schreibst du die Variable im nächsten Zyklus auf False.
Ok und wie mache ich das... ?
Den Programmcode habe ich nur kopiert von einer Wagoschulung. Der hatte dies damals so gemacht.
 
Die zyklische Abfrage ist sicher.
Der Timer fbZyklischeAbfrage zählt doch nur, wenn keine Anfrage aktiv ist (xSendTrigger = FALSE) denn der Eingang ist negiert.
Zur Sicherheit wurde ich noch xIstVerbunden UND verknüpfen. Eventuell sogar noch negiert den Timer Ausgang. Im ungünstigen Timingfall wird sonst xSendTrigger dauerhaft auf TRUE gesetzt.

Ich würde die Struktur typMasterAnSlaveSchreiben sowohl im Master wie auch im Slave nutzen.
Im Slave die Struktur auf das Merkerwort 0 mappen. Dann werden die Daten 1 zu 1 ausgetauscht und niemand muss sich darum kümmern wo diese liegen.
Dies sollte auch mit diesem Beispiel besprochen worden sein.

Grüße
 
Die zyklische Abfrage ist sicher.

Code:
xXTrigger = False
-> es läuft die Wartezeit
durch den Ton xTrigger = True
-> das senden wird angestoßen
im selber Zyklus
Bedingung von Ton nicht erfüllt da xTrigger = True (Bedingung negiert)
der Ton setzt xTrigger = False
das löschen des Triggers sollte aber durch den Modbus Bausteine erfolgen
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Dann werden die Daten 1 zu 1 ausgetauscht und niemand muss sich darum kümmern wo diese liegen
Auch das ist nur bedingt richtig.
Wenn ich nicht weis wo meine Daten liegen kann ich auch kein vollständiges Abbild senden.
Die Bool werden zu Byte. Mein Real hat 4 Byte.
Damit ist die zu senden Länge viel zu kurz mit 9 Worten
Die Struktur hat zum Senden 21 Byte -> wird aufgefüllt auf 22 Byte.
Damit ist mein vollständiges Abbild 11 Worte groß.
 
Ich sehe da nur eine CFC Zeichnung und der Ausgang des Timers setzt das Bit nur. Im Code wird dieses nicht zurückgesetzt.

Und wenn auf dem Master und den Slave die gleiche Struktur verwendet wird muss nichts beachtet werden.
Denn ein BOOL ist dann auf beiden Steuerungen ein Byte groß.
Natürlich muss die ganze Struktur übertragen werden. Dies sollte jedoch schnell auffallen.
 
Damit ist die zu senden Länge viel zu kurz mit 9 Worten
Die Struktur hat zum Senden 21 Byte -> wird aufgefüllt auf 22 Byte.
Damit ist mein vollständiges Abbild 11 Worte groß.
Ja solangsam verstehe ich wie es funktioniert.
Mal ne Dumme Frage:
Könnte ich auch mein Offset bei 12288 anfangen lassen und zb. 200 Worte durchlaufen lassen.
In der Variablenliste deklariere ich:
test1 At%MD0;
test2 At%MD10;
test3 At%MD20;
wenn ich dann zb. in meinen Struct drin stehen habe:
test1
test2
test3

bekomme ich dann in Slave die richtigen werte von MD0/10/20 oder stehen
die Werte in MD0/1/2 drinne?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Könnte ich auch mein Offset bei 12288 anfangen lassen und zb. 200 Worte durchlaufen lassen.
So ganz verstehe ich deine Frage nicht
Dein Slave stellt einen Speicher für externe Geräte zur Verfügung. Dieser beginnt bei Adresse 12288. Damit Codesys auf diesen Speicher zugreifen kann wird er ab %MW0 für Codesys abgebildet.
Mit Modbus ist das Lesen/Schreiben von maximal 125 Worte in einem Aufruf möglich. Wenn du also 200 Worte lesen/schreiben möchstest sind mindestens 2 Aufrufe nötig.

Die einfachste Art der Kommunikation ist wie bereits Tobsucht erwähnt hat einen Struct aufzubauen und diesen auf beiden Steuerungen zu verwenden.
Code:
TYPE st_Kommunikation :
STRUCT
    rVar1     : REAL;
    rVar2     : REAL;
    diVar1     : DINT;
    iVar1     : INT;
    by_Var1 : BYTE;
    xVar1     : BOOL;
END_STRUCT
END_TYPE
Hier ist lediglich zu beachten von großen nach kleinen Datentypen zu definieren um die Erzeugung von Füllbyte zu vermeiden und das Datentypen mit 2 oder mehr Byte nicht auf einem Halbbyte landen.
Code:
typDatenaustausch AT %MW0 : st_Kommunikation;
Deine Variable definierst du auf beiden Steuerungen auf der gleichen Adresse (als Beispiel hier %MW0)
Jetzt kannst du symbolisch oder auch direkt über die Adresse auf die Variablen zugreifen.
Das einzige was du tun musst ist die Länge der Variable berechnen um sie an dem Masterbaustein anzugeben.
 
Ok das habe ich weitgehenst verstanden. Wenn ich also
typDatenaustausch AT %MW1000 : st_Kommunikation; angebe dann fängt die erste Struct variable bei MW1000
an ohne diese in der Variablentabelle als Test AT% MD500:Real; deklariert zu haben.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich habe soeben 2 Steuerungen ausgeliehen bekommen. Ich habe nun 2 Projekte erstellt mit versuchsvariablen.

Ich habe nun mal die Variante versucht, über Steuerungsconfig -> Modbusmaster -> slave anlegen und Variablen deklariert welche
geschrieben und gelesen werden. Gibt es hierfür irgendwelche Nachteile?
Weil das ist ja super einfach und schnell gemacht + mein Baustein wird ja einfach generiert.
 
Zuletzt bearbeitet:
typDatenaustausch AT %MW1000 : st_Kommunikation; angebe dann fängt die erste Struct variable bei MW1000
genau. Das erste Byte deiner Struktur wird dann auf %MW1000 Low Byte gelegt. Alle anderen Variablen werden danach eingereiht. Im Hintergrund werden schon alle Variablen per AT auf Adressen gemappt. Codesys zeigt es halt nicht an.
Wenn du nur einen symbolischen und keinen absoluten Zugriff im ControllerB bauchst kannst du die Länge auch wie KLM schrieb berechnen lassen.
 
Zurück
Oben