WaitWindowEvent erhält nicht ausgelöste Events

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
Kiffi
Beiträge: 10711
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: WaitWindowEvent erhält nicht ausgelöste Events

Beitrag von Kiffi »

@alDo:
ts-soft hat geschrieben:Serielle Schnittstelle ist schon sehr schnell.
ich werfe mal die kühne Behauptung in den Raum, dass es u. U.
nicht sinnvoll ist, die Daten in der selben Geschwindigkeit auf
den Bildschirm bringen zu wollen.

Ist im Prinzip wie die Anzeige einer Stoppuhr: Was nützt es mir, wenn
ich unter großem Aufwand und CPU-Belastung die hundertstel oder
tausendstel Sekunden anzeige, wenn der Anwender sie letztendlich
nur als Geflimmer wahrnimmt?

Grüße ... Kiffi
a²+b²=mc²
gpphjs
Beiträge: 11
Registriert: 07.07.2006 13:35
Wohnort: 18374 Seeheilbad Zingst

Re: WaitWindowEvent erhält nicht ausgelöste Events

Beitrag von gpphjs »

ich denke mal das Problem könnte im Auslesen der COM- Schnittstelle liegen. Ich hatte da auch ein Problem und habe die Abfrage dann dach jedem Byte gemacht, also nicht AvailableSerialPortInput(0) > 7 sondern AvailableSerialPortInput(0) > 0. Dann brauchst du auch ein Trennzeichen, wenn es aber genau zwei Zeichen sind, musst du das Beispiel entsprechend abändern. In der Variablen „text“ steht alles was du brauchst und kannst dann weiter proggen:

Code: Alles auswählen

If OpenWindow(0, 0, 0, 600, 100, "COM-Test", #PB_Window_SystemMenu) 
If OpenSerialPort(0, "COM1", 9200, #PB_SerialPort_NoParity, 8, 1,#PB_SerialPort_NoHandshake, 1024, 1024)
 text.s=""
 Repeat
   
 While AvailableSerialPortInput(0) > 0
    Inhalt= ReadSerialPortData(0, @Puffer,1)
    If  PeekS(@Puffer)=Chr(Asc(#LF$)) 
 ;   If PeekS(@Puffer)=Chr(Asc(#CR$))
    text=""
    Else  
    text=text+PeekS(@Puffer)
    EndIf     
 Wend
      StartDrawing( WindowOutput(0) )
       DrawText(10, 30,text)      
      StopDrawing()
  
    Event = WaitWindowEvent(5)
    Select Event
      Case #PB_Event_CloseWindow
        Quit = 1
      EndSelect
 
  Until Quit = 1
EndIf
EndIf
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

Re: WaitWindowEvent erhält nicht ausgelöste Events

Beitrag von ts-soft »

@gpphjs
ändere doch mal folgendes:

Code: Alles auswählen

;If  PeekS(@Puffer)=Chr(Asc(#LF$)) 
If PeekS(@Puffer) = Chr(#LF)
weil diese hin und zurück ist doch überflüssig :wink:
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Re: WaitWindowEvent erhält nicht ausgelöste Events

Beitrag von Kaeru Gaman »

ts-soft hat geschrieben:@gpphjs
ändere doch mal folgendes:

Code: Alles auswählen

;If  PeekS(@Puffer)=Chr(Asc(#LF$)) 
If PeekS(@Puffer) = Chr(#LF)
weil diese hin und zurück ist doch überflüssig :wink:
dann würde auch

Code: Alles auswählen

If  PeekS(@Puffer)= #LF$
reichen.
aber geht das überhaupt? müßte PeekS nicht einen längeren String auslesen und dann nicht "=" sein?
wie wärs mit

Code: Alles auswählen

If  Asc(PeekS(@Puffer)) = #LF
weil Asc automatisch nur den Code des ersten Zeichens liefert...
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
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

Re: WaitWindowEvent erhält nicht ausgelöste Events

Beitrag von ts-soft »

Ganz unrecht haste ja nicht, aber wenn, dann bitte:

Code: Alles auswählen

If  PeekC(@Puffer) = #LF 
:wink:
ansonsten haste dasselbe doppelgemoppel nur auf die andere seite gebracht :mrgreen:
gpphjs
Beiträge: 11
Registriert: 07.07.2006 13:35
Wohnort: 18374 Seeheilbad Zingst

Re: WaitWindowEvent erhält nicht ausgelöste Events

Beitrag von gpphjs »

@ts-soft, @Kaeru Gaman

Ihr habt beide recht, aber ich lese immer nur ein Zeichen von der COM

Code: Alles auswählen

 ReadSerialPortData(0, @Puffer,1) 
das ist überhaupt der Trick. Ich weiß nicht, wann welche Daten von meinem Logger über die COM kommen,
also lese ich immer nur ein Zeichen und werte das aus. So kann ich relativ einfach Logger und Programm synchronisieren.
Macht man das nicht, hat man Probleme, z.B. wenn ich 7 Zeichen lese
und mitten in der Zeichenkette steht #CR oder #LF, dann kann das bei der Auswertung der Zeichenkette zu Fehlern führen.
Darum mein Beispielprogramm für @alDo. Ich vermute, sein Durcheinander entsteht hier.
alDo
Beiträge: 41
Registriert: 28.01.2010 16:50
Wohnort: Hannover

Re: WaitWindowEvent erhält nicht ausgelöste Events

Beitrag von alDo »

Guten Tag alle zusammen. Was für Diskussionen hier entstehen wenn man mal einen Tag auf der Messe ist wow. :mrgreen:
Ich habe scheinbar meinen Fehler gefunden. Ich habe das Zwischenspeichern der Daten versucht so umzusetzen :oops: :

Code: Alles auswählen

SpeicherArray$() = DatenByte$()
So funktionierts natürlich:

Code: Alles auswählen

For n=0 To 7
  SpeicherArray$(n) = DatenByte$(n)
Next
Könnt mich ohrfeigen dafür :freak:
Ist im Prinzip wie die Anzeige einer Stoppuhr: Was nützt es mir, wenn
ich unter großem Aufwand und CPU-Belastung die hundertstel oder
tausendstel Sekunden anzeige, wenn der Anwender sie letztendlich
nur als Geflimmer wahrnimmt?
Dient dem Zweck zu sehen ob die Leitung 'tot' oder 'lebendig' ist. Ausserdem schreib ich in einen Tracer, der die aufeinanderfolgenden Datensätze mit Timestamp ausgibt.

@ts-soft
Dein Timer sieht sehr interessant aus. Mein Tracer arbeitet mit ElapsedMilliSeconds und teilweise tritt die Differenz von 16ms auf. Werde deinen Code höchstwahrscheinlich einbauen. :D Bei weiteren Fragen zum Timer kann ich in Zukunft auf dich zählen?
Von den Threads lass ich lieber die Finger von, wenn ich sehe was ich da oben schon für nen Murks code. :iamwithstupid:
OS: Windows XP
PB: 4.40 (x86)
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

Re: WaitWindowEvent erhält nicht ausgelöste Events

Beitrag von ts-soft »

alDo hat geschrieben:Bei weiteren Fragen zum Timer kann ich in Zukunft auf dich zählen?
Ich denke mal, damit kommste klar, ansonsten kannste natürlich frägen.
Benutzeravatar
mk-soft
Beiträge: 3845
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: WaitWindowEvent erhält nicht ausgelöste Events

Beitrag von mk-soft »

Hi

Ich finde es besser die Daten mit einen Thread zu lesen. Ausser dem kann man dann den Thread mehrmals auf rufen um mehrere Comports zu überwachen.
Dazu muss aber Threadsafe in den Options aktiviert werden.

Habe mal einen kompletten Code dafür als Ansatz geschrieben. Der Thread gibt die Daten dann erst raus wenn ein #LF$ gefunden wurde.
Mit einen Buffer von 2048 byte sollte es auch nicht zu einer blockierung der Schnittstelle führen. Auch wenn ein Delay vom 10ms als Pause eingetragen wurde wenn keine Daten anliegen.

Habe den code noch nicht mit echten Daten getestet...

Code: Alles auswählen

;- Konstanten
Enumeration ; Window ID
  #Window
EndEnumeration

Enumeration ; Menu ID
  #Menu
EndEnumeration

Enumeration ; MenuItem ID
  #Menu_Start
  #Menu_Stop
  #Menu_Exit
EndEnumeration

Enumeration ; Statusbar ID
  #Statusbar
EndEnumeration

Enumeration ; Gadget ID
  #List
EndEnumeration

; ***************************************************************************************

; Es müssen immer alle Variablen declariert werden

EnableExplicit

; ***************************************************************************************

Structure udtThread
  cmd.i
  stat.i
  ; Comport Daten
  SerialPort.i
  SerialPortName$
  Baud.i
  Paritaet.i
  Data.i
  Stop.i
  HandshakeModus.i
  EingabePufferGroesse.i
  AusgabePufferGroesse.i
EndStructure

Declare thReadComPort(*this.udtThread)

; ***************************************************************************************

Procedure UpdateWindow()

  Protected x,y,dx,dy
  Protected mn,st,tb
  
  x = 0
  y = 0
  mn = MenuHeight()
  st = StatusBarHeight(#StatusBar)
  ;tb = ToolBarHeight(#ToolBar)
  dx = WindowWidth(#Window)
  dy = WindowHeight(#Window) - mn - st - tb
  ResizeGadget(#List, x, y, dx, dy)
  
EndProcedure

Global MutexWriteLog
MutexWriteLog = CreateMutex()

Procedure WriteLog(Info.s)
  Protected temp.s
  
  LockMutex(MutexWriteLog)
  temp = FormatDate("%YYYY.%MM.%DD %HH:%II:%SS - ", Date()) + Info
  AddGadgetItem(#List, -1, temp)
  If CountGadgetItems(#List) > 500
    RemoveGadgetItem(#List, 0)
  EndIf
  UnlockMutex(MutexWriteLog)
  
EndProcedure

;- Globale Variablen
Global exit = 0

Global object.udtThread

With object
  ; \SerialPort kommt von #PB_Any
  \SerialPortName$ = "COM1"
  \Baud = 19200
  \Paritaet = #PB_SerialPort_NoParity
  \Data = 8
  \Stop = 1
  \HandshakeModus = #PB_SerialPort_NoHandshake
  \EingabePufferGroesse = 2048
  \AusgabePufferGroesse = 2048
EndWith

Global hThread1

; Main in eine Procedure gekapselt

Procedure Main()

  Protected style, event, window, menu, gadget, type
  
  ;- Fenster
  style = #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget
  If OpenWindow(#Window, #PB_Ignore, #PB_Ignore, 400, 300, "Fenster", style)
    ; Menu
    If CreateMenu(#Menu, WindowID(#Window))
      MenuTitle("&Datei")
        MenuItem(#Menu_Start, "&Start")
        MenuItem(#Menu_Stop, "St&op")
        MenuBar()
        MenuItem(#Menu_Exit, "Be&enden")
    EndIf
    ; Statusbar
    CreateStatusBar(#Statusbar, WindowID(#Window))
    ; Gadgets
    ListViewGadget(#List, 0,0,0,0)
    
    ; Init
    hThread1 = CreateThread(@thReadComPort(), object)
    WriteLog("Programm gestartet")
    
    ;-- Hauptschleife
    Repeat
      event = WaitWindowEvent()
      Select event
        Case #PB_Event_Menu                       ; ein Menü wurde ausgewählt
          menu = EventMenu()
          Select menu
            Case #Menu_Exit
              If object\stat = 0
                Exit = 1
              Else
                MessageRequester("Stop", "Thread läuft noch")
              EndIf
            Case #Menu_Start
              object\cmd = 1
            Case #Menu_Stop
              object\cmd = 2
          EndSelect
        Case #PB_Event_Gadget                     ; ein Gadget wurde gedrückt
          gadget = EventGadget()
          type = EventType()
        
        Case #PB_Event_CloseWindow                ; das Schließgadget vom Fenster wurde gedrückt
          window = EventWindow()
          If window = #Window
            If object\stat = 0
              Exit = 1
            Else
                MessageRequester("Stop", "Thread läuft noch")
            EndIf
          EndIf
         
        Case #PB_Event_Repaint                    ; der Fensterinhalt wurde zerstört und muss neu gezeichnet werden (nützlich für 2D Grafik-Operationen)
        Case #PB_Event_SizeWindow                 ; das Fenster wurde in der Größe verändert
          window = EventWindow()
          If window = #Window
            UpdateWindow()
          EndIf

        Case #PB_Event_MoveWindow                 ; das Fenster wurde verschoben
        Case #PB_Event_ActivateWindow             ; das Fenster wurde aktiviert (hat den Fokus erhalten)
        Case #PB_Event_SysTray                    ; das SysTray wurde aktiviert
     
      EndSelect
     
    Until Exit
    
    object\cmd = 3
    Delay(1000)
    
  EndIf
EndProcedure : Main() 

; ***************************************************************************************

Procedure thReadComPort(*this.udtThread)

  Protected rcv.s, temp.s, exit.i, result.i, *buffer, pos1.i, pos2.i
  
  With *this
    exit = #False
    temp = ""
    *buffer = AllocateMemory(\EingabePufferGroesse)
    
    Repeat
      ; Command
      Select \cmd
        Case 0 ; Nothing
        
        Case 1 ; Init comport
          If \stat = 0
            \SerialPort = OpenSerialPort(#PB_Any, \SerialPortName$, \Baud, \Paritaet, \Data, \Stop, \HandshakeModus, \EingabePufferGroesse, \AusgabePufferGroesse)
            If \SerialPort = 0
              \stat = 100
            Else
              WriteLog("ComPort geöffnet. Warten auf Daten...")
              \stat = 1
            EndIf
          EndIf
          \cmd = 0
          
        Case 2 ; Close comport
          If \stat > 0 And \stat < 100
            CloseSerialPort(\SerialPort)
            WriteLog("Comport geschlossen.")
          EndIf
          \stat = 0
          \cmd = 0
          
        Case 3 ; Exit thread
          If \stat = 0
            exit = #True
          EndIf
          \cmd = 0
          
      EndSelect
      
      ; Status
      Select \stat
        Case 0 ; Nothing
          Delay(100)
        Case 1 ; Wait data
          result = AvailableSerialPortInput(\SerialPort)
          If result
            \stat = 2
          Else
            Delay(10)
          EndIf
        
        Case 2 ; Read data
          result = ReadSerialPortData(\SerialPort, *buffer, \EingabePufferGroesse)
          \stat = 3
        
        Case 3 ; Check data
          rcv = PeekS(*buffer, result)
          pos1 = 1
          Repeat
            pos2 = FindString(rcv, #LF$, pos1)
            If pos2
              temp + Mid(rcv, pos1, pos2 - pos1)
              WriteLog("Data - " + temp)
              pos1 = pos2 + 1
              temp = ""
            Else
              temp = Mid(rcv, pos1) ; Rest für den nächsten empfang bis LF zwichenspeichern
              Break
            EndIf 
          ForEver
          \stat = 1 ; zurück zum warten auf daten
          
        Case 100 ; Error
          WriteLog("Fehler beim öffnen des Comport")
          \stat = 0
      
      EndSelect
      
    Until exit
    
    ; Exit
    FreeMemory(*buffer)
            
  EndWith

EndProcedure

; ***************************************************************************************

; ***************************************************************************************
FF :wink:

P.S.
- Bugfix
- Habe WriteLog mal mit ein Mutex gekapselt um diesen aus verschiedenen Thread aufrufen zu können.
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Antworten