# Vergangene Sekunden ab Zeit X berechnen in SCL



## ssyn (16 Februar 2022)

Ich habe eine Frage. Will die Sekunden ab bestimmte Ereignis berechnen und danach bestimmte Prozedur starten.
Ich versuchte es mit TON und TOF machen, aber konnte nicht da die Lösung finden, wenn die PV nicht bekannt ist.

Dann finde die Lösung - einfach die Intervall vom Task benutzen. Z.B. Intervall ist t#20ms, dann geht es mit folgende Code


```
IF maschine2.OnOff AND testing < 1000 THEN
    testing:= testing + 1;  
ELSE
    maschine1.OnOff:=TRUE;  
END_IF
```

Sobald ist die "Maschine2" ist TRUE, dann nach 20 Sekunden startet "Maschine1". 

Aber  weiß nicht ob es ist gute Code, weil in Zukunft das Intervall geändert werden könnte. Gibt es die Alternative ohne Intervall solche Aufgabe zu lösen?

P.S. Die Aufgabe ist NICHT einfach nach 20 Sekunden etwas machen, sondern die Anzahl von Sekunden ab Ereignis berechnen.


----------



## JSEngineering (16 Februar 2022)

ssyn schrieb:


> Ich versuchte es mit TON und TOF machen, aber konnte nicht da die Lösung finden, wenn die PV nicht bekannt ist.


Was meinst Du mit "PV nicht bekannt"?
Auf welchem System programmierst Du?
Die Intervall-Lösung ist nicht schön, da sich durch Unterbrechungen ggf. die Zyklen verlängern können - je nach dem, wei genau Du die Zeit haben mußt. - Neben dem bereits von Dir genannten Grund.
Außerdem ist der Code nicht offensichtlich zu verstehen, man muß erst die Zusatzinformation "Zykluszeit" einholen.

Am besten ist, ein TON zu verwenden. Aber damit hast Du ja irgendein Problem... welches?


----------



## ssyn (16 Februar 2022)

JSEngineering schrieb:


> Am besten ist, ein TON zu verwenden. Aber damit hast Du ja irgendein Problem... welches?



Sorry, ich hab falsch es erklärt. Ich will genau die Anzahl von Sekunden ab Ereignis X berechnen.  Danach benutze sie weiter. So, Stoppuhr für Sekunden und ich weiß nicht, wann muss sie gestoppt werden, das hängt von andere Variables ab.


----------



## JSEngineering (16 Februar 2022)

Dein Code-Beispiel sagt aber was Anderes: Du schaltest Maschine1 erst X Sekunden nach Maschine2 ein. Das ist ein TON.

Wenn Du nur Zeit messen willst: Systemzeit auslesen, wegspeichern und bei Ereignis 2 dann die Systemzeit erneut auslesen, voneinander abziehen und Du hast mit der Differenz die vergangene Zeit.


----------



## idtell (16 Februar 2022)

ist hier nicht nur das hier gesucht ? beim starten :start_Time:=TIME(); dann aktivetime := TIME() -start_Time; ?


----------



## PN/DP (16 Februar 2022)

Eine Problemstellung korrekt und verständlich formulieren ist meistens schon die halbe Lösung.

Man könnte in einer zyklischen Task (z.B. OB35 alle 100 ms) einen endlos-Zähler (DINT) programmieren, und im "normalen" Programm beim Ereignis den Zählerstand lokal speichern. Dann ist die seit dem Ereignis vergangene Zeit die Differenz zwischen Zählerstand jetzt und gemerktem Zählerstand. (Man könnte auch vorwärts in die Zukunft rechnen.)

Um wieviele Sekunden maximal geht es? Wie genau / mit welcher Auflösung muß die Zeit abgemessen werden?

Harald


----------



## ssyn (16 Februar 2022)

idtell schrieb:


> ist hier nicht nur das hier gesucht ? beim starten :start_Time:=TIME(); dann aktivetime := TIME() -start_Time; ?



Versuchte es zu machen gleich, kriege seltsame Zeit - T#5h6m13s177ms

Obwohl jetzt ist 11:54


----------



## DeltaMikeAir (16 Februar 2022)

ssyn schrieb:


> Versuchte es zu machen gleich, kriege seltsame Zeit - T#5h6m13s177ms


Dann zeig doch einfach einmal, was du da machst. Den Code also


----------



## ssyn (16 Februar 2022)

JSEngineering schrieb:


> Wenn Du nur Zeit messen willst: Systemzeit auslesen, wegspeichern und bei Ereignis 2 dann die Systemzeit erneut auslesen, voneinander abziehen und Du hast mit der Differenz die vergangene Zeit.



Kannst du bitte Beispiel oder Link für solche Lösung geben?


----------



## JSEngineering (16 Februar 2022)

ssyn schrieb:


> Kannst du bitte Beispiel oder Link für solche Lösung geben?


Sag doch erstmal, auf welchem System Du programmierst...


----------



## ssyn (16 Februar 2022)

Jetzt nur lerne SCL, prüfe Code in Simulation in Codesys V3.5.

Name: CODESYS Control Win V3
Hersteller: 3S - Smart Software Solutions GmbH
Kategorien: Steuerungen (SPS)
Typ: 4096

P.S. DeltaMikeAir, eigentlich in Code gibts nix, habe nur ein Struct und Enum erstellt.


```
timee:= TIME();
```

WERT: T#5h56m30s310ms (noch läuft weiter).


----------



## DeltaMikeAir (16 Februar 2022)

ssyn schrieb:


> Jetzt nur lerne SCL, prüfe Code in Simulation in Codesys V3.5.


Der Form halber:
CoDeSys wäre die Sprache ST
SCL kommt aus dem Siemens Universum


----------



## ssyn (16 Februar 2022)

Hmm, ich dachte , dass ST = SCL. Oder nicht? Gibt es große Unterschiede dazwischen?


----------



## DeltaMikeAir (16 Februar 2022)

ssyn schrieb:


> Hmm, ich dachte , dass ST = SCL. Oder nicht? Gibt es große Unterschiede dazwischen?


Im Prinzip gleich, in Details ( ein wenig ) unterschiedlich. Wenn jemand SCL sagt, dann denkt man gleich an Siemens und bei ST an CoDeSys...


----------



## DeltaMikeAir (16 Februar 2022)

Vertippt


----------



## idtell (16 Februar 2022)

ssyn schrieb:


> Versuchte es zu machen gleich, kriege seltsame Zeit - T#5h6m13s177ms


time() zeigt die Zeit ab Steuerungstart an (in ms). Wenn Du bei Steuerung Strom nimmst und wieder gibst dann startet Zeit neu bei 0ms. Ist in der Hilfe leider verzwickt den Befehl zu finden da es einen gleichnamigen Datentyp gibt.
einmal den Startzeipunkt deiner Messung erfassen. dann während die Messung aktiv ist den aktuellen Zeitwert damit offsettieren = Messzeit.
eventuell das Resultat wandeln =>  time_to_dint(resultat) /1000 damit es in Sekunden ist.


----------



## ssyn (16 Februar 2022)

idtell, danke für tipp, ich fand gerade schon selbst die Konventierung TIME_TO_LREAL gefunden und hatte gedacht, ob es für mich eine Lösung wäre.


----------



## Heinileini (16 Februar 2022)

ssyn schrieb:


> ```
> IF maschine2.OnOff AND testing < 1000 THEN
> testing:= testing + 1;
> ELSE
> ...


Statt ...

```
testing := testing + 1 ;
```
... wäre es "lesbarer" ...

```
testing := testing + 20 ; // ZyklusZeit 20 ms addieren
```
... zu schreiben.
Und ja, natürlich kann man in ...

```
IF maschine2.OnOff AND testing < 1000 THEN
// oder 
IF maschine2.OnOff AND testing < 20 * 1000 THEN
```
... statt mit einer Konstatnen '1000' oder '20 * 1000' mit einer Variablen vergleichen.
Z.B.:

```
IF maschine2.OnOff AND testing < anzahlSekunden * 1000 THEN
```



ssyn schrieb:


> idtell, danke für tipp, ich fand gerade schon selbst die Konventierung TIME_TO_LREAL gefunden und hatte gedacht, ob es für mich eine Lösung wäre.


Warum per 'TIME_TO_LREAL' in LREAL konvertieren? Dann müsstest aber beide zu vergleichenden Werte in LREAL konvertieren --> unnötiger, überflüssiger, irreführender Umweg!
'TIME_TO_DINT' sollte es auch geben (aber eigentlich hier unnötig sein?).


----------



## ssyn (16 Februar 2022)

Heinileini, als ich verstehe, 


```
time1:= TIME_TO_DINT (TIME());
//Ereignis 1
time2:= TIME_TO_DINT (TIME());
//Ereignis 2
sekunden:= time2-time1;
```


bringt mir anzahl von Sekunden zwischen time2 und time1 ?


----------



## idtell (16 Februar 2022)

ms , dividiere das noch durch 1000


----------



## ssyn (16 Februar 2022)

Heinileini schrieb:


> Warum per 'TIME_TO_LREAL' in LREAL konvertieren? Dann müsstest aber beide zu vergleichenden Werte in LREAL konvertieren --> unnötiger, überflüssiger, irreführender Umweg!



Sorry, ich bin nur ein paar Wochen in SCL und mache natürlich viel dummes. ☹️


----------



## Frohnius (17 Februar 2022)

hmm also wenn du einen klaren startzeitpunkt hast und die zeit stoppen willst ...
dann nimm doch einfach ein TON (wie hier schon einige geschrieben haben)

egalTON(IN:=start, PT:=t#max ........ usw
und über egalTON.ET erhälst du doch die aktuell abgelaufene zeit


----------



## StructuredTrash (17 Februar 2022)

Warum soll er einen TON nehmen, wenn er ihn gar nicht braucht. Bei Start- und Endzeitpunkt mit der TIME()-Funktion die aktuelle Zeit lesen und die Differenz bilden ist doch weit effizienter als in jedem Zyklus einen TON aufzurufen, der niemals ablaufen soll.


----------



## Frohnius (21 Februar 2022)

hmm da hast du wohl schon recht ....
die abfrage "if ereignis zeit merken" und "if ereignis differenz berechnen" muss ja auch in jedem zyklus laufen ...
spart mal angenommen sogar zykluszeit - aber meinst dass der cpu-load unterschied tatsächlich messbar, oder einer beachtung wert ist ?

ich habe sogar recht aktuell beides ausprobiert und getestet ... um die exakte laufzeit eines schiebers zu messen ....
und zumindest bei einer schneider / codesys M251 lässt sich kein unterschied feststellen bei 2ms Zykluszeit ...


----------



## idtell (21 Februar 2022)

Naja da wird der ms-Sekundenwert natürlich nicht mehr viel bringen. Da gibs nur noch den Weg über die us .. aber die Funktion ist nicht immer verfügbar. "verfügbar" Ausdruck unglücklich gewählt, eher so : wenn das System darunter die Zeit einfach nur in ms-Auflösung liefert, dann springt der Wert einfach in eben


----------



## Frohnius (21 Februar 2022)

jupp .. naja und in meinem fall muss ich die exakte zeit stoppen, wenn der schieber die endlage verlässt ... also sind soweiso trigger abfragen nötig .. was TON mit erledigt ... 
ich verwende bei sowas ganz gerne die zuverlässigen standard bausteine, die schon immer funktioniert haben.

aber das ist eben geschmackssache weder die eine, noch die andere möglichkeit halte ich für besser, schlechter oder falsch.


----------



## StructuredTrash (21 Februar 2022)

Frohnius schrieb:


> aber meinst dass der cpu-load unterschied tatsächlich messbar, oder einer beachtung wert ist ?


Heutzutage wohl nicht mehr, es sei denn Du hättest sehr, sehr viele solcher Messungen im Programm.
Dass ich solchen Dingen Beachtung schenke, liegt wohl daran, dass ich schon Programmier-Opa bin. Früher musste man um jede Mikrosekunde kämpfen.


----------



## Frohnius (22 Februar 2022)

StructuredTrash schrieb:


> Dass ich solchen Dingen Beachtung schenke, liegt wohl daran, dass ich schon Programmier-Opa bin. Früher musste man um jede Mikrosekunde kämpfen.



was sps angeht bin ich noch nicht sooo lange dabei und deshalb wohl durchaus verwöhnt 
aber ich weiß genau was du meinst ... als ich in früher jugend C64 in assembler programmiert habe, war das oft am limit mit 0,9 MHz taktfrequenz und bei jedem rasterzeilen-interupt gings um millisekunden


----------



## Heinileini (22 Februar 2022)

Frohnius schrieb:


> ... war das oft am limit mit 0,9 MHz taktfrequenz und bei jedem rasterzeilen-interupt gings um millisekunden


Jetzt mal für einen SPS-Opa, der - warum auch immer - den C64 übersprungen hat: was ist denn ein RasterZeilen-Interrupt? Interrupt ist klar, aber diese ominösen RasterZeilen? Hat das was mit dem Glotzophon als AnzeigeMedium zu tun?


----------



## Frohnius (23 Februar 2022)

der video-chip des c64 lieferte bei jedem zeilenwechsel einen interupt den man nutzen konnte um z.b. etwas darzustellen was nicht "flackern" darf oder im rand des bildschirmes die farbe zu wechseln ... und hier blieben auch nur ein paar wenige taktzyklen zeit  man konnte z.b. dadurch einen sprite (=bewegliches bitmap mit 16x16 pixel  - das limit des chips waren 8 stück ) einfach am bildschirm weiter unten noch einmal verwenden ... und ihn natürlich rechtzeitig oben wieder einblenden bevor das nächste bild aufgebaut wird ....
vergleicht man software von damals - und heute, unter berücksichtigung der enormen leistungsfähigkeit aktueller hardware - ist die software einfach nur dramatisch schlechter geworden.


----------



## ssyn (13 April 2022)

Ich habe selbst neue Lösung gefunden:


```
VAR
aaa : BOOL;
ttt2 :RTC;
ttt0: DINT;
END_VAR
...
ttt2(EN:=aaa);
ttt0 := TIME_TO_DINT(ttt2.CDT - ttt2.PDT) / 1000;
```


----------

