Schreiben einer Modbus-Variablen in festgelegten Zeitschritten

L

Luk-11

Guest
Zuviel Werbung?
-> Hier kostenlos registrieren
Hey,

ich versuche in Structured Text (es muss ST sein) ein Programm für den Modbus-Master zu schreiben, das eine Variable des Slaves setzt. Diese Variable soll sich alle 5s ändern.
Hierzu habe ich ein kleines Programm geschrieben, welches meiner Meinung nach funktionieren müsste. Leider funktioniert es nicht.

Ich könnte mir vorstellen, dass es daran liegt, dass die while-Schleife in den ersten 5s mehrfach durchlaufen wird und hierbei immer wieder TimerEnable auf True setzt. Wird somit auch jedes mal wieder Timer.PT auf 0 gesetzt?

Ich kenne mich leider nicht so gut aus..


programm.PNG

Anhang anzeigen 45366
 
Zuletzt bearbeitet von einem Moderator:
Hallo,

beide Varianten (auch die erste) sind falsch wie Du schon bemerkt hast.

Versuch das nächste Malbitte den Code mit den CODE Tags einzufügen und nicht als Bild, wenn es nur um den CODE geht.

Code:
MBCFG_ModbusSlave.xNewVar1 := W2; //Hier wird MBCFG_ModbusSlave.xNewVar1 immer auf den Wert von W2 gesetzt

MyTimer(IN:=NOT MyTimer.Q, PT:=t#5s);
IF MyTimer.Q THEN
    MBCFG_ModbusSlave.xNewVar1 := MBCFG_ModbusSlave.XNewVar1 +5; // s. oben
END_IF
Damit könnte der Wert alle 5s erhöht werden, wenn er nicht jedesmal auf W2 zurückgesetzt wird. Siehe Anmerkung im Code.

Schleifen funktionieren so gar nicht in einem SPS Programm, das arbeitet bereits zyklisch. So wird die Schleifen jedesmal im Zyklus durchlaufen.
Gruß

PS: So wie der Timer automatisch neu gestartet wird hast Du einen Jitter von zusätzlich einer Zykluszeit, 5s+Zykluszeit
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Hey,

vielen Dank dir!

Warum ist es in deinem Code nicht erforderlich, die IN-Condition nach Durchlauf des if-Statements wieder zu ändern?
Was ich damit meine: Im ersten Durchlauf des Programms ist "MyTimer.Q = FALSE" und somit ist "NOT MyTimer.Q = TRUE". Somit wird der Timer angestellt und 5s später ist "MyTimer.Q = TRUE". Nun wird die Bedingung ausgeführt. Aber MyTimer.Q sollte jetzt für immer TRUE bleiben, weil ich es ja nicht wieder ausstelle.

Dein Code funktioniert einwandfrei - ich verstehe diesen Punkt nur gerade nicht.

Übrigens: Ich wollte natürlich dieses hier erreichen:
Code:
MBCFG_ModbusSlave.xNewVar1 := W2;
MyTimer (IN := NOT MyTimer.Q, PT := t#5s);
IF (MyTimer.Q) THEN
    W2 := W2 + 5;
END_IF
 
Bau dir den Timer mal in FUP auf, simuliere das ganze und guck dir bei [+] die Timer Variablen an.

ton_bsp.JPG

Und dazu gibt es noch in der Codesys Hilfe eine Darstellung des Signalverhaltens.

ton_bsp2.JPG
 
Zuletzt bearbeitet:
Ok, ich glaube, ich verstehe es: MyTimer.Q wird erst nach MyTimer.PT Sekunden TRUE. Und es bleibt auf TRUE so lange, bis MyTimer ausgeschaltet wird, IN also FALSE wird. Und in Thrusers Code geschieht das sobald MyTimer.Q TRUE wird.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Genau. Dein Timer TON ist eine Einschaltverzögerung. Er wird nach 5 Sekunden TRUE --> deine IF Bedingung wird genau 1x ausgeführt. Im nächsten Zyklus geht das wieder von vorne los mit den 5 Sekunden.
 
Hey mek_meik,

ich fürchte ich muss noch einmal nachfragen: Kann es denn nicht auch passieren, dass die 5s dann abgelaufen sind, wenn das Programm gerade 'MyTimer(IN:=NOT MyTimer.Q, PT=t#5ms);' ausführt? In dem Fall wird ja der Timer abgeschaltet, bevor MyTimer.Q angeschaltet wurde. Und dann würde die if-Condition nie ausgeführt werden ..
 
Nein, das kann nicht passieren. Intern funktioniert der Timer so: Beim high Trigger von IN merkt er sich die aktuelle Systemzeit als Startzeit. In den folgenden SPS-Zyklen prüft er bei seinem Aufruf, ob
Aktuelle Systemzeit - Startzeit >= PT, und erst wenn das der Fall ist, setzt er Q auf true.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
... ich würde eventuell (wegen der schon öfter zu diesem Thema geführten Diskussionen) über eine (statische) Hilfsvariable gehen - also Timer.Q auf Hilfsvariable und mit der dann den Rest machen (Timer abwerfen und Zählen) ...

Gruß
Larry
 
@Larry Laffer
Ich habe die von Dir genannten Diskussionen nicht mitverfolgt. Wo gibt es denn Zweifelsfälle, die den Einsatz einer Hilfsvariablen ratsam erscheinen lassen?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ah, dass ich auf den Thread nicht selbst gestossen bin, wo ich mich doch so gern über die Absonderlichkeiten eines namhaften deutschen SPS-Herstellers amüsiere.
Zum Glück ist 3S (noch) nicht auf dem Trip, dem Anwender irgendwelchen Pseudo-Komfort zu bieten, den er dann nicht mehr unter Kontrolle hat. Ein CodeSys/TC-Timer ist ein FB wie jeder andere auch, d. h. er tut nur dann ewtas, wenn er aufgerufen wird.
 
An den Siemens IEC Timer Thread mußte ich auch heute morgen denken als ich die Frage las. Hatte nur leider keine Zeit zu Antworten. Auch als ich das Beispiel so geschrieben hatte war ich kurz davor darauf einzugehen, daß es Bei Siemens so zu Problemen führen kann.

Gruß

PS Außerdem war es damals nur als kleine Beispiel gedacht wie man einen Timer ansteuert der sich immer neu startet.
 
Zuletzt bearbeitet:
Um das Thema abzurunden mal ein Auszug aus der Codesys Doku
...werden die IEC-Timer-Werte während der Ausführung einer IEC-Task eingefroren. Aufrufe von IEC-Zeitgebern (beispielsweise TON) während der Ausführung einer IEC-Task führen darum immer zu den gleichen Timer-Werten, auch wenn die physikalische Zeit weiterläuft. Das heißt, es ist nicht möglich, beispielsweise in einer Schleife aktiv zu warten, weil die IEC-Timer-Werte sich im aktuellen Task-Scan nicht verändern.

Holger
 
Zuviel Werbung?
-> Hier kostenlos registrieren
@StructuredTrash, HolgerMaik:
Schön zu hören, dass es auch Systeme gibt, bei denen es wie man (ich es) erwarten würde funktioniert.
Dann verbucht meinen Beitrag einfach unter "schön, dass ich dieses Problem nicht habe" ... 8)

Gruß
Larry
 
Nein, das kann nicht passieren. Intern funktioniert der Timer so: Beim high Trigger von IN merkt er sich die aktuelle Systemzeit als Startzeit. In den folgenden SPS-Zyklen prüft er bei seinem Aufruf, ob
Aktuelle Systemzeit - Startzeit >= PT, und erst wenn das der Fall ist, setzt er Q auf true.

Jetzt erreicht mein Programmcode also die Zeile
Code:
MyTimer(IN := NOT MyTimer.Q, PT := t#5s);

Die Systemzeit wird gespeichert und 5s später wird MyTimer.Q TRUE. Wenn aber exakt zu dieser Zeit wieder
Code:
MyTimer(IN := NOT MyTimer.Q, PT := t#5s);
ausgeführt wird, wird PT FALSE. Und dann wird
Code:
IF (MYTimer.Q) THEN
     W2 := W2 + 5;
END IF

auch nicht ausgeführt. Dass die Startzeit von der Systemzeit subtrahiert wird ändert das nicht, oder?
Sorry, ich finde das voll verwirrend
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Du mußt in dem Fall die IF-Abfrage VOR den Timer-Aufruf schreiben ...
Also :
Code:
IF (MYTimer.Q) THEN
     W2 := W2 + 5;
END IF[

MyTimer(IN := NOT MyTimer.Q, PT := t#5s);
Gruß
Larry
 
Jetzt erreicht mein Programmcode also die Zeile
Code:
MyTimer(IN := NOT MyTimer.Q, PT := t#5s);

Die Systemzeit wird gespeichert und 5s später wird MyTimer.Q TRUE. Wenn aber exakt zu dieser Zeit wieder
Code:
MyTimer(IN := NOT MyTimer.Q, PT := t#5s);
ausgeführt wird, wird PT FALSE. Und dann wird
Code:
IF (MYTimer.Q) THEN
     W2 := W2 + 5;
END IF

auch nicht ausgeführt. Dass die Startzeit von der Systemzeit subtrahiert wird ändert das nicht, oder?
Sorry, ich finde das voll verwirrend

Du musst Dich von der Vorstellung lösen, dass MyTimer.Q "von selbst" TRUE wird. Er wird erst TRUE, wenn Du MyTimer aufrufst und dabei min. 5 Sekunden vergangen sind. Und dann bleibt Q TRUE, bis Du den Timer im folgenden SPS-Zyklus wieder aufrufst.
 
Hallo Luk
mal aufgedröselt
1. deine Task startet
2. irgendwo während der Laufzeit der Task kommt dein Timer Aufruf. Jetzt wird der Zeitstempel der Systemzeit gespeichert.
3. deine Task läuft weiter und kommt zum Ende.
4. deine Task startet erneut. zu diesem Zeitpunkt wird wieder der Zeitstempel der Systemzeit gespeichert.
5. irgendwo während der Laufzeit der Task kommt deine Abfrage "Ton.Q" jetzt wird der Zeitstempel deiner Startzeit mit dem Zeitstempel des Taskeintrittes verglichen und der Ausgang wird eben gesetzt oder nicht.
6. der Task läuft weiter
7. alles beginnt von vorn.

Das hat den Vorteil, dass egal zu welchem Zeitpunkt während der Task der Zeitstempel abgefragt wird es immer zum gleichen Ergebnis führt.
Das hat allerding auch Nachteile, die zur Vollständigkeit erwähnt werden sollten.
Die Laufzeit der IEC Timer ist immer ein vielfaches der Tasklaufzeit. Was dazu führt, das die Laufzeit der Timer um maximal eine Tasklaufzeit verlängert wird. Dies tritt dann auf wenn der Timer während der Tasklaufzeit abgelaufen ist. Durch das einfrieren des Zeitstempels beim Taskeintritt wird dies aber erst im nächsten Zyklus wirksam.

Ich hoffe ich hab dich jetzt nicht vollständig verwirrt:D
Holger
 
Zurück
Oben