Page 1 of 3
RS-232 receive data
Posted: Sat Feb 13, 2016 8:46 pm
by europa81
Hi all,
I want to receive data from a µController (AVR 2560) and display. For that end I wrote a little programm which counts from 0 to 100 on the µController and sends it via COM9 @ 1200 Bd, 8, N, 1.
This little programme is supposed to read the COM9 and display the nrs. While in any Terminal the numbers count up correctly, this code does display Nrs. 48 ~ 56 and then garbage.
Code: Select all
#WindowColor=$FAFAFA
Define flags = #PB_Window_ScreenCentered|#PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget
OpenWindow(0,0,0,250,250,"RS-232",flags)
WindowBounds(0,150,150, #PB_Ignore, #PB_Ignore)
SetWindowColor(0,#WindowColor)
TextGadget(0,10,10,80,30, "Data")
TextGadget(1,90,10,80,30,"Nrs")
OpenSerialPort(0,"COM9",1200,#PB_SerialPort_NoParity,8,1,#PB_SerialPort_NoHandshake,512,512)
AddWindowTimer(0,0,100)
Repeat
Select WaitWindowEvent()
Case #PB_Event_Timer:Gosub rx
Case #PB_Event_CloseWindow:CloseSerialPort(0):End
EndSelect
ForEver
rx:; Subroutine Receive
If AvailableSerialPortInput(0)>0
ReadSerialPortData(0,@byte,1)
SetGadgetText (1,StrU(byte, #PB_Byte))
EndIf
Return
It appears that the
is always executed.
And help would be appreciated with a hint how to understand the buffer within
. Is it not possible to read a single byte directly from the serial port ?
Thanks in advance
Re: RS-232 receive data
Posted: Sat Feb 13, 2016 10:34 pm
by infratec
Hi,
try this:
Code: Select all
#WindowColor=$FAFAFA
Procedure CheckRx()
Protected Byte.a
While AvailableSerialPortInput(0)
If ReadSerialPortData(0, @Byte, 1) = 1
AddGadgetItem(0, -1, RSet(Hex(Byte, #PB_Byte), 2, "0") + #LF$ + Str(Byte) + #LF$ + Chr(Byte))
EndIf
Wend
EndProcedure
Define flags = #PB_Window_ScreenCentered|#PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget
OpenWindow(0,0,0,250,250,"RS-232",flags)
WindowBounds(0,150,150, #PB_Ignore, #PB_Ignore)
SetWindowColor(0,#WindowColor)
ListIconGadget(0, 10, 10, 230, 230, "Hex", 60, #PB_ListIcon_FullRowSelect)
AddGadgetColumn(0, 1, "Dez", 60)
AddGadgetColumn(0, 2, "Ascii", 60)
OpenSerialPort(0,"COM9",1200,#PB_SerialPort_NoParity,8,1,#PB_SerialPort_NoHandshake,1024,16)
AddWindowTimer(0,0,100)
Repeat
Select WaitWindowEvent()
Case #PB_Event_Timer
If EventTimer() = 0
CheckRx()
EndIf
Case #PB_Event_CloseWindow
CloseSerialPort(0)
End
EndSelect
ForEver
But if you do something with more data, you'll need an own thread for the serial stuff.
Bernd
Re: RS-232 receive data
Posted: Sat Feb 13, 2016 10:48 pm
by infratec
Since it is windows, you can not access the port directly like in DOS.
Windows itself stores the received bytes inside a buffer which size is written in the OpenSerialPort()
With ReadSerialPortData() you can read one byte out of the receive buffer.
So you can build up a state machine for received data.
AvailableSerialPortInput() is 'nonblocking' it does not wait for serial data.
Bernd
Re: RS-232 receive data
Posted: Sat Feb 13, 2016 11:23 pm
by europa81
infratec wrote:Since it is windows, you can not access the port directly like in DOS.
Windows itself stores the received bytes inside a buffer which size is written in the OpenSerialPort()
With ReadSerialPortData() you can read one byte out of the receive buffer.
So you can build up a state machine for received data.
AvailableSerialPortInput() is 'nonblocking' it does not wait for serial data.
Bernd
Hello Bernd,
thank you a lot. I have read your advice and am still at loss. That is because of the @-sign before the byte-variable. What does that stand for ? And you beat me into another sleepless night again with your
. Does it count to zero ?
The output of your programm is:

so I might have the output wrong from the µController.
In the end I would like to communicate with a QuadCopter FlightController via RS-232, but the light at the end of the tunnel seems far !
Thomas
Re: RS-232 receive data
Posted: Sat Feb 13, 2016 11:28 pm
by infratec
Hi,
@ is the address operator
ReadSerialPorData() writes to a buffer not to a variable.
So you need the address of Byte and not the variable Byte.
Is only the security check that the event is really coming from Timer 0
(You can have more than one timer

)
You did not run the latest version.
But it looks that you always sends '0' + CRLF
Bernd
Re: RS-232 receive data
Posted: Sat Feb 13, 2016 11:35 pm
by europa81
infratec wrote:Hi,
You did not run the latest version.
But it looks that you always sends '0' + CRLF
Bernd
Hi Bernd,
ok, I got rid off the 10 & 13 with the Bascom-code on the µController:
Code: Select all
$regfile = "m2560def.dat"
$framesize = 32
$swstack = 32
$hwstack = 32
$crystal = 16000000
$baud = 1200
Dim X As Byte
Do
For X = 0 To 100
Print X;
Waitms 300
Next X
Loop
End
But I only see the Nr. 48. Now, I shall spend the night on threads. At the end I would like to communicate with a NAZE32 Copter-FlightController.
Thomas
Re: RS-232 receive data
Posted: Sat Feb 13, 2016 11:44 pm
by infratec
Use PRINTBIN instead of PRINT
Re: RS-232 receive data
Posted: Sat Feb 13, 2016 11:45 pm
by infratec
Re: RS-232 receive data
Posted: Sat Feb 13, 2016 11:48 pm
by infratec
If you search in the 'Coding Questions' section you will find many examples (most by me

) for communication and threads.
Bernd
Re: RS-232 receive data
Posted: Sat Feb 13, 2016 11:52 pm
by europa81
Thank you for that hint. With Printbin it does
kind of work. I beg to differ though on the CRLF. If you put a
";"
after the
-command, there will be no CRLF.
Now I will have to spend the night on your
&
. And those
threads ....
Thomas
Re: RS-232 receive data
Posted: Sat Feb 13, 2016 11:55 pm
by infratec
Then I wish you a 'good' night

Re: RS-232 receive data
Posted: Sun Feb 14, 2016 10:50 am
by infratec
A Thread example:
Code: Select all
EnableExplicit
CompilerIf Not #PB_Compiler_Thread
MessageRequester("Info", "Enable Thread-Safe in compiler options!")
End
CompilerEndIf
Enumeration #PB_Event_FirstCustomValue
#Com_Event_RxBytes
#Com_Event_TxBytes
#Com_Event_RxComplete
#Com_Event_Exit
EndEnumeration
Structure ComParameterStructure
COM$
Thread.i
Semaphore.i
Mutex.i
Rx$
Tx$
Exit.i
EndStructure
Procedure ComThread(*Parameter.ComParameterStructure)
Protected.a Byte
Protected.i Port, RxLen, RxBytes, State
Protected Rx$
Port = OpenSerialPort(#PB_Any, *Parameter\COM$, 1200, #PB_SerialPort_NoParity, 8, 1, #PB_SerialPort_NoHandshake, 128, 128)
If Port
Repeat
RxLen = AvailableSerialPortInput(Port)
If RxLen
While RxLen
If ReadSerialPortData(Port, @Byte, 1) = 1
RxBytes + 1
PostEvent(#Com_Event_RxBytes, 0, 0, 0, RxBytes)
Debug Byte
Select State
Case 0
If Byte = #CR
State + 1
Else
*Parameter\Rx$ + Chr(Byte)
EndIf
Case 1
If Byte = #LF
PostEvent(#Com_Event_RxComplete)
WaitSemaphore(*Parameter\Semaphore)
EndIf
State = 0
EndSelect
RxLen - 1
EndIf
Wend
ElseIf TryLockMutex(*Parameter\Mutex)
If Len(*Parameter\Tx$)
WriteSerialPortString(Port, *Parameter\Tx$, #PB_Ascii)
*Parameter\Tx$ = ""
EndIf
UnlockMutex(*Parameter\Mutex)
Else
Delay(3)
EndIf
Until *Parameter\Exit
CloseSerialPort(Port)
EndIf
PostEvent(#Com_Event_Exit)
EndProcedure
Define.i Event, Exit
Define ComParameter.ComParameterStructure
OpenWindow(0, 0, 0, 640, 480, "Com - Test", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
ButtonGadget(0, 10, 10, 80, 25, "Connect")
CreateStatusBar(0, WindowID(0))
AddStatusBarField(100)
AddStatusBarField(100)
AddStatusBarField(100)
AddStatusBarField(100)
StatusBarText(0, 0, "disconnected", #PB_StatusBar_Center)
StatusBarText(0, 1, "Rx: 0", #PB_StatusBar_Center)
StatusBarText(0, 2, "Tx: 0", #PB_StatusBar_Center)
ComParameter\COM$ = "COM9"
ComParameter\Semaphore = CreateSemaphore()
ComParameter\Mutex = CreateMutex()
Repeat
Event = WaitWindowEvent()
Select Event
Case #Com_Event_RxBytes
StatusBarText(0, 1, "Rx: " + Str(EventData()), #PB_StatusBar_Center)
Case #Com_Event_TxBytes
StatusBarText(0, 2, "Tx: " + Str(EventData()), #PB_StatusBar_Center)
Case #Com_Event_RxComplete
StatusBarText(0, 3, ComParameter\Rx$, #PB_StatusBar_Center)
Select ComParameter\Rx$
Case "ping"
LockMutex(ComParameter\Mutex)
ComParameter\Tx$ = "pong"
UnlockMutex(ComParameter\Mutex)
EndSelect
ComParameter\Rx$ = ""
SignalSemaphore(ComParameter\Semaphore)
Case #Com_Event_Exit
ComParameter\Exit = #False
SetGadgetText(0, "Connect")
StatusBarText(0, 0, "disconnected", #PB_StatusBar_Center)
Case #PB_Event_Gadget
Select EventGadget()
Case 0
If IsThread(ComParameter\Thread)
ComParameter\Exit = #True
Else
ComParameter\Thread = CreateThread(@ComThread(), @ComParameter)
If ComParameter\Thread
SetGadgetText(0, "Disconnect")
StatusBarText(0, 0, "connected", #PB_StatusBar_Center)
EndIf
EndIf
EndSelect
Case #PB_Event_CloseWindow
If IsThread(ComParameter\Thread)
ComParameter\Exit = #True
If WaitThread(ComParameter\Thread, 1000) = 0
KillThread(ComParameter\Thread)
EndIf
EndIf
FreeMutex(ComParameter\Mutex)
FreeSemaphore(ComParameter\Semaphore)
Exit = #True
EndSelect
Until Exit
If you want a stable program, than don't show any text direct from inside the thread.
Use always the way with PostEvent().
At least in Linux and OS X you run in big trouble if you do it directly.
Bernd
Re: RS-232 receive data
Posted: Sun Feb 14, 2016 12:58 pm
by europa81
infratec wrote:A Thread example:
Bernd
Bernd, Guten Morgen !
and thank you. I am still working on that thread part, but one question which is bugging me since: how does the @byte know which position within the receive-buffer is the actual one ? I would expect something like:
Code: Select all
buffer_length = available_bytes_in_buffer
for x=0 to buffer_length-1
receive$=receive$+byte(x)
next x
with then receive$ containing the entire buffer.
cheers
Thomas
__________________________________________________
Code tags added
14.02.2016
RSBasic
Re: RS-232 receive data
Posted: Sun Feb 14, 2016 1:54 pm
by europa81
Have been doing some more work on the programme - at my limited intellectual level and am proud to have a moving bar alongside a working programme:
Code: Select all
#WindowColor=$FAFAFA
Define flags = #PB_Window_ScreenCentered|#PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget
OpenWindow(0,0,0,250,60,"RS-232",flags)
WindowBounds(0,150,150, #PB_Ignore, #PB_Ignore)
SetWindowColor(0,#WindowColor)
TextGadget(0,80,10,35,20, "Data:")
TextGadget(1,120,10,45,20,"Nrs")
TrackBarGadget (2, 5, 40, 240, 30, 0, 100, #PB_TrackBar_Ticks)
OpenSerialPort(0,"COM9",1200,#PB_SerialPort_NoParity,8,1,#PB_SerialPort_NoHandshake,512,512)
AddWindowTimer(0,0,20)
Repeat
Select WaitWindowEvent()
Case #PB_Event_Timer:Gosub rx
Case #PB_Event_CloseWindow:CloseSerialPort(0):End
EndSelect
ForEver
rx:; Subroutine Receive
b.l=AvailableSerialPortInput(0)
If ReadSerialPortData(0,@Puffer,b)
p$=Str(puffer)
SetGadgetText (1,RSet(p$,8))
SetGadgetState (2,Puffer)
EndIf
Return
I shall now modify from Subroutine to Procedure. That Thread-thing is still spanish/latin/greek to me as well as the above question as to the pointer knowing which byte of the buffer is to be read. It is a pitty that the serial port cannot trigger an interrupt but that instead a timer wastes plenty of time checking for available data.
Thomas
Re: RS-232 receive data
Posted: Sun Feb 14, 2016 2:10 pm
by europa81
here is the Bascom-code for completeness sake:
Code: Select all
$regfile = "m2560def.dat"
$framesize = 32
$swstack = 32
$hwstack = 32
$crystal = 16000000
$baud = 1200
Dim X As Byte
Dim Y As Byte
Do
For X = 0 To 100
Printbin X;
Waitms 100
Next X
For X = 100 To 0 Step -2
Printbin X
Waitms 40
Next X
For X = 0 To 40
Y = Rnd(100)
Printbin Y
Waitms 150
Next X
Loop
End
I notice a fragile behavior of the PB-Programme though: if alone I wish to reposition the running programme on the screen it starts receiving garbage. Could probably be helped by lowering the timer-nr, but that is a lot of wasted time. Guess, I need to learn more about the RS-232 buffer.
Thomas
PS: Forum-question - how can I include an image without the need of hosting it on another server first ?