Use serin as on a Basic Stamp

tcpip

New Member
I use to program Basic Stamp's but want to switch to Picaxe.
Now I want to use this Basic Stamp program on a Picaxe (20x2) but I don't know how?

serStr VAR Byte(10) ' make 10-byte array
serStr(9) = 0 ' put 0 in last byte of array
SERIN 1, 16468, [STR serStr\9\"*"] ' stop at "*" or nine bytes
DEBUG STR serStr ' display

Any help would be welcome..
 

nick12ab

Senior Member
So this code receives up to nine bytes (aborted by "*") and sticks it into an array. Unfortunately, the PICAXE doesn't have arrays. However, alternatives are to use the 127-byte scratchpad or just use some normal variables (b0, b1, b2, ... b55). The scratchpad is more suitable for large numbers of variables (i.e. if you want to expand your code for more variables) and the individual variable approach is more suitable for small numbers of bytes to be received.

Variable method example code
Code:
#picaxe 20x2
symbol baud = N2400        'Change appropriately
symbol pin = C.1            'Change appropriately
main:
    serin pin,baud,b0
    if b0 = "*" then skip
    serin pin,baud,b1
    if b1 = "*" then skip
    serin pin,baud,b2
    if b2 = "*" then skip
    serin pin,baud,b3
    if b3 = "*" then skip
    serin pin,baud,b4
    if b4 = "*" then skip
    serin pin,baud,b5
    if b5 = "*" then skip
    serin pin,baud,b6
    if b6 = "*" then skip
    serin pin,baud,b7
    if b7 = "*" then skip
    serin pin,baud,b8
skip:
    debug
    goto main
The scratchpad uses a pointer for access. Let's call the associated variables the ptr family of variables.

Variable nameDescription
ptrSets or gets pointer value
@ptrSets or gets byte stored at pointer value
@ptrincSets or gets byte stored at pointer value then increments ptr by 1
@ptrdecSets or gets byte stored at pointer value then decrements ptr by 1

This is a code example which should do what you want it to do.
Code:
#picaxe 20x2
symbol baud = N2400        'Change appropriately
symbol pin = C.1            'Change appropriately
symbol anotherpin = A.0        'Change appropriately
main:
    ptr = 0
    for b4 = 0 to 8
        serin pin,baud,@ptr
        if @ptr = "*" then : exit : endif
        inc ptr
    next b4
    ptr = 0
    for b4 = 0 to 8
        serout anotherpin,baud,(@ptrinc)
    next b4
    goto main
Note that for the serin part, I don't use @ptrinc because I don't want to increment ptr until I have checked whether @ptr = "*" or not.
 

womai

Senior Member
The first example likely won't work if the bytes come in back-to-back - in that case the if's will take more time to process than the stop bit takes. Instead I would suggest using background serial receive (available on the X1 and X2 parts, e.g. 28X2) and checking the scratchpad byte at the hserptr location. That way the serial receive is done "automagically" in the background and you program simply checks for the end character (*) and then transmits the data - this would then be VERY similar to what the Stamp is doing (and be MUCH cheaper than the latter!). Look up hsersetup, hserin, hserptr in the Picaxe Basic manual.

Wolfgang
 

tcpip

New Member
Thanks, nick12ab for your message. Wolfgang is right, I've tested it. The bytes come in back-to-back and it's not working, only if I send the bytes seperately it works.

Wolfgang, I've had a look in the Picaxe manual but it's not becoming clear to me and an example program is missing. Do you have a example?
 

womai

Senior Member
Here's the important part of the manual (from the hserin command description): Hardware serial input can be configured in two ways: (use hsersetup command for that): 1) ... 2) automatic in the background (mode bit0 = 1) (not M2 parts) --> this is want you need to use In automatic background mode the hardware serial input is fully automated. Serial data received by the hardware pin is saved into the scratchpad memory area as soon as it is received. Upon the hsersetup command the serial pointer (hserptr) is reset to 0. When a byte is received it is saved to this scratchpad address, the hserptr variable is incremented and the hserinflag flag is set (must be cleared by user software). Therefore the value ‘hserptr -1’ indicates the last byte written, and ‘hserinflag = 1’ indicates a byte has been received (see also the setintflags command).

You could continuously poll the hserinflag, but it would be better to set up an interrupt that reacts to hserinflag (see the setint command). Polling may be easier to start with, though.

So something like this (untested!):

Code:
hsersetup .... // set up background receive  

my_loop:  

    hserinflag = 0 '  nothing received yet 
    hserptr = 0 ' store received data in scratchpad  starting at index 0 
    ptr = 0 ' used to read out scratchpad 
    b0 = ' ' ' dummy, something else than the end marker *
    
    '  wait until a byte has been received 
    do     
        if hserinflag > 0 then '  something has been received         
            b0 = @ptrinc ' read last received  byte         
            hserinflag = 0
        endif 
    while b0  '*' 

    ptr = 0 ' now echo  received data  
    do while b0  '*'     
        hserout ptrinc 
    loop

goto my_loop
The first loop still needs to execute fast enough (faster than the bytes come in, otherwise you miss the hserinflag changing again), but now you've got a full byte (10 bits including start and stop bit) of time instead of just the stop bit. I.e. a factor of 10 easier. A 28X2 running at 16 or 32 MHz should easily be able to handle this at 9600 baud or so.
 

womai

Senior Member
Thinking about it a bit more, a more stable version that would be able to cope with data even when coming in faster than you can process it - so the serial data rate could be as high as you like, as long as you don't receive more data than the scratchpad can hold:

Code:
my_loop:
hserptr = 0 ' store received data in scratchpad starting at index 0
ptr = 0 ' used to read out scratchpad
b0 = ' ' ' dummy, something else than the end marker *

' wait until a byte has been received
do
if ptr < hserptr 0 then ' something has been received (could be more than one byte)
b0 = @ptrinc ' read next received byte not yet processed
endif
while b0 '*' ' until end marker

ptr = 0 ' now echo received data

do while b0 '*'
hserout ptrinc
loop

goto my_loop
[/CODE]
 

hippy

Technical Support
Staff member
Untested but this should work for HSERIN. Similar to nick12ab's second code example in post #2 ...

Code:
#Picaxe 20X2
#Terminal 9600

Do

  hserPtr = 0
  ptr = 0

  HserSetup B2400_8, %000

  Do
    Do : Loop while ptr = hserPtr
    If @ptrInc = "*" Then Exit
  Loop Until ptr > 8

  HserSetup Off

  SerTxd( "Received :" )
  ptr = 0
  Do
    If @ptr = "*" Then Exit
    SerTxd( " ", #@ptrInc )
  Loop Until ptr > 8
  SerTxd( CR, LF )

Loop
 

tcpip

New Member
Womai, I've change the code to get a syntaxcheck but it doesn't work

Code:
#Picaxe 20X2
#Terminal 9600

HserSetup B2400_8, %00


my_loop: 
hserptr = 0 ' store received data in scratchpad starting at index 0 
ptr = 0 ' used to read out scratchpad 
b0 = ""  ' dummy, something else than the end marker * 

' wait until a byte has been received 
do 
if ptr < hserptr  then ' something has been received (could be more than one byte) 
b0 = @ptrinc ' read next received byte not yet processed 
endif 
loop while  b0 = "*" ' until end marker 

ptr = 0 ' now echo received data 

do  
SerTxd (@ptrinc) 
loop while b0 = "*" 

goto my_loop
The same goes for hippy

Code:
#Picaxe 20X2
#Terminal 9600


Do

  hserPtr = 0
  ptr = 0

  HserSetup B2400_8, %00

  Do
    Do : Loop while ptr = hserPtr
    SerTxd( "Ptr", ptr, CR, LF )
    If @ptrInc = "*" Then Exit
  Loop Until ptr > 8

 HserSetup Off

  SerTxd( "Received :" )
  ptr = 0
  Do
    If @ptr = "*" Then Exit
    SerTxd( " ", #@ptrInc )
  Loop Until ptr > 8
  SerTxd( CR, LF )

Loop
 

womai

Senior Member
Well, I did say untested :) I did not try to run it through the compiler, even less ran it, just hacked it up as an example to give you some ideas (easier than trying to explain a few lines of code in a couple pages of verbal description!). Actually I would have been surprised to see it compile or work right away.

One thing I spotted in your code though, it should be

loop while b0 <> "*"

(you currently have b0 = "*") - two occurrences to change.
 

hippy

Technical Support
Staff member
Womai, I've change the code to get a syntaxcheck but it doesn't work ...
The same goes for hippy
Possibly. The added SERTXD may be messing things up but in what way does it not work, how have you got your hardware connected etc ?

Edit : HserSetup B2400_8, %000 should be %001 in my code. Said it was untested, and there may be other bugs :)
 

tcpip

New Member
I found what I did wrong, used hrserSetup mode the wrong way. Now it's working with the code from Hippy. Many thanks
 
Top