Time Funktion, weche Zeiteinheit?

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Time Funktion, weche Zeiteinheit?

Beitrag von mschnell »

Unter Windows oder "normalem" Linux ist eine Zeitmessung sowieso nur sinnvoll, wen die zeitlichen Messpunkte nicht kritisch sind. Das OS kann Dein Programm ungefragt Sekunden lang einfach nicht ranlassen, wenn da irgendwelche internen Prozesse Vorrang haben (z.B. ein USB-Stick wird erkannt) .

-Michael

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: Time Funktion, weche Zeiteinheit?

Beitrag von Timm Thaler »

Naja, die Wahrscheinlichkeit dafür ist mit Mehrkern-Prozessoren deutlich gesunken. Und wenn man wirklich zeitkritische Sachen machen muss, kann man auch - konnte man zumindest früher unter Windows - die Prozesspriorität kurzzeitig bis auf "Realtime" erhöhen. Aber wirklich nur kurzzeitig, denn das hat den Rest fast komplett lahmgelegt. Geht das heute nicht mehr?

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Time Funktion, weche Zeiteinheit?

Beitrag von mschnell »

Genau !

Ob man mit "Wahrscheinlichkeit dass der Messwert einigermaßen stimmt" leben kann, hängt natürlich von der Anwendung ab.

-Michael
Zuletzt geändert von mschnell am Do 25. Okt 2018, 11:44, insgesamt 1-mal geändert.

siro
Beiträge: 730
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: Time Funktion, weche Zeiteinheit?

Beitrag von siro »

Für Zeitmessungen unter Windows nehme ich jetzt immer folgenden Code:

Wichtig: es muss
Uses Windows mit aufgenommen werden.

Code: Alles auswählen

 
var freq,tStart,tStop:Int64;
var t:Single;
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  QueryPerformanceFrequency(freq)
 
  QueryPerformanceCounter(tStart);   // Startzeit
  Sleep(1000);                           
  QueryPerformanceCounter(tStop)// Endzeit
 
  t:=(tStop-tStart) / freq;    // in Sekunden umrechnen
  Form1.caption:=FloatToStr(t)// Ausgabe
end;         
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: Time Funktion, weche Zeiteinheit?

Beitrag von Timm Thaler »

Ich hab so dunkel im Hinterkopf, dass das ziemlich genau das ist, was auch GetTickCounts unter Windows macht.

siro
Beiträge: 730
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: Time Funktion, weche Zeiteinheit?

Beitrag von siro »

Du kannst mit QueryPerformanceCounter viel präziser auflösen, wohl bis zu 100 Nanosekunden.

https://docs.microsoft.com/de-de/window ... ime-stamps
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Time Funktion, weche Zeiteinheit?

Beitrag von mschnell »

Was soll eine Hohe Auflösung nützen, wenn eine Präzision sowieso nur im Sekunden-Bereich möglich ist ?

-Michael

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: Time Funktion, weche Zeiteinheit?

Beitrag von Timm Thaler »

mschnell hat geschrieben:Was soll eine Hohe Auflösung nützen, wenn eine Präzision sowieso nur im Sekunden-Bereich möglich ist ?


Ist sie ja nicht. Mit Priorität auf RealTime ist reproduzierbares Timing im 100usec und msec-Bereich möglich. Ich hab das mal für MM-Protokoll für Modellbahn über die serielle Schnittstelle gemacht*. Zumindest unter Win98 ging das, ob das moderne OS noch zulassen weiß ich nicht.

Man muss aber aufpassen, das System wird echt unbedienbar, wenn man vergisst die Prio wieder zurückzustellen, und nach 2 Sekunden schießt Windows das Programm dann ab.

*) und natürlich geht das nur mit echten Uarts, nicht mit OS-gepufferten USB-seriell-Wandlern.

siro
Beiträge: 730
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: Time Funktion, weche Zeiteinheit?

Beitrag von siro »

Die hohe Auflösung gibt Sinn wenn man mal eine Abschätzung für die Laufzeit einer Funktion haben möchte,
oder vergleichen will, geht der Code schneller, oder doch eher da andere.

@TimmThaler:
Schade, haste leider recht, die echten Uarts gibts ja nicht mehr.
Da konnte ich noch direkt die Interrupts programjerien usw.
Mit den USB Convertern geht das leider nicht mehr. Die Puffern zu viel.
Man hinkt immer hinterher, obwohl man das teilweise einstellen kann.
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: Time Funktion, weche Zeiteinheit?

Beitrag von Timm Thaler »

siro hat geschrieben:Schade, haste leider recht, die echten Uarts gibts ja nicht mehr.
Da konnte ich noch direkt die Interrupts programjerien usw.


Zum einen haben viele Motherboards noch eine COM1, nur nicht nach aussen geführt. Zum anderen gibt es PCI-Steckkarten für bis zu 8 Uarts. Die sind schon sehr Echtzeit. Nur über Register ansprechend kannst Du die auch nicht, das geht aber seit Win98 nicht mehr, oder war es Win95?

Also wer noch echte Uarts braucht, hat schon Möglichkeiten.

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Time Funktion, weche Zeiteinheit?

Beitrag von mschnell »

Timm Thaler hat geschrieben: Mit Priorität auf RealTime ist reproduzierbares Timing im 100usec und msec-Bereich möglich.

Die Frage ist nicht nach "möglich" sondern nach "garantiert".

-Michael

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: Time Funktion, weche Zeiteinheit?

Beitrag von Timm Thaler »

mschnell hat geschrieben:Die Frage ist nicht nach "möglich" sondern nach "garantiert".


Dann schreib ichs halt noch mal um: Mit Priorität auf RealTime ist reproduzierbares Timing im 100usec und msec-Bereich garantiert.

Und ja, das war garantiert. Mit RealRTime hattest Du die höchste Priorität, und alle anderen Prozesse wurden zurückgestellt. Da reagierte auch kein Fenster mehr und andere Programme hatten Pause. Da liefen nur noch die rudimentärsten Betriebssystemaufgaben, die dann zum Beispiel Dein Programm abgeschossen haben, wenn Du das zu lange getrieben hast.

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Time Funktion, weche Zeiteinheit?

Beitrag von mschnell »

OK ! Super !

Mit welchen Windows Versionen geht das und wie genau (in Lazarus) ?

Gruß und Dank,
-Michael

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: Time Funktion, weche Zeiteinheit?

Beitrag von Timm Thaler »

mschnell hat geschrieben:Mit welchen Windows Versionen geht das und wie genau (in Lazarus) ?


Nix Lazarus. Das war in PureBasic unter Zugriff auf die Win-Api.

Hiermit wurde der Kalibrierwert ermittelt für 100usec:

Code: Alles auswählen

Procedure.f InitTimer()
  FREQ.Large_integer 
  mem = AllocateMemory(8)  ;Speicher reservieren, sonst gehts nich
  If QueryPerformanceFrequency_(mem)  ;Bestimmen der frequenz
    CopyMemory(mem, @FREQ, 8)  ;Variable kopieren
    Zeit.f = (FREQ\lowpart) / 10000  ;Kalibrierwert Counts pro 100usec
    ProcedureReturn Zeit.f
  Else
    ProcedureReturn 0  ;kein Hardware-Timer
  EndIf
  FreeMemory(mem) 
EndProcedure


Hiermit wurde die Pause erzeugt:

Code: Alles auswählen

Procedure.f DelayTimer(tdelay.f)
  TIMER.Large_integer
  mem = AllocateMemory(8)  ;Speicher reservieren, sonst gehts nich
  If QueryPerformanceCounter_(mem)
    CopyMemory(mem, @TIMER, 8)
    start = TIMER\lowpart  ;alten Low-wert sichern
    Repeat
      If QueryPerformanceCounter_(mem)
        CopyMemory(mem, @TIMER, 8)
        Zeit.f = TIMER\lowpart - start
      EndIf
    Until Zeit >= tdelay
    ProcedureReturn Zeit.f
  Else
    ProcedureReturn 0  ;kein Hardware-Timer
  EndIf
  FreeMemory(mem)
EndProcedure


Und hiermit wurde es aufgerufen:

Code: Alles auswählen

  SetPriorityClass_(GetCurrentProcess_(),#REALTIME_PRIORITY_CLASS) 
  ComSendByte(hcom, @dtxd(0), 9)
  DelayTimer(vdel * t100us)
  ComSendByte(hcom, @dtxd(0), 9)
  DelayTimer(vdel * t100us)
  ComSendByte(hcom, @dtxd(0), 9)
  DelayTimer(vdel * t100us)
  ComSendByte(hcom, @dtxd(0), 9)
  DelayTimer(2 * vdel * t100us)
  SetPriorityClass_(GetCurrentProcess_(),#NORMAL_PRIORITY_CLASS)


Der Witz war, dass Märklin-Motorola eine Codierung mit "Trits" gemacht hat (http://home.mnet-online.de/modelleisenbahn-digital/Dig-tutorial-start.html), weil sie Motorola-Chips für IR-Fernbedienungen als Sender in der Basisstation und Empfänger in den Loks und Weichendekodern verwendet haben. Diese Chips haben eine Adresse und dann einen Befehl geschickt. Adresse und Befehl wurden mit kurzen oder langen Pulsen derart kodiert, dass zwei Pulse jeweils ein "Trit" mit 3 Zuständen ergaben.

Nun konnte man den Uart auf 38400 Baud und 6 Datenbits setzen und konnte dann mit den 8 Bits (Startbit, 6 Datenbits, Stoppbit) genau das Muster für 2 Pulse bzw. ein "Trit" erzeugen, das machen die ComSend-Aufrufe für jeweils eine Folge von 5 Adress-Trits + 4 Befehls-Trits. Damit der Empfänger das akzeptiert, musste der Befehl aber in einem engen Zeitraster wiederholt werden. Das Zeitraster machen die DelayTimer-Aufrufe.

Für Loks wurde mit der halben Taktrate wie für Weichen gesendet. Da der Empfänger nur jeweils Befehle seiner Taktrate (eingestellt mit RC-Glied) erkannte, konnte man alle Adressen doppelt belegen.

Märklin hat hier ganz clever die IR-Fernbedienungschips zweckentfremdet. Heute würde man das natürlich mit einem µC machen.

Antworten