Too slow to parse 9600 baud data?

bigg_al

New Member
I have wasted countless hours writing "test" programs to try and figure out why seemingly simple tasks don't work properly with a Picaxe.
In this case it involves the high speed serial commands. I have tried a dozen different ways to parse incoming 9600 baud data looking for a particular string.
I tried both background and hserin. I was using sertxd to send some data to the terminal but figured that was slowing things down. So I went with blinking an led when the string was found in the data stream. Even at 16Mhz, the absolute smallest simplest loop doesn't catch all the occurrences of the string. ("FA")

setfreq m16
HSERSETUP B9600_16,%110

top:
hserin 0,14,("F")
get 0,b5
if b5=65 then pulsout d.1,5000
endif
goto top

A fun fact I found while working on this: The ptr for the scratchpad goes all the way to 1023.
P.S. The data stream is blocks of data with short pauses between blocks.

Your thoughts?
Thanks, Al
 

inglewoodpete

Senior Member
I have wasted countless hours writing "test" programs to try and figure out why seemingly simple tasks don't work properly with a Picaxe.
In this case it involves the high speed serial commands. I have tried a dozen different ways to parse incoming 9600 baud data looking for a particular string.
Not "wasted" but valuable learning time!
I tried both background and hserin. I was using sertxd to send some data to the terminal but figured that was slowing things down. So I went with blinking an led when the string was found in the data stream. Even at 16Mhz, the absolute smallest simplest loop doesn't catch all the occurrences of the string. ("FA")

setfreq m16
HSERSETUP B9600_16,%110

top:
hserin 0,14,("F")
get 0,b5
if b5=65 then pulsout d.1,5000
endif
goto top
Both SerTxd and PulsOut will cause (internal) hSerial interrupts to be ignored, so you have to avoid them. SerTxd is not a background command, bit-banging its output. Rather than PulsOut, High or Low commands, I'd use the Toggle command: each transition causes the LED's state to change.

16MHz is not particularly fast for a PICAXE. To parse log serial strings incoming at 9600baud, go for the fastest speed possible.

On the other hand, your "Get 0,65" may or may not fetch the character you are expecting because the command is not synchronised to the incoming data; nor is your code above placing data in the scratchpad for later access.
A fun fact I found while working on this: The ptr for the scratchpad goes all the way to 1023.
P.S. The data stream is blocks of data with short pauses between blocks.
Referring to ptr and the scratchpad indicates that you are using a X2 part but you don't say which one.

I would use background serial data reception exclusively. I have successfully used it to receive and decode GPS data at 9600baud.
 

neiltechspec

Senior Member
I have successfully received 9600 baud string using 16Mhz clock & serin command on M2 Picaxe's on numerous occasions.
One being a GPS based Dallas Clock setter & Time / Date display.
Another being a Solar Inverter Data display using RS485, serout to trigger the Inverter data trans & serin to capture the data.

Neil.
 

AllyCat

Senior Member
Hi,
Your thoughts?
You appear to be using a 28 or 40X2 which I've never used (or needed to). You should very probably be using Background Receive, but may still need a 20X2 or external resonator to get up to a 32 or 64 MHz clock. Even then, you must avoid SERTXD, SEROUT and SERIN which are all bit-banged communications and thus disable internal interrupts. It would also be wise to code the "marker" PULSOUT as HIGH pin : PAUSE 4 : LOW pin , which is interruptable at all levels. You could also use HSEROUT, but maybe only for individual characters.

Personally, I've managed to receive fully concatonated serial bytes at 9600 baud (i.e. 1.04 ms/character) with an M2 and 16 MHz clock (32 MHz is also available), using the HSERIN hardware. But the M2s do have several "bugs" which need workarounds, as discussed in this thread (and its links). My approach employed an interrupt routine to transfer the HSERIN bytes to a software/RAM circular buffer (up to 100 bytes in an 08M2, 500 bytes in most other M2s). It only returned to the main program when the HSERIN pin became inactive, but even so, the main program can use only a "selected" subset of instructions. Unfortunately these are not formally documented, probably because "not all PICaxes are created equal", and is moving beyond the "intended" application of PICaxe Basic (and perhaps most interpreted languages in general).

Cheers, Alan.
 
Last edited:

bigg_al

New Member
40X2, I am relying on the CPU to parse the incoming data for the "F". Once that is received then the next 14 characters go in the scratchpad at 0.
I guess it isn't a true independent UART even in "background" mode. I already tried receiving various byte counts in background mode and then using a for/next loop to parse. It still misses characters whether I wait for 20 bytes or 300 bytes.

I was looking at PIC Basic and the commands look just like Picaxe basic. Are they the same or does Pic Basic turn the code into machine code verses Picaxe basic being interpreted?
 

AllyCat

Senior Member
Hi,

I've never used background receive (which is part of the PICaxe interpreter), but I wouldn't expect to be able to (reliably) mix the two modes at the same time. AFAIK the PIC hardware UART has only a two-byte buffer, which is organised as a FIFO, so each received character may be read only once (unless the buffer is "empty").

I've not used PIC Basic, but would expect it to be compiled to machine code or assembler. However, PICaxe basic is not only interpreted buy tokenised down to a bit level, with even constants tokenised to save space when only 256 bytes were available for program storage (and to protect the IP of the interpreter code).

Cheers, Alan.
 

inglewoodpete

Senior Member
40X2, I am relying on the CPU to parse the incoming data for the "F". Once that is received then the next 14 characters go in the scratchpad at 0.
I guess it isn't a true independent UART even in "background" mode. I already tried receiving various byte counts in background mode and then using a for/next loop to parse. It still misses characters whether I wait for 20 bytes or 300 bytes.

I was looking at PIC Basic and the commands look just like Picaxe basic. Are they the same or does Pic Basic turn the code into machine code verses Picaxe basic being interpreted?
No, that is not possible unless you change modes mid stream, which will almost certainly cause character(s) to be dropped. Incoming data will not be placed in the scratchpad unless you set that mode - in which case you will not be able to effectively use the hSerIn command.

The following two pieces of code are taken directly from one of my (reliably working!) projects which uses a 28X2. Identical code will work in any X2 chip, although 20X2's scratchpad is smaller. Of course, the code is for a different purpose: extracting the time from GPS data packets.

The first block should be run once in your initialisation code.
Rich (BB code):
      'Initialise serial Downlink for GPS comms
      hSerSetup B9600_32, %00001  '9600 baud @ 32MHz, Background, no invertion
      '                   %abcde where, for X2 chips:
      '              Bit e (bit 0): Foregrd/Backgrd mode e=0 foreground; e=1*background
      '              Bit d (bit 1): Transmit mode -      d=0*No invert;  d=1 Invert transmit
      '              Bit c (bit 2): Receive  mode -      c=0*No invert;  c=1 Invert receive
      '              Bit b (bit 3): disable hserout      b=0 enable;     b=1 disable
      '              Bit a (bit 4): disable hserin       a=0 enable;     a=1 disable
      '
      Ptr = 0
      hSerPtr = 0
The second block would be located in your main loop. It watches for differences between the two pointers and processes any data in the scratchpad found between the pointers. Byte variables start with a 'b'; Words with 'w' and Bit variables with 't'
Rich (BB code):
' ***** hReceive: Receive serial data via the background serial port and process
'
' Transfers received data from Scratchpad RAM into an area of main RAM starting at bRecCount
'
' Entry: hSerPtr          Points to next byte BEYOND the last received byte
'        Ptr              Points to next byte of received data IF data has been received
'        bPktLen          = 0
'  Uses: wSearchPtr       Source pointer for scratchpad data
'        wBufferedDataLen Byte count for current GPS data packet
'        wPktDataPtr      Points to Start-of-Data, after the "$GPGGA," header
'  Exit: bPktLen          Number of bytes received
'        Ptr              Points to location of the next byte to be processed
'        
hReceive:Do Until Ptr = hSerPtr
            If @Ptr = "$" Then
               wPktStartPtr = Ptr
               wBufferedDataLen = hSerPtr - Ptr And %1111111111  'Restrict to max value 1023
               If wBufferedDataLen > 13 Then '14 or more chars in buffer
                  GoSub Check_GPS_Header     'Compare header with "$GPGGA,"
                  If tMismatch = False Then  'Have start of a good packet, with Time data
                     wBufferedDataLen = hSerPtr - Ptr And %1111111111  'Restrict to max 1023
                     wPktDataPtr = Ptr       'Save location of packet start "$" pointer
                     If wBufferedDataLen >= 82 Then   'Don't log until entire GPS packet received
                                             'Bit-banged SerTxd interferes with background receive
                        bPktLen = 6          'Length of "$GPGGA,"
                        GoSub hRecCheckSum   'Confirm packet validity
                        If tGoodPacket = True Then
                           If tNoGPSDataYet = True Then
                              tNoGPSDataYet = False
                              Low oLED       'Turn off LED after first valid GPS pkt received
                              SerTxd("   Checksum Rec'd=", #bRecdCSum, ", Calc'd=", #bCalcCSum)
                              SerTxd(" First valid pkt.", CR, LF)
                           EndIf
                           Ptr = wPktDataPtr 'Restore pointer to start of packet's data
                           GoSub hReadGPSData'Receive and synchonise to GPS time
                        Else
                           SerTxd("   Checksum Rec'd=", #bRecdCSum, ", Calc'd=", #bCalcCSum)
                           SerTxd(" **Bad pkt**", CR, LF)
                        EndIf
                     Else                    'Less than required data buffered
                        Ptr = wPktStartPtr   'Reset Ptr to start of packet
                     EndIf 'wBufferedDataLen >= 82
                     Exit                    'Exit Do loop after (good or bad) full packet received
                  EndIf 'tMismatch = False
               EndIf 'wBufferedDataLen > 13
            EndIf '@Ptr = "$" Then
            Inc Ptr                          'Continue search for Start-of-packet marker ($)
         Loop
         Return
 

oracacle

Senior Member
The other thing that you are forgetting, is the difference in the way each works. I suspect that PIC basic is compiled to "raw" PIC instructions. PICAXE on the other hand uses a token based interpreter which in some cases can cause some unexpected behaviour when directly compared to other systems.
The up side is it makes it very easy to get started and get a successful output for the more basic project that students would be creating in the learning environment - this what PICAXE is designed for, and it does it extremely well. That being said, and as others will tell you, PICAXE also does also do well in more complex projects providing that you can work around the quirks of the system.
 

Flenser

Senior Member
bigg_al,

As inglewoodpete mentioned in post #7 there are two modes for using the hardware serial.

This is from the manual section for HSERSETUP:
Code:
Hardware serial input can be configured in two ways:
1) via hserin command only (mode bit0 = 0)
2) automatic in the background (mode bit0 = 1) (not M2 parts)
In this code from your post #1 you configure the hardware serial for HSERIN only so background receive will not work in this program:
Code:
setfreq m16
HSERSETUP B9600_16,%110        ; <-- this configures the hardware setup for HSERIN only

top:
hserin 0,14,("F")              ; <-- so this cmd works as expected
get 0,b5                       ; <-- no background receive is done in this mode so nothing is ever written to the scratchpad at location 0 for this GET
if b5=65 then pulsout d.1,5000
endif
goto top
 
Top