Verfälschte Messwerte durch Windows?

Anfängerfragen zum Programmieren mit PureBasic.
PB42
Beiträge: 243
Registriert: 13.10.2005 03:21

Verfälschte Messwerte durch Windows?

Beitrag 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
Benutzeravatar
bobobo
jaAdmin
Beiträge: 3873
Registriert: 13.09.2004 17:48
Kontaktdaten:

Beitrag 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)
‮pb aktuel 6.2 windoof aktuell und sowas von 10
Ich hab Tinnitus im Auge. Ich seh nur Pfeifen.
PB42
Beiträge: 243
Registriert: 13.10.2005 03:21

Beitrag 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!
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

nuja..
es ist ja kein geheimnis, dass ElapsedMilliseconds um 12-15ms ungenau ist...
da ist schon oft drüber gesprochen worden...
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag 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().
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag 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.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Christi
Beiträge: 154
Registriert: 31.08.2004 14:17
Kontaktdaten:

Beitrag von Christi »

timeGetTime_() is recht genau
Benutzeravatar
MVXA
Beiträge: 3823
Registriert: 11.09.2004 00:45
Wohnort: Bremen, Deutschland
Kontaktdaten:

Beitrag von MVXA »

Wer es richtig genau mag, der nimmt select_() ;). Ist zwar nicht dafür
gedacht und eigentlich auch dreckig aber es funktioniert...
Bild
PB42
Beiträge: 243
Registriert: 13.10.2005 03:21

Beitrag 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!
PB42
Beiträge: 243
Registriert: 13.10.2005 03:21

Beitrag 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!
Antworten