AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Timing-Event im 10ms-Bereich

Ein Thema von MaxDelphi · begonnen am 29. Jun 2009 · letzter Beitrag vom 25. Jul 2009
Antwort Antwort
Seite 1 von 2  1 2      
MaxDelphi

Registriert seit: 29. Jun 2009
17 Beiträge
 
#1

Timing-Event im 10ms-Bereich

  Alt 29. Jun 2009, 10:33
Hallo Forum,

ich hab folgendes Problem:
Ich hätte gerne Ereignisse im 10ms (oder kleiner) - Takt, die mir die CPU nicht verstopfen.

Habe hier schon etliches über genaue Zeitmessung, usw gelesen aber nicht das geeignete gefunden.

Was ich bisher getestet habe:
1.HighPrecision-Timer von TMS -> hält die 10ms recht gut ein, aber CPU-Last steigt auf 100%, da er die CPU-Ticks zählt.
2.TTimer mit Intervall 10ms liefert ca. alle 15-16ms einen Event auch wenn ich noch kleinere Zeiten einstelle.
3.Idee 2 TTimer mit 20ms um 10ms versetzt anstarten. Den Versatz habe ich über TMS HighprecisionDelay realisiert. -> 2 Ereignisse im 15ms-Raster + 1 Ereignis im 0ms-Raster.

Wie habe ich das herausgefunden:
Mit einem Button habe ich den Timer angestoßen, mit einem zweiten wieder gestoppt. Während der Timer lief habe ich mir die aktuellen Zeiten (now) und deren Differenzen in einen String schreiben lassen. Wenn gestoppt wurde habe ich den String in einer Memo ausgegeben. Auch den Now an sich habe ich überprüft indem ich am Anfang und am Ende der Routine die Zeit gemessen habe und die Differenz ausgeben habe.

Ich weiß, daß ein solches Verhalten machbar ist, denn ich habe es in NI LabView überprüft. -> 10ms Taktzeit Prozessorlast <5%

4.Nachdem ich das mit LabView hinbekommen habe, hab ich mir eine Delphi-DLL gebaut die eine WM_USER-Message sendet. Diese DLL habe ich in LabView verwendet um mir genaue Timing-Events zu senden. Die LabView-Routine habe ich wiederum als DLL abgebunden und wieder in Delphi aufgerufen. Ergebnis war wie bei 2.

Anbei der Code für 2.) mit drei unterschiedlichen Varianten der Zeitermittelung zum Test.

Delphi-Quellcode:
unit TimerTest;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls;

type
  TForm1 = class(TForm)
    Timer1: TTimer;
    Memo1: TMemo;
    Button1: TButton;
    Button2: TButton;
    procedure Timer1Timer(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private-Deklarationen }
    Msg   : string;
    OldTime   : TDateTime;
    Freq   : Int64;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

FUNCTION TimeStamp:Int64;
asm
   rdtsc
end;

FUNCTION TimeStampFrequency:int64;
var oldpriority:word; q0,q1,qf,ts0,ts1:int64; seconds:extended;
begin
   oldpriority:=GetThreadPriority(GetCurrentThread);
   SetThreadPriority(GetCurrentThread,THREAD_PRIORITY_TIME_CRITICAL);
   QueryPerformanceCounter(q0);
   ts0:=TimeStamp;
   Sleep(200);
   ts1:=TimeStamp;
   QueryPerformanceCounter(q1);
   SetThreadPriority(GetCurrentThread,oldpriority);
   QueryPerformanceFrequency(qf);
   seconds:=(q1-q0)/qf*1000;
   result:=Trunc((ts1-ts0)/seconds+0.5);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
   CmdStart, CmdEnd   : TDateTime;
   i, j   : Integer;
begin
//   CmdStart   := Now * 86400000;
//   CmdStart   := GetTickCount();
   CmdStart   := TimeStamp;
   j   := 1;
   for i := 0 to 100 do
      j   := i;
//   Msg   := Msg + Format('%d %8.8fms ',[j,CmdStart-OldTime]);
   Msg   := Msg + Format('%d %8.8fms ',[j,(CmdStart-OldTime)/Freq]);
//   CmdEnd   := Now * 86400000;
//   CmdEnd   := GetTickCount();
   CmdEnd   := TimeStamp;
//   Msg   := Msg + Format('%8.8fms',[CmdEnd-CmdStart])+#13#10;
   Msg   := Msg + Format('%8.8fms',[(CmdEnd-CmdStart)/Freq])+#13#10;
   OldTime   := CmdStart
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
   Memo1.Clear;
   Msg   := '';
//   OldTime   := Now * 86400000;
//   OldTime   := GetTickCount();
   OldTime   := TimeStamp;
   Timer1.Interval   := 10;
   Timer1.Enabled   := True;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
   Timer1.Enabled   := False;
   Memo1.Text   := Msg;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
   Freq   := TimeStampFrequency;
end;

end.
Die Funktionen TimeStamp und TimeStampFrequency sind aus Eurem Beitrag "exakte Zeitmessungen auf Multiprozessoren" entnommen.


Hat irgendjemand eine Idee wie ich Delphi zu solchen Timing-Events überreden kann ohne die CPU zu blockieren?

Für Eure Hilfe Danke im voraus.
MfG,
MaxDelphi
  Mit Zitat antworten Zitat
Reinhard Kern

Registriert seit: 22. Okt 2006
772 Beiträge
 
#2

Re: Timing-Event im 10ms-Bereich

  Alt 29. Jun 2009, 13:05
Zitat von MaxDelphi:
...
Ich hätte gerne Ereignisse im 10ms (oder kleiner) - Takt, die mir die CPU nicht verstopfen.
...
Hallo,

die Frage taucht immer und immer wieder auf, und die exakte Antwort kann wie immer nur heissen: Desktopsysteme wie Windows oder Linux sind keine Echtzeitsysteme, zuverlässig funktionieren wird das NIEMALS.

Damit es annähernd funktioniert, also fast immer mit seltenen Ausfällen, müsstest du wahrscheinlich in die Treiberprogrammierung einsteigen, auf Anwendungsebene wird das nicht gehen. Ich nehem an, Labview macht es auch so, kann mich aber täuschen.

Wenn du derzeit auf eine untere Grenze bei 15 ms stösst, so kann auch ein schnellerer Rechner helfen, bei doppelter Ausführungsgeschwindigkeit solltest du dann unter 10 ms kommen, aber das ist keine echte Lösung.

Gruss Reinhard
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.152 Beiträge
 
Delphi 12 Athens
 
#3

Re: Timing-Event im 10ms-Bereich

  Alt 29. Jun 2009, 13:12
Zitat von MaxDelphi:
Wie habe ich das herausgefunden:
Mit einem Button habe ich den Timer angestoßen, mit einem zweiten wieder gestoppt. Während der Timer lief habe ich mir die aktuellen Zeiten (now) und deren Differenzen in einen String schreiben lassen. Wenn gestoppt wurde habe ich den String in einer Memo ausgegeben. Auch den Now an sich habe ich überprüft indem ich am Anfang und am Ende der Routine die Zeit gemessen habe und die Differenz ausgeben habe.
nimm mal kein NOW zur Zeitmessung, denn dieses hat schonmal nur Genauigkeiten in dem gemessenem Bereich (8 bzw. 16 ms),
also kleinere Einheiten kannst du damit eh nicht genau messen.
Auch GetTickCount kann bei solch kleinen Messeinheiten nicht genutzt werden.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
MaxDelphi

Registriert seit: 29. Jun 2009
17 Beiträge
 
#4

Re: Timing-Event im 10ms-Bereich

  Alt 29. Jun 2009, 13:19
@ Reinhard,

danke für die Antwort.

Wenn die Frage immer wieder auftaucht, hat dann noch keiner so einen Mini-Trieber geschrieben der diese Funktion besitzt oder einen Link parat wie man so einen Trieber schreiben kann??

Könnte man eventuell über den DependencyWalker oder ähnliche Programme herausschnüffeln wie das geht?

Ich wäre für jede Hilfe dankbar.

@ himitsu,

danke für den Hinweis, aber die Zeitmessung in diesem Fall dient nur der Überprüfung der Aufgabe Timing-Events im 10ms-Raster.

Wie du im Quell-Code unschwer erkennen kannst habe ich 3 verschiedene Arten der Zeitmessung ausprobiert.
MfG,
MaxDelphi
  Mit Zitat antworten Zitat
Reinhard Kern

Registriert seit: 22. Okt 2006
772 Beiträge
 
#5

Re: Timing-Event im 10ms-Bereich

  Alt 29. Jun 2009, 13:20
Hallo,

lies mal über WaitForSingleObject. Dies bewirkt eine Wiederaufnahme des Threads unmittelbar, während eine WM_TIMER-Message nur in die Warteschleife eingefügt wird und dann IRGENDWANN abgearbeitet.

Gruss Reinhard
  Mit Zitat antworten Zitat
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#6

Re: Timing-Event im 10ms-Bereich

  Alt 29. Jun 2009, 13:24
Zitat von Reinhard Kern:
die Frage taucht immer und immer wieder auf, und die exakte Antwort kann wie immer nur heissen: Desktopsysteme wie Windows oder Linux sind keine Echtzeitsysteme, zuverlässig funktionieren wird das NIEMALS.
Richtig
Zitat:
Wenn du derzeit auf eine untere Grenze bei 15 ms stösst, so kann auch ein schnellerer Rechner helfen, bei doppelter Ausführungsgeschwindigkeit solltest du dann unter 10 ms kommen, aber das ist keine echte Lösung.
Mööööp - falsch

Windows als nicht-Echtzeit-System teilt die Zeit in viele, kleine Abschnitte ein. Dann lässt es dein Programm einen Abschnitt lang rechnen und danach ist Schluss, andere Programme kommen dran. (Präemtives Multitasking lässt grüßen) Nach ca. 15ms kommt dein Programm wieder dran.

Die einzige Lösung, unter Windows halbwegs genau diese Zeit zu messen ist das zählen der Prozessorzyklen (vorzugsweise mit Priorität "Echtzeit") was aber - wie du bereits bemerkt hast - 100% CPU Last verursacht.

Ein Schnellerer Prozessor würde legendlich dazu führen, dass du in deiner Zeitspanne mehr abarbeiten kannst, diese 15ms werden dadurch aber iirc nicht wesentlich beinflusst.
  Mit Zitat antworten Zitat
jbaertle

Registriert seit: 2. Mär 2007
Ort: München
20 Beiträge
 
Delphi 7 Professional
 
#7

Re: Timing-Event im 10ms-Bereich

  Alt 29. Jun 2009, 13:44
Hallo,
je nach Aufwand, den man treiben muss, kann man z.B. Microsoft Windows XP Embedded verwenden. Dies ist ein auf den ersten Blick bekanntes (und funktionales) Windows XP, welches sich soweit "aufrüsten" lässt, dass es üblichen Anforderungen an Echtzeitsystemen (zumindest im Bereich von Werkzeugmaschinen) gerecht wird. Wir verwenden beispielsweise die Sinumerik 840 Di sl, wo wir definierte 6 ms Zykluszeit zur Verfügung haben. Ähnliches gibt es auch z.B. von Beckhoff.
Das ist aber keine Spielerei sondern geht schwer ins Geld, d.h. man macht es nur, wenn man muss.
MfG
  Mit Zitat antworten Zitat
MaxDelphi

Registriert seit: 29. Jun 2009
17 Beiträge
 
#8

Re: Timing-Event im 10ms-Bereich

  Alt 29. Jun 2009, 14:43
@ jfheins,

Zitat:
Windows als nicht-Echtzeit-System teilt die Zeit in viele, kleine Abschnitte ein. Dann lässt es dein Programm einen Abschnitt lang rechnen und danach ist Schluss, andere Programme kommen dran. (Präemtives Multitasking lässt grüßen) Nach ca. 15ms kommt dein Programm wieder dran.
das scheint mir eine sehr gute Erklärung für das Problem zu sein!
Aber wäre das nicht ein Ansatz um das Problem zu lösen. Kommt man vielleicht programmiertechnisch an die Einteilung der Zeitscheibe heran, so daß man sie zumindestens zeitweise umstellen kann, z.B. alle 7,5ms ist mein Programm an der Reihe.

Hat da schon mal jemand was gemacht? Wenn ja wie geht das?
MfG,
MaxDelphi
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.152 Beiträge
 
Delphi 12 Athens
 
#9

Re: Timing-Event im 10ms-Bereich

  Alt 29. Jun 2009, 15:50
genau timen kann man damit nichts, man könnte nur die Process- und Thread-Priorität erhöhen, dann kommt es theoretisch öfters mal in den Bearbeitungsprozess rein, aber wie of und wie lange Windows sich dann mit deinem Programm befaßt, ist damit nicht bestimmt.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#10

Re: Timing-Event im 10ms-Bereich

  Alt 29. Jun 2009, 16:03
Verwende Windows 3.x - das kann sowas

Unter Win 3.x wird noch kooperatives "Multitasking" betriben, das heißt deine Anwendung hat alle Zeit die es will und wird nicht gestört

Ansonsten: Oben wurde ein modifiziertes WinXP angesprochen, oder verwende einen Mikrocontroller - da haste auch nen Prozessor für dich alleine.

Bitte nicht angegriffen fühlen - aber soweit ich weis wirst du unter einem normalen WinXP (&Vista&Win7) nicht in diesen Genauigkeitsbereich kommen.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:10 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz