RS-232 receive data

Just starting out? Need help? Post your questions and find answers here.
User avatar
RSBasic
Moderator
Moderator
Posts: 1228
Joined: Thu Dec 31, 2009 11:05 pm
Location: Gernsbach (Germany)
Contact:

Re: RS-232 receive data

Post by RSBasic »

europa81 wrote:PS: Forum-question - how can I include an image without the need of hosting it on another server first
Not at all. You can upload only on foreign server.
Image
Image
europa81
User
User
Posts: 24
Joined: Tue Oct 20, 2015 11:42 pm
Location: Southern Germany

Re: RS-232 receive data

Post by europa81 »

Thanks, will keep hosting elsewhere when need be.

Here now is the code with procedure instead of a subroutine:

Code: Select all

#WindowColor=$FAFAFA

Procedure rs232()
 b.l=AvailableSerialPortInput(0)
If ReadSerialPortData(0,@Puffer,b)
  p$=Str(puffer)
  SetGadgetState (2,Puffer)
  EndIf
EndProcedure 

Define flags = #PB_Window_ScreenCentered|#PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget
OpenWindow(0,0,0,300,100,"RS-232",flags)
WindowBounds(0,150,150, #PB_Ignore, #PB_Ignore)
SetWindowColor(0,#WindowColor)
TextGadget(0,5,10,48,20, "rx-data:", #PB_Text_Center)
TextGadget(1,5,50,48,20, "tx-data:", #PB_Text_Center)
TrackBarGadget (2, 55, 10, 240, 30, 0, 100)
TrackBarGadget (3, 55, 50, 240, 30, 0, 100) 
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: rs232()
    Case #PB_Event_CloseWindow:CloseSerialPort(0):End
EndSelect
ForEver
as you see, I am preparing to send data out over the serial port. Basically read the position of the tx-data TrackBar and send that byte in order for the µController to control the brightness of a LED by PWM. And again I run into the same problem: the command WriteSerialPort requires a Buffer. How in the world can I know where the buffer is ?

Other question: when I resize or reposition the running programme, it will start to receive garbage. Probably due to a buffer-overrun. How can I force the programme to keep running while it is being resized ?
Thomas
infratec
Always Here
Always Here
Posts: 7583
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: RS-232 receive data

Post by infratec »

Hi,

the bytes are already in a 'buffer' (from the OS and it's driver) as I told you.
Withe ReadSerialPortData() you transfer the bytes from the OS buffer to a buffer of your choice.

A buffer is a memory area, so you need a pointer which points at this memory.
If you want to fetch one byte after an other, than a buffer of one byte is enough.

You can define a byte variable (Byte.a) and give the ReadSerialPortData() procedure the address of this byte.
This is done via @Byte which means address of the variable Byte.

If you want to transfer more than one byte, than you need a 'real' buffer which needs to be allocated with
AllocateMemory().

If you want to write serial port data you have 2 choices
For a string WriteSerialPortString() and for bytes WriteSerialPortData().
But normally you need the #PB_Ascii flag for the string variant.

I hope you can follow these explanations.

Bernd
infratec
Always Here
Always Here
Posts: 7583
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: RS-232 receive data

Post by infratec »

In your last example the variable 'Puffer' is declared 'on the fly' which means it is an integer variable.

For a beginner, and also for me, it is a good decission to use EnableExplicit at beginning of your code.
Then you have to define your variables before you can use them.

This has one big advantage:
If you make a typo like Pufer instead of Puffer you will be informed that something is wrong.
Without you are searching for hours until you find out that your value is written to the wrong variable.

Bernd
infratec
Always Here
Always Here
Posts: 7583
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: RS-232 receive data

Post by infratec »

Btw. I don't see any try to send something.
infratec
Always Here
Always Here
Posts: 7583
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: RS-232 receive data

Post by infratec »

Code: Select all

buffer_length = available_bytes_in_buffer
for x=0 to buffer_length-1
  receive$=receive$+byte(x)
next x
This works also in PB.

Code: Select all

buffer_length = AvailableSerialPortInput(0)
For x=1 To buffer_length
  ReadSerialPortData(0, @Byte, 1)
  receive$ = receive$ + Chr(Byte)
Next x
But when is your data finished?

2 posibillities:
1. you use a length byte in front
2. you only send ascii values and terminate the string with a CR

Bernd
infratec
Always Here
Always Here
Posts: 7583
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: RS-232 receive data

Post by infratec »

Code: Select all

EnableExplicit

#WindowColor=$FAFAFA

Procedure rs232()
  
  Protected RxByte.a
  
  While AvailableSerialPortInput(0)
    If ReadSerialPortData(0,@RxByte,1) = 1
      SetGadgetState(2, RxByte)
    EndIf
  Wend
EndProcedure

Define TxByte.a

Define flags = #PB_Window_ScreenCentered|#PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget
OpenWindow(0,0,0,300,100,"RS-232",flags)
WindowBounds(0,150,150, #PB_Ignore, #PB_Ignore)
SetWindowColor(0,#WindowColor)
TextGadget(0,5,10,48,20, "rx-data:", #PB_Text_Center)
TextGadget(1,5,50,48,20, "tx-data:", #PB_Text_Center)
TrackBarGadget (2, 55, 10, 240, 30, 0, 100)
TrackBarGadget (3, 55, 50, 240, 30, 0, 100)
OpenSerialPort(0,"COM3",1200,#PB_SerialPort_NoParity,8,1,#PB_SerialPort_NoHandshake,512,512)
AddWindowTimer(0,0,20)

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_Timer: rs232()
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 3
          TxByte = GetGadgetState(3)
          Debug TxByte
          WriteSerialPortData(0, @TxByte, 1)
      EndSelect
    Case #PB_Event_CloseWindow:CloseSerialPort(0):End
  EndSelect
ForEver
Bernd
europa81
User
User
Posts: 24
Joined: Tue Oct 20, 2015 11:42 pm
Location: Southern Germany

Re: RS-232 receive data

Post by europa81 »

infratec wrote:

Code: Select all

buffer_length = available_bytes_in_buffer
for x=0 to buffer_length-1
  receive$=receive$+byte(x)
next x
This works also in PB.

Code: Select all

buffer_length = AvailableSerialPortInput(0)
For x=1 To buffer_length
  ReadSerialPortData(0, @Byte, 1)
  receive$ = receive$ + Chr(Byte)
Next x
But when is your data finished?

2 posibillities:
1. you use a length byte in front
2. you only send ascii values and terminate the string with a CR

Bernd
Hello Bernd,
that is exactly the point - where is the x as pointer there ?? I still do not understand the @-sign. How does it know what to point to ?
And yes, I did not implement any tx-routine yet because of that buffer-issue. I tried today other compilers because there seems to be no answer !
I shall program the µController to terminate each sentence with a CRLF so the string can be parsed.
thanks
<Thomas>
infratec
Always Here
Always Here
Posts: 7583
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: RS-232 receive data

Post by infratec »

Hi,

I wrote your code with sending. Look above :mrgreen:
You can define a byte variable (Byte.a) and give the ReadSerialPortData() procedure the address of this byte.
This is done via @Byte which means address of the variable Byte.
Since you read only one byte after an other you need no X inside the loop.
ReadSerialPortData() 'reads' out bytes from the OS rx buffer.
It's a FIFO structure. So if you call it the next time it returns the next data -> no need for a pointer.

If you want to terminate it with CRLF, you are limited to transfer only ASCII.
And you need double of time: 50 needs 0x35 0x30 0x0D 0x0A instead of a single 0x32.
But if you have a 'text' driven interface it makes live easier to use ASCII.

Bernd
infratec
Always Here
Always Here
Posts: 7583
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: RS-232 receive data

Post by infratec »

Hi,

I extended my thread example to read in a complete line with CRLF at the end.

And trust me:
There is no easier solution which works on all main OSs than PB.

And even if you 'only' write a windows program PB is easy and you get always help when needed.

If you find an easier way, tell me the solution :mrgreen:
europa81
User
User
Posts: 24
Joined: Tue Oct 20, 2015 11:42 pm
Location: Southern Germany

Re: RS-232 receive data

Post by europa81 »

Thank you, Bernd !
I trust you that PB is the easiest solution. What I like most is that you can compile such small stand-alone .exe-files.
Your new code works fine and the problem of repositioning and resizing is solved. Probably because you read the entire buffer. I lowered the timer to some crazy numbers (such as 1ooo ms) and it works fine.
As to chr vs byte: I am planning to read out the data from a 3-axis accelerometer which basically behaves like three ADC at 8-Bit resolution. This means, any combination is going to be possible. However, we never know, when the client is going to be connected or whether a byte has been corrupted during transmission. The only way out is going to be a protocoll with a start/end code and some sort of checksum.
As I plan to make this thread a starting point to all of us who are getting introduced to PB and the control of robots via the serial port (FTDI et al), let's get there step-by-step. Tomorrow I'll post the code with two rx/tx channels and we continue from there.
be well
<Thomas>
europa81
User
User
Posts: 24
Joined: Tue Oct 20, 2015 11:42 pm
Location: Southern Germany

Re: RS-232 receive data

Post by europa81 »

Alright, took another path: installed a RGB-LED on the AVR Board and control the three channels with three TrackBars individually. This code still uses one Byte only to transmit the three values by splitting up the range of 0 ~ 255 into:

Red: 0 ~ 80
Green: 81 ~ 161
Blue: 162 ~ 242

Next task is now to control three servos and use a different protocol allowing for full 8-Bit resolution each.

Code: Select all

EnableExplicit

#WindowColor=$F0F0F0

Define TxByte.a

Define flags = #PB_Window_ScreenCentered|#PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget
OpenWindow(0,0,0,300,200,"RGB-Steuerung",flags)
WindowBounds(0,200,200, #PB_Ignore, #PB_Ignore)
SetWindowColor(0,#WindowColor)
TextGadget (0, 70, 5, 190, 20, "RGB-Steuerung", #PB_Text_Center)
TextGadget(1,5,30,30,20, "R: ", #PB_Text_Center)
TextGadget(2, 5, 60, 30, 20, "G:", #PB_Text_Center)
TextGadget(3, 5, 90, 30, 20, "B: ", #PB_Text_Center)
TrackBarGadget (4, 55, 30, 240, 30, 0, 80)
TrackBarGadget (5, 55, 60, 240, 30, 0, 80)
TrackBarGadget (6, 55, 90, 240, 30, 0, 80)

OpenSerialPort(0,"COM9",9600,#PB_SerialPort_NoParity,8,1,#PB_SerialPort_NoHandshake,512,512)
TxByte=0
WriteSerialPortData(0,@TxByte,1)
TxByte=81
WriteSerialPortData(0,@TxByte,1)
TxByte=162
WriteSerialPortData(0,@txbyte,1)
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 4
          TxByte = GetGadgetState(4)
          WriteSerialPortData(0, @TxByte, 1)
        Case 5
          TxByte=GetGadgetState(5)+81
          WriteSerialPortData(0,@TxByte,1)
        Case 6
          TxByte=GetGadgetState(6)+162
          WriteSerialPortData (0,@TxByte,1)
      EndSelect
    Case #PB_Event_CloseWindow:CloseSerialPort(0):End
  EndSelect
ForEver
cheers
<Thomas>
infratec
Always Here
Always Here
Posts: 7583
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: RS-232 receive data

Post by infratec »

Hi,

you can also use a 'packet' of 3 bytes with a guaranted minimum delay between the packets.
Than you can detect if it is a complete packet by checking a receive timeout between the bytes.
For example:

B1 max.10ms B2 max.10ms B3 min.100ms B1 max.10ms B2 max.10ms B3 min.100ms

If you received a byte you can check if the next byte is only max 15ms later.
If this happens 2 times, than you received a complete valid 3 byte packet.

I hope it's clear what I mean.

Bernd
europa81
User
User
Posts: 24
Joined: Tue Oct 20, 2015 11:42 pm
Location: Southern Germany

Re: RS-232 receive data

Post by europa81 »

Thank you, Bernd. That was clear. Using the timing on the serial channel could make sure when a message starts. Else, one could use a certain start-Byte such as 0xFE and avoid repetition of the following sequence.
My goal is to keep most of the workload on the PC-Side as the AVR has so much less computing power.
Thanks
<Thomas>
europa81
User
User
Posts: 24
Joined: Tue Oct 20, 2015 11:42 pm
Location: Southern Germany

Re: RS-232 receive data

Post by europa81 »

Now I am ready to receive a row of binary data which need to be analyzed. As you proposed, it should be done with AllocateMemory. In the programme I write:

Code: Select all

*uavdata=AllocateMemory (256)
and the compiler is unhappy with a non-declared variable. My questions:
(1) what does the "*" in front of the name of the allocated memory stand for ?
(2) why is the compiler unhappy ? I am thinking that the word before AllocateMemory is the name of the memory and not a variable.

cheers
Thomas
Post Reply