Seite 1 von 1

ElapsedMilliseconds() - Wonach wird gemessen?

Verfasst: 23.10.2012 06:54
von BSP
Hallo Allerseits.

Wonach misst ElapsedMilliseconds()?
Kann es zu leichten Schwankungen kommen, wenn sich die Netzfrequenz ändert?
Kommt es über den Tag verteilt überhaupt zu Netzschwankungen?

Zum Hintergrund meiner Frage:
Ich habe mir eine Schaltung gebastelt, die das Rad am Stromzähler überwacht.
Ein Sensor erkennt die rote Markierung am Rad.
Für die weiteren Berechnungen bestimme ich die Zeit der Markierung mit ElapsedMilliseconds()

Code: Alles auswählen


stick=InitJoystick()
If Not stick
  MessageRequester("","Kein Stick angeschlossen")
  End
EndIf

font=LoadFont(0,"",16)
;Debug stick
OpenWindow(0,0,0,400,360,"Stick",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)

TextGadget(1,10 ,10,120,30,"U : ",#PB_Text_Border)
SetGadgetFont(1,font)
TextGadget(2,130,10,100,30,"T : ",#PB_Text_Border)
SetGadgetFont(2,font)
TextGadget(3,250,10,140,30,"U/min : ",#PB_Text_Border)
SetGadgetFont(3,font)

Global joysensor   = 3 ; Der Sensor
Global joyschalter = 1 ; Schalter
Global ende
Global AnzUmdrehungen
Global ZeitJeUmdrehung
Global zeit = ElapsedMilliseconds()

Procedure abfrage(*dummy)

Repeat
  If ende:Break:EndIf
  
  If ExamineJoystick(0)
    
    If JoystickButton(0, joysensor)
      If z3=0 : z3=1
        AnzUmdrehungen+1
        ZeitJeUmdrehung = ElapsedMilliseconds()-zeit
        zeit = ElapsedMilliseconds()
      EndIf
    Else
      z3=0
    EndIf
    
  EndIf
  ForEver
  
EndProcedure
Thread = CreateThread(@abfrage(), 0)

Repeat
If Not AnzUmdrehungen1=AnzUmdrehungen
  SetGadgetText(1 ,"U : "+Str(AnzUmdrehungen))
  SetGadgetText(2,"T : "+StrF(ZeitJeUmdrehung/1000,2))
  UmJeMin.f=60000/ZeitJeUmdrehung
  SetGadgetText(3,"U/min : "+StrF(UmJeMin,3))
  a$="u: "+Str(AnzUmdrehungen)
  a$+" - U/min: "+StrF(UmJeMin,1)
  SetWindowTitle(0,a$)
  AnzUmdrehungen1=AnzUmdrehungen
EndIf
Until WaitWindowEvent(10)=#PB_Event_CloseWindow
ende=1
Wie Ihr seht, läuft die Sensorabfrage in einem Thread .
Und manchmal treten in den Berechnungen Schwankungen auf, für die ich keine Erklärung finde.
Demnach läuft das Rad gelegentlich mal über eine halbe Umdrehung je Min schneller, obwohl bei mir nichts eingeschaltet hatte.
Zuletzt fast eine Stunde lang.

Darum meine Frage:
Gibt der Rechner den Zähltakt vor,
oder kann das Netzabhängig sein?

Gruß & Dank im Voraus:
Bernd

PS: Der Unterschied betrug heute morgen zwischen 05.00 / 06.00 Uhr einen Anstieg von über 0.7 U/min.

Re: ElapsedMilliseconds() - Wonach wird gemessen?

Verfasst: 23.10.2012 09:44
von NicTheQuick
Ein Computer ist natürlich unabhängig von der Netzfrequenz. Da gibt's ja Quarze, die für die Taktung genutzt werden. Davon abgesehen kommt aus deinem PC-Netzteil nur Gleichspannung 'raus, von der man nicht mehr auf die Netzfrequenz schließen kann.

Ich würde es eher mal so versuchen 'ElapsedMilliseconds()' nur einmal pro Triggerung abzufragen und nicht doppelt, damit es nicht passiert, dass beide verschiedene Werte liefern.

Code: Alles auswählen

Procedure abfrage(*dummy)
	Protected lastTime.i = ElapsedMilliseconds()
	Protected currentTime.i
	
	Repeat
		If ende : Break : EndIf
		
		If ExamineJoystick(0)
			If JoystickButton(0, joysensor)
				If z3 = 0
					z3 = 1
					currentTime = ElapsedMilliseconds()
					ZeitJeUmdrehung = currentTime - lastTime
					lastTime = currentTime
					AnzUmdrehungen + 1
				EndIf
			Else
				z3 = 0
			EndIf
		EndIf
		
	ForEver
	
EndProcedure
Ein weiterer Punkt ist, dass du dich nicht mit dem Synchronisieren von Threads auskennst, aber ich hatte jetzt auch keine Lust noch eine Semaphore einzubauen. Aber damit du trotzdem weißt, was ich meine, hier eine kurze Erklärung:
Da "AnzUmdrehungen + 1" vor der Aktualisierung von "ZeitJeUmdrehung" steht, kann es passieren, dass "If Not AnzUmdrehungen1=AnzUmdrehungen" auslöst und die Gadgets aktualisiert bevor "ZeitJeUmdrehung" in deinem Thread geändert wurde. Deswegen habe ich jetzt "AnzUmdrehungen + 1" nach der Änderung von "ZeitJeUmdrehung" eingefügt.

Achja, und die globale Variable "zeit" braucht man jetzt auch nicht mehr.

Re: ElapsedMilliseconds() - Wonach wird gemessen?

Verfasst: 23.10.2012 22:20
von Kevin
Hi,
ElapsedMilliseconds() ist sehr ungenau du kannst stattdessen QueryPerformanceFrequency verwenden

hier ein Beispiel dazu:

Code: Alles auswählen

Global HRC_Init=0
Global HRC_Frequency.Large_integer
Global HRC_GetTime.Large_integer
Procedure HRC_Init()
  If QueryPerformanceFrequency_(@HRC_Frequency)
    HRC_Frequency\lowpart/1000
    HRC_Init=1
  EndIf
EndProcedure
Procedure.d HRC_GetTime()
  If HRC_Init=1
    QueryPerformanceCounter_(@HRC_GetTime)
    ProcedureReturn HRC_GetTime\lowpart/HRC_Frequency\lowpart
  Else
    ProcedureReturn ElapsedMilliseconds()
  EndIf
EndProcedure

HRC_Init()

time=ElapsedMilliseconds()
Delay(113)
re=ElapsedMilliseconds()-time

dtime.d=HRC_GetTime()
Delay(113)
dre.d=HRC_GetTime()-dtime

Debug "113:  "+StrF(re,1)+", "+StrF(dre,1)


time=ElapsedMilliseconds()
Delay(8)
re=ElapsedMilliseconds()-time

dtime.d=HRC_GetTime()
Delay(8)
dre.d=HRC_GetTime()-dtime

Debug "8:  "+StrF(re,1)+", "+StrF(dre,1)
mfg kevin

Re: ElapsedMilliseconds() - Wonach wird gemessen?

Verfasst: 23.10.2012 22:42
von BSP
Hallo NicTheQuick.
Ein Computer ist natürlich unabhängig von der Netzfrequenz. Da gibt's ja Quarze, die für die Taktung genutzt werden. Davon abgesehen kommt aus deinem PC-Netzteil nur Gleichspannung 'raus, von der man nicht mehr auf die Netzfrequenz schließen kann.
Ja, so hatte ich auch gehofft.
Aber da ich mich nicht sooo genau auskenne dachte ich mir,
frage lieber mal nach. Kann ja sein, das meine Unwissenheit etwas übersieht.

Deine Änderungen sind logisch und verständlich.
Danke für die Hinweise.
Ähnliche Änderungen muss ich in meiner Hauptschleife auch noch vornehmen, wo ich die Var "AnzUmdrehungen" , die ja im Thread gesetzt wird, ebenfalls mehr als einmal abfrage.

Richtig erkannt hast Du auch, das ich mich mit dem Synchronisieren von Threads nicht auskenne.
Die Threads waren bisher für mich immer ein Grauen und ich habe meine Versuche damit immer wieder schnell aufgegeben.
Nun bleibt mir aber nichts anderes übrig, als mich damit zu beschäftigen. Ich nehme Deinen Hinweis auf "Semaphore" mal als Tip, mich in die Richtung weiter zu beschäftigen.

Eine Frage habe ich aber noch:
Was hat Vorrang? Daten speichern oder der Thread?
Ich muß die Daten ja ab und zu mal speichern, und da wäre es unschön, wenn der Thread dann eine Umdrehung übersieht.
Nicht tragisch, aber unschön. Einmal am Tag werden die Stände sowieso "synchronisiert. Dazu habe ich in meine Sensorschaltung extra einen weiteren Taster mit eingebaut.

Gruß & Dank für Deine Aufmerksamkeit:

@Kevin.
Ich wollte meine Antwort gerade rausschicken als ich Deinen Beitrag sah.
Ich werde mich nachher noch genauer damit auseinander setzen.
Bisher habe ich folgende Erfahrung gemacht:
Wenn ich meine Werte "UmJeMin" auf eine Nachkommastelle runde "StrF(UmJeMin,1)" , sieht das Ganze recht Stabil aus und man erkennt auf jeden Fall trotzdem jeden Druck auf einen Lichtschalter.
Und ein mal am Tag wird meine Schaltung sychronisiert. Dazu dient das Mitzählen der Umdrehungen und ein extra Taster.
Bei Druck auf Den merkt sich mein PRG die Zeit und ich kann den genauen Zählerstand wie bisher von Hand nachtragen.

Danke auch Dir.

Bernd