Serial Port comunication witch arduino
Re: Serial Port comunication witch arduino
If you can not find out, why my code is not working, then you did not understand how your arduino communicate.
If you don't know this, then you run in much more trouble if you start with threads.
First you have to know what it answers when you send your commands. (all bytes of it, not only the readable text)
You have to know when the answer is finished.
All other things are 'fishing blind'.
If you don't know this, then you run in much more trouble if you start with threads.
First you have to know what it answers when you send your commands. (all bytes of it, not only the readable text)
You have to know when the answer is finished.
All other things are 'fishing blind'.
Re: Serial Port comunication witch arduino
What I'm missing here is the description of the protocol. Normally there is always a document how the protocol is structured.
As it looks it is ASCII and with end character #CRLF$. Otherwise my example could not work as a thread with the end character 'CRLF' set.
So it applies:
Without a description of the protocol, you don't have to start at all.
As it looks it is ASCII and with end character #CRLF$. Otherwise my example could not work as a thread with the end character 'CRLF' set.
So it applies:
Without a description of the protocol, you don't have to start at all.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Re: Serial Port comunication witch arduino
I have extended the example so that you can copy the content of the ListView to the clipboard with Context.
Let's see what the output of the Comport delivers ?!
Let's see what the output of the Comport delivers ?!
Code: Select all
;-TOP
; Comment : Comport Manager Over Thread and Callback
; Author : mk-soft
; Version : v0.06
; Created : 26.01.2018
; Updated : 25.09.2020
; *****************************************************************************
CompilerIf #PB_Compiler_Thread = 0
CompilerError "Use Option Threadsafe!"
CompilerEndIf
Prototype ProtoReceiveCB(Text.s)
Prototype ProtoStatusCB(Status, *ComData)
Enumeration
#ComThread_Stopped
#ComThread_Startup
#ComThread_Running
EndEnumeration
Enumeration
#ComStatus_Nothing
#ComStatus_OpenPort
#ComStatus_ClosePort
#ComStatus_ErrorOpenPort
#ComStatus_ErrorSend
#ComStatus_ErrorReceive
#ComStatus_ErrorDataSize
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 = #ComThread_Startup
\SendCount = 0
\ReceiveCount = 0
\ComID = OpenSerialPort(#PB_Any, \Port, \Baud, \Parity, \DataBit, \StopBit, \Handshake, \BufferSize, \BufferSize)
If \ComID
\Status = #ComThread_Running
Else
If \StatusCB
\StatusCB(#ComStatus_ErrorOpenPort, *ComData)
EndIf
\Status = #ComThread_Stopped
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 = #False
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 = #ComThread_Stopped
\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, Text.s, i
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(2, 605, 545, 90, 25, "Send")
ButtonGadget(3, 695, 545, 90, 25, "On/Off")
AddKeyboardShortcut(0, #PB_Shortcut_Return, 1000)
CreatePopupMenu(1)
MenuItem(101, "Copy ListView")
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 0
If EventType() = #PB_EventType_RightClick
DisplayPopupMenu(1, WindowID(0))
EndIf
Case 2 ; send button
If ComData\Status = #ComThread_Running And ComData\SendSignal = #False
ComData\SendText = GetGadgetText(1)
ComData\SendSignal = #True
EndIf
Case 3 ; on/off button
If ComData\Status
ComData\Exit = 1
Else
InitComport()
EndIf
EndSelect
Case #PB_Event_Menu
Select EventMenu()
Case 101 ; popup menu
Text = ""
For i = 0 To CountGadgetItems(0) - 1
text + GetGadgetItemText(0, i) + #CRLF$
Next
SetClipboardText(Text)
EndSelect
EndSelect
ForEver
EndIf
EndProcedure : Main()
CompilerEndIf
Last edited by mk-soft on Sat Sep 03, 2022 11:14 am, edited 3 times in total.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Re: Serial Port comunication witch arduino
many thanks,
the description of the protocol,I have no idea.
Maybe i think a bit too simple,I suppose the Arduino works well that it is ok.
The arduino receives textstrings with gcode commands for example: G2 X6.962 Y6.4654 I0.25 J-0.433
from the PC ,when the arduino is ready is sends "ok" ,then the PC can send the next line of gcode ,if a "?" command is send ,the arduino anwers with the actual position of the machine.
This can be used to show the movement of a tool
There are many ohter commands and the arduino accept them ,so I think that it works fine.
Your code is a good start,but I still have to learn a lot.
the description of the protocol,I have no idea.
Maybe i think a bit too simple,I suppose the Arduino works well that it is ok.
The arduino receives textstrings with gcode commands for example: G2 X6.962 Y6.4654 I0.25 J-0.433
from the PC ,when the arduino is ready is sends "ok" ,then the PC can send the next line of gcode ,if a "?" command is send ,the arduino anwers with the actual position of the machine.
This can be used to show the movement of a tool
There are many ohter commands and the arduino accept them ,so I think that it works fine.
Your code is a good start,but I still have to learn a lot.
Re: Serial Port comunication witch arduino
What...
You must have a description, or you program the Arduino yourself. Somehow from where you must know what is sent and received.
Everything else is nonsense.
You must have a description, or you program the Arduino yourself. Somehow from where you must know what is sent and received.
Everything else is nonsense.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Re: Serial Port comunication witch arduino
Here some more info about the protocol.
https://github.com/gnea/grbl/wiki/Grbl- ... am-to-grbl
Streaming Protocol: Simple Send-Response [Recommended]
The send-response streaming protocol is the most fool-proof and simplest method to stream a G-code program to Grbl. The host PC interface simply sends a line of G-code to Grbl and waits for an ok or error: response message before sending the next line of G-code. So, no matter if Grbl needs to wait for room in the look-ahead planner buffer to finish parsing and executing the last line of G-code or if the host computer is busy doing something, this guarantees both to the host PC and Grbl, the programmed G-code has been sent and received properly. An example of this protocol is published in our simple_stream.py script in our repository.
more...
https://github.com/gnea/grbl/wiki/Grbl- ... am-to-grbl
Streaming Protocol: Simple Send-Response [Recommended]
The send-response streaming protocol is the most fool-proof and simplest method to stream a G-code program to Grbl. The host PC interface simply sends a line of G-code to Grbl and waits for an ok or error: response message before sending the next line of G-code. So, no matter if Grbl needs to wait for room in the look-ahead planner buffer to finish parsing and executing the last line of G-code or if the host computer is busy doing something, this guarantees both to the host PC and Grbl, the programmed G-code has been sent and received properly. An example of this protocol is published in our simple_stream.py script in our repository.
more...
Re: Serial Port comunication witch arduino
as I have written:
You have also to know the bytes which you not see, like CR and LF
So use a terminal program which shows you also the hex bytes and tell us what is transmitted.
Do you see as last 'Ok' ?
Is it followed by a CR or a LF or both?
Or do you see a new prompt?
Is there a space after it?
If you don't know this, you will never get success. With or without thread.
And since we don't have this programm running, it is your job to investigate this.
You have also to know the bytes which you not see, like CR and LF
So use a terminal program which shows you also the hex bytes and tell us what is transmitted.
Do you see as last 'Ok' ?
Is it followed by a CR or a LF or both?
Or do you see a new prompt?
Is there a space after it?
If you don't know this, you will never get success. With or without thread.
And since we don't have this programm running, it is your job to investigate this.
Re: Serial Port comunication witch arduino
infratec,
maybe you are right,You are probably an advanced programmer.
The mksoft code also works very well.
But as far as I can test the simple communication seems to work.
The Arduino accepts all the commands.If a valid code has been processed the arduino will send "OK"
If there is an error, the arduino replies that an error has occurred.
While the arduino is moving an axis , I can send a "?" to request the position .
I can send as many "?" as possible the arduino keep sending the position of the machine .
What else can I do, it seems to work anyway.
maybe you are right,You are probably an advanced programmer.
The mksoft code also works very well.
But as far as I can test the simple communication seems to work.
The Arduino accepts all the commands.If a valid code has been processed the arduino will send "OK"
If there is an error, the arduino replies that an error has occurred.
While the arduino is moving an axis , I can send a "?" to request the position .
I can send as many "?" as possible the arduino keep sending the position of the machine .
What else can I do, it seems to work anyway.
Re: Serial Port comunication witch arduino
Simply check whether control characters (ASCII < 32) are present.
See PB character table
See PB character table
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Re: Serial Port comunication witch arduino
what do you mean?
the arduino sends a CR, LF character (13,10).
There are no other control chars.
As far as I understand the GBRL in the arduino just receives text,and answer with text + CR+LF.
the arduino sends a CR, LF character (13,10).
There are no other control chars.
As far as I understand the GBRL in the arduino just receives text,and answer with text + CR+LF.
Re: Serial Port comunication witch arduino
So there is no prompt?
You see an empty line for entering new commands?
Or something like in DOS you see c:\> for example, in linux maybe : $
You see an empty line for entering new commands?
Or something like in DOS you see c:\> for example, in linux maybe : $
Re: Serial Port comunication witch arduino
there is actually no promts, only 'ok' or error or another text message.
It's just sending, waiting for answers and responding accordingly.
in fact, just textstrings are sent back and forth.I don't know how to explain it differently.
when the GRBL is connected to the PC, a message is sent to the PC.
Grbl 1.1f ['$' for help]
Then the Arduino is ready to receive commands.
If a command is sent to the arduino, the arduino will check this command and if there is no error, the command will be executed.
If there is an incorrect command, the Arduino will send an error code to the PC.
When the Arduino finishes executing the command, it sends an "OK".
Now the PC can send a new command and so on.That's what needs to be done.
Of course other messages can be sent and received,but it is just text.
Some commands examples:
$G (view parser state) answer [GC:G0 G54 G17 G21 G90 G94 M5 M9 T0 F0 S0]
ok
$I (view build info) answer[ VER:1.1f.20170801:][OPT:V,15,128] ok
It's just sending, waiting for answers and responding accordingly.
in fact, just textstrings are sent back and forth.I don't know how to explain it differently.
when the GRBL is connected to the PC, a message is sent to the PC.
Grbl 1.1f ['$' for help]
Then the Arduino is ready to receive commands.
If a command is sent to the arduino, the arduino will check this command and if there is no error, the command will be executed.
If there is an incorrect command, the Arduino will send an error code to the PC.
When the Arduino finishes executing the command, it sends an "OK".
Now the PC can send a new command and so on.That's what needs to be done.
Of course other messages can be sent and received,but it is just text.
Some commands examples:
$G (view parser state) answer [GC:G0 G54 G17 G21 G90 G94 M5 M9 T0 F0 S0]
ok
$I (view build info) answer[ VER:1.1f.20170801:][OPT:V,15,128] ok
Last edited by ludoke on Mon Dec 16, 2019 10:10 pm, edited 1 time in total.
Re: Serial Port comunication witch arduino
So it always sends an OK at the end of the transmission.
But still: ist there a CR+LF behind?
But still: ist there a CR+LF behind?
Re: Serial Port comunication witch arduino
there is also een CR +LF after the 'OK'.
Re: Serial Port comunication witch arduino
It can only be #CRLF$, otherwise it would not work with my thread example for Comport communication.
There is #CRLF$ entered as end identifier and passes the string without #CRLF$ to the callback.
When entering SendText and then the start signal SendSignal the end identifier #CRLF$ is automatically added and transmitted.
There is #CRLF$ entered as end identifier and passes the string without #CRLF$ to the callback.
When entering SendText and then the start signal SendSignal the end identifier #CRLF$ is automatically added and transmitted.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive