Seite 1 von 1

Exakter Timer

Verfasst: 11.07.2008 14:21
von pede
Hallo

Ich möchte einen auf die Hundertstel Sekunde exate Stoppuhr programmieren.

Soweit mein Code:

Code: Alles auswählen

Enumeration 
    #window_main
    #text_m ;minuten
    #text_s ;sekunden
    #text_c ;hundertstel
    #frame_m
    #frame_s
    #frame_c
    
    #font_stopper
EndEnumeration

SetPriorityClass_(GetCurrentProcess_(),#HIGH_PRIORITY_CLASS)

LoadFont(#font_stopper, "Arial", 40, #PB_Font_Bold)

Global minuten = 0
Global sekunden = 0
Global hundertstel = 0

Procedure Open_window_main()
    OpenWindow(#window_main, #PB_Ignore, #PB_Ignore, 400, 200, "Cube Stopper ", #PB_Window_SystemMenu)
    CreateGadgetList(WindowID(#window_main))
    
    Frame3DGadget(#frame_m, 25, 25, 100, 100, "Minuten")
    TextGadget(#text_m, 45, 45, 60, 60, "00")
    SetGadgetFont(#text_m, FontID(#font_stopper))

    Frame3DGadget(#frame_s, 145, 25, 100, 100, "Sekunden")
    TextGadget(#text_s, 165, 45, 60, 60, "00")
    SetGadgetFont(#text_s, FontID(#font_stopper))

    Frame3DGadget(#frame_c, 265, 25, 100, 100, "Hundertstel")
    TextGadget(#text_c, 285, 45, 60, 60, "00")
    SetGadgetFont(#text_c, FontID(#font_stopper))

EndProcedure

Procedure timer(hwnd, uMsg, idEvent, dwEvent)
    Shared minuten
    Shared sekunden
    Shared hundertstel
    hundertstel = hundertstel + 1
    If hundertstel > 9 
        hundertstel = 0
        sekunden = sekunden + 1
        If sekunden > 59
            sekunden = 0
            minuten = minuten + 1
        EndIf
    EndIf
    
    sekunden$ = Str(sekunden)
    minuten$ = Str(minuten)
    hundertstel$ = Str(hundertstel)
    
    SetGadgetText(#text_c, hundertstel$)
    SetGadgetText(#text_m, minuten$)
    SetGadgetText(#text_s, sekunden$)      
    
EndProcedure

Open_Window_main()

hwnd = WindowID(#window_main)
timer = SetTimer_(hwnd, 1, 100, @timer())
ende = 0

Repeat
    event = WaitWindowEvent(10)
    Select Event
        Case #PB_Event_CloseWindow
            ende = 1
    EndSelect
Until ende = 1 
Das Problem ist, dass das Programm alles andere als genau funktioniert.
Auf 20 Sekunden geht die "Stoppuhr" ca. 1 Sekunde nach...

kann ich das irgendwie vermeiden?

Danke für die Hilfe
lg

Verfasst: 11.07.2008 14:29
von ZeHa
Ruf doch einfach immer die aktuelle Zeit ab und stelle diese dar. Dafür sind die Timer ja da, und die stimmen dann auch :)

Wenn Du einfach nur Ganzzahlen aufsummierst, ist es klar, daß irgendwann Abweichungen auftreten.

Verfasst: 11.07.2008 15:00
von Bisonte
ZeHa hat geschrieben:Ruf doch einfach immer die aktuelle Zeit ab und stelle diese dar. Dafür sind die Timer ja da, und die stimmen dann auch :)
Wenn man dafür die Date() Funktion nimmt... wie bastel ich denn aus dieser Zahl die Hundertstel ? Es sind ja "nur" Sekunden

Verfasst: 11.07.2008 15:06
von Deluxe0321
vll. gettickcount_()? Verwende ich zumindest immer um Timer im Millisekundenbereich zu erstellen.

Verfasst: 11.07.2008 15:28
von ZeHa
...oder timeGetTime_() oder ElapsedMilliSeconds() ;)

Da kriegst Du Tausendstel-Sekunden, brauchst also bloß durch 10 zu teilen :)

Verfasst: 11.07.2008 20:18
von pede
Danke erstmal für die ganzen Antworten.

Wie in meinem Beispiel oben, möchte ich jedoch, dass die zeitliche Änderung dargestellt wird, wie bei einer Stoppuhr...

Und genau deswegen habe ich auch eine Timerprocedure verwendet...

Bei der graphischen Darstellung versagt auch ElapseMilliseconds(), oder?
Bisonte hat geschrieben:Wenn man dafür die Date() Funktion nimmt... wie bastel ich denn aus dieser Zahl die Hundertstel ? Es sind ja "nur" Sekunden
genau deswegen habe ich auch einen anderen Ansatz gewählt...

Verfasst: 11.07.2008 21:57
von ZeHa
ElapseMilliseconds() liefert Dir die Zeit in Millisekunden, seit der Rechner eingeschalten wurde. Also rufst Du beim Starten der Uhr die Funktion auf und speicherst den Wert z.B. als startTime.

Nun brauchst Du nur in Deiner Hauptschleife ständig die neue Zeit abzufragen und von dieser die startTime abziehen. Schon hast Du die vergangene Zeit. Diese kannst Du dann entsprechend divideren um auf Deine unterschiedlichen Angaben zu kommen, z.B. so:

Code: Alles auswählen

startTime = ElapsedMilliseconds()

Repeat
    time = ElapsedMilliseconds() - startTime

    centiseconds = (time / 10) % 100
    seconds = (time / 1000) % 60
    minutes = (time / 60000) % 60
    hours = (time / 3600000) % 60

    ; hier kommt dann der Code hin, wo Du die Zahlen auf die entsprechenden Felder setzt

    WindowEvent()
    Delay(0) ; keine Ahnung ob das was bringt, das sollen andere hier beantworten
Forever

Verfasst: 11.07.2008 23:04
von ts-soft
Hab den Code von Zeha mal etwas Systemfreundlicher gestaltet :wink:

Code: Alles auswählen

EnableExplicit

Global Time.l

Procedure timerCB(hwnd, uMsg, idEvent, dwEvent)
  Static NewTime.l
  Protected hours.l, minutes.l, seconds.l, centiseconds.l, zeit.s
 
  If NewTime <> Time
    NewTime = ElapsedMilliseconds() - Time
    centiseconds = (NewTime / 10) % 100
    seconds = (NewTime / 1000) % 60
    minutes = (NewTime / 60000) % 60
    hours = (NewTime / 3600000) % 60
   
    zeit = RSet(Str(hours), 2, "0") + ":" + RSet(Str(minutes), 2, "0") + ":" + RSet(Str(seconds), 2, "0") + "::" + RSet(Str(centiseconds), 3, "0")
    SetWindowTitle(0, zeit)
  EndIf
EndProcedure

Procedure Main()
 
  If OpenWindow(0, #PB_Ignore, #PB_Ignore, 190, 50, "00:00:00::000", #PB_Window_SystemMenu) And CreateGadgetList(WindowID(0))
   
    ButtonGadget(0, 10, 10, 80, 30, "Start / Stop", #PB_Button_Toggle)
    ButtonGadget(1, 100, 10, 80, 30, "Pause", #PB_Button_Toggle)
   
    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          Break
        Case #PB_Event_Gadget
          Select EventGadget()
            Case 0
              SetGadgetState(1, 0)
              If GetGadgetState(0)
                Time = ElapsedMilliseconds()
                SetTimer_(WindowID(0), 1, 20, @timerCB())
              Else
                Time = 0
                KillTimer_(WindowID(0), 1)
              EndIf
            Case 1
              If GetGadgetState(0)
                If GetGadgetState(1)
                  KillTimer_(WindowID(0), 1)
                Else
                  SetTimer_(WindowID(0), 1, 20, @timerCB())
                EndIf
              Else
                SetGadgetState(1, 0)
              EndIf
           EndSelect
      EndSelect
    ForEver
  EndIf
EndProcedure

Main()

Verfasst: 12.07.2008 10:33
von pede
:allright: :praise: :praise: :praise: :praise: :praise: :praise:

DANKE an alle =)

mfg
pede