Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Hilfe bei einer Art Stopuhr


Blamaster - Mo 09.02.09 17:52
Titel: Hilfe bei einer Art Stopuhr
Hi,

ich brauche gerade mal Hilfe bei einer Art Stoppuhr. Ziel ist folgendes, ich habe eine Liste mit Millisekunden.

Nun brauchte ich eine "Stopuhr", welche in Millisekunden hochgezählt und dann mit dem Millisekundenwert aus der Liste verglichen wird. Sobald die Millisekunden übereinstimmen soll eine procedure ausgeführt werden und der nächste Wert der Liste angegelichen.

Jemand eine Idee wie das umsetzbar ist ?

mfg Blamaster


jaenicke - Mo 09.02.09 17:58

Am Anfang den Wert von GetTickCount merken, dann im Timer schauen ob der erste Wert der sortierten Liste mit Millisekunden erreicht ist. Danach dort zum nächsten gehen usw.
Ein Timer ist zwar nicht so genau, aber das wäre die einfachste Variante.

Unschöner aber ggf. genauer wären eine Warteschleife + QueryPerformanceCounter + ggf. Delay, das wäre nur sinnvoll, wenn es wirklich praktisch auf einzelne Millisekunden ankommt und nur um eine kurze Wartezeit insgesamt.


Hidden - Mo 09.02.09 18:00

Hi :)

Ergänzend: Du könntest den Timer auch auf ein Sicherheitsintervall davor stellen. Um die 100ms vor Erreichen des kritischen Zeitpunktes gehst du dann in die Warteschleife. Damit hast du's genau und hältst außerdem das System nicht auf.

mfG,


Blamaster - Mo 09.02.09 23:11

Hi,

beim erreichen einer Übereinstimmung sollen nur 2 Bytes über den Com Port gesendet werden.

Die Frage ist nur ob man überhaupt mit einem timerintervall von 1 ms arbeiten kann.

mfg Blamaster


jaenicke - Mo 09.02.09 23:21

Nein, kann man nicht, ca. 15ms ist das Minimum, manchmal mehr. Wenn das wirklich auf die Millisekunde genau sein soll, dann wäre wohl ein Thread die beste Lösung. Der kann eine niedrigere Priorität bekommen und kurz vor dem nächsten Ereignis dauerhaft prüfen.

Würde das das Hauptprogramm machen, würde es ggf. zu viel Rechnerleistung verwenden und auch nicht mehr reagieren.

Ist das wirklich so wichtig, ob das um wenige Millisekunden abweicht? Wenn ja, dann bleibt dir eigentlich nur ein Thread.


Blamaster - Mo 09.02.09 23:40

Hi,

nein wenn es um nur wenige Millisekunden abweicht ist das ganze unproblematisch. Es muss nur ebend für den Abgleich jede Millisekunde erfasst werden.

Wenn ich z.B. einen Timer auf 20ms setze und darin z.B. Inr(I) setzen würde und das ganze dann mit 24 Millisekunden abgeglichen werden soll würde ich ja zu keinem richtigen Ergebnis kommen.

Mir fehlt da irgendwie glaube ich gerade der richtige Denkansatz.

mfg Blamaster


jaenicke - Di 10.02.09 01:19

Du musst ja nicht testen ob die Zeit übereinstimmt, sondern ob die Zeit für das nächste Event erreicht oder überschritten ist. Und wenn das Timerevent dann ein paar Millisekunden später ausgelöst wird, dann wird dann das Event ausgelöst. ;-)


Blamaster - Di 10.02.09 14:07

Hi,

da kommt dann aber zwischen 1 ms und dem minimum für einen timer von 20 ms doch einen recht hohe differenz gibt es da nicht eine bessere Lösung ?

mfg blamaster


oldmax - Di 10.02.09 14:26

Hi
Ich hatte ein ähnliches Problem, hab mich dann mit der Stopuhr vom PC gelöst und einen Microcontroler damit beauftragt. Der paßt nun schön auf und zählt die Zeit. Kommt nun ein Ereignis, kann er selbst etwas tun und auch dem PC-Programm mitteilen, das da was war. Mit Zeitstempel und sonstigem Schnickschnack.
Anfangs hab ich mich da auch schwer getan, aber ich muß sagen, Atmega und Delphi sind zusammen ein ideales Paar.
Und es muß auch gar nicht teuer sein. Zum Einstieg reichen knappe 50 -60 €.
Da wär ein Programmer ca.15 € bei Pollin, ein Steckbrett für schnellen Schaltungsaufbau mit ein paar Widerständen Kondensatoren Dioden LED's etc und ein Billig-Steckernetzteil. Die Software gibt's im Internet.
Ob dir das hilft weiß ich nicht, denn ich kenne deinen Anwendungsfall nicht. Willst du allerdings sowieso externe Signale auswerten, bei Wettkämpfen oder ähnlichen Veranstaltungen, dann solltest du mal darüber nachdenken.
Gruß oldmax


Narses - Di 10.02.09 14:26

Moin!

Windows ist einfach kein Echtzeit-Betriebssystem, damit muss man leben. :nixweiss: Wenn du so exakte Zeitmessungen brauchst, geht das nur mit Polling unter hoher CPU-Last. :(

Aber, mal so Interessehalber: 20ms sind 1/50tel Sekunde, was machst du denn da, um so genaue Zeitmessungen zu benötigen. :gruebel:

cu
Narses


Blamaster - Di 10.02.09 14:49

Hi,

wenn ichs mir recht überlege ist eine so hohe genauigkeit wirklich nicht nötig.

Nur kann sich das bei einer langen Timerlaufzeit nicht recht schnell in die höhe treiben ? Denn der Verzug wird dann ja immer größer und größer kann man grob sagen in welchem Abweichungsrahmen man sich da bewegt ?

Und was genau bringt ein abgleich mit GetTickCount und wie resourcen fressend ist das ganze ?

mfg blamaster


jaenicke - Di 10.02.09 15:00

user profile iconBlamaster hat folgendes geschrieben Zum zitierten Posting springen:
Nur kann sich das bei einer langen Timerlaufzeit nicht recht schnell in die höhe treiben ? Denn der Verzug wird dann ja immer größer und größer kann man grob sagen in welchem Abweichungsrahmen man sich da bewegt ?
Wie gesagt: ca. alle 15-25ms ist ca. das Minimum alle die ein Timer ausgelöst werden kann.

Aber das hat doch mit der Laufzeit nix zu tun und mit der Genauigkeit des Abgleichs an sich schon gar nicht. :gruebel:

user profile iconBlamaster hat folgendes geschrieben Zum zitierten Posting springen:
Und was genau bringt ein abgleich mit GetTickCount und wie resourcen fressend ist das ganze ?
Mit GetTickCount misst du ja die vergangene Zeit, das geht sehr schnell.


Blamaster - Di 10.02.09 15:07

Ich meine gelesen zu haben das der Delphi Timer nich besonders genau zählt. Und da würde mit der Zeit die spanne der Ungenauigkeit immer größer werden oder nicht ?

mfg Blamaster


jaenicke - Di 10.02.09 15:11

user profile iconBlamaster hat folgendes geschrieben Zum zitierten Posting springen:
Ich meine gelesen zu haben das der Delphi Timer nich besonders genau zählt. Und da würde mit der Zeit die spanne der Ungenauigkeit immer größer werden oder nicht ?
Wie das? Ob du nun alle 10 Millisekunden ein Timerereignis bekommst oder teilweise alle 20 und manchmal alle 30 ändert doch an der Genauigkeit nix. Du registrierst nur ggf. erst ein paar Millisekunden später, dass die Zeit erreicht ist.

Wenn 1 ms nach dem letzten Timerevent die Zeit erreicht wird und das nächste nach 10ms kommst, dann kommt es 9ms später, wenn das erst 20ms nach dem letzten kommt, dann sind es eben 19ms. Wenn eben die nächste Prüfung passiert.

Kann es sein, dass du dir überlegst die Zeitmessung anhand der Anzahl der vergangenen Timerereignisse zu machen? :shock:


Blamaster - Di 10.02.09 16:27

Ich hatte mir das so gedacht (Timer gestellt auf 20ms)

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
procedure TForm1.Timer1Timer(Sender: TObject);
var
I:Integer;
begin
I:= I + 20;

If I >= WertAusListen Then // mach irgendwas
end;

Oder übersehe ich da eine bessere Lösung ?

mfg Blamaster

Moderiert von user profile iconNarses: Delphi-Tags hinzugefügt


jaenicke - Di 10.02.09 17:39

Dass das so nix wird, ist klar.

Im Button zum Starten merkst du dir den Wert von GetTickCount. Im Timer rechnest du dann die Differenz zwischen dem gespeicherten und dem aktuellen Wert aus, das sind die seither vergangenen Millisekunden... ;-)


Blamaster - Di 10.02.09 19:19

Hi,

Danke soweit gehts nun. Ist es schlauf den Abgleich der Zeit innerhalb des On Timer Ereignis zu machen ?

mfg blamaster


jaenicke - Di 10.02.09 19:39

Ja, sicher.

Und zur Speicherung der Ereignisse könntest du z.B. eine verkettete Liste benutzen. Dann wäre das Löschen des abgearbeiteten Eintrags z.B. sehr schnell möglich (anders als bei z.B. einem Array).


Blamaster - Mi 11.02.09 11:00

Hi,

Danke für die Hilfe !

Ist es schlau das senden über dem Comport auch im Timer Event zu setzen ?

Denn ist es nicht so das der Code im Timer Event nicht größer sein sollte (länger dauern sollte) als das Timerintervall dauert ?

mfg Blamaster


Nico72 - Mi 11.02.09 12:47

Hallo,

wenn du Angst hast, das dein Timer sich selbst einholt, setze einfach am Anfang deiner OnTimer-Methode den Timer auf Enabled=false und am Ende wieder auf Enabled=true. Vielleicht in einem try-finally-Block.