Zeitmessung im us bereich #Hilfe bei SysTimeGetUs()

CodeSysStarter

Level-1
Beiträge
4
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Moin Ich schlage mich seit einer Woche mit einem Problem rum.

Ich möchte eine Zeitmessung machen. Messe Systemzeit an Punkt A und an Punkt B. Die Differenz ergibt die Laufzeit.
Soweit so gut.

In meinem Programm habe Ich mit SysTimeGetMs() aus der SysTimeCore bereits eine Funktionierende aber nicht ausreichende Zeitmessung implementiert.
Jetzt möchte Ich SysTimeGetUs() verwenden und habe keine Idee wie ich mit dier funktion umgehen soll.
Im speziellen wie müssen die Pramameter übergeben werden. Welche Parameter müssen über geben werden?

Ich verwende Codesys 3.5 Patch 2 und alles soll erstmal auf dem Imulator laufen.

ICh bin für jede Hilfe Dankbar.

mfg CodeSysStarter
 
Also soweit ich Dokumentation dazu gefunden habe (Google ist da nicht besonders hiflreich): SysTimeGetUs bekommt als in/out-Parameter die Variable, in der die Zeit gespeichert werden soll, und gibt als Rückgabewert einen Fehlercode.
 
Ja also ich hatte das mal porbiert wie folgt:

VAR
t1: TIMER;
END_VAR

___________________________

fehler := SysTimeGetUs(ADR (t1));

dabei wirft der kompiler mir aber vor das Ich einen wert mit schreibzugriff über geben muss
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Du musst mal nachsehen, welche Datentypen die Funktion haben möchte.
Ichkenne die Funktion nicht, habe hier aber ein Beispiel mit deren Anwendung+ Variablendeklaration gefunden. Gemessen wird hier eine Codeausführungszeit.
 
Zuletzt bearbeitet:
Hi
so:

1. SysTime library im Bibliotheksmanager hinzu
2. Dekalration:

Code:
VAR
 dwTime: DWORD;
 st1, st2: SysTime;
 std: SysTimeDate;
 TimeStamp: SYSTIME;
 i: DINT;
 diValue1: DINT:=10000;
 diCounter: DINT;
 nState: INT;
END_VAR

Implementierung:

Code:
SysTimeGetUs(st1);
 
//code to measure
FOR i:=1 TO diValue1 DO
 diCounter:=diCounter+1;
END_FOR
 

SysTimeGetUs(st2);
dwTime := ANY_TO_DWORD(st2 - st1);

Grüße
 
Danke für die Unterstüzung,
@weißnix_ und @Edwin:

Danke für die grandiose Hilfe:
Der gebene Link war Super hilfreich und das Code Bsp noch viel mehr.
Ich hatte erwarteet das Codesys alle Projekt bekannten Datentypen farblich hervorhebt ,aber das war wohl mein Trugschluss.
Aufjedenfall läuft es jetzt.

Danke für die schnelle und kompetente Unterstüzung
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,

es ist zwar schon eine Zeit lang her, als dieser Thread eröffnet wurde, aber kann hier nicht ein Überlauf bei der Berechnung der Differenz entstehen, also die Startzeit < Endzeit? Zugegeben, wir haben einen 32 bit Wert... aber ich weiß nicht wo weggezählt wird.
Meine Bedürfnisse sind zwar nur im ms-Bereich, aber theoretisch ist das doch möglich?

LG, PAHO
 
Zugegeben, wir haben einen 32 bit Wert... aber ich weiß nicht wo weggezählt wird.
Doch! Beim 1. Einlesen der Zeit liest Du den Wert "wo weggezählt wird".
Und von dem beim 2. Einlesen eingelesenen Wert ziehst Du den "wo weggezählt wordenen" Wert ab.
Die Wahrscheinlichkeit, dass das 1. Einlesen direkt vor dem Überlauf stattfindet und das 2. direkt danach ist zwar klein, aber durchaus nicht 0.
Das ist aber kein Grund zur Panik. Wenn Du z.B. von 1 (beim 2. Einlesen) eine -1 (beim 1. Einlesen) abziehst, ist das Ergebnis - oh Wunder - 2, also völlig korrekt.
 
Ok, da ich eine etwas andere Anforderung habe (Laufzeitmessung von z.B. Stellantrieben), wird der 1. Wert bei mir über viele Zyklen gespeichert. Genauer gesagt, vom Startzeitpunkt der Bewegung des Antriebes bis zum Ende der Bewegung.

Ich verwende Codesys mit einem Revpi Connect+ und habe nun einen eigenen "Time-Task" mit einer Zykluszeit von 100us angelegt. Dort Zählt mir ebenfalls ein 32bit-Wert mit dem Programmdurchlauf hoch bzw. runter. Meinen ersten Test nach dürfte das ganz brauchbar sein. Da ich aus der Sparte Mikrocontroller komme und dort mit eigenen Interrupts von Timern der Controller gearbeitet habe, ist das hier ein wenig anders.

Könnte das Zählen mit dem Programmzyklus ein Problem werden? Meine Auflösung ist nicht sehr hoch - komme normal mit 100ms Schritten aus.

LG, PAHO
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Dein letzter Beitrag verwirrt mehr als das er aufklärt...
Wie lang sind die Zeiten die Du messen willst und mit welcher Auflösung brauchst Du die? Kann es passieren daß während einer Zeitmessung die SPS AUS oder in STOP ist?

Harald
 
Wie lang sind die Zeiten die Du messen willst ...?
Genau! Ich hatte die Aufgabenstellung eigentlich so verstanden, dass Anfang und Ende der MessPeriode im selben Zyklus (oder zwei aufeinander folgenden Zyklen) liegen.
Können innerhalb der MessPeriode mehr als ein (eigentlich ein "halber") Überlauf stattfinden? Aber ich möchte Harald nicht vorgreifen. Er kann so perfekt beschreiben, dass auch dieser Fall leicht beherrschbar ist. ;)
 
Vorweg mal danke für die Antworten! Da ich bei meiner Suche nach Zeitmessungen auf diesen Thread gestoßen bin, habe ich nicht bedacht dass meine Anforderung etwas abweicht...

Die Anforderung ist: Laufzeitmessung von Stellantrieben in Millisekunden mit Prozentberechnung der aktuellen Öffnung. Ich möchte also mitzählen, wie lange der Stellantrieb bei Signale "Öffnen" und Schließen" läuft. Öffnen natürlich hochzählen und Schließen runterzählen. Grenzwerte sind die von mir vorgegebene Gesamtlaufzeit in Millisekunden -> z.B. 150 Sekunden Laufzeit = 150000ms = 100%.

Bei der SysTime dachte ich mir eben, weil ich ja über X-Zyklen die Zeit messe, dass ein Überlauf sehr wohl stattfinden könnte und die Berechnung dann komplett falsch ist. Da müsste ich den Überlauf erkennen und ebenfalls in die Berechnung einbinden.
Jetzt dachte ich mir, ich lege einen Task an welcher mit einer definierten Zykluszeit von 100us läuft, zähle mit einem Byte bis 10 und lasse dann meinen Millisekunden-INT32 hoch bzw. runterzählen, welcher dann die tatsächliche Laufzeit darstellt.

Grundsätzlich funktioniert das auch recht gut beim simulieren - aber ich weiß eben nicht ob diese Zykluszeiten grundsätzlich eingehalten werden, oder ob man doch eher auf SysTime ausweichen sollte.

Danke und LG!
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Für die Messung der Zykluszeit gibt es hier einige Beispiele.

Wenn Ausgang gesetzt ist, merkst du dir das für den nächsten Zyklus (DB, . . .)
am Zyklusanfang merkst du dir die Zykluszeit vom letzten Zyklus

Am Anfang deines aktuellen Zyklus addierst du einfach die Zykluszeit vom letzten Zyklus wenn der Ausgang gesetzt war.
Danach den Ausgangsmerker (DB, . . .) zurücksetzen

danach erst dein reguläres Programm aufrufen.
 
Jetzt dachte ich mir, ich lege einen Task an welcher mit einer definierten Zykluszeit von 100us läuft, zähle mit einem Byte bis 10 und lasse dann meinen Millisekunden-INT32 hoch bzw. runterzählen, welcher dann die tatsächliche Laufzeit darstellt.
Was soll das bringen, eine Task von 100µs zu verwenden, wenn Du nur ganze Millisekunden zählen willst/brauchst? Da kannst Du auch direkt in einer 1ms Task zählen.

Bei der Schließzeit mußt Du nicht rückwärts zählen, Du kannst auch den skalierten %-Wert von 100% abziehen.

Bei der SysTime dachte ich mir eben, weil ich ja über X-Zyklen die Zeit messe, dass ein Überlauf sehr wohl stattfinden könnte und die Berechnung dann komplett falsch ist. Da müsste ich den Überlauf erkennen und ebenfalls in die Berechnung einbinden.
Da brauchst Du nichts besonderes beachten. Mit einem Millisekunden-INT32-Zähler kannst Du ohne weiteren Aufwand Zeiten bis ca 596 Stunden (ca. 24,8 Tage) messen mit einer Auflösung von 1 ms (mit ein bisschen mehr Programmierung doppelt so lange). Du brauchst auch nicht den Zählerstand beim Mess-Start auf 0 setzen, sondern kannst den Zähler frei laufen lassen und Dir nur den Zählerstand_Start merken. Es ist egal ob während der Messung ein 32-Bit-Überlauf stattfindet, weil bei einem reinen Vorwärtszähler dank des genialen Zweierkomplements die Differenz "Zählerstand_Ende - Zählerstand_Start" immer die korrekte positive Differenz ist, solange die Zeitdifferenz kleiner als der halbe Zählumfang (die 24,8 Tage) ist. Wenn es in der CPU schon einen 32 Bit Systemzeitzähler der Millisekunden gibt, dann würde ich den direkt verwenden.

Harald
 
Wenn da in jedem Zyklus eine gerundete ms Zeit dazu gezählt bzw. abgezogen wird, kann sich ein zusätzlicher Fehler aufsummieren, ich würde daher eher die Zeit messen solange die Ansteuerung dauert.

tonOeffnen: TON; tonSchliessen: TON; tOeffnungMem : TIME; tOeffnungTotal : TIME; bSchliesst: BOOL; bOeffnet: BOOL;

IF NOT bOeffnet AND tonOeffnen.ET > T#0ms THEN tOeffnungMem:=tOeffnungMem+tonOeffnen.ET; END_IF; IF NOT bSchliesst AND tonSchliessen.ET > T#0ms THEN tOeffnungMem:=tOeffnungMem-tonSchliessen.ET; END_IF; tOeffnungTotal:=tOeffnungMem+tonOeffnen.ET-tonSchliessen.ET; tonOeffnen(IN:=bOeffnet , PT:=T#5d , Q=> , ET=> ); tonSchliessen(IN:=bSchliesst,PT:=T#5d,Q=> ,ET=>);

Das geht mit einem ganz normalen Timer. Bleibt das Problem, dass bei jeder Signalzustandsänderung auch ein Rundungsfehler passiert und sich aufsummieren kann. Desweiteren ist das Ding irgendwann ganz offen oder geschlossen. Wie wird das erkannt? Hat das Ding Endschalter die abgefragt werden können um ggf. die Zeit auf Min bzw. Max zu setzen?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Paho
Das genaueste Ergebnis liefert das Auslesen der Systemzeit.
Die IEC Timer sind immer an die Tasklaufzeit gebunden.
.
PS
Die tatsächliche Laufzeit deines Stellantriebes ist allerding von viel mehr als das setzen einer Variable abhängig.
Dazu kommen Buslaufzeiten, Ansprechzeiten der I/O Karten, Reaktionszeiten der Relais/Schütze sowie mechanische Verzögerungen (Getriebe, Reibung...)
Du solltest dir viel mehr Gedanken darüber machen wie du deine Positionen syncronisierst als der letzten ms hinterher zu laufen.
Es wird immer eine Diskrepanz zwischen Soll- und Istposition bei reiner theoretischen Betrachtung geben.
 
Zurück
Oben