Frage zu AddWindowTimer()

Für allgemeine Fragen zur Programmierung mit PureBasic.
BSP
Beiträge: 203
Registriert: 01.02.2009 14:04

Re: Frage zu AddWindowTimer()

Beitrag von BSP »

@Daffy0815

Wie, womit Du die ProgrammProceduren letztenendes füllst,
bleibt Dir überlassen.
Viel Spass.
BSP

Code: Alles auswählen

; Window
#window0 = 0

; Gadgets
Enumeration
  #txtgadget1
  #txtgadget2
  #txtgadget3
  #txtgadget4
  #imggadget1
  #endebutton
  #pausebutton
EndEnumeration

; Images
#image1 = 0

; Timer
Enumeration
  #timer1
  #timer2
  #timer3
  #timer4
  #timer5
EndEnumeration

Global ende=0
Global y , x1 , x2


Procedure Programm1()
  ;Uhrzeit
  Protected zeit$
  zeit$ = FormatDate("%hh.%ii.%ss",Date())
  If GetGadgetText(#txtgadget1) <> zeit$
    SetGadgetText(#txtgadget1,zeit$)
  EndIf
EndProcedure

Procedure Programm3()
  ; Grafik
  GrabImage(#image1,#image1,1,0,180,180)
  StartDrawing(ImageOutput(#image1))
    x1+(Random(2)-1)
    If x1<1 : x1=1 : EndIf
    If x1>170 : x1=170 : EndIf
    LineXY(179,179,179,x1,RGB(255,0,0))
    LineXY(179,x1,179,0,RGB(0,255,0))
  StopDrawing()
  SetGadgetState(#imggadget1,ImageID(#image1))
EndProcedure

Procedure Programm4()
; Position X1
  SetGadgetText(#txtgadget3,"X 1 = "+Str(x1))
EndProcedure

;-===== OpenWindow
If OpenWindow(#Window0, 100, 100, 200, 300, "Testfenster",  #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_SizeGadget | #PB_Window_TitleBar | #PB_Window_ScreenCentered)
  TextGadget(#txtgadget1, 10,10,80,20,"",#PB_Text_Border | #PB_Text_Center)
  TextGadget(#txtgadget2,110,10,80,20,"",#PB_Text_Border | #PB_Text_Center)
  CreateImage(#image1,180,180)
  ImageGadget(#imggadget1,10,40,0,0,ImageID(#image1))
  TextGadget(#txtgadget3, 10,230,80,20,"",#PB_Text_Border | #PB_Text_Center)
  TextGadget(#txtgadget4,110,230,80,20,"",#PB_Text_Border | #PB_Text_Center)
  ButtonGadget(#endebutton,10,260,60,30,"Ende")
  ButtonGadget(#pausebutton,130,260,60,30,"Pause",#PB_Button_Toggle)
Else: End : EndIf

;-===== SetTimer
SetTimer_(WindowID(#Window0), #timer1, 10, @Programm1())
SetTimer_(WindowID(#Window0), #timer3, 1, @Programm3())
SetTimer_(WindowID(#Window0), #timer4, 10, @Programm4())

;-===== Hauptschleife
Repeat 
  
  Select WaitWindowEvent(10)
  Case #PB_Event_CloseWindow
    ende=1
  
  Case #PB_Event_Gadget
    Select EventGadget()
    Case #endebutton
      ende=1
    Case #pausebutton
      If GetGadgetState(#pausebutton)
        KillTimer_(WindowID(#Window0),#timer3)
        SetGadgetText(#txtgadget2,"Pause")
      Else
        SetTimer_(WindowID(#Window0), #timer3, 0, @Programm3())
        SetGadgetText(#txtgadget2,"Läuft")
      EndIf
    EndSelect
  EndSelect
  
Until ende; = ;#WM_CLOSE

;-===== Ende
KillTimer_(WindowID(#Window0),#timer1)
KillTimer_(WindowID(#Window0),#timer3)
KillTimer_(WindowID(#Window0),#timer4)
End
PB 5.31 (x86) & (x64) Win10
Benutzeravatar
TheCube
Beiträge: 169
Registriert: 20.07.2010 23:59
Computerausstattung: Risen 3400G 16MB Win10-64Bit
Wohnort: NRW

Re: Frage zu AddWindowTimer()

Beitrag von TheCube »

@ BSP: Aufwändiges Beispiel :allright: Besonders programm3() hat mir eine Verbesserung für meine selbstgetüftelten Kurven-Scroll Anzeige gebracht.
Die war mit CopyImage/DrawImage & zwei Buffern nämlich zu umständlich :oops:

@Daffy0815
Beim Querlesen habe ich den Eindruck bekommen, dass du gar keinen Timer brauchst ... insbesondere:
Die Anfragen erzeugen im Subsytem einen Interrupt und wenn die Anfragen zu häufig kommen dann hat das Subsystem keine Zeit mehr die "eigentliche Arbeit" zu verrichten.
Du willst halt einigermassen regelmässig dein µC-Subsystem abfragen ... da reichts doch Timer-los einfach so:

Code: Alles auswählen

; Window
#window0 = 0
; Images
#image1 = 0
; Gadgets
#imggadget1 = 0

Global exitthread

If OpenWindow(#Window0, 100, 100, 200, 300, "Testfenster",  #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_SizeGadget | #PB_Window_TitleBar | #PB_Window_ScreenCentered)
  CreateImage(#image1,180,180)
  ImageGadget(#imggadget1,10,40,0,0,ImageID(#image1))
Else: End : EndIf


Procedure DoSomething(*dummy)   ;Hier scrollt´s (oder du fragst deinen µC ab)
  Repeat
  GrabImage(#image1,#image1,1,0,180,180)
  StartDrawing(ImageOutput(#image1))
    x1+(Random(2)-1)
    If x1<1 : x1=1 : EndIf
    If x1>170 : x1=170 : EndIf
    LineXY(179,179,179,x1,RGB(255,0,0))
    LineXY(179,x1,179,0,RGB(0,255,0))
  StopDrawing()
  SetGadgetState(#imggadget1,ImageID(#image1))
  Delay(100)            ; 100ms den Thread schlafen legen
  Until exitthread=1
EndProcedure

Thread=CreateThread(@DoSomething(),0)

Repeat
  Select WaitWindowEvent(1)
  Case #PB_Event_CloseWindow
    ende=1
  EndSelect
Until ende; = ;#WM_CLOSE
Ohne Fenster und Grafikspielerei darfst du sogar die Windowevent-Abarbeitung vergessen ... >:)
Benutzeravatar
Daffy0815
Beiträge: 390
Registriert: 15.06.2005 00:44
Wohnort: 65719 Hofheim
Kontaktdaten:

Re: Frage zu AddWindowTimer()

Beitrag von Daffy0815 »

@TheCube

Nee, so einfach ist es leider nicht!
Das was beim Subsystem abgefragt wird und wie oft ist abhängig vom jeweils aktiven Fenster und/oder der ausgeführten Funktion.
Auch sendet das Subsystem "ungefragt" an den PC!

Das Subsystem ist sogar in Lage autark ohne den PC zu arbeiten.
(Das habe ich Gott sei Dank auch voll im Griff ohne mich mit den "Überraschungs-Eiern" von PureBasic und der Gate$-Company stundenlang herumschlagen zu müssen)
Auch werden für die Messanwendung hochgenaue und hochaufgelöste Zeiten benötigt und da kann man den Windows-PC ja offensichtlich voll vergessen.

Real benötige ich einfach mehrere, unterschiedliche TimeOut's bei denen ich mir keine Gedanken darüber machen muss aus welchem Grund die gerade mal wieder keinen Bock haben zu funktionieren.

Ich habe meine fensterunabhängige Timerroutine nun in ein rückwärtszählende Timeoutroutine umgewandelt.

Hier der Code dazu:

Code: Alles auswählen

Global TimeOld.i
Global TimeOutTimer.i
#TimeOutBasisplatine = 1000 ;Millisekunden
Global RefreshTimer.i
#RefreshTime = 2500  ;Millisekunden
;
Procedure Timer(*Dummy)
    ;
    TimeOld.i = ElapsedMilliseconds()
    ;
    Repeat
        TimeNew.i = ElapsedMilliseconds()
        ;
        If TimeNew.i <> TimeOld.i
            If TimeOld.i < 0 : TimeOld.i = TimeOld.i + 2147483648 : EndIf
            If TimeNew.i < 0 : TimeNew.i = TimeNew.i + 2147483648 : EndIf
            TimeDiff.i = TimeNew.i - TimeOld.i
            TimeOld.i = TimeNew.i
            ;
            TimeOutTimerTemp.i = TimeOutTimer.i
            TimeOutTimerTemp.i = TimeOutTimerTemp.i - TimeDiff.i
            If TimeOutTimerTemp.i < 0 : TimeOutTimerTemp.i = 0 : EndIf
            TimeOutTimer.i = TimeOutTimerTemp.i
            ;
            RefreshTimerTemp.i = RefreshTimer.i
            RefreshTimerTemp.i = RefreshTimerTemp.i - TimeDiff.i
            If RefreshTimerTemp.i < 0 : RefreshTimerTemp.i = 0 : EndIf
            RefreshTimer.i = RefreshTimerTemp.i
        EndIf
    ForEver
EndProcedure
;
;
;
Procedure PresetTimeOutTimer()
    ;
    TimeOutTimer.i = #TimeOutBasisplatine
    ;
EndProcedure
;
;
;
Procedure PresetRefreshTimer()
    ;
    RefreshTimer.i = #RefreshTime
    ;
EndProcedure
;
;
;
TimerThread.i=CreateThread(@Timer(),0)
;
;
;
PresetRefreshTimer() 
PresetTimeOutTimer()
ZyklusZaehler.i = 5
;
While ZyklusZaehler.i    
    If Not TimeOutTimer.i
        Debug "#TimeOutBasisplatine"
        PresetTimeOutTimer()
    EndIf
    If Not RefreshTimer.i
        Debug "#TimeOutRefreshTimer"
        PresetRefreshTimer() 
        ZyklusZaehler.i = ZyklusZaehler.i - 1
    EndIf
Wend
;
KillThread(TimerThread.i)
;
End

Gruß

Daffy


PS. Natürlich könnte man um Rechenzeit zu sparen den Thread auch noch killen wenn kein TimeOut-Zähler mehr aktiv ist und bei den "Presets" wieder aktivieren.
Wir sind LINUX
Widerstand ist zwecklos - Sie werden emuliert
matbal
Beiträge: 261
Registriert: 30.03.2011 20:53

Re: Frage zu AddWindowTimer()

Beitrag von matbal »

Ich verstehe nicht, wieso du hier überhaupt einen Thread verwendest. Der Thread schreibt in einer Schleife ständig Zeitwerte in deine Timer-Variablen, und er lastet einen Prozessorkern damit voll aus

Dein Hauptprogramm läuft auch in einer Schleife und wartet darauf, daß der Zeitpunkt kommt, die Schleife zu unterbrechen. Hier wird der zweite Prozessorkern voll ausgelastet.

Deine Methode macht im Prinzip genau das Gleiche wie das hier, wenn ich es richtig erkannt habe.

Code: Alles auswählen

#TimeOutBasisplatine = 1000 ;Millisekunden
#RefreshTime = 2500  ;Millisekunden

ZyklusZaehler.i = 5

Time = ElapsedMilliseconds()
TimeOutTime = Time + #TimeOutBasisplatine
RefreshTime = Time  + #RefreshTime

While ZyklusZaehler
   Time = ElapsedMilliseconds()
   
   If Time - TimeOutTime >= 0
      Debug "#TimeOutBasisplatine"
      TimeOutTime = Time + #TimeOutBasisplatine
   EndIf
   
   If Time - RefreshTime >= 0
      Debug "#TimeOutRefreshTimer"
      RefreshTime + #RefreshTime 
      ZyklusZaehler = ZyklusZaehler - 1
   EndIf
   
Wend
Benutzeravatar
Daffy0815
Beiträge: 390
Registriert: 15.06.2005 00:44
Wohnort: 65719 Hofheim
Kontaktdaten:

Re: Frage zu AddWindowTimer()

Beitrag von Daffy0815 »

@matbal

Wenn es nur um das Beispielprogramm ginge dann hättest Du recht aber die Sache hat doch einen ganz anderen Hintergrund.
Ich kann das hier nicht so richtig darstellen denn dann müsste ich hier ca. 30000 Zeilen Code nebst zugehöriger Hardware(simulation) einstellen :)

Gruß

Daffy
Wir sind LINUX
Widerstand ist zwecklos - Sie werden emuliert
BSP
Beiträge: 203
Registriert: 01.02.2009 14:04

Re: Frage zu AddWindowTimer()

Beitrag von BSP »

@Daffy0815
Achtung:
Beispiel ist als Ergänzung gedacht und so alleine nicht Lauffähig.
Bitte beachte Procedure Program5()

Gruß: BSP

Code: Alles auswählen

Global NewList Liste()

Procedure Program5()
  If AddElement(Liste())
    Liste() = eingangssignal_der_schnittstelle
  Else
    MessageRequester("Achtung","Rechner ist voll")
  EndIf
EndProcedure

;Der Timer erledigt das Einlesen Deiner Schnittstelle
SetTimer_(#window0,#timer5,1,@Program5)

;-===== Haupt- Programmschleife
Repeat

;Nun hast Du Zeit
;zur Auswertung_derListe

Until ende
PS.
@TheCube
Na, wenn wenigstens einer seinen Spass dran hatte,
wars ja nicht umsonst. :D
PB 5.31 (x86) & (x64) Win10
BSP
Beiträge: 203
Registriert: 01.02.2009 14:04

Re: Frage zu AddWindowTimer()

Beitrag von BSP »

Oder so:

Code: Alles auswählen

Structure Messung
  signal.i
  zeit.i
EndStructure

Global NewList Liste.Messung()

Procedure Program5()
  If AddElement(Liste())
    Liste()\signal = eingangssignal_der_schnittstelle
    Liste()\zeit = Date()
  Else
    MessageRequester("Achtung","Rechner ist voll")
  EndIf
EndProcedure

;Der Timer erledigt das Einlesen Deiner Schnittstelle
SetTimer_(#window0,#timer5,1,@Program5)
PB 5.31 (x86) & (x64) Win10
Antworten