Serial Port comunication witch arduino

Just starting out? Need help? Post your questions and find answers here.
xxfreshman
User
User
Posts: 17
Joined: Mon Jun 13, 2016 8:22 pm

Re: Serial Port comunication witch arduino

Post by xxfreshman »

hurray now it works :-)
infratec
Always Here
Always Here
Posts: 7577
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Serial Port comunication witch arduino

Post by infratec »

But if you want a real good code for handling this kind of communication stuff, you need a serial 'Thread'.

Else you come always in trouble with the GUI stuff and the communication.
I have already done several examples of such a stuff in this forum.
I hope you can find it.
ludoke
Enthusiast
Enthusiast
Posts: 155
Joined: Fri Jul 08, 2016 5:35 pm
Location: Essen (Belgium)

Re: Serial Port comunication witch arduino

Post by ludoke »

xxfreshman
i have this code,it works, with the arduino, but the smarter programmers recommend the use of threading, but I don't know how to do that, maybe someone can improve my code.
The arduino is loaded with the GRBL cnc program.

Code: Select all

Enumeration
  #main_win:#state:#compoort:#open:#close:#zend:#rec
  #message
EndEnumeration
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Global serial_in.s, port.s ,temp$
Global  data_in.i
Global verbonden=0
;----------------------------------------------------------
Declare find_port()
Declare zend()
Declare lees_poort()
Declare open_port()
Declare close_port()
Declare port_error()
;-----------------------------------------------------------------
If OpenWindow (#main_win,0,0,1320,740, "TEST COMPORT", #PB_Window_SystemMenu | #PB_Window_MaximizeGadget  )
  TextGadget(#state,20,650,140,30,"COM=close", #PB_Text_Center)
  ButtonGadget(#Open,20,100,140,30,"OPEN")
  ButtonGadget(#Zend,20,150,140,30,"Zend")
  StringGadget(#message,20,200,50,30,"$")
  TextGadget(#rec,20,250,540,30,temp$,#PB_Text_Border )
  ButtonGadget(#close,20,350,140,30,"CLOSE")
Repeat  ;main loop 
  ev = WaitWindowEvent()          
            Select Ev    
                Case #PB_Event_Gadget                                             
                    Select EventGadget()
                       Case #PB_Event_CloseWindow
                         appQuit = 1  
                       Case #zend                         
                         zend()
                         Delay(250);wait a bit ,have change it with no result
                         lees_poort()                      
                       Case #open
                         find_port()                         
                       Case #close
                         close_port()
                    EndSelect               
             EndSelect    
          Until ev=#PB_Event_CloseWindow 
           End 
  EndIf
  ;---------------------------------------------------------
  Procedure close_port()
    CloseSerialPort(#compoort)
    SetGadgetText(#state,"COM=close"):SetGadgetColor(#state,#PB_Gadget_BackColor,$8344F7)
    verbonden=0
  EndProcedure  
;-----------------------------------------------------------------------------------------
 Procedure open_port()
   OpenSerialPort(#compoort, port$ ,115200,#PB_SerialPort_NoParity, 8, 1, #PB_SerialPort_NoHandshake, 1, 1) 
 If IsSerialPort(#compoort)<>0  And verbonden=1  
               SetGadgetText(#state,port$+"=OPEN")                        
               SetGadgetColor(#state,#PB_Gadget_BackColor,$A7EC16)
            Else
                port_error()
           EndIf       
EndProcedure
;-----------------------------------------------------------------------------------------
Procedure find_port()
  port.s
For Port_nr = 1 To 20  
  Port = "COM"+Str(port_nr)     
     OpenSerialPort(#compoort, port ,115200,#PB_SerialPort_NoParity, 8, 1, #PB_SerialPort_NoHandshake, 1, 1) 
       WriteSerialPortString(#compoort,"$")        ;write something
       Delay(100)
       Data_in = AvailableSerialPortInput(#compoort)            ;test data      
       If data_in > 0          
          Serial_in = Space(data_in)                                                                      
          ReadSerialPortData(#compoort, @serial_in,data_in)               ;read data ,length
             Verbonden = 1:  serial_in = " "           
             Port$ = "COM"+Str(port_nr)
             Break                   
     CloseSerialPort(#compoort)
    EndIf
Next
   OpenSerialPort(#compoort, port$ ,115200,#PB_SerialPort_NoParity, 8, 1, #PB_SerialPort_NoHandshake, 1, 1) 
 If IsSerialPort(#compoort)<>0   And verbonden=1
               SetGadgetText(#state,port$+"=OPEN")                        
               SetGadgetColor(#state,#PB_Gadget_BackColor,$A7EC16)
            Else
             port_error()
           EndIf       
EndProcedure
;-----------------------------------------------------------------------------------------
Procedure zend() 
  
  zend$=GetGadgetText(#message)
  zend$=zend$+Chr(13)+Chr(10)
  ;Debug zend$
   If verbonden=1
     WriteSerialPortString(#compoort,zend$)
   Else
     port_error() 
  EndIf   
EndProcedure 
;---------------------------------------------------------------------
Procedure port_error()
  MessageRequester("SerialPort","COMPORT NOT OPEN,RESTART PROGRAMMA OR PRESS F1")
    SetGadgetText(#state,"COM=close"):SetGadgetColor(#state,#PB_Gadget_BackColor,$8344F7)
EndProcedure  
;-----------------------------------------------------------------------------------
Procedure lees_poort() ;this works and lees_poort1() works also 
   Define i
  Protected Result.l,*BufferIn, SerIn.l, MMFresponse.s
  If IsSerialPort(#comPoort)
    *BufferIn = AllocateMemory(200)
    SerIn = AvailableSerialPortInput(#comPoort)
    If SerIn >0 
      Result = ReadSerialPortData(#comPoort, *BufferIn, SerIn)
      MMFresponse = PeekS(*BufferIn ,Result ,#PB_Ascii)
        Debug  result;MMFresponse
    EndIf
    FreeMemory(*BufferIn) 
  EndIf
  SetGadgetText(#rec, MMFresponse )
EndProcedure
;-----------------------------------------------------------------------
Procedure lees_poort1()
  temp$=""
  If verbonden=0
    port_error()
  Else
    Data_in=AvailableSerialPortInput(#compoort)
        If data_in >0
           serial_in=Space(data_in)
           ReadSerialPortData(#compoort, @serial_in, data_in)
           temp$=PeekS(@serial_in,data_in,#PB_Ascii) 
           Debug temp$
        EndIf  
         SetGadgetText(#rec,temp$)
         data_in=0
  EndIf    
      EndProcedure 
infratec
Always Here
Always Here
Posts: 7577
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Serial Port comunication witch arduino

Post by infratec »

Your code can not work. With or without thread.

You send in unicode, but receive in ASCII.
I think one is wrong.

But you should open an other thread, because your problem has nothing to do with this problem.

Code: Select all

EnableExplicit

Enumeration
  #main_win
  #state
  #compoort
  #open
  #close
  #zend
  #rec
  #message
EndEnumeration






Procedure port_error()
  MessageRequester("SerialPort","COMPORT NOT OPEN,RESTART PROGRAMMA OR PRESS F1")
  SetGadgetText(#state,"COM=close")
  SetGadgetColor(#state,#PB_Gadget_BackColor,$8344F7)
EndProcedure


Procedure close_port()
  CloseSerialPort(#compoort)
  SetGadgetText(#state,"COM=close")
  SetGadgetColor(#state,#PB_Gadget_BackColor,$8344F7)
EndProcedure


Procedure find_port()
 
  Protected Port_nr.i, Port$, Byte.a
 
  For Port_nr = 1 To 20
    Port$ = "COM" + Str(port_nr)
    If OpenSerialPort(#compoort, Port$, 115200, #PB_SerialPort_NoParity, 8, 1, #PB_SerialPort_NoHandshake, 512, 512)
      WriteSerialPortString(#compoort, "$" + #CR$, #PB_Ascii)        ;write something
      Delay(100)
      If AvailableSerialPortInput(#compoort)            ;test data
        While AvailableSerialPortInput(#compoort)
          ReadSerialPortData(#compoort, @Byte, 1)               ;read data ,length
        Wend
        SetGadgetText(#state, Port$ + "=OPEN")
        SetGadgetColor(#state, #PB_Gadget_BackColor, $A7EC16)
        Break
      Else
        CloseSerialPort(#compoort)
      EndIf
    EndIf
  Next
 
  If Not IsSerialPort(#compoort)
    port_error()
  EndIf
 
EndProcedure


Procedure zend()
 
  If IsSerialPort(#compoort)
    WriteSerialPortString(#compoort, GetGadgetText(#message) + #CR$, #PB_Ascii)
  Else
    port_error()
  EndIf
 
EndProcedure


Procedure lees_poort()
  
  Protected Result.i, *BufferIn, SerIn.i, MMFresponse$
  
  If IsSerialPort(#comPoort)
    *BufferIn = AllocateMemory(512, #PB_Memory_NoClear)
    If *BufferIn
      SerIn = AvailableSerialPortInput(#comPoort)
      Debug "SerIn: " + Str(SerIn)
      If SerIn > 0
        Result = ReadSerialPortData(#comPoort, *BufferIn, MemorySize(*BufferIn))
        MMFresponse$ = PeekS(*BufferIn, Result, #PB_Ascii)
        Debug Str(result) + " " + MMFresponse$
        SetGadgetText(#rec, MMFresponse$)
      EndIf
      FreeMemory(*BufferIn)
    EndIf
  EndIf
  
EndProcedure




Define ev.i, appQuit.i


If OpenWindow(#main_win,0,0,1320,740, "TEST COMPORT", #PB_Window_SystemMenu | #PB_Window_MaximizeGadget)
  TextGadget(#state,20,650,140,30,"COM=close", #PB_Text_Center)
  ButtonGadget(#Open,20,100,140,30,"OPEN")
  ButtonGadget(#Zend,20,150,140,30,"Zend")
  StringGadget(#message,20,200,50,30,"$")
  TextGadget(#rec,20,250,540,30,"",#PB_Text_Border)
  ButtonGadget(#close,20,350,140,30,"CLOSE")
  Repeat  ;main loop
    ev = WaitWindowEvent()
    Select Ev
      Case #PB_Event_Gadget
        Select EventGadget()
          Case #PB_Event_CloseWindow
            appQuit = 1
          Case #zend
            zend()
            Delay(250)
            lees_poort()
          Case #open
            find_port()
          Case #close
            close_port()
        EndSelect
    EndSelect
  Until ev = #PB_Event_CloseWindow
EndIf
Last edited by infratec on Sat Dec 14, 2019 12:18 am, edited 3 times in total.
ludoke
Enthusiast
Enthusiast
Posts: 155
Joined: Fri Jul 08, 2016 5:35 pm
Location: Essen (Belgium)

Re: Serial Port comunication witch arduino

Post by ludoke »

infratec
thank you for viewing my code, but due to the small changes you have made, I can no longer open the com port.
I don't get it that well, but with my code it appears to work, I can communicate with the Arduino.
you said: you should open an other thread.
I'm not sure how to handle threading, I've been searching for a long time, but I can't find a simple example.Usually it's too complicated for me,my head is a confused mess of threads mutexes and semaphores .
How can I easily create a thread for the serial port?
infratec
Always Here
Always Here
Posts: 7577
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Serial Port comunication witch arduino

Post by infratec »

ludoke
Enthusiast
Enthusiast
Posts: 155
Joined: Fri Jul 08, 2016 5:35 pm
Location: Essen (Belgium)

Re: Serial Port comunication witch arduino

Post by ludoke »

infratec,many thanks.
you are a grandmaster in pB.
I'm going to try to understand those examples, but it remains complicated for me.
infratec
Always Here
Always Here
Posts: 7577
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Serial Port comunication witch arduino

Post by infratec »

I modified the code above.

For port testing it sends now a CR. Normally a programm replies with a new prompt.
ludoke
Enthusiast
Enthusiast
Posts: 155
Joined: Fri Jul 08, 2016 5:35 pm
Location: Essen (Belgium)

Re: Serial Port comunication witch arduino

Post by ludoke »

I cannot open the port.
But by changing , Protected Port_nr.i, Port$, Result$ to global variables then it works.

But I'm thinking, if a serial or USB port sends data to the PC, can this give an event?

In the old days there was an interrupt number for com2 and com1.
infratec
Always Here
Always Here
Posts: 7577
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Serial Port comunication witch arduino

Post by infratec »

What have you to send to get an reply?

CR?
$?
$+CR?

And what is the answer?
ludoke
Enthusiast
Enthusiast
Posts: 155
Joined: Fri Jul 08, 2016 5:35 pm
Location: Essen (Belgium)

Re: Serial Port comunication witch arduino

Post by ludoke »

the program in the arduino is loaded with GRBL (https://github.com/grbl/grbl/wiki)

when using my code en send ? + CR +LF or send $ + CR +LF

the arduino answer
[HLP:$$ $# $G $I $N $x=val $Nx=line $J=line $SLP $C $X $H ~ ! ? ctrl-x]
ok
ok

GRBL is open source for control CNC ,there are many Gcode senders for milling but not for controlling a lathe and that is what I try to make.
It is only for hobby and it is also a challenge to learn something more about purebasic.
The next few days I will try to find out if I can understand something of the examples you quote in connection with threading.
infratec
Always Here
Always Here
Posts: 7577
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Serial Port comunication witch arduino

Post by infratec »

Hi,

please test my code again.
Only if this code works, I can start to implement this in a thread.

So if it not works, bring it to work. :wink:
ludoke
Enthusiast
Enthusiast
Posts: 155
Joined: Fri Jul 08, 2016 5:35 pm
Location: Essen (Belgium)

Re: Serial Port comunication witch arduino

Post by ludoke »

infratec,
After you have adjusted the code I don't get it working anymore, I don't know what is wrong.
I do understand that I have to work with threads to create a reliable program.
The attached code works, but how do I get that done with threading ?

Code: Select all

;program send gcode commands to an arduino ,the arduino processes the commands and answers with 'ok' 
;with '?' command the arduino send the position of the machine.
;

Enumeration
  #main_win:#state:#compoort:#open:#close:#zend:#rec
  #message:#view
EndEnumeration
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Global serial_in.s, port.s ,temp$
Global  data_in.i,Port_nr
Global verbonden=0
;----------------------------------------------------------
Declare find_port()
Declare zend()
Declare lees_poort()
Declare open_port()
Declare close_port()
Declare port_error()
Declare OnGadgetEvent()
;-----------------------------------------------------------------
If OpenWindow (#main_win,0,0,1320,740, "TEST COMPORT", #PB_Window_SystemMenu | #PB_Window_MaximizeGadget  )
  TextGadget(#state,20,650,140,30,"COM=close", #PB_Text_Center)
  ButtonGadget(#Open,20,100,140,30,"OPEN")
  ButtonGadget(#Zend,20,150,140,30,"Zend")
  StringGadget(#message,20,200,50,30,"$")
  TextGadget(#rec,20,250,540,30,temp$,#PB_Text_Border )
  ButtonGadget(#close,20,350,140,30,"CLOSE")
  ButtonGadget(#view,200,350,100,30,"VIEW RX")
  find_port()  
Repeat  ;main loop 
  ev = WaitWindowEvent()          
            Select Ev    
                Case #PB_Event_Gadget                                             
                    Select EventGadget()
                       Case #PB_Event_CloseWindow
                         appQuit = 1                  
                       Case #zend                         
                         zend()                                    
                       Case #open
                         find_port()                         
                       Case #close
                         close_port()
                       Case #view    ;look what is received
                         lees_poort()
                    EndSelect               
             EndSelect    
          Until ev=#PB_Event_CloseWindow 
           End 
  EndIf
  ;--------------------------------------------------------- 
  Procedure close_port()
    CloseSerialPort(#compoort)
    SetGadgetText(#state,"COM=close"):SetGadgetColor(#state,#PB_Gadget_BackColor,$8344F7)
    verbonden=0
  EndProcedure  
;-----------------------------------------------------------------------------------------
 Procedure open_port()
   OpenSerialPort(#compoort, port$ ,115200,#PB_SerialPort_NoParity, 8, 1, #PB_SerialPort_NoHandshake, 1, 1) 
 If IsSerialPort(#compoort)<>0  And verbonden=1  
               SetGadgetText(#state,port$+"=OPEN")                        
               SetGadgetColor(#state,#PB_Gadget_BackColor,$A7EC16)
            Else
                port_error()
           EndIf       
EndProcedure
;-----------------------------------------------------------------------------------------
Procedure find_port()

For Port_nr = 1 To 20  
  Port$ = "COM"+Str(port_nr)     
     OpenSerialPort(#compoort, port$ ,115200,#PB_SerialPort_NoParity, 8, 1, #PB_SerialPort_NoHandshake, 1, 1) 
       WriteSerialPortString(#compoort,"x" + #CRLF$,#PB_Ascii)        ;write something
       Delay(100)
       Data_in = AvailableSerialPortInput(#compoort)            ;test data      
       If data_in > 0          
          Serial_in = Space(data_in)                                                                      
          ReadSerialPortData(#compoort, @serial_in,data_in)               ;read data ,length
             Verbonden = 1:  serial_in = " "           
             Port$ = "COM"+Str(port_nr)
             Debug port$
             Break                   
             CloseSerialPort(#compoort)
            
    EndIf
Next
   OpenSerialPort(#compoort, port$ ,115200,#PB_SerialPort_NoParity, 8, 1, #PB_SerialPort_NoHandshake, 1, 1) 
 If IsSerialPort(#compoort)<>0   And verbonden=1
               SetGadgetText(#state,port$+"=OPEN")                        
               SetGadgetColor(#state,#PB_Gadget_BackColor,$A7EC16)
            Else
             port_error()
           EndIf       
EndProcedure
;-----------------------------------------------------------------------------------------
Procedure zend() 
  zend$=GetGadgetText(#message)
  zend$=zend$+Chr(13)+Chr(10)
  ;Debug zend$
   If verbonden=1
     WriteSerialPortString(#compoort,zend$,#PB_Ascii)
   Else
     port_error() 
  EndIf   
EndProcedure 
;---------------------------------------------------------------------
Procedure port_error()
  MessageRequester("SerialPort","COMPORT NOT OPEN,RESTART PROGRAMMA OR PRESS F1")
    SetGadgetText(#state,"COM=close"):SetGadgetColor(#state,#PB_Gadget_BackColor,$8344F7)
EndProcedure  
;-----------------------------------------------------------------------------------
Procedure lees_poort()
  temp$=""
  If verbonden=0
    port_error()
  Else
    Data_in=AvailableSerialPortInput(#compoort)
        If data_in >0
           serial_in=Space(data_in)
           ReadSerialPortData(#compoort, @serial_in, data_in)
           temp$=PeekS(@serial_in,data_in,#PB_Ascii) 
          ; Debug temp$
        EndIf  
         SetGadgetText(#rec,temp$)
         data_in=0
  EndIf    
      EndProcedure 
Marc56us
Addict
Addict
Posts: 1600
Joined: Sat Feb 08, 2014 3:26 pm

Re: Serial Port comunication witch arduino

Post by Marc56us »

ludoke wrote:the program in the arduino is loaded with GRBL (https://github.com/grbl/grbl/wiki)
This site is obsolete the lastest GRBL is 1.1 and documentation is here https://github.com/gnea/grbl
ludoke wrote:when using my code en send ? + CR +LF or send $ + CR +LF
the arduino answer
[HLP:$$ $# $G $I $N $x=val $Nx=line $J=line $SLP $C $X $H ~ ! ? ctrl-x]
ok
ok
This display only help on commands (list availables commands), type $$ to see configuration stored in chipset.

The two main problems with serial programs are connection speed and data buffer management.
It's often difficult to manage and it makes it look like random errors.

By putting the reception part in a thread you can keep your hand on the rest of the program, but sending a command remains linked to the complete emptying of the buffer. This is why a CNC machine does not seem to respond immediately to manual commands sending by software but work find with serial software.

:wink:
ludoke
Enthusiast
Enthusiast
Posts: 155
Joined: Fri Jul 08, 2016 5:35 pm
Location: Essen (Belgium)

Re: Serial Port comunication witch arduino

Post by ludoke »

I find this program ,it is with thread ,and it works .
I try to implemented in my code.

Code: Select all

; Comment : Comport Manager Over Thread and Callback
; Author  : mk-soft
; Version : v0.05
; Created : 26.01.2018
; Updated : 03.04.2018

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

CompilerIf #PB_Compiler_Thread = 0
  CompilerError "Use Option Threadsafe!"
CompilerEndIf
 
Prototype ProtoReceiveCB(Text.s)
Prototype ProtoStatusCB(Status, *ComData)

Enumeration
  #ComStatus_Nothing
  #ComStatus_OpenPort
  #ComStatus_ClosePort
  #ComStatus_ErrorOpenPort
  #ComStatus_ErrorSend
  #ComStatus_ErrorReceive
  #ComStatus_ErrorDataSize
  #zend
EndEnumeration

Structure udtComData
  ; Header
  ThreadID.i
  Exit.i
  Status.i
  ; Port Data
  ComID.i
  Port.s
  Baud.i
  Parity.i
  DataBit.i
  StopBit.i
  Handshake.i
  BufferSize.i
  ; End Of Text
  EndOfText.s
  ; Send Data
  SendSignal.i
  SendCount.i
  SendText.s
  SendError.i
  ; Receive data
  ReceiveCount.i
  ReceiveText.s
  ReceiveError.i
  ; Callback
  *StatusCB.ProtoStatusCB
  *ReceiveCB.ProtoReceiveCB
EndStructure

Procedure thComport(*ComData.udtComData)
 
  Protected *Send, *Receive, SendText.s, SendLen, ReceiveText.s, ReceiveLen, Pos
 
  With *ComData
    ; Startup
    \Status = 1
    \SendCount = 0
    \ReceiveCount = 0
    \ComID = OpenSerialPort(#PB_Any, \Port, \Baud, \Parity, \DataBit, \StopBit, \Handshake, \BufferSize, \BufferSize)
    If \ComID
      \Status = 2
    Else
      If \StatusCB
        \StatusCB(#ComStatus_ErrorOpenPort, *ComData)
      EndIf
      \Status = 0
      ProcedureReturn 0
    EndIf
    If \StatusCB
      \StatusCB(#ComStatus_OpenPort, *ComData)
    EndIf
    *Send = AllocateMemory(\BufferSize)
    *Receive = AllocateMemory(\BufferSize)
    ; Loop
    Repeat
      If \SendSignal
        SendText = \SendText + \EndOfText
        SendLen = StringByteLength(SendText, #PB_Ascii)
        If SendLen <= \BufferSize
          PokeS(*Send, SendText, SendLen, #PB_Ascii)
          If WriteSerialPortData(\ComID, *Send, SendLen) = 0
            \SendError = SerialPortError(\ComID)
            If \StatusCB
              \StatusCB(#ComStatus_ErrorSend, *ComData)
            EndIf
          Else
            \SendError = 0
            \SendCount + 1
          EndIf
        Else
          If \StatusCB
            \StatusCB(#ComStatus_ErrorDataSize, *ComData)
          EndIf
        EndIf
        \SendSignal = 0
      EndIf
      ReceiveLen = AvailableSerialPortInput(\ComID)
      If ReceiveLen
        ReceiveLen = ReadSerialPortData(\ComID, *Receive, ReceiveLen)
        If ReceiveLen = 0
          \ReceiveError = SerialPortError(\ComID)
          If \StatusCB
            \StatusCB(#ComStatus_ErrorReceive, *ComData)
          EndIf
        Else
          \ReceiveError = 0
        EndIf
        ReceiveText + PeekS(*Receive, ReceiveLen, #PB_Ascii)
        Repeat
          pos = FindString(ReceiveText, \EndOfText, 1, #PB_String_NoCase)
          If pos
            \ReceiveText = Left(ReceiveText, pos - 1)
            ReceiveText = Mid(ReceiveText, pos + Len(\EndOfText))
            \ReceiveCount + 1
            If \ReceiveCB
              \ReceiveCB(\ReceiveText)
            EndIf
          EndIf
        Until pos = 0
      EndIf
      Delay(10)
    Until \Exit
    ; Shutdown
    CloseSerialPort(\ComID)
    If \StatusCB
      \StatusCB(#ComStatus_ClosePort, *ComData)
    EndIf
    FreeMemory(*Send)
    FreeMemory(*Receive)
    \Status = 0
    \ComID = 0
    \Exit = 0
    ProcedureReturn 1
  EndWith
 
EndProcedure

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

; Threaded String Helper
Procedure AllocateString(String.s)
  Protected *mem
  *mem = AllocateMemory(StringByteLength(String) + SizeOf(Character))
  If *mem
    PokeS(*mem, String)
  EndIf
  ProcedureReturn *mem
EndProcedure

Procedure.s FreeString(*Mem)
  Protected result.s
  If *Mem
    result = PeekS(*Mem)
    FreeMemory(*Mem)
  EndIf
  ProcedureReturn result
EndProcedure

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

CompilerIf #PB_Compiler_IsMainFile
 
  Global ComData.udtComData
 
  Enumeration EventCustomValue #PB_Event_FirstCustomValue
    #My_Event_NewData
    #My_Event_NewState
  EndEnumeration
 
  ; ---------------------------------------------------------------------------
 
  Procedure ReceiveCB(Text.s)
    PostEvent(#My_Event_NewData, 0, 0, 0, AllocateString(Text))
  EndProcedure
 ;---------------------------------------------------
  Procedure MyEventNewDataCB()
    Protected Text.s
    Text = FreeString(EventData())
    AddGadgetItem(0, -1, Text)
    SetGadgetState(0, CountGadgetItems(0) - 1)
    SetGadgetState(0, -1)
  EndProcedure
 
  BindEvent(#My_Event_NewData, @MyEventNewDataCB())
 
  ; ---------------------------------------------------------------------------
 
  Procedure StatusCB(Status, *ComData.udtComData)
    PostEvent(#My_Event_NewState, 0, 0, Status, *ComData)
  EndProcedure
 ;------------------------------------------------------------------------
  Procedure MyEventNewStateCB()
    Protected Text.s, Status, *ComData.udtComData
    Status = EventType()
    *ComData = EventData()
    Select Status
      Case #ComStatus_OpenPort
        Text = "ComStatus: Open Port " + *ComData\Port
      Case #ComStatus_ClosePort
        Text = "ComStatus: Close Port " + *ComData\Port
      Case #ComStatus_ErrorOpenPort
        Text = "ComError: Open Port " + *ComData\Port
      Case #ComStatus_ErrorSend
        Text = "ComError Send: Port " + *ComData\Port + " - ErrorCode " + *ComData\SendError
      Case #ComStatus_ErrorReceive
        Text = "ComError Receive: Port " + *ComData\Port + " - ErrorCode " + *ComData\ReceiveError
    EndSelect
    If Bool(Text)
      StatusBarText(0, 0, Text)
    EndIf
  EndProcedure
 
  BindEvent(#My_Event_NewState, @MyEventNewStateCB())
 
  ; ---------------------------------------------------------------------------
 
  Procedure InitComport()
    With ComData
      If \Status
        ProcedureReturn 2 ; Always running
      EndIf
      \Port = "COM4"
      \Baud = 115200
      \Parity = #PB_SerialPort_NoParity
      \DataBit = 8
      \StopBit = 1
      \Handshake = #PB_SerialPort_NoHandshake
      \BufferSize = 2048
      \EndOfText = #CRLF$
      \StatusCB = @StatusCB()
      \ReceiveCB = @ReceiveCB()
      \ThreadID = CreateThread(@thComport(), ComData)
      If Not \ThreadID
        StatusBarText(0, 0, "Comport " + \Port + ": Error Create Thread")
        ProcedureReturn 0 ; Error create thread
      Else
        ProcedureReturn 1 ; ok
      EndIf
    EndWith
  EndProcedure
 
  Procedure Main()
    Protected Event
    If OpenWindow(0, #PB_Ignore, #PB_Ignore, 800, 600, " Test Comport", #PB_Window_SystemMenu)
      CreateStatusBar(0, WindowID(0))
      AddStatusBarField(#PB_Ignore)
      ListViewGadget(0, 0, 0, 800, 540)
      StringGadget(1, 5, 545, 590, 25, "")
      ButtonGadget(#zend, 605, 545, 90, 25, "Send")
      ButtonGadget(3, 695, 545, 90, 25, "On/Off")
      AddKeyboardShortcut(0, #PB_Shortcut_Return, 1000)
      Repeat
        Event = WaitWindowEvent()
        Select Event
          Case #PB_Event_CloseWindow
            If ComData\Status
              MessageRequester("Info", "Comport Is Open!", #PB_MessageRequester_Warning)
            Else
              Break
            EndIf
          Case #PB_Event_Gadget
            Select EventGadget()
              Case #zend  ;(2)
                If ComData\Status = 2 And ComData\SendSignal = 0
                  ComData\SendText = GetGadgetText(1)
                  ComData\SendSignal = 1
                EndIf
              Case 3  ;on/off
                If ComData\Status
                  ComData\Exit = 1
                Else
                  InitComport()
                EndIf
            EndSelect
          Case #PB_Event_Menu
            Select EventMenu()
            ;  Case 1000
              ;  If GetActiveGadget() = 1
                ;  PostEvent(#PB_Event_Gadget, 0, 2, #PB_EventType_LeftClick)
                ;  Debug "1000"
               ; EndIf
            EndSelect
        EndSelect
      ForEver
    EndIf
  EndProcedure : Main()
Post Reply