Frage zu Wago 750 Feldbuscontroller - Modbus Verständnisfrage

Hölligma

Level-1
Beiträge
48
Reaktionspunkte
3
Zuviel Werbung?
-> Hier kostenlos registrieren
Moin,

kurze Frage zu Wago 750 in Kombination mit Modbus. Also ich habe mir ein Python Skript (pymodbus) geschrieben, um meine Wago 750 inkl. den I/O Modulen zu steuern.

Jetzt meine Frage, nach den Zugriffen auf die Register sowohl lesend als auch schreibend, setze ich ein Timeout von 10 ms. Weil ich festgestellt habe, dass es manchmal zu Problemen kommt, wenn direkt hintereinander auf Register zugegriffen wird. Warum ist das so, oder mache ich etwas falsch? Also nicht das dieses Timeout stört oder mein Skript unbrauchbar macht, allerdings wirft das eine weitere Frage auf.

Kann man gleichzeitig von verschiedenen Skripten oder auch mehreren Clients auf dieselben Register oder Coils der Wago zugreifen ohne das es zu Problemen käme? Ich bin leider noch nicht ausgiebig zum Testen gekommen und möchte das hier im Vorfeld geklärt habe.

Diese Frage ist für mich vor allem deswegen von Bedeutung, weil ich mit dem Wissen dann meine Softwareweiterentwicklung besser planen könnte. Müsste ich im Falle, dass ein simultaner Zugriff lesen und/oder schreiben nicht möglich ist, mein Skript mehr auf asyncrone I/O auslegen? Ob ich das mit timeouts dann so hinbekomme oder asyncio verwenden müsste, wird sich dann hoffentlich ergeben. Vielleicht hat in der Hinsicht jemand noch einen konkreten Tip oder kann mir Alternativen aufzeigen?

Ich würde mich sehr freuen, wenn sich jemand meldet, der mit Wago und Modbus mehr Erfahrung hat als ich. Danke im Voraus und schon mal schönes Wochenende gewünscht :)
 
ich kenne mich mit Wago nicht wirklich aus, würde aber über folgendes nachdenken:
Das auslesen separat erledigen und in einen Merkerbereich (Siemens DB) schreiben lassen.
Mit deinem Skript nur aus diesem Merkerbereich arbeiten, Ergebnisse daraus in einen anderen Merkerbereich schreiben
Von hier aus dann das Senden an Modbus anstoßen (nur geänderte Werte)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Im Handbuch findest Du die Information dass sich bis zu 15 Clients verbinden können. Es werden also bis zu 15 parallele TCP/IP Verbindungen auf den Port 502 unterstützt.
Wenn die Clients auf die gleichen Bereiche schreiben, gibt es natürlich Konflikte. Beim Lesen kann es zu keinen Konflikten kommen.

Edit: die 750er Serie ist groß, die Beschränkung auf 15 Verbindungen bezieht sich auf die Geräte der 2. bis 4. Generation.
 
ich kenne mich mit Wago nicht wirklich aus, würde aber über folgendes nachdenken:
Das auslesen separat erledigen und in einen Merkerbereich (Siemens DB) schreiben lassen.
Mit deinem Skript nur aus diesem Merkerbereich arbeiten, Ergebnisse daraus in einen anderen Merkerbereich schreiben
Von hier aus dann das Senden an Modbus anstoßen (nur geänderte Werte)

Hi, eine Siemens hab ich nicht, ist mehr so ein privates Projekt. Manche Zustände werden zusätzlich in eine MySQL Datenbank gespeichert, aber ich glaube, ich verstehe, was du meinst, eine Art I/O Buffer. Darüber will ich mal nachdenken, danke!

Im Handbuch findest Du die Information dass sich bis zu 15 Clients verbinden können. Es werden also bis zu 15 parallele TCP/IP Verbindungen auf den Port 502 unterstützt.
Wenn die Clients auf die gleichen Bereiche schreiben, gibt es natürlich Konflikte. Beim Lesen kann es zu keinen Konflikten kommen.

Edit: die 750er Serie ist groß, die Beschränkung auf 15 Verbindungen bezieht sich auf die Geräte der 2. bis 4. Generation.

Top, danke für die Info!
 
Jetzt meine Frage, nach den Zugriffen auf die Register sowohl lesend als auch schreibend, setze ich ein Timeout von 10 ms. Weil ich festgestellt habe, dass es manchmal zu Problemen kommt, wenn direkt hintereinander auf Register zugegriffen wird. Warum ist das so, oder mache ich etwas falsch? Also nicht das dieses Timeout stört oder mein Skript unbrauchbar macht, allerdings wirft das eine weitere Frage auf.

Kann man gleichzeitig von verschiedenen Skripten oder auch mehreren Clients auf dieselben Register oder Coils der Wago zugreifen ohne das es zu Problemen käme? Ich bin leider noch nicht ausgiebig zum Testen gekommen und möchte das hier im Vorfeld geklärt habe.

Diese Frage ist für mich vor allem deswegen von Bedeutung, weil ich mit dem Wissen dann meine Softwareweiterentwicklung besser planen könnte. Müsste ich im Falle, dass ein simultaner Zugriff lesen und/oder schreiben nicht möglich ist, mein Skript mehr auf asyncrone I/O auslegen? Ob ich das mit timeouts dann so hinbekomme oder asyncio verwenden müsste, wird sich dann hoffentlich ergeben. Vielleicht hat in der Hinsicht jemand noch einen konkreten Tip oder kann mir Alternativen aufzeigen?

Ich würde mich sehr freuen, wenn sich jemand meldet, der mit Wago und Modbus mehr Erfahrung hat als ich. Danke im Voraus und schon mal schönes Wochenende gewünscht :)

Modbus/TCP ist nur ein Protokollstack auf einer leistungsarmen Maschine - und 10 ms sind da schon sehr wenig Zeit. Das ist der Buszugriffszyklus. Wenn Du noch schneller zugreifst ist irgenwann der interne Puffer voll... Keine Ahnung was dann passiert, aber bestimmt was Unlustiges. Der wagoeigene Baustein hat Abarbeitungszeiten um dei 30 ms, wenn ich mich nicht irre.

Was meinst du mit "asynchronen I/O"? Ohne Änderung der Konfiguration sind die asynchron zur internen PLC.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
es manchmal zu Problemen kommt, wenn direkt hintereinander auf Register zugegriffen wird. ..., oder mache ich etwas falsch?
Du schreibst ja nicht direkt in die I/O sondern in den Speicher auf dem Kopf. Dieser wird wiederum durch das System über den K-Bus auf die Karten geschrieben. Hier Lese- oder Schreibzugriffe unter 10ms anzupeilen ist schon sehr sportlich.

Ich denke beim lesen & schreiben aus deinem Script heraus ist ordentlich Potential zur Verbesserung. Baue dein PA im Script als Block zusammen und übertrage den gesamten Speicherblock.
 
Was meinst du mit "asynchronen I/O"? Ohne Änderung der Konfiguration sind die asynchron zur internen PLC.

Danke, ah das bezieht sich auf das Programm bzw. Modbus, damit meine ich, dass ich das so programmieren muss, dass nicht lese und schreib Zugriffe zur gleichen Zeit auf dieselben Register passieren.
 
Danke, ah das bezieht sich auf das Programm bzw. Modbus, damit meine ich, dass ich das so programmieren muss, dass nicht lese und schreib Zugriffe zur gleichen Zeit auf dieselben Register passieren.

Na, das ist immer eine gute Idee. Das Protokoll ist sowieso seriell - tatsächlich gleichzeitig passiert da nix. Schreiben - warten - lesen. Ich würde nicht mal meine Hand dafür in's Feuer legen das die abgeschickten Befehle tatsächlich in der Reihenfolge abgearbeitet werden, in der du sie losschickts. Zurück zum Anfang: Du willst zu schnell etwas Geschriebenes zurücklesen od. revers. Übe dich in Geduld - wenigstens so 30 - 50 ms ;-)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Du schreibst ja nicht direkt in die I/O sondern in den Speicher auf dem Kopf. Dieser wird wiederum durch das System über den K-Bus auf die Karten geschrieben. Hier Lese- oder Schreibzugriffe unter 10ms anzupeilen ist schon sehr sportlich.

Ich denke beim lesen & schreiben aus deinem Script heraus ist ordentlich Potential zur Verbesserung. Baue dein PA im Script als Block zusammen und übertrage den gesamten Speicherblock.

Also es kommt darauf an, lesen sequenziell mit 10 ms Pause dazwischen waren bis jetzt kein Problem, was ich testen konnte. Beim Schreiben habe ich 100 ms Pause zwischen den Zugriffen.

Mein Skript ist aktuell so ausgelegt, dass nur in die Register geschrieben wird, wenn ein Benutzer auf einen Button drückt, also wenn ein Gerät über ein Relais zum Beispiel eingeschalten wird. Das geht schon mal eh nicht gleichzeitig, dass zwei Buttons gedrückt werden, und falls doch, ist ja das time.sleep(0.1) also der timeout so zu sagen als Sicherung da.

Es gibt abgesehen davon aber noch parallele Programmroutinen im Python Programm selbst. Und hier kann es durch Zufall, vorkommen, dass ein gleichzeitiger Zugriff stattfindet. An dem Punkt bin ich mir noch nicht sicher, ob dafür alleine nicht threading ausreichend ist. Ist jetzt vermutlich zu sehr Python spezifisch. Deswegen habe ich noch das mit Asyncio erwähnt, ich müsste das erst noch ausgiebig testen, weil besonders viele Informationen gibt es dazu nicht im Netz.

Meine ursprüngliche Frage, wie es bei der Wago mit simultanen Zugriffen aussieht, wäre denke ich beantwortet, vielen lieben Dank!
 
Zuletzt bearbeitet:
Na, das ist immer eine gute Idee. Das Protokoll ist sowieso seriell - tatsächlich gleichzeitig passiert da nix. Schreiben - warten - lesen. Ich würde nicht mal meine Hand dafür in's Feuer legen das die abgeschickten Befehle tatsächlich in der Reihenfolge abgearbeitet werden, in der du sie losschickts. Zurück zum Anfang: Du willst zu schnell etwas geschriebenes zurücklesen. Übe dich in Geduld - wenigstens so 30 - 50 ms ;-)

Ok, perfekt, danke für die Info! Das im Programm zu ändern, sollte kein Problem sein^^ Dann machen bei jeglichen Zugriffen 50 ms und bin auf der sicheren Seite.^^
 
mmroutinen im Python Programm selbst. Und hier kann es durch Zufall, vorkommen, dass ein gleichzeitiger Zugriff stattfindet. An dem Punkt bin ich mir noch nicht sicher, ob dafür alleine threading ausreicht. Ist jetzt vermutlich zu sehr Python spezifisch. Meine ursprüngliche Frage, wie es bei der Wago mit simultanen Zugriffen aussieht, wäre denke ich beantwortet, vielen lieben Dank!
Wenn das 1 Programm ist, dann wäre schon ein Abstraktionslevel für die Hardwarezugriffe ratsam. Mehrere Programme gehen auf der Wago dann auf die verschiedenen TCP/IP-Verbindungen --> eigene Stacks.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn das 1 Programm ist, dann wäre schon ein Abstraktionslevel für die Hardwarezugriffe ratsam. Mehrere Programme gehen auf der Wago dann auf die verschiedenen TCP/IP-Verbindungen --> eigene Stacks.
Im Moment 1 Programm und aktuell noch 1 Verbindung die Aufgebaut wird. Da läuft ein websocket und arbeitet alle I/O's ab, also sowohl für websocket client und server als auch modbus.

Zur Steuerung der Kühlung zum Beispiel läuft per Thread eine Coroutine, diese überwacht die bzw. vergleicht die Soll mit der Ist Temperatur und schaltet halt die Pumpe ein oder aus oder später meinetwegen schneller oder langsamer oder steuert den Wärmetauscer Lüfter usw...

Bis jetzt läuft es zwar besser als erwartet, keine Fehler, keine Abstürtze aber dennoch, will ich das so professionell wie möglich machen, und da bin ich bei meiner Recherche auf synchrone Programmierung gestoßen und das es da eben zu Problemen kommen kann.

Wie mache ich das mit dem Abstraktionslevel? Also was meinst du damit genau?
 
Im Moment 1 Programm und aktuell noch 1 Verbindung die Aufgebaut wird. Da läuft ein websocket und arbeitet alle I/O's ab, also sowohl für websocket client und server als auch modbus.

Das ist der Kommunikationspunkt, ja verstanden. Aber keine Zugriffsregelung. Normal setzt man EAV (Eingabe, Ausgabe, Verarbeitung) an; oft auch/ bzw. früher immer EVA-Prinzip (Eingabe, Verarbeitung, Ausgabe).

Wenn du das mit Threads/Coroutinen machst kommst du vmtl. aktuell auf vllt. sowas hier (T wie thread)

T1(E) T2(A) T3(EAVAV) T4(EE) - kann man natürlich auch machen, hat die potenziellen Probleme der schnellen Zugriffe, da die Threads "unabhängig" (je nach tatsächlicher Zielplatform) voneinander laufen.

Besser wäre: T1(EA) T2(V) T3(V) T4(V) - da ergibt sich die Abstraktion von allein, weil du eine Schnittstelle zu T1 brauchst. Und nur T1 braucht auf die Zeit zwischen den Zugriffen zu achten...

Ich hoffe das ist verständlich.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn's dann schon so komplex werden muss, dann werf ich mal das Stichwort Message-Queue oder Message-Bus in den Ring.

Danke für den Tipp, das schaue ich mir mal genauer an!

Auch wenn ich zu meinem aktuellen Kenntnisstand wohl die direkte, aber asynchrone (asyncio) Verarbeitung der Busbefehle präferiere... aber man kann nie wissen, so ein Tipp kann Goldwert sein, thx^^
 
Wenn das 1 Programm ist, dann wäre schon ein Abstraktionslevel für die Hardwarezugriffe ratsam. Mehrere Programme gehen auf der Wago dann auf die verschiedenen TCP/IP-Verbindungen --> eigene Stacks.

Ach jetzt glaube ich zu verstehen, was du meinst. Die KModbus Befehle quais auslagern in eine seperate Klasse oder Programm? Das finde ich eine gute Idee, vorausgesetzt, dass ich das richtig verstanden habe.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Das ist der Kommunikationspunkt, ja verstanden. Aber keine Zugriffsregelung. Normal setzt man EAV (Eingabe, Ausgabe, Verarbeitung) an; oft auch/ bzw. früher immer EVA-Prinzip (Eingabe, Verarbeitung, Ausgabe).

Wenn du das mit Threads/Coroutinen machst kommst du vmtl. aktuell auf vllt. sowas hier (T wie thread)

T1(E) T2(A) T3(EAVAV) T4(EE) - kann man natürlich auch machen, hat die potenziellen Probleme der schnellen Zugriffe, da die Threads "unabhängig" (je nach tatsächlicher Zielplatform) voneinander laufen.

Besser wäre: T1(EA) T2(V) T3(V) T4(V) - da ergibt sich die Abstraktion von allein, weil du eine Schnittstelle zu T1 brauchst. Und nur T1 braucht auf die Zeit zwischen den Zugriffen zu achten...

Ich hoffe das ist verständlich.

Ok, so ist es für mich besser verständlich, vielen lieben Dank.

Im Moment sieht es noch so aus, vereinfacht dargestellt:

T1(EAV)T2(AV)T3(EV)

Ich muss sehen wie ich das umsetze, ansonsten asyncio, damit lässt sich dieses Prinzip auch realisieren. Ich werde aber deine Idee mir auch noch mal genauer ansehen, dazu will ich mir etwas Zeit lassen, um das sauber zu planen.

Hast du dafür ein Beispiel im Netz, gibt nicht so viel gute Beispiele im Netz was dieses Thema angeht und dann auch sauber und umfangreich erklärt wird.
 
Ok, so ist es für mich besser verständlich, vielen lieben Dank.

Im Moment sieht es noch so aus, vereinfacht dargestellt:

T1(EAV)T2(AV)T3(EV)

Ich muss sehen wie ich das umsetze, ansonsten asyncio, damit lässt sich dieses Prinzip auch realisieren. Ich werde aber deine Idee mir auch noch mal genauer ansehen, dazu will ich mir etwas Zeit lassen, um das sauber zu planen.

Hast du dafür ein Beispiel im Netz, gibt nicht so viel gute Beispiele im Netz was dieses Thema angeht und dann auch sauber und umfangreich erklärt wird.
Bitte :) so hatte ich es schon vermutet.

holgermaik "Baue dein PA im Script als Block zusammen und übertrage den gesamten Speicherblock." Und zwar in einem Thread, dass ist auch meine Meinung. (PA Prozessabbild)

Eine message queue ist architektonisch etwas völlig anderes. Geht auch, kann man machen - keine Ahnung, ob das hier angemessen ist. IMHO meist völlig überzogen, zumal sie auch eigene Probleme mit sich bringt. Okay, als Script kannst du dich vmtl. auf die Potenz eines PCs verlassen.

Ich baue da eher simple Handshakes zwischen Tasks auf...

Beispielseiten kenne ich nicht. Wenn du bis hierher gekommen bist, schaffst du den Rest auch :)
 
holgermaik "Baue dein PA im Script als Block zusammen und übertrage den gesamten Speicherblock." Und zwar in einem Thread, dass ist auch meine Meinung. (PA Prozessabbild)

Mehrere oder mindestens 2 Threads benötige ich aber, weil dort eine Routine als While Schleife benötigt wird, die ständig läuft, und die würde das gesamte Skript blockieren. Also auch den I/O der über den Websocket abgehandelt wird.

Aktuell habe ich 2 Klassen in dem Skript, ich überlege, ob ich eine dritte nur für Modbus baue, dann wäre Websocket und Modbus ebenfalls logisch getrennt. Und für die Modbus Kommunikation einen eigenen Thread, bleibt dann nur noch die Frage, wie ich die Kommunikation zwischen den Threads hinbekomme.

Also für den Fall T(Socekt_I/O) <-> T(Modbus_I/O) <-> T(Controll)

Also für den Fall, ein Button wird gedrückt, dann kommt am Websocket Server via JSON {"Relais1" : "on"} das wird dann über IF Bedingungen verglichen usw. und dann kommt direkt der modbus Befehl -> zB. write_coils(adress, Unit) ... Dann müsste ich jetzt alle Befehle über eine Datenbank noch zusätzlich speichern oder auslesen. Über Variablen habe ich das auch schon probiert, nur hier treten dann, wenn mehrere Clients auf den Server zugreifen, komischen Effekte auf. Weil dann für den Websocket mit verschiedenen Clients, self nicht mehr für alle dasselbe ist, also da wird die Verbindung gespeichert und ein neues Objekt generiert (nach meinem Verständnis). Mit globalen Variablen habe ich das noch nicht getestet. Ich muss mir dazu noch mal Gedanken machen...
 
Zuletzt bearbeitet:
Zurück
Oben