# Zeitmessung in Structur Text



## Leto (7 März 2012)

Moin moin,

ich muss bei TwinCat eine Zeitmessung realisieren. Das ganze soll folgender Maßen realisiert werden:

Mittels negativer Flanke eines digitalen Eingangs wird die Zeitmessung gestartet. Bei der zweiten negativen Flanke des selben digitalen Eingangs soll die Zeitmessung gestoppt werden, die gemessene Zeit in ms in eine Variable kopiert werden und gleichzeitig die Zeitmessung neu gestartet werden.

Die Messung dient zur Ermittlung der Zykluszeit einer Anlage.

Hat jemand einen Vorschlag, wie ich dieses Problem in ST lösen kann?

Vielen Dank im Vorraus.

Gruß


----------



## StructuredTrash (7 März 2012)

Eine Zählvariable in jedem Programmzyklus um 1 erhöhen. Bei der digitalen Signalflanke die Zählvariable in eine andere kopieren und dann wieder auf 0 setzen. Anlagenzyklus = Zähler * Taskzykluszeit.


----------



## asci25 (8 März 2012)

Nimm doch einen ganz normalen Timer (TON). Die abgelaufene Zeit kannst Du am Ausgang ET abnehmen.


----------



## Leto (8 März 2012)

Mit dem Gedanken hatte ich auch schon gespielt, nur bin ich leider ein Anfänger in Sachen ST und wüsste nicht wie ich das codieren soll.


----------



## drfunfrock (8 März 2012)

```
VAR
  timer : TON;
END_VAR

timer(PT:=t#1000s,IN:=FALSE);
timer(in:=TRUE);


time := timer.ET;
```


----------



## asci25 (8 März 2012)

drfunfrock schrieb:


> ```
> VAR
> timer : TON;
> END_VAR
> ...



Du musst den Timer aber nicht zweimal aufrufen, was soll denn das überhaupt bringen? Einmal IN:=False und gleich danach IN:=TRUE? Da kann der Timer doch gar nicht starten.

Mach es so:

```
timer(IN:={Startbedingung,bool},PT:={länger als die längste mögliche Taktzeit,time});
time := timer.ET; (*So wie im vorigen Beispiel angegeben*)
```


----------



## M_o_t (8 März 2012)

Ich bin mir zwar nicht sicher ob das TwinCat anbietet, aber normalerweise kannst du ja bei fallender Flanke die Systemzeit auslesen auf ein Variable speichern. Bei der zweiten fallenden Flanke wieder Systemzeit auslesen und die zuvor gespeicherte Zeit subtrahieren = Vergangene Zeit und zugleich wieder auf Zeitstempel für die nächste Messeung.

Gruß
M_o_t


----------



## 1985zottel (8 März 2012)

Hi

Ich hatte schon einmal fast die selbe Aufgabenstellung, hab das so gelöst:

Erste Flanke -> Timer 1 startet.

Zweite Flanke -> Timer 1 Stopt und Timer 2 startet, zusätzlich wird die gemessene Zeit von Timer 1 gespeichert (Merkerword, DB, ...)

Dritte Flanke -> Timer 2 Stopt und Timer 1 Startet wieder, Zeit von Timer 2 überschreibt gespeicherte Zeit.

Hab den Timerwechsel einfach mit einer FlipFlop schaltung gemacht. (Stromstoßschalter)


Hoffe ich konnte dir weiterhelfen


----------



## StructuredTrash (9 März 2012)

Bietet noch jemand mehr Timer?


```
VAR
   ZyklusZaehler:UDINT;
   GemesseneZeit:TIME;
END_VAR;


IF Triggerflanke
THEN
   GemesseneZeit:=UDINT_TO_TIME(Zykluszaehler*Taskzykluszeit);
   Zykluszaehler:=0;
END_IF;
ZyklusZaehler:=ZyklusZaehler+1;
```


----------



## Leto (3 April 2012)

Moin,

@ StructuredTrash:

Klingt logisch, aber woher bekomme ich die Taskzykluszeit?


----------



## Guarnere (3 April 2012)

Kannst du unter Ressourcen> Task Konfiguration selber bestimmen


----------



## DaHauer (3 April 2012)

vielleicht hilft Dir das weiter:
http://www.sps-forum.de/showthread.php/52080-Betriebsstundenzähler-über-Zykluszeit-erstellen


----------



## Leto (3 April 2012)

Ok, danke.

Jetzt habe ich aber noch eine abschließende Frage:

Wie kann ich in ST einen digitalen Eingang auf die positive oder negative Flanke abfragen?


----------



## Cerberus (3 April 2012)

Leto schrieb:


> Wie kann ich in ST einen digitalen Eingang auf die positive oder negative Flanke abfragen?



Mit den Bausteinen F_Trig und R_Trig aus der Standard.lib


----------



## Leto (3 April 2012)

Ok. Hab es dann doch über die Suche gefunden in ST.


```
VAR   
    timer :TON;
    GemesseneZeit:TIME;
    ZyklusZaehler:UDINT;
    fStartflanke: R_TRIG;
END_VAR
```


```
fStartflanke(CLK:= DI_Conv1TriggerPosNotReached);
IF (fStartflanke.Q) THEN
   GemesseneZeit:=UDINT_TO_TIME(Zykluszaehler*10); (*10 = 10ms Taskzyklus *)
   Zykluszaehler:=0;
END_IF;
ZyklusZaehler:=ZyklusZaehler+1;
```

Sollte so funktionieren denke ich.

Vielen Dank an alle


----------



## Cerberus (3 April 2012)

Leto schrieb:


> Ja, die sind mir bekannt, nur deren Aufruf mittels Structur Text leider nicht.



Als erstes deklarierst du eine Variable vom Typ R_Trig bzw. F_Trig und den Eingang:


```
fbRTrig: R_TRIG;
bInput1 AT %I*: BOOL;
```

Dann musst du den entsprechenden digitalen Eingang einbauen:


```
fbRTrig(CLK:= bInput1);
```

Zum Schluss musst du den Baustein noch auswerten:


```
fbRTrig();
IF NOT fbRTrig.Q THEN[INDENT]/* Dein Code */[/INDENT]
END_IF
```


----------



## asci25 (3 April 2012)

Cerberus schrieb:


> A
> Zum Schluss musst du den Baustein noch auswerten:
> 
> 
> ...



Es reicht aber, die Funktion einmal aufzurufen. Den 2.Aufruf fbRTrig(); kannst Du Dir sparen.


```
IF NOT fbRTrig.Q THEN[INDENT]/* Dein Code */
[/INDENT]
END_IF
```


----------



## Cerberus (3 April 2012)

asci25 schrieb:


> Es reicht aber, die Funktion einmal aufzurufen. Den 2.Aufruf fbRTrig(); kannst Du Dir sparen.
> 
> 
> ```
> ...



Aber nur wenn der erste Aufruf zyklisch aufgerufen wird. Passiert der erste Aufruf in einem Case-Step und die Abfrage in einem anderen Case-Step, dann muss vor der Abfrage erst der Baustein aktualisiert werden, wie in meinem Beispiel.


----------



## asci25 (3 April 2012)

Ich will jetzt auf keinen Fall eine Grundsatzdiskussion starten oder jemanden angreifen. Die Case Funktion war nicht ersichtlich.
Aber ich würde in so einem Fall den ersten Aufruf durch


```
fbRTrig.CLK:= bInput1;
```

ersetzen. 

 Das wäre aus meiner Sicht sauberer. So bleibt es bei einem zyklischen Aufruf.

Aber verwendet der TE überhaupt ein Case? Wahrscheinlich nicht....

Darum würde ich Ihm empfehlen:


```
fbRTrig(CLK:= bInput1);
If fbRTrig.Q Then
..
```


----------

