Seite 1 von 2

Verfälschte Messwerte durch Windows?

Verfasst: 22.02.2007 19:03
von PB42
Hallo,

ich habe spaßeshalber mal einen Code geschrieben, mit dem man seine Reaktionszeit messen kann. Man kann von dem Code halten, was man will, aber den Button "Stop" frage ich mit Absicht nicht als Gadget ab, sondern über WindowMouseX() und WindowMouseY(), damit die Zeitmessung schon beim Drücken des Buttons geschieht und nicht erst beim Loslassen.

Was mir bei den Zeitmessungen auffällt, sind charakteristische Werte, die sich oft wiederholen: Manchmal dreimal nacheinander z.B. 219 Millisekunden. Da frage ich mich, ob es denn sein kann, daß das menschliche Gehirn dreimal nacheinander auf eine 1000stel-Sekunde genau gleich reagiert, oder ob hier evtl. Windows irgendwie dafür sorgt, daß bestimmte Zeitwerte regelrecht "einzurasten" scheinen: 172 Ms, 188 Ms, 203 Ms, 219 Ms, 234 Ms, 250 Ms. Es fällt auf, daß die Abstände dieser typischen Messwerte 15 bzw. 16 Ms betragen. Der Code:

Code: Alles auswählen

InitSprite()
InitMouse()
OpenWindow(0,0,0,500,500,"Reaktionszeitmesser",#PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget)
CreateGadgetList(WindowID(0))

LoadFont(0,"Arial",17)
SetGadgetFont(#PB_Default, FontID(0))
TextGadget(0,100,25,300,40,"Reaktionszeitmesser",#PB_Text_Center)

LoadFont(1,"Arial",14)
SetGadgetFont(#PB_Default, FontID(1))
TextGadget(1,0,75,500,25,"Bitte auf 'Start' klicken, dann warten,",#PB_Text_Center)
TextGadget(2,0,100,500,25,"bis das farbige Rechteck erscheint",#PB_Text_Center)
TextGadget(3,0,125,500,25,"und mit 'Stop' die Messung beenden.",#PB_Text_Center)
ButtonGadget(4,175,350,70,48,"Start")
ButtonGadget(5,255,350,70,48,"Stop")
CheckBoxGadget(6,146,410,20,20,"") : SetGadgetState(6,1)

LoadFont(2,"Arial",10)
SetGadgetFont(#PB_Default, FontID(2))
TextGadget(7,165,412,200,20,"Zeitmessung in Millisekunden") 

Repeat
Event = WaitWindowEvent(10)

  ggst6 = GetGadgetState(6)
  
  If ggst6 = 1
  SetGadgetText(7,"Zeitmessung in Millisekunden")
  EndIf  
    If ggst6 = 0
    SetGadgetText(7,"Zeitmessung in Sekunden")
    EndIf
        
      If sz = 0
      sz = 1
      a = Random(8000) + 2000
      EndIf 
        
      If st = 0  
        Select Event      
        Case #PB_Event_Gadget    
          Select EventGadget()      
          Case 4;Start        
          st = 1
          d = Random(5)
          If d = 0
          a1 = 230
          b = 230
          c = 0
          EndIf
            If d = 1
            a1 = 0
            b = 230
            c = 0
            EndIf 
              If d = 2
              a1 = 0
              b = 0
              c = 230
              EndIf                
                If d = 3
                a1 = 250
                b = 0
                c = 0
                EndIf 
                  If d = 4
                  a1 = 0
                  b = 250
                  c = 250
                  EndIf 
                    If d = 5
                    a1 = 200
                    b = 0
                    c = 250
                    EndIf 
          SetGadgetText(0,"")
          SetGadgetText(1,"")
          SetGadgetText(2,"")
          SetGadgetText(3,"")
          StartDrawing(WindowOutput(0))
          Box(0,0,500,349,RGB(193,193,193))
          StopDrawing()
          EndSelect
        EndSelect
      EndIf  
           
        If st = 1 And zk = 0
        zk = 1
        zm = ElapsedMilliseconds() + a
        EndIf
          If st = 1      
          elpm = ElapsedMilliseconds()
                                      
              If zm < elpm             
              StartDrawing(WindowOutput(0))
              Box(0,0,500,349,RGB(a1,b,c))
              StopDrawing()
              
                If stz = 0
                stz = 1
                startzeit = ElapsedMilliseconds()
                EndIf
                                  
                    If event = #WM_LBUTTONDOWN And WindowMouseX(0) >=255 And WindowMouseX(0) <=325 And WindowMouseY(0) >=350 And WindowMouseY(0) <=398;Stop
                      StartDrawing(WindowOutput(0))
                      Box(0,0,500,349,RGB(193,193,193))
                      StopDrawing()
                      ausgabezeit.d = ElapsedMilliseconds() - startzeit
                      ggst6 = GetGadgetState(6)
                      If ggst6 = 1 
                      SetGadgetText(1,StrD(ausgabezeit.d,0) + " Millisekunden")
                      EndIf 
                        If ggst6 = 0                        
                        l$ = StrD(ausgabezeit.d/1000)
                        While (Right(l$,1)) = "0"
                        l$ = Left(l$, Len(l$)-1)
                        Wend
                          If Right(l$,1) = "."
                          l$ = Left(l$, Len(l$)-1)
                          EndIf                                                 
                        SetGadgetText(1,l$ + " Sekunden")
                        EndIf            
                      st = 0
                      stz = 0
                      sz = 0
                      zk = 0
                      zm = 0
                    EndIf  
                      
              EndIf
          EndIf 
Until Event = #PB_Event_CloseWindow 
Ich lerne gerne etwas neues über Windows. Danke.

PB42

Verfasst: 22.02.2007 19:51
von bobobo
exakte Zeitmessungen wären in Echtzeitbetriebssystemen dann
auch aussagefähig. Windoof ist keins !

Setzt die Priorität Deines Programms so hoch wie möglich, damit andere
Progse nicht so leicht dazwischenfunken können (tun werden sie es aber
doch irgendwann mal)

Verfasst: 22.02.2007 20:03
von PB42
Danke Bobobo, das ist dann auch schon die gesuchte Erklärung. Als nächstes kann dann mein obiges Programm gleich in die Tonne. Macht nix, war ja kein großer Aufwand.

Edit: Folgendes Beispiel steht in der PB-Hilfe zu ElapsedMilliseconds():

Code: Alles auswählen

StartTime = ElapsedMilliseconds()             ; ermittelt den aktuellen Wert
  Delay(1000)                                   ; wartet 1000 Millisekunden
  ElapsedTime = ElapsedMilliseconds()-StartTime ; der 'ElapsedTime' Wert sollte ca. 1000 Millisekunden betragen
Wenn man da statt Delay(1000) mal Delay(100) einsetzt, kommt richtig Spaß auf! Wenn ich das vorher gewußt hätte!

Verfasst: 22.02.2007 21:09
von Kaeru Gaman
nuja..
es ist ja kein geheimnis, dass ElapsedMilliseconds um 12-15ms ungenau ist...
da ist schon oft drüber gesprochen worden...

Verfasst: 22.02.2007 23:41
von AND51
Nun, sind es wirklich bis zu 16 ms? :?
Ich habe nie Abweichungen gesehen, die gröer als 10 ms waren. Nun gut, das ist von vielen Faktoren abhängig.

Was ich eigentlich sagen wollte: Ich würde an deiner Stelle nicht WaitWindowEvent() nehmen, sondern nur WaitWindowEvent().

Verfasst: 22.02.2007 23:59
von ts-soft
AND51 hat geschrieben:Nun, sind es wirklich bis zu 16 ms? :?
Ich habe nie Abweichungen gesehen, die gröer als 10 ms waren. Nun gut, das ist von vielen Faktoren abhängig..
Unter NT sinds normal 10 ms, unter 9x ca. 57 ms. MultiMedia oder
HighResTimer sind genauer.

Verfasst: 23.02.2007 00:15
von Christi
timeGetTime_() is recht genau

Verfasst: 23.02.2007 00:26
von MVXA
Wer es richtig genau mag, der nimmt select_() ;). Ist zwar nicht dafür
gedacht und eigentlich auch dreckig aber es funktioniert...

Verfasst: 23.02.2007 01:08
von PB42
timeGetTime_() is recht genau
Das stimmt, habe ich ausprobiert: Die Differenz war unter XP sehr oft nicht größer als eine Ms. Für 100% exakte Messungen geht das zwar auch nicht, aber immernoch um Klassen besser als ElapsedMilliseconds(). Danke für den Tipp!

Verfasst: 23.02.2007 01:16
von PB42
@MVXA

Wenn ich select_() einsetze, kommt da immer "Incorrect number of parameters". Die WindowID x in die Klammern reinzuschreiben oder auch (WindowID(x)), hilft auch nicht weiter. Bin gespannt, wie's richtig geht!