# Schrittketten Transition mit Zeitablauf in Codesys



## Eppo (2 Februar 2016)

Hallo,
ich habe mich freiwillig verpflichtet meine Facharbeit mit CoDeSys zu machen,
leider wird bei uns im Unterricht nur mit S7 gearbeitet.
Nun lerne ich mir selbst mein Wissen an und habe einige Programme aus dem S7 Unterricht
genommen und mit Codesys umgesetzt.

Bei den Schrittketten stehe ich jetzt vor dem Problem,
dass ich bei Schrittketten für die Transitionen gern zeitliche Aktivierungen haben möchte.
Dies geht ja zum einen i.d. ich eine Variable zeitlich verzögert in den Aktionen setze und diese als Weiterschaltbedingung nehme, in S7 gibt es da den Compare-Baustein welchem ich sagen kann wie lange der vorhergehende Schritt aktiv sein soll.

Gibt es so etwas im Codesys auch oder geht das nur mittels erwähnten verzögertenSetzens einer Variablen?


----------



## excelite (3 Februar 2016)

Hallo,

ja klar kann man da auch machen ich finde ST am effizientesten. Da kannst du über die Funktion TIME() die aktuelle Zeit holen seit dem Einschalten der PLC. Geht dann eigentlich ganz einach:


```
VAR
iStep : INT := 0; (* Schrittvariable *)
tWaitTime : TIME := t#0s;
END_VAR

(* CODEBEREICH *)
CASE iStep OF
0:
IF bStart THEN (* Irgendeine Bedinung / Transistion *)
tWaitTime := TIME() + t#3s; (* Nun die Zeit holen und deine Wartezeit dazu addieren welcher Wert die TIME() zurückgibt ist egal, du arbeitest ja nur mit dem relativen Offset *)
iStep := 10;

10:
IF TIME() > tWaitTime AND bWeitereTransition THEN (* Hier nun deine Zeit abfragen und evtl. noch eine weitere Transition *) 
; (* Irgendetwas tun in diesem Schritt oder auch nicht *)
tWaitTime := TIME() + t#2s; (* Nun kannst du die Variable gleich wieder neu beschreiben wenn du möchtest. Wenn du keine weitere Verzögerung willst dann einfach nicht setzen, sondern erst wieder wenn du sie brauchst *)
iStep := 20; (* Schritt auf nächsten Wert setzen oder wieder auf 0 wenn die Kette hier zu Ende ist *)
END_IF;


20:
; (* ....*)

END_CASE;
```

Das Ganze kannst du natürlich auch noch um ein Timeout erweitern wenn du willst. Mache ich immer wenn ich auf externe Signale warte die evtl. ausfallen können wie beispielsweise ein Zylinder mit Endschalter. Dann kannst du eine Fehlermeldung absetzen wenn nicht innerhalb einer Zeit der Endschalter geschaltet wird:



```
VAR
iStep : INT := 0; (* Schrittvariable *)
tWaitTime : TIME := t#0s;
tTimeout : TIME := t#0s;
END_VAR

(* CODEBEREICH *)
CASE iStep OF
0:
IF bStart THEN (* Irgendeine Bedinung / Transistion *)
tWaitTime := TIME() + t#3s; (* Nun die Zeit holen und deine Wartezeit dazu addieren welcher Wert die TIME() zurückgibt ist egal, du arbeitest ja nur mit dem relativen Offset *)
iStep := 10;

10:
IF TIME() > tWaitTime AND bWeitereTransition THEN (* Hier nun deine Zeit abfragen und evtl. noch eine weitere Transition *) 
; (* Irgendetwas tun in diesem Schritt oder auch nicht *)
tWaitTime := TIME() + t#2s; (* Nun kannst du die Variable gleich wieder neu beschreiben wenn du möchtest. Wenn du keine weitere Verzögerung willst dann einfach nicht setzen, sondern erst wieder wenn du sie brauchst *)
iStep := 20; (* Schritt auf nächsten Wert setzen oder wieder auf 0 wenn die Kette hier zu Ende ist *)
END_IF;


20:
IF TIME() > tWaitTime THEN
bZylinderausfahren := TRUE;
tTimeout := TIME() + t#2s;
iStep := 30;
END_IF;

30:
IF bZylinderEndschalterGS THEN
; (* mache irgendwas anderes oder weiter... *)
iStep := 40;
ELSIF TIME() > tTimeout THEN
bFehler := TRUE; 
istep := 1000 + iStep; (* Ich springe hier dann immer in den Schritt 1000 + aktuelle SChrittnummer dann kann man nachher schön sehen wo die Kette den Fehler ausgelöst hat. Musst du aber nicht. Kannst auch anders behandeln *)
END_IF;

1000...1999: (* Fehler auffangen und damit irgendwas tun *)
(* hier kannst du zum Beispiel den fehler quittieren *)
IF bFehlerQuittieren then
bFehler := FALSE;
istep := 0;
END_IF;

END_CASE;
```




Ach und wenn du eine sehr performante Schrittkette brauchst z.B. bei Socketprogrammierung bei der du gerne mehrere Schritte in einem Zyklus durchlaufen möchtest kannst du das Ganze noch in einer Repeatschleife nutzen:


```
REPEAT

iOldStep := iStep; (* aktuellen Schritt merken und alle Schritte ausführen bis der Schritt sich nicht mehr ändert dann weißt du, dass die Bedingung auf die gewartet wird nicht erfüllt ist ==> raus und Zyklus beenden sonst gibt es eine Endlosschleife!! *)

CASE iStep OF
0:
 (* hier natürlich Code rein *)
10:
(* hier natürlich Code rein *)
20:
(* hier natürlich Code rein *)
1000..1999:
(* hier natürlich Code rein *)
END_CASE;

UNTIL iStep = iOldStep OR iStep = 0
(* die Abfrage iStep = 0 kannst du rein machenn wenn du nicht sicher bist ob evtl. die Schrittkette immer und immer wieder durchlaufen wird das würde dann auch zu einer Endlosschleife führen, meistens wird das aber nicht benötigt *)
END_REPEAT
```


----------



## Eppo (4 Februar 2016)

Danke,

das klingt super.
Da ich eine Pumpe ansteuern muss, wollte ich eh eine Alarmabschaltung nehmen, falls der Druck im System meiner Anlage nicht aufgebaut wird (z.B. kein pumpfähiges Medium oder Leck im System),
da kann ich den Timeout ganz gut gebrauchen.


----------



## dingo (4 Februar 2016)

Hallo Eppo,
klar geht das auch mit der AS in CODESYS.

In der CODESYS Hilfe ist AS detalliert beschrieben, schaue Dir mal die Qualifier zu AS an.

Oder hier von IPSTA gute Erklärungen:
http://www.ipsta.de/download/freies/Folge_13.pdf <-AS Teil1
http://www.ipsta.de/download/freies/Folge_14.pdf <-AS Teil2

http://www.ipsta.de/seiten_html/wissenswertes_frei.html

MfG aus OWL


----------

