TTimer viel zu ungenau

Zur Vorstellung von Komponenten und Units für Lazarus
Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: TTimer viel zu ungenau

Beitrag von Mathias »

Was willst du überhaupt machen, das du so ein genauer Timer brauchst ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

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

Re: TTimer viel zu ungenau

Beitrag von siro »

was will ich machen :

Ich möchte eine neue Regelung programmieren/ausprobieren für ein Medizingerät.
Das soll später zwar in einem Embedded System laufen, welches mit C programmiert werden muss,
(Firma will das so) aber zum Testen und probieren, analysieren usw. möchte ich das lieber in Pascal machen.
Das Gerät selbst liefert mir nur "rohe" Messwerte, anhand dieser Werte soll die Reglung dann greifen.
So kann ich eine grafische Auswertung der Paramter/Regelung machen und "mal eben" etwas ändern
und "rasch" Ideen verwirklichen.
Diese Worte gibt es aber leider nicht in "C", da geht nix schnell und schon garnicht "mal eben"
Allein die Integer Promotion ist eine Katastrophe, die Präzedenztabelle jenseits jeder Vernunft.
Optimierungen, die mir den Code zerstückeln und zerstören....(sorry, ich schweife ab, ja ich bin ein C Gegner :lol: ).

Zurück zum Thema:
Das Timing sollte also schon relativ genau sein, Plus Minus paar Prozente spielen dabei jetzt nicht die
große Rolle. Also ob 1 Millisekunde oder 1,1 bzw. 0,9 ist im momentan Falle nicht so tragisch,
aber wenn da Abweichungen von 100 und sogar 400 Millisekunden auftauchen, ist das natürlich unbrauchbar.

Ich hab das schon so für eine Pumpensteuerung in Delphi gemacht und ruckizucki
war die Regelung fertig und ich konnte auch gleich einen grafischen Nachweis dafür bringen,
zudem das Verhalten des Motor inspizieren bei Last und ähnliches.

Es geht mir also um die Echtzeit Kurvendarstellung und Steuerung eines externen Gerätes.
Wobei Echtzeit ja hier noch extrem langsam ist mit einer Millisekunde....


Nachtrag: ich überleg grad ob ich nicht mit der RS232 synchronisieren kann. Mein Gerät liefert ja Quarzgenau jede Millisekunde Messwerte... :roll:
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: TTimer viel zu ungenau

Beitrag von Warf »

siro hat geschrieben:was will ich machen :

Ich möchte eine neue Regelung programmieren/ausprobieren für ein Medizingerät.
Das soll später zwar in einem Embedded System laufen, welches mit C programmiert werden muss,
(Firma will das so) aber zum Testen und probieren, analysieren usw. möchte ich das lieber in Pascal machen.
Das Gerät selbst liefert mir nur "rohe" Messwerte, anhand dieser Werte soll die Reglung dann greifen.
So kann ich eine grafische Auswertung der Paramter/Regelung machen und "mal eben" etwas ändern
und "rasch" Ideen verwirklichen.
Diese Worte gibt es aber leider nicht in "C", da geht nix schnell und schon garnicht "mal eben"
Allein die Integer Promotion ist eine Katastrophe, die Präzedenztabelle jenseits jeder Vernunft.
Optimierungen, die mir den Code zerstückeln und zerstören....(sorry, ich schweife ab, ja ich bin ein C Gegner :lol: ).

Zurück zum Thema:
Das Timing sollte also schon relativ genau sein, Plus Minus paar Prozente spielen dabei jetzt nicht die
große Rolle. Also ob 1 Millisekunde oder 1,1 bzw. 0,9 ist im momentan Falle nicht so tragisch,
aber wenn da Abweichungen von 100 und sogar 400 Millisekunden auftauchen, ist das natürlich unbrauchbar.

Ich hab das schon so für eine Pumpensteuerung in Delphi gemacht und ruckizucki
war die Regelung fertig und ich konnte auch gleich einen grafischen Nachweis dafür bringen,
zudem das Verhalten des Motor inspizieren bei Last und ähnliches.

Es geht mir also um die Echtzeit Kurvendarstellung und Steuerung eines externen Gerätes.
Wobei Echtzeit ja hier noch extrem langsam ist mit einer Millisekunde....


Nachtrag: ich überleg grad ob ich nicht mit der RS232 synchronisieren kann. Mein Gerät liefert ja Quarzgenau jede Millisekunde Messwerte... :roll:


Du könntest es als Simulation schreiben, also du verwendest einfach den Timer normal, aber tust so als wäre die Zeitdifferenz immer konstant 1ms (auch wenn sie das ja nicht ist).

Die andere Option wäre das gesamte system zu skalieren, also statt 1ms arbeitest du auf 100 ms basis, und teilst dann dafür alle Resultate durch 100, damit wird es zwar langsamer, aber da du das gesamte system mitskalierst bleiben die Resultate dennoch korrekt (ist etwas einfacher zu implementieren als mein erster Vorschlag)

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: TTimer viel zu ungenau

Beitrag von Mathias »

Diese Worte gibt es aber leider nicht in "C", da geht nix schnell und schon garnicht "mal eben"
Allein die Integer Promotion ist eine Katastrophe, die Präzedenztabelle jenseits jeder Vernunft.
Optimierungen, die mir den Code zerstückeln und zerstören....(sorry, ich schweife ab, ja ich bin ein C Gegner :lol: ).

Kürzlich habe ich wegen sowas auch mehrere Stunden verschwendet.
Ich habe anstelle von "~" ein "!" geschrieben, unter Pascal wäre dies ein einfaches "not" gewesen. :twisted:

Das Timing sollte also schon relativ genau sein, Plus Minus paar Prozente spielen dabei jetzt nicht die
große Rolle. Also ob 1 Millisekunde oder 1,1 bzw. 0,9 ist im momentan Falle nicht so tragisch,
aber wenn da Abweichungen von 100 und sogar 400 Millisekunden auftauchen, ist das natürlich unbrauchbar.

Ist dies mit einem Arduino nicht lösbar, dort läuft nichts im Hintergrund was abbremsen könnte.
Bei meinen Versuchen die ich gemacht habe, habe ich festgestellt, das dort der Timer sehr genau ist.
Beim Due, beim Uno weis ich es nicht, kann man den Timer Prioritäten zuweisen.

Wie hoch ist deine Messfrequenz ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: TTimer viel zu ungenau

Beitrag von Warf »

Mathias hat geschrieben:Kürzlich habe ich wegen sowas auch mehrere Stunden verschwendet.
Ich habe anstelle von "~" ein "!" geschrieben, unter Pascal wäre dies ein einfaches "not" gewesen. :twisted:


Lustigerweise ist das das eine der wenigen Sachen die ich an C besser finde als an Pascal, wer auch immer auf die Idee kam für Logische und Bitweise Operatoren das selbe Schlüsselwort zu nehmen war wohl nicht ganz bei Bewusstsein bei dieser Entscheidung. Allein das man bei z.B. A = B And C = D die Gleich Operationen umklammern muss damit man keinen Compilererror bekommt, da die starke Bindung der Bitoperation die Priorität von And höher setzt als von =. Bei nur einem Boolschen And wäre eine so hohe Priorität nicht nötig (Noch schlimmer ist es wenn A, B und C als Longbools verwendet und Integer ungleich True (-1) und False (0) darin speichert, dann fliegt einem If A = B And C komplett um die Ohren). Überall ist Pascal strikter als C, außer bei diesen Operatoren (Was vermutlich damit zusammen hängt das diese erst später zu Pascal hinzugefügt wurden). Vor allem da es einen Riesen unterschied macht ob man Logisch oder Bitweise operiert, ein wenig wird das zwar durch das Strikte Typsystem kompensiert was schnell Compilerfehler verursacht, aber wenn man wie oben erwähnt Longbool als Typ verwendet um Integer als Bools zu verwenden (wie in C) landet man sehr schnell in Teufels Küche

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

Re: TTimer viel zu ungenau

Beitrag von siro »

[i]{OT ein}
auch wenn es "etwas" vom Thema abweicht, manchmal gehört es irgendwie dazu :wink:

x := 1 SHL 8 + 1; in Pascal kommt dabei 257 heraus
x = 1 << 8 + 1; in C kommt dabei 512 heraus.......

Eine Shift links Operation ist eine Multiplikation mit 2 hoch n.
Eine Shift rechts Operation ist eine Division durch 2 hoch n.
Wie wir mal gelernt haben: Punktrechnung geht VOR Strichrechnung.
!!! gilt nicht in C, siehe Präzedenztabelle von „C“

Naja, einer der Gründe warum ich das lieber in Pascal mache.
---------------------------------------------------
oder warum geht meine Berechnung nicht:

#define precision 16384

static U16 Offset;
static U32 FactorDiv;
static U32 FactorMod;

S32 calculate(U16 aducnt)
{
return ((((aducnt - Offset) * FactorDiv) + FactorMod) / precision);
}

die Werte stehen beim Aufruf der Funktion wie folgt:

aducnt = 699
Offset = 734
FactorDiv = 38254
FactorMod = 2508
precision = 16384

Herauskommen müste eigentlich : 81 getestet mit Pascal Software
die "C" Funktion liefert jedoch 262062 zurück.
-----------------------
und so setzt sich das täglich fort..... 8)

{OT AUS}
[/i]
Erstmal nochmal Danke für eure Anteilnahme und Ideen (Warf+Mathias)
Ich könnte die Abweichungen des Timers, welche sich ja ermitteln lassen, mit in die Berechnungen der Regelung aufnehmen.
Bei sehr schnellen Änderungen kann ich aber nicht schnell genug dagegensteuern. Bei kleineren Differenzen wird das
in der Regelung vermutlich sogar garnicht auffallen.

Die Hardware bzw. das Zielsystem ist ja fertig und funktioniert auch tadellos.
Ist auch schon zertifiziert und im Einsatz im Operationssaal an Patienten und alles in "C" :oops:
Mein Messtakt ist 1000 Hz auf 6 Kanälen mit einem 12 Bit ADU
Also 6000 Messwerte die Sekunde. Das läuft auch auf die Mikrosekunde Quarzgenau.
Die Prioritäten in der CPU von NXP Controller Typ:LPC1768 kann ich ja selbst festlegen.


Neue Algorhythmen in "C" machen wirklich keinen Spass, man stochert ständig an irgendwelchen Ungereimheiten,
Problemen die es in Pascal garnicht gibt, daher

möchte ich es mir vereinfachen und das läuft auch schon einigermaßen.
Im Gerät wird nur noch gemessen, die Messwerte werden zeitsynchron jede Millisekunde
mit 115200 Baud an den PC gesendet.

Die Regelung (auf dem PC, nun in Pascal) prüft, rechnet , macht sonst was und
sendet dann über die RS232 Kommandos zurück an das Gerät was zu tun ist.

Beispielsweise eine Pulsbreite um ein pneumatisches Ventil zu steuern.
Schaut sich also die Druckwerte an und entscheidet wie das Ventil geregelt werden soll.

Anfangs habe ich nur die P I D Werte und einige andere Filterwerte vom PC übertragen.
Für ein paar neue Ideen und Experimente will ich halt die gesamte Regelung auslagern
auf den PC. Da bin ich wesentlich flexibler und kann auch wesentlich effizeinter arbeiten
als auf dem Zielsystem mit "C"

So schlecht sieht das ja auch garnicht aus mit meinem jetzigen Timer.
Für eine Machbarkeiststudie sicher schon ausreichend.

Wenns dann doch mal wieder länger dauert mit dem Timer schnapp ich mir nen Snickers..... :mrgreen:
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: TTimer viel zu ungenau

Beitrag von Mathias »

Herauskommen müste eigentlich : 81 getestet mit Pascal Software
die "C" Funktion liefert jedoch 262062 zurück.


Was meinst du, spuckt C++ hier raus ?

Code: Alles auswählen

Serial.println(1000*1000);

Es kommt 16960.
Erst wen man es so schreibt, dann kommt 1'000'000 .

Code: Alles auswählen

Serial.println(1000*1000L);
// oder
Serial.println(1000000);

Es ist schon wahnsinnig, das C++ an so etwas einfachen scheitert. :evil:
Nicht mal Konstanten kann es zusammenzählen, das kann jeder Grundschüler besser. :mrgreen:
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

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

Re: TTimer viel zu ungenau

Beitrag von siro »

Noch einen kurzen letzten Beitrag zum Thema Echtzeit unter Windows:

Es gibt tatsächlich Möglichkeiten, hochpräzise Timer zu generieren:

Die Firma Kithara bietet spezielle Software für Windows an.
http://kithara.com/de/download

Mikrosekundengenaue Timer sollen damit machbar sein. Leider hat das auch seinen Preis :roll:
Es gibt wohl Module mit direkter Delphi Anbindung. Ein RealTime Bundel kostet so schlappe 2400 Euro :shock:
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: TTimer viel zu ungenau

Beitrag von mschnell »

siro hat geschrieben:Noch einen kurzen letzten Beitrag zum Thema Echtzeit unter Windows:

Es gibt tatsächlich Möglichkeiten, hochpräzise Timer zu generieren:

Die Firma Kithara bietet spezielle Software für Windows an.
http://kithara.com/de/download

Mikrosekundengenaue Timer sollen damit machbar sein. Leider hat das auch seinen Preis :roll:
Es gibt wohl Module mit direkter Delphi Anbindung. Ein RealTime Bundel kostet so schlappe 2400 Euro :shock:

Ich habe Kithara vor längerer Zeit einmal (mit Delphi) verwendet.

Man kann - wenn man will - auf einen Hardware Interrupt drei Callbacks bekomme: In der Interrupt-Service-Funktion, in einem eigenen Thread und im Mainthread der Applikation. Jeweils sind für die Software unterschiedliche Aktionen erlaubt (sonst Absturz)

Funktionierte damals sehr gut, war aber ziemlich aufwendig zu programmieren und zu debuggen und ziemlich teuer.

-Michael

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: TTimer viel zu ungenau

Beitrag von Mathias »

Vielleicht gibt es eine Möglichkeit denn Hardware-Timer des PCs anzusprechen.
Evtl. mit Treiber.

https://de.wikipedia.org/wiki/Programma ... rval_Timer

Ich denke kaum, das von für so etwas einfaches 2400€ ausgeben muss.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

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

Re: TTimer viel zu ungenau

Beitrag von siro »

@Mathias,
denau das machen die vermutlich bei Kithara,
Die Motherboards haben ja "richtige" Hardwaretimer.
Das war früher ein 8254 mit drei 16 Bit Timern.
Dann gabs 2 Interrupt Controller die cascadiert waren vom Typ 8259
Heute befindet sich hauptsächlich ein Intel Chip (die Southbridge) vom Typ 82801 auf den Boards,
wobei es hier zig Varianten gibt ICH6, ICH9 (I/O Controller Hub) gibt.
Das sind Chips mit hunderten von Beinchen und entsprechenden Datenblättern.
Intel® I/O Controller Hub 6 (ICH6) Family hat z.B. 786 Seiten Info....
Dazu gibts HPET (High Precision Event Timers) Specification von Intel
Das ist doch recht aufwändig und dann muss man noch wissen wie man das Windows dabei umgeht.
Da muss ich leider auch passen...obwohl mich das auch sehr interessiert.

@Michael: habt Ihr das damals offiziell gekauft ?
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: TTimer viel zu ungenau

Beitrag von mschnell »

Mathias hat geschrieben:Vielleicht gibt es eine Möglichkeit denn Hardware-Timer des PCs anzusprechen.


"Ansprechen" reicht nicht.

Der Timer-Code muss höhere Priorität als das Betriebssystem haben, weil er sonst an jeder Stelle beliebig lange unterbrochen werden kann. Das ist nur vermeidbar, wenn ein Explizites realtim-Betribessystem wie "Linux RT" verwendet wird, Deshalb muss der User-Code (z.B.) in der Interrupt-Service-Routine laufen. Das geht mit Kithara oder auch mit einem eigenen Treiber (in Linux prinzipiell möglich, in Windows sicher sehr aufwändig.

-Michael
Zuletzt geändert von mschnell am Mo 11. Jun 2018, 14:37, 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: TTimer viel zu ungenau

Beitrag von siro »

Hallo zusammen,
ich möchte (muss) das Thema mit dem WindowsTimer nochmal aufgreifen.

Nachdem ich heute die Lazarus Version 1.8.2 Windows 64 Bit auf meinen Windows 7 Rechner installiert habe,
gingen plötzlich diverse Programme von mir nicht mehr.

Ich hab dann nochmal downgegraded auf 1.8.0 und alles lief wieder einwandfrei.

Recht schnell konnte ermittelt werden, daß der Verursacher meine eigene Timerkomponente ist..
Nachdem ich diese nochmals gründlich untersucht habe, bin ich erstaunt, daß der Fehler nicht schon viel früher aufgetaucht ist.
Da ist ein richtiger böser BUG drin.


Hier der Code, welcher unter Lazarus 1.8.0 einwandfrei lief:

Code: Alles auswählen

 
procedure TimerProc(hWnd: HWND; uMsg: UINT; idEvent: UINT_PTR; dwTime: DWORD); stdcall;
begin
  With TPreciseTimer(TObject(idEvent)) do begin
    if FInTimerProc then begin
      Stop;
      FInTimerProc:=FALSE;
      exit;     { der letzte Aufruf wurde noch nicht beendet }
    end;
    FInTimerProc:=TRUE;            { der neue Aufruf ist in Arbeit }
    if Assigned(OnTimer) then OnTimer(TObject(idEvent)); { Benutzer Routine }
    FInTimerProc:=FALSE;           { der Aufruf wurde beendet }
  end;
end;
 



und hier der modifizierte Code, welcher nun auch unter Lazarus 1.8.2 läuft.

Code: Alles auswählen

 
 
procedure TimerProc(uTimerId:UINT; uMsg:UINT; dwUser: UINT_PTR; dw1: DWORD; dw2:DWORD); stdcall;
begin
  With TWinTimer(TObject(dwUser)) do begin
    if FInTimerProc then begin
      Stop;
      FInTimerProc:=FALSE;
      exit;     { der letzte Aufruf wurde noch nicht beendet }
    end;
    FInTimerProc:=TRUE;            { der neue Aufruf ist in Arbeit }
    if Assigned(OnTimer) then OnTimer(TObject(dwUser)); { Benutzer Routine }
    FInTimerProc:=FALSE;           { der Aufruf wurde beendet }
  end;
end;                 



Eigentlich hat die TimerProc einen Parameter mehr, somit müste das einen Stackfehler auslösen (zumindest irgendwann...)
Das Programm lief aber auch über Tage ohne Probleme.

So ganz verstehen tue ich es nicht, Microsoft hat irgendwie zwei verschiedene Variationen von der TimerProc
Aber nun geht es ja und ich kann beruhigt ins Wochenende gehen.

Siro
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

Antworten