# TON-Timer mehrmals starten bzw. zurücksetzen



## sefo (18 Juni 2013)

Hallo, 

ich bin recht neu in der SPS-Welt und bin gerade dabei ein Ablauf (in TwinCAT mit ST) zu programmieren. Allerdings bin ich gleich am Anfang auf ein Problem mit den Timern gestoßen. Ich verwende im Moment den TON.

TON-Timer
http://infosys.beckhoff.com/index.php?content=../content/1031/el320x/html/bt_el320x_techdat.htm&id=

Was ich machen will: 
Ich toggle meinen Starbutton in der Visualisierung. Wenn er gedrückt wird soll ein Timer starten, nachdem 5sec verstrichen sind sollen dann entsprechende Ventile geschalten werden.
Ich hab das mit zwei If-Schleifen realisiert. Beim ersten Durchlauf funktioniert alles wie es soll. Doch wenn ich den Startbutton ein zweites mal drücke, springt er mir gleich in die zweite If-Schleife, 
weil das Ausgangssignal Q vom TON immer noch TRUE ist. D.h. ich sollte in der zweiten Schleife den Timer zurücksetzen.
 Ich habe keine Ahnung wie ich das Problem lösen oder umgehen kann.
Gibt es eine Möglichtkeit das Q oder ET (abgelaufene Zeit des Bausteins) zurückzusetzen? 

Hättet ihr mir evlt. eine Idee?

Hier mein Programm:

IF Startbutton THEN  (*Wenn Startbutton gedrückt*)
  timer.PT:=T#5s;     (*Sollwert Zeit*)
  timer.IN:=TRUE;      (*Startsignal für Timer*)
  timer();                 (*Aufrufen des Timers*)
    IF timer.Q THEN    (*Wenn Timer abgelaufen*)
      Timer.IN:=FALSE;
  END_IF
END_IF


Gruß
Jonas


----------



## bits'bytes (18 Juni 2013)

```
IF Startbutton THEN (*Wenn Startbutton gedrückt*)
  timer.PT:=T#5s; (*Sollwert Zeit*)
  timer.IN:=TRUE; (*Startsignal für Timer*)
  timer(); (*Aufrufen des Timers*)
  IF timer.Q THEN (*Wenn Timer abgelaufen*)
   Timer.IN:=FALSE;
  END_IF
END_IF
```

Hi,
a) Code immer unter 
	
	



```
setzen --> Lesbarkeit
b) timer fub immer aufrufen (zyklisch, keine Bedingungen)
c) wenn timer.IN = 0 wird ==> rücksetzen erfolgt


bg
bb


[CODE]

timer.IN := Startbutton and not start_ventile
timer ()
if (timer.Q) then
  start_ventile := 1
end_if
```


----------



## Larry Laffer (18 Juni 2013)

Hallo,
was der wichtigste Teil des Beitrages von Bits'Bytes ist (der aber m.E. nicht so raus kam) ist, dass du den Timer-Aufruf in deine IF-Abfrage hinein-geschrieben hast. Das geht vom generellen Code-erstellen schon zu machen, bringt aber das Problem mit sich, das der TON (oder TOF) den Eingangs-Trigger ggf. nicht mitbekommt. Deshalb ist es sinnig (man sollte es sich auch gar nicht erst anders angewöhnen) es so zu machen, wie es bb in seinem Code-Beispiel gepostet hat ...

Gruß
Larry


----------



## sefo (19 Juni 2013)

Hallo Larry und bb,

vielen Dank für die Hilfe. Jetzt tut es. Hat mir auch für das allgemein Verständnis weitergeholfen.
Bei mir wurde der Timer immer in Schleife aufgerufen und mein timer.In-Signal war ständig True und dadurch war auch mein Q-Signal ständig auf True. -> Wie gesagt, bin noch Anfänger.

Gibt es eigentlich einen bestimmten Grund, dass es mit den Timern so umständlich realisiert wurde? Sie haben sicherlich für gewissen Anwendungen ihre Berechtigung mit den gebotenen Funktionen.
Aber ich kenn z.B. von anderen (SPS-/Motor-)Steuerungen die nicht nach IEC-Norm sind, dass es einen Befehl wie "wait" oder "delay" gibt, wo man einfach sagt "delay 50ms" und der nächste Befehl wird dann um 50ms verzögert.


----------



## wonderfulworld (24 Juni 2013)

Hi,
darf man Fragen was für eine Steuerung du meinst. Es gibt zwei Echtzeitkonzepte bei SPSen. Das erst ist Codesys/Step7 (und noch viele andere) und das andere ist zum Beispiel Jetter, SIMOTION. Im ersten Konzept wird das Programm immer zyklisch (innerhalb einer definierten Zykluszeit) abgearbeitet und zwar immer von oben bis ganz unten. Bei ablaufgesteuerten Systemen ist das anders. Da wird das Programm bis zu der Stelle abgearbeitet wo es warten muss (, zum Beispiel weil eine Zeit noch nicht abgelaufen ist oder ein Eingang gerade nicht kommt), anschließend wird nur noch im Zykluszeitraster kontrolliert ob diese Bedingung erfüllt wird. Ist Sie dann irgendwann erfüllt, wird dann da weitergemacht.

Gruß wonderfulworld


----------



## StructuredTrash (24 Juni 2013)

sefo schrieb:


> Gibt es eigentlich einen bestimmten Grund, dass es mit den Timern so umständlich realisiert wurde? Sie haben sicherlich für gewissen Anwendungen ihre Berechtigung mit den gebotenen Funktionen.
> Aber ich kenn z.B. von anderen (SPS-/Motor-)Steuerungen die nicht nach IEC-Norm sind, dass es einen Befehl wie "wait" oder "delay" gibt, wo man einfach sagt "delay 50ms" und der nächste Befehl wird dann um 50ms verzögert.


Der Grund für die zyklsche Bearbeitung ist, dass eine SPS meistens eine Vielzahl voneiander unabhängiger Abläufe steuern soll. Bei einem "Wait" oder "Delay" in einem der Abläufe würden alle anderen Abläufe aber auch nicht weiter bearbeitet.


----------



## wonderfulworld (24 Juni 2013)

StructuredTrash schrieb:


> Der Grund für die zyklsche Bearbeitung ist, dass eine SPS meistens eine Vielzahl voneiander unabhängiger Abläufe steuern soll. Bei einem "Wait" oder "Delay" in einem der Abläufe würden alle anderen Abläufe aber auch nicht weiter bearbeitet.



Ja das stimmt für zyklische Systeme, aber nicht für alle SPSen. Ich möchte ja nicht korinthenkacken, aber ich bin irgendwie von diesen ablaufgesteuerten Steuerungen begeistert, deshalb nochmal ne kleine Erklärung.
In ablaufgesteuerten Systemen gibt es in der Regel sogar deutlich mehr Tasks (100 Tasks sind keine Seltenheit) als in zyklischen Systemen(hier befindet sich die Anzahl der Tasks doch eher im einstelligen Bereich). Der Trick in ablaufgesteuerten Steuerungen ist der, das die einzelnen Tasks schon in einer definierten garantierten Zykluszeit abgearbeitet werden, aber falls ein "Wait", "Delay" oder auch nur eine Weiterschaltbedingung fehlt, dann unterbricht der Scheduler(also der Taskverwalter) die Arbeitung und stellt der CPU eine andere Task zur Abarbeitung zur Verfügung. Er kontrolliert zwar im Zykluszeitraster ob die Weiterschaltbedingung erfüllt ist. Ist das nicht der Fall, dürfen die anderen Tasks wieder ran, ist es der Fall, dann wird da weitergemacht wo das letzte Mal aufgehört wurde. Diese Technik spart Zykluszeit und ist eigentlich schon irgendwie richtig elegant, aber hat sich soweit ich weiß nicht richtig durchgesetzt. Die einzigen Steuerungen die das meines Wissens einsetzen sind Jetter und SIMOTION. Gearbeitet hab ich mit diesen Steuerungen noch nicht, vielleicht find ich auch deshalb das Konzept so toll.
Gruß wonderfulworld


----------



## Larry Laffer (25 Juni 2013)

@Wonderfulworld:
Beachte aber bitte bei deinen Ausführungen, dass diese sich (wie du ja selber schreibst) auf die Ausnahme und nicht auch die gebräuchliche Regel beziehen - und schon gar nicht auf die ursprüngliche Frage des TE ...

Gruß
Larry


----------



## S7-kub (21 August 2013)

Und genau über dieses Problem einer Ablaufsteuerung, also dass sie "wartet", stolpere ich zurzeit bei Jetter:

Innerhalb des Ablaufes in einer Anlage habe ich nach jeder Bedingung Schrittmerker eingefügt um den Ablauf kontrollieren zu können und bei Festhängen einer z.B. pneumatischen Bewegung die Anlage zu stoppen. Der Bediener soll z.B. die Info bekommen: "Modul A, Schritt 5, Schieber nicht in AST gefahren". Es ist immer nur EIN Schrittmerker "true".

_Funktionsbeschreibung:
Auswertung Schritt 1 nach Schritt 2
Wenn Schritt 1 ausgeführt/aktiv >> maximal 1500mS warten auf Schritt 2, falls Schritt 1 früher fertig ist > wunderbar, weiter mit Auswertung Schritt 2 nach Schritt 3
Wenn Schritt 2 nach 1500mS nicht aktiv >> Störung und Info

Auswertung Schritt 2 nach Schritt 3
Wenn Schritt 2 ausgeführt/aktiv >> maximal1500mS warten auf Schritt 3, falls Schritt 2 früher fertig ist > wunderbar, weiter mit Auswertung Schritt 3 nach Schritt 4
Schritt 1 nach Schritt 2 Überwachung nicht mehr auswerten
Wenn Schritt 3 nach 1500mS nicht aktiv >> Störung und Info

Auswertung Schritt 3 nach Schritt 4
Wenn Schritt 3 ausgeführt/aktiv >> maximal 1500mS warten auf Schritt 4, falls Schritt 3 früher fertig ist > wunderbar, weiter mit Auswertung Schritt 4 nach Schritt 5
Schritt 2 nach Schritt 3 Überwachung nicht mehr auswerten
Wenn Schritt 4 nach 1500mS nicht aktiv >> Störung und Info
usw_

in (m)einer zyklische-SPS-Welt kein Problem: mehrere Timer, Timer stoppt wenn Bedingung nicht erfüllt, nächster Timer wird anhand der Eingangsbedingung gestartet.

Nun steht bei JetSym ST/STX dass immer nur EIN Timer pro Task verfügbar ist. Mein Ansatz

```
// wenn Schritt_01: Überwachungszeit starten
    if step_01_PappToBelt then
        // warten auf nächste Bedingung => Schritt_02 wird aktiviert
        delay (tn_Steps_PappToBelt); //(T#1500mS);
        // wenn Schritt_02 nach Überwachungszeit nicht erreicht => Fehler Bedingung Schritt_01 nach Schritt_02
        If step_01_PappToBelt and not step_02_PappToBelt then
             num_PappToBelt_StepError := 1;    // Die Nummer dient zum Anzeigen einer Fehlermeldung
             b_PappToBelt_StepError := TRUE;    // Schnellstopmerker setzen
        End_If;
    End_If;

    // wenn Schritt_02: Überwachungszeit starten
    if step_02_PappToBelt then
        // warten auf nächste Bedingung => Schritt_03 wird aktiviert
        delay (tn_Steps_PappToBelt); //(T#1500mS);
        // wenn Schritt_03 nach Überwachungszeit nicht erreicht => Fehler Bedingung Schritt_02 nach Schritt_03
        If step_02_PappToBelt and not step_03_PappToBelt then
            num_PappToBelt_StepError := 2;    // Die Nummer dient zum Anzeigen einer Fehlermeldung
            b_PappToBelt_StepError := TRUE;    // Schnellstopmerker setzen
        End_If;
    End_If;

    // wenn Schritt_03: Überwachungszeit starten
    if step_03_PappToBelt then
        // warten auf nächste Bedingung => Schritt_04 wird aktiviert
        delay (tn_Steps_PappToBelt); //(T#1500mS);
        // wenn Schritt_04 nach Überwachungszeit nicht erreicht => Fehler Bedingung Schritt_03 nach Schritt_04
        If step_03_PappToBelt and not step_04_PappToBelt then
            num_PappToBelt_StepError := 3;    // Die Nummer dient zum Anzeigen einer Fehlermeldung
            b_PappToBelt_StepError := TRUE;    // Schnellstopmerker setzen
        End_If;
    End_If;
```

arbeitet in der Praxis nicht, der erste delay wartet stur bis die Zeit abgelaufen ist. Bis dahin sind aber schon nächsten Schritte fertig und sollten überwacht werden. Der delay-Befehl wird also nicht "verworfen" sobald die (If)-Bedingung dafür = false wird.

In der JetSym ST Hilfe habe ich einen Hinweis auf EIN "Zeitregister" für jeden Task gefunden. Das könnte zur Not ja manuell auf "0" gesetzt werden.
Auch eine Start_Timer // End_Timer Anweisung wird dort beschrieben, die wohl anders als der delay arbeitet.
Zu beidem finde ich nichts unter JetSym STX (= aktuelle Software) oder in den Registerbeschreibungen der JC340 (CPU).

Bis auf solch "kleine lästige Haken und Ösen" ( ich vermisse auch einen "flash xxx mS"-Befehl für einen einfachen Blinker einer Leuchte) ist die Jetter und ihre Programmierungsweise für meinen aktuellen Anwendungsfall ideal. Ablaufsteuerung mit pneumatisch gesteuerten Bewegungen und 2 Servoachsen zum Transport und alles an Positionierung und so wird in *einer* CPU mit *einer* Programmiersofware abgegolten


----------



## Larry Laffer (21 August 2013)

S7-kub schrieb:


> ...der erste delay wartet stur bis die Zeit abgelaufen ist. Bis dahin sind aber schon nächsten Schritte fertig und sollten überwacht werden. Der delay-Befehl wird also nicht "verworfen" sobald die (If)-Bedingung dafür = false wird.



Hallo,
das wäre aus meiner Sicht und meinem Verständnis eines Befehls Delay vollkommen unlogisch. Der Befehl an sich wird ja bedingungslos ausgeführt ...
Die Aufgabe ist es also zu Starten und die Zeit abzulaufen und am Ende ggf. einen Rückgabewert zu liefern.
Du mußt hier also aus meiner Sicht schon deine Vorgehensweise überdenken ...

Gruß
Larry


----------



## S7-kub (21 August 2013)

Larry Laffer schrieb:


> Hallo,
> das wäre aus meiner Sicht und meinem Verständnis eines Befehls Delay vollkommen unlogisch. Der Befehl an sich wird ja bedingungslos ausgeführt ...
> Die Aufgabe ist es also zu Starten und die Zeit abzulaufen und am Ende ggf. einen Rückgabewert zu liefern.
> Du mußt hier also aus meiner Sicht schon deine Vorgehensweise überdenken ...
> ...



Einspruch : Durch die Aufgabe ist die Vorgehensweise doch eigentlich definiert.

Bedingung 1 ist erfüllt, warte 1500mS OB Bedingung 2 erfüllt ist.
Uups, Bedingung 2 ist nach 1000mS schon erfüllt >> prima, vergiss deine jetzige Aufgabe, es gibt eine neue nämlich
Bedingung 2 ist erfüllt, warte 1000mS OB Bedingung 3 erfüllt ist.
Uups, Bedingung 3 ist nach 500mS schon erfüllt >> prima, vergiss deine jetzige Aufgabe, es gibt eine neue nämlich
Bedingung 3 ist erfüllt, warte 2000mS OB Bedingung 4 erfüllt ist.
Ohhh, die 2000mS sind um und Bedingung 4 ist immer noch nicht erfüllt >> Fehler generieren, Anlage stillsetzen.

In einer zyklischen SPS wären das 3 (4) Zeilen mit 3 einschaltverzögernden Timern.
XIC Bed01 BST TON Tim01 NXB XIC Tim01.DN XIO Bed02 OTL error_1 BND
XIC Bed02 BST TON Tim02 NXB XIC Tim02.DN XIO Bed03 OTL error_2 BND
XIC Bed03 BST TON Tim03 NXB XIC Tim03.DN XIO Bed04 OTL error_3 BND

Störung Quittieren mit
XIC Reset BST OTU error_1 NXB error_2 NXB error_3 BND


oder auch 

```
Bed01
---] [-----------------------------Tim01-
               |
               |  Tim01  Bed02            error_1
               |---] [-----]/[-----------(L)---

  Bed02
---] [-----------------------------Tim02-
               |
               |  Tim02  Bed03            error_2
               |---] [-----]/[-----------(L)---

  Bed03
---] [-----------------------------Tim03-
               |
               |  Tim03  Bed04            error_3
               |---] [-----]/[-----------(L)---


  Reset                                    error_1
--] [-------------------------------(U)---
               |
               |                             error_2
               |------------------------(U)---
               |
               |                             error_3
               |------------------------(U)---
```


In einer Ablaufsteuerung geht es halt nicht "so einfach"

In einer Ablaufsteuerung ist das Verhalten des Befehls "delay" also absolut logisch. Eine Bedingung ist erfüllt und die nächste Anweisung sagt: "warte gefälligst ab bis deine Zeit abgelaufen ist, alles was bis dahin (woanders) passiert kann dir egal sein, erst wenn deine Zeit um ist prüfst du die nächste Anweisung".

DAS ist nicht das was ich brauche.

Ich benötige "trotz" Ablaufsteuerung: wenn eine Eingangsbedingung nicht mehr erfüllt ist soll die Überwachungszeit und der dahinter liegende Code dafür verworfen und die zweite Eingangsbedingung mit der dazu gehörenden Überwachungszeit abgearbeitet werden.

Aber ich möchte in diesem Faden auf keinen Fall eine Diskussion Pro/Kontra Zyklisch/Ablauf lostreten 

Nach 35 Jahren zyklisch erfordert das Umdenken und Umsetzen in ablaufend halt etwas von ..... "Loslassen", da hat man schnell was in Erinnerung was _*so*_ eben nicht geht. 

Grüße vom Rhein

der KUB


----------



## Larry Laffer (22 August 2013)

... wo war hier jetzt der Widerspruch zu meiner Aussage ?
Wenn du schon mit AWL kommst dann darfst du den Delay mit einem Impulstimer gleichsetzen ...

Gruß
Larry


----------



## S7-kub (22 August 2013)

Larry Laffer schrieb:


> ... wo war hier jetzt der Widerspruch zu meiner Aussage ?
> Wenn du schon mit AWL kommst dann darfst du den Delay mit einem *Impulstimer* gleichsetzen ...
> 
> Gruß
> Larry



welcher aber, im Gegensatz zum delay in der Ablaufsteuerung, die nachfolgenden Anweisungen nicht blockiert. DAS ist mein Dilemma mit dem delay.

Gruß, der KUB


----------



## Larry Laffer (22 August 2013)

Sory ... jetzt verstehe ich erst, was du die ganze Zeit gemeint hast ... 
Der von dir verwendete Delay stoppt die Bearbeitung in der Zeile für die Dauer der Verzögerung. Das hatte ich komplett anders verstanden ... 8)

Du solltest zur Lösung auf einen IEC-Timer ausweichen - meine Wahl wäre ein TON.
Wenn du den außerhalb der IF-Abfrage an den jeweiligen Schritt hängst (jeder Schritt ein neuer Timer) dann kannst du das innerhalb der Abfrage wieder wie einen Timeout auswerten - in etwa so wie dein KOP-Konstrukt.

Gruß
Larry


----------



## S7-kub (22 August 2013)

Larry Laffer schrieb:


> .......
> Der von dir verwendete Delay _*stoppt*_ die Bearbeitung in der Zeile für die Dauer der Verzögerung.
> .........



Jenauuuu! Alles an Code nach der Zeile "wartet" bis die delay-Zeit abgelaufen ist. Ablaufsteuerung halt. Normalerweise will man das ja auch, es gibt bis zum Ablauf der "WARTE"-Zeit innerhalb der Funktionalität eh nix zu tun (als zu warten)




Larry Laffer schrieb:


> ........
> 
> Du solltest zur Lösung auf einen IEC-Timer ausweichen - *meine Wahl wäre ein TON*.
> Wenn du den außerhalb der IF-Abfrage an den jeweiligen Schritt hängst (jeder Schritt ein neuer Timer) dann kannst du das innerhalb der Abfrage wieder wie einen Timeout auswerten - *in etwa so wie dein KOP-Konstrukt.
> ...



Lieber Larry,

genau DAS würde ich ja liebend gerne tun WENN denn die Programmiersprache sowas hergeben würde....  (was sie anhand der Tatsache dass sie als Ablaufsteuerung konzipiert wurde nicht tut/braucht).

Dank der qualifizierten und engagierten Hotline von Jetter habe ich seit einigen Stunden einen Beispielcode WIE die Aufgabe zu lösen ist. Den versuche ich jetzt erst mal zu verstehen und dann umzusetzen.

Ich schlage vor, wir überlassen den Thread ab jetzt wieder dem Originalthema. Danke für die fachkompetente Diskussion an dieser Stelle. Man liest sich  

Grüße aus Venlo, der KUB


----------



## drfunfrock (22 August 2013)

Du kannst eine State-Machine nicht vernünftig programmieren, wenn du blockierende Kommandos hast. Im Grund lassen sich SM auch leichter programmieren, wenn man das Prinzip verstanden hat. Du hast immer einen Zustand, der dann in Abhängigkeit von den Eingangssignalen in einen anderen Zustand übergeht. Ein Zustand, dass kann eine Variable sein. Z.B. mit den Inhalten 1: Stop, 2: Run, 3: Wait. Die Eingangssignale können Timer, IOs oder Variable sein, die sich änderrn. Das hat den Vorteil, dass Quasi alles parallel ablaufen kann ohne dass du dir den Kopf in den meisten Fällen zerbrechen musst.


----------

