Seite 4 von 4

Re: WaitWindowEvent erhält nicht ausgelöste Events

Verfasst: 03.03.2010 21:06
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

Re: WaitWindowEvent erhält nicht ausgelöste Events

Verfasst: 04.03.2010 12:40
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

Re: WaitWindowEvent erhält nicht ausgelöste Events

Verfasst: 04.03.2010 12:50
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:

Re: WaitWindowEvent erhält nicht ausgelöste Events

Verfasst: 04.03.2010 14:10
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...

Re: WaitWindowEvent erhält nicht ausgelöste Events

Verfasst: 04.03.2010 16:26
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:

Re: WaitWindowEvent erhält nicht ausgelöste Events

Verfasst: 05.03.2010 09:35
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.

Re: WaitWindowEvent erhält nicht ausgelöste Events

Verfasst: 05.03.2010 12:32
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:

Re: WaitWindowEvent erhält nicht ausgelöste Events

Verfasst: 05.03.2010 12:48
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.

Re: WaitWindowEvent erhält nicht ausgelöste Events

Verfasst: 07.03.2010 17:27
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.