e!Cockpit Modbus Abfrage

Florian Se.

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

ich habe ein PFC 8204 mit e!Cockpit und versuche zur Zeit mit Modbus einen Stromzähler abzufragen. Ich mache das mit der WagoAPPModbus library. Es gibt dazu ja ein Anwendungsbeispiel bei dem ein Geröt abgefragt wird. Das funktioniert soweit auch super.
Wie gehe ich das technisch an, wenn ich verschiedene Registerbereiche (nicht zusammenhängend) abfragen will, oder ein 2. Gerät am Bus? Wenn ich die Query austausche hab ich den Eindruck, dass sich immer nur alles überschreibt

Muss ich dann jedesmal eine neues Programm schreiben? Ich will am Ende einfach nur 4 Stromzähler direkt hintereinander abfragen. Wie bekomme ich die zeitliche Reihenfolge hin?
Gibt es da auch Beispiele?

Liebe Grüße,
Florian
 
Hallo Florian,

wie willst Du die Zähler auslesen Modbus/TCP oder Modbus/RTU ...?
Es gibt im eCockpit bei der Gerätestruktur/Produktkatalog Sonstige Kommunikationsteilnehmer.
Da sollte was dabei sein.

Wolfgang
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Florian,

meinst Du die Bibliothek WagoAppPlcModbus? Es gab nämlich auch eine WagoAppModbus.

Für jeden Server würde ich einen Client anlegen. Jeder Client kann dann mehrere Anfragen verwalten. Dazu kann eine Jobliste als Array of Query angelegt werden.
Nach dem Abarbeiten eines Jobs, kann zum nächsten geschaltet werden.

Grüße
 
Hallo Florian,

wie willst Du die Zähler auslesen Modbus/TCP oder Modbus/RTU ...?
Es gibt im eCockpit bei der Gerätestruktur/Produktkatalog Sonstige Kommunikationsteilnehmer.
Da sollte was dabei sein.

Wolfgang

Modbus RTU, das ist dann aber die Variante über den Konfigurator oder? Den habe ich nämlich nicht ans laufen bekommen. Da weiß ich auch nicht welchen Datentyp ich einstellen muss. Ich muss 2 Register auslesen, in dem eine Vorzeichenbehaftete Ganzzhal drinsteht.
 
Hallo Florian,

meinst Du die Bibliothek WagoAppPlcModbus? Es gab nämlich auch eine WagoAppModbus.

Für jeden Server würde ich einen Client anlegen. Jeder Client kann dann mehrere Anfragen verwalten. Dazu kann eine Jobliste als Array of Query angelegt werden.
Nach dem Abarbeiten eines Jobs, kann zum nächsten geschaltet werden.

Grüße

Ich meinte die WagoAppPlcModbus. Es ist eine RTU Kommunikation. Also für jeden Slave einen Master oder? Hab das vergessen zu sagen. Wie stelle ich dann sicher, dass die Master nicht gleichzeitig auf den Bus zugreifen?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Florian,

bei Modbus RTU kann es nur eine Masterinstanz geben.
Die serielle Schnittstelle kann nur von einer Instanz genutzt werden. Weitere Instanzen würden melden, dass die Schnittstelle schon verwendet wird.

Das Vorgehen mit der Joblist bleibt, nur dass dort alle Anfrage an alle Slaves abgelegt werden.


Grüße
 
Hallo Tobsucht,

ich hab das jetzt mit der Jobliste umgesetzt. Hier im Forum gab es ja ein Beispiel dafür. Allerdings wird da immer so schnell es geht die Jobs direkt hintereinander abgefragt.

Code:
mySerialMaster( I_Port      := COM1,        // my serial port
                utQuery:=Jobliste[iJobCounter], 
                xTrigger:=xTrigger, 
                utResponse:=Responseliste[iJobCounter]
              );
              
              //Auf Jobende warten
FB_F_Trig (clk:=xTrigger);

//Jobende erfolgt, nächsten Job starten
IF FB_F_Trig.Q THEN
    xTrigger :=TRUE;
    iJobCounter := (iJobCounter+1) MOD 2;
END_IF

Ich habe das Gefühl, dass die SPS damit sehr stark belastet wird oder das generell nicht richtig funktioniert. (Busüberlastung oder so?)
Kann man das auch so programmieren, dass alle 500ms die Jobliste einmal abgearbeitet wird. Ich hab eher C programmiert und muss mich erst noch in die Programmierung mit einer SPS einarbeten.

Also ich könnte mir vorstellen, dass man einen Task mit 500 ms laufen lässt und dann in einer While Schleife all Jobs abarbeiten lässt??
 
Hallo;
Ich habe das Gefühl, dass die SPS damit sehr stark belastet wird oder das generell nicht richtig funktioniert. (Busüberlastung oder so?)
Kann man das auch so programmieren, dass alle 500ms die Jobliste einmal abgearbeitet wird. Ich hab eher C programmiert und muss mich erst noch in die Programmierung mit einer SPS einarbeten.

Also ich könnte mir vorstellen, dass man einen Task mit 500 ms laufen lässt und dann in einer While Schleife all Jobs abarbeiten lässt??

Hier e!Cockpit Modbus-TCP findest Du ein Beispiel mit Timer.

Gruß
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Thruser,

danke für die Info. Ist das dabei aber nicht so, dass nur die Zeit zwischen den Jobs eine bestimmte Dauer hat?

Ich würde gerne möglichst kurz hintereinander 4 Jobs ausführen im Zylus von 500ms...

LG Florian
 
HALLO
Hallo Thruser,

danke für die Info. Ist das dabei aber nicht so, dass nur die Zeit zwischen den Jobs eine bestimmte Dauer hat?

Ich würde gerne möglichst kurz hintereinander 4 Jobs ausführen im Zylus von 500ms...

LG Florian

Du könntest jetzt die Zeit auf 125ms setzen, dann wäre die Belastung schön verteilt.

Oder versuche mal folgendes (ungetestet):
Code:
mySerialMaster( I_Port      := COM1,        // my serial port
                utQuery:=Jobliste[iJobCounter], 
                xTrigger:=xTrigger, 
                utResponse:=Responseliste[iJobCounter]
              );
              


FB_F_Trig (clk:=xTrigger);


IF FB_F_Trigger.Q THEN
    iJobCounter := (iJobCounter+1) MOD iMaxJobs;
    IF iJobCounter=0 THEN
        xTimer:=TRUE;
    ELSE
        xTrigger:=TRUE;
    END_IF
END_IF


delay(IN := xTimer, PT := T#500MS); // TON


IF delay.Q THEN
    xTimer:=FALSE;
    xTrigger:=TRUE;
END_IF

Da sollte jetzt zwischen zwei Ausführungen der Jobliste eine Pause von 500ms liegen.

Eine weitere Möglichkeit (auch ungetestet):
Code:
IF xTrigger & (iJobCounter=0) THEN
    xTimer:=True;
END_IF


delay(IN := xTimer; PT := T#500MS); //TON


mySerialMaster( I_Port      := COM1,        // my serial port
                utQuery:=Jobliste[iJobCounter], 
                xTrigger:=xTrigger, 
                utResponse:=Responseliste[iJobCounter]
              );
              


FB_F_Trig (clk:=xTrigger);


IF FB_F_Trigger.Q THEN
    iJobCounter := iJobCounter+1);
    IF NOT (iJobCounter=iMaxJobs) THEN
        xTrigger:=TRUE;
    END_IF
END_IF


IF delay.Q & (iJobCounter=iMaxJobs) THEN
    xTrigger:=TRUE;
    xTIMER:=FALSE;
    iJobCounter:=0;
END_IF

Hier sollte der Durchlauf der Jobliste jetzt alle 500ms gestartet werden.

Also im ersten Beispiel kommt zu den 500ms noch die Abarbeitungszeit der Jobliste dazu. Im zweiten Beispiel sollte, mit Jitter, alle 500ms die Abarbeitung gestartet werden.

Zusätzliche Variablen, FB müssen noch deklariert werden. Darauf habe ich jetzt verzichtet.

Gruß
 
Hi,

ich hab noch ein paar kleine Typos rausgeholt, aber er funktioniert nicht der Code. Zumindest hab ich den Eindruck.
Im Debugger kann ich das sauch nicht wirklich nachvollziehen, da der Timer asynchron hochzählt oder?


Code:
IF (xTrigger AND (iJobCounter=0)) THEN
    xTimer:=True;
END_IF


delay(IN := xTimer, PT := T#500MS); //TON
delay.ET;

mySerialMaster( I_Port      := COM1,        // my serial port
                utQuery:=Jobliste[iJobCounter], 
                xTrigger:=xTrigger, 
                
                utResponse:=Responseliste[iJobCounter]
              );
              


FB_F_Trigger (clk:=xTrigger);


IF FB_F_Trigger.Q THEN
    iJobCounter := (iJobCounter+1);
    IF NOT (iJobCounter=iMaxJobs) THEN
        xTrigger:=TRUE;
    END_IF
END_IF


IF delay.Q AND  (iJobCounter=iMaxJobs) THEN
    xTrigger:=TRUE;
    xTIMER:=FALSE;
    iJobCounter:=0;
END_IF
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,
Hi,

ich hab noch ein paar kleine Typos rausgeholt, aber er funktioniert nicht der Code. Zumindest hab ich den Eindruck.
Im Debugger kann ich das sauch nicht wirklich nachvollziehen, da der Timer asynchron hochzählt oder?

ja da habe ich mit dem Timer Mist gebaut. Der läuft nur einmal durch, da er keinen Flankenwechsel erkennt.

So müßte es gehen:
Code:
IF (xTrigger AND (iJobCounter=0)) THEN
    xTimer:=True;
END_IF




mySerialMaster( I_Port      := COM1,        // my serial port
                utQuery:=Jobliste[iJobCounter], 
                xTrigger:=xTrigger, 
                
                utResponse:=Responseliste[iJobCounter]
              );
              


FB_F_Trigger (clk:=xTrigger);


IF FB_F_Trigger.Q THEN
    iJobCounter := (iJobCounter+1);
    IF NOT (iJobCounter=iMaxJobs) THEN
        xTrigger:=TRUE;
    END_IF
END_IF


IF delay.Q AND  (iJobCounter=iMaxJobs) THEN
    xTrigger:=TRUE;
    xTIMER:=FALSE;
    iJobCounter:=0;
END_IF


delay(IN := xTimer, PT := T#500MS); //TON
delay.ET; // So funktioniert das nicht. Entweder einer Dummy Variablen zuweisen oder den Deklarationsteil im Onlinemodus ansehen.
Dadurch ergibt sich jetzt ein Jitter von mindestens einer Zykluszeit. Sonst könnte man den delay Timer auch zweimal aufrufen, einmal oben und einmal unten.

Gruß
 
Hallo,

irgendwie bin ich mit dem Code nicht wirklich klar gekommen. Habe jetzt mal selbst was versucht. Im Sekundentakt werden die Jobs ausgeführt. Stimmt das so?
Code:
Timer(IN := NOT (Timer.Q), PT := T#500MS); //TP Timer
Timer.ET;//nur für live ansicht

FB_R_Trigger (clk:=Timer.Q);
//Es wird ein 1 Sekundentakt erkannt
IF FB_R_Trigger.Q THEN
    xTrigger := TRUE;
    iJobCounter := 0;
END_IF


mySerialMaster( I_Port      := COM1,        // my serial port
                utQuery:=Jobliste[iJobCounter], 
                xTrigger:=xTrigger,                 
                utResponse:=Responseliste[iJobCounter]
              );
              
//Jobende erfolgt, nächsten Job starten
IF xTrigger = FALSE AND iJobCounter < (iMaxJobs -1)  THEN 
  iJobCounter := iJobCounter +1;
  xTrigger := TRUE;
END_IF


Viele Grüße
 
Also Hintergrund ist, dass ich oft die gleichen Werte habe. So 10 sek. lang und ich glaube, dass er die Werte nicht richtig abruft, weil bei einem Stromzähler so oft die gleichen Werte ist ja unwarscheinlich. Entweder weil das Skript nicht läuft oder weil sonst was passiert. TimeOut oder so.
Kann man das irgendwo sehen?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,
Also Hintergrund ist, dass ich oft die gleichen Werte habe. So 10 sek. lang und ich glaube, dass er die Werte nicht richtig abruft, weil bei einem Stromzähler so oft die gleichen Werte ist ja unwarscheinlich. Entweder weil das Skript nicht läuft oder weil sonst was passiert. TimeOut oder so.
Kann man das irgendwo sehen?

ich schau mir das mal die Woche an. Muß eh noch etwas anderes ausprobieren.

Hast Du die 500ms mal verlängert? Ich weiß ja jetzt nicht mit wieviel b/s Du arbeitest, aber da kann schon mal etwas an Zeit zusammenkommen bei der seriellen Kommunikation.

Gib mir mal Deine Kommunikationsparameter der Schnittstelle und am besten auch die Modbusadressen oder verlinke auf das Handbuch zu Deinem Zähler.

Bei einem Zähler von Saia steht z.B. im Handbuch auch, daß die Werte nur alle 10s aktualisiert werden.

Gruß
 
So,

ich habe mal was getestet. Die Timerfunktion arbeitet so wie sie soll. Hier mal mein Beispiel, den Modbusbaustein habe ich durch einen Dummy ersetzt, der alle 10 Aufrufe xTrigger zurücksetzt.

Code:
PROGRAM PLC_PRG
VAR
    FB_Dummy:FB_TEST;
    FB_F_Trigger: F_Trig;
    delay: TON;
    
    xTrigger: BOOL := TRUE;
    xTimer: BOOL;
    
    iJobCounter: INT;
    iMaxJobs: INT := 4;
    iCounter:INT;
    tTime:TIME;
END_VAR
Code:
IF (xTrigger AND (iJobCounter=0)) THEN
    xTimer:=True;
END_IF

FB_Dummy (xTrigger:=xTrigger, iCounter=>iCounter);

FB_F_Trigger (clk:=xTrigger);

IF FB_F_Trigger.Q THEN
    iJobCounter := (iJobCounter+1);
    IF NOT (iJobCounter=iMaxJobs) THEN
        xTrigger:=TRUE;
    END_IF
END_IF

IF delay.Q AND  (iJobCounter=iMaxJobs) THEN
    xTrigger:=TRUE;
    xTIMER:=FALSE;
    iJobCounter:=0;
END_IF

delay(IN := xTimer, PT := T#10000MS, ET => tTime); //TON
und hier die Dummyfunktion
Code:
FUNCTION_BLOCK FB_TEST
VAR_OUTPUT
    iCounter:INT;
END_VAR
VAR_IN_OUT
    xTrigger:BOOL;    
END_VAR
Code:
IF xTrigger THEN
    iCounter:=iCounter+1;
    IF iCounter=10 THEN
        iCounter := 0;
        xTrigger := FALSE;
    END_IF
END_IF
Time1.PNG
Time2.PNG
Gruß
 
Servus,
es passt zwar nicht ganz zu der ersten Frage, aber habe ein ähnliches Problem mit der PFC 200.

Habe ein Problem mit der Modbusauslesung von digitalen Werten.

Habe eine CPU 750-8202 und mehrere Feldbuskoppler 750-352.



Die analogen Werte können über Modbus TCP oder UDP ausgelesen werden, die digitalen Werte können nicht abgefragt werden.



Habe den Koppler 750-342 mit dem 750-352 ausgetauscht und es funktioniert.



Habe den selben Versuch mit Codesys V2.3 gestartet, und ich kann alles lesen.

Alle Eingänge können gelesen werden und Ausgänge kann ich über die Koppler schreiben.



Sobald ich die Koppler mit E-Cockpit auslesen möchte kommen nur die Zustände von dem Koppler 342.

Die Koppler 352 zeigen mir alle Zustände über IO-Check an, aber im Programm werden keine Zustände angezeigt.


Die einzelnen Variablen sind über den Modbus Konfigurator veröffentlicht und sind als Read Only deklariert.


Das kann doch nicht sein?

Worin liegt der Fehler?

Danke im Voraus, Tom
 
Zurück
Oben