Shop OBEX P1 Docs P2 Docs Learn Events
BS2E to Propeller Backpack Half Duplex I/O Example (was weirdness) — Parallax Forums

BS2E to Propeller Backpack Half Duplex I/O Example (was weirdness)

Martin_HMartin_H Posts: 4,051
edited 2011-08-09 19:08 in Propeller 1
I have a project where I need to use the propeller backpack's bottom three pin header for half duplex bi-directional communication with a BS2E. So I figured I would write a simple app that sent a string between the microcontrollers to learn how to do it.

So I send a string from the BS2E to the propeller backpack and the prop sends the string to the serial terminal. It mostly works except the first 2 or 3 bytes sent are garbled on the Parallax Serial Terminal.

Here's the Spin code prop backpack side:
CON

  _clkmode      = xtal1 + pll8x
  _xinfreq      = 10_000_000


OBJ
  pst     : "Parallax Serial Terminal" 
  io      : "basic_sio"

PUB start | i

  dira[16..17]~~
  pst.Start(115200)    
  pst.str(STRING("I/O TestStart", 13)) 
  io.start
  repeat
    pst.Char(io.in)

Here's the PBasic code Stamp side:
io     PIN 6           ' Serial I/O pin for Propeller Backpack. 

#SELECT $STAMP
  #CASE BS2, BS2E, BS2PE
    baud    CON  84 + 32768
  #CASE BS2SX, BS2P
    baud    CON  240 + 32768
  #CASE BS2PX
    baud    CON  396 + 32768
#ENDSELECT

DEBUG "Program starts here", CR

LOW io            'Reset the Propeller Backpack
PAUSE 500
INPUT io

PAUSE 2000        'Wait for it to come out of reset.

DEBUG "Propeller out of reset", CR

'Start sending data for the demo.
SEROUT io, baud, ["This is a demo of the Propeller Backpack"]
DEBUG "Data sent", CR

Anyone see any gotchas with what I'm doing?

As an FYI, the propeller backpack is one slick piece of engineering.

Comments

  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2011-08-01 19:37
    Two things I thought of:
    1) Stamp's aren't real good for high baud rates, try a more sedate 19,200
    2) Is there a pull-up resistor on the transmit line from the Stamp? Otherwise it will float and generate garbage on the Prop's side
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-08-01 19:43
    Martin,

    Put your io.start ahead of everything else. You want it ready to receive characters right away.

    (And thanks for the "slick" comment! :) )

    -Phil
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-08-01 19:44
    Peter,

    1. He's using 9600 baud from the Stamp.

    2. The Backpack provides the pull-up.

    -Phil
  • Martin_HMartin_H Posts: 4,051
    edited 2011-08-01 19:55
    Thanks Phil, I'll try that tomorrow as it is getting late here. That makes total sense as dropping the first few characters does sound like a race condition with the basic_sio startup, the stamp send, and the first read.
  • Martin_HMartin_H Posts: 4,051
    edited 2011-08-02 20:21
    Moving the io.start worked like a champ. I was able to serout the string and print it on the propeller side. I then tweaked the pbasic program to serout the string a single byte at a time, and that worked fine.

    For the final step I modified the Spin code to echo the character back (using io.out(theChar)), and added a serin after the serout in the pbasic code. That didn't work and it looked like the Basic stamp is hanging on the serin. I'm guessing that by the time the Basic Stamp was ready, the Prop already sent the character. So I added a waitcnt in the Spin code, but to no avail.

    Current Spin:
    CON
    
      _clkmode      = xtal1 + pll8x
      _xinfreq      = 10_000_000
    
    
    OBJ
      pst     : "Parallax Serial Terminal" 
      io      : "basic_sio"
    
    PUB start | i, val
    
      dira[16..17]~~
      io.start 
      pst.Start(115200)    
      pst.str(STRING("I/O TestStart", 13)) 
      repeat
        val := io.in
        pst.Char(val)
        ' Wait 100 ms to give the BS a chance to do a serin.
        waitcnt(clkfreq / 10 + cnt)
        io.out(val)
    

    Current PBasic:
    io     PIN 6           ' Serial I/O pin for Propeller Backpack.
    
    #SELECT $STAMP
      #CASE BS2, BS2E, BS2PE
        baud    CON  84 + 32768
      #CASE BS2SX, BS2P
        baud    CON  240 + 32768
      #CASE BS2PX
        baud    CON  396 + 32768
    #ENDSELECT
    
    message  DATA 39, "This is a demo of the Propeller Backpack"
    
    strCnt  VAR Word ' Counter for stringOut.
    char    VAR Byte ' Character (byte) to send via Serout.
    char2   VAR Byte ' Character (byte) recieved via Serin.
    strAddr VAR Word ' Base address of the string.
    
    '-------[ Program starts here. ]-----------------------------------------------
    DEBUG "Program starts here", CR
    
    LOW io            'Reset the Propeller Backpack
    PAUSE 500
    INPUT io
    
    PAUSE 2000        'Wait for it to come out of reset.
    
    DEBUG "Propeller out of reset", CR
    
    'Start sending data for the demo.
    strAddr = message
    GOSUB StringOut
    DEBUG "Data sent", CR
    
    StringOut:
      READ strAddr, strCnt       ' Get the number of bytes in the string.
      strAddr = strAddr + 1
      strCnt = strCnt + strAddr  ' Set the endpoint of the string.
      FOR strAddr = strAddr TO strCnt ' For each byte of the string:
        READ strAddr, char            ' put the byte into char
        SEROUT io, baud, [char]       ' and send it out the port.
    
        ' Now catch the echo from the backpack and debug out.
        SERIN io, baud, [BIN char2]
        DEBUG "char2 = ", DEC char2, CR
      NEXT
    

    Now I've done serout and serin full duplex on separate pins in pbasic, but never half duplex on a single pin. Are there any examples around? I imagine changing the pin from an output to an input and flow control are the challenge here.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-08-02 20:29
    Obviously, the BASIC Stamp, being a single-process controller, can't receive data while it's transmitting. (Even if it could, it wouldn't work over a half-duplex channel anyway.) But please post your latest code, and I'll try to sort it out for you.

    -Phil
  • Martin_HMartin_H Posts: 4,051
    edited 2011-08-03 05:36
    Phil, we had a collision as I was adding the code while you responded. I understand the Basic Stamp's single threaded nature and the limitations of half duplex communication. What I want to do is have the Basic Stamp send a command byte to the propeller backpack, the propeller processes the command, and then responds with the results.

    I could use the propeller backpack's tx and rx lines for full duplex communication with the Basic Stamp, but I'd like to be able to keep the line scan camera updating the PC based line scan camera monitor program. Plus the propeller backpack's manual mentioned the use of half duplex communication on the single pin and I've never seen it done.

    Thanks for the help as this is new territory to me.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-08-03 11:44
    Martin,

    In your BS2 program you have the following line:
    SERIN io, baud, [BIN char2]

    This waits for a string of ones and zeroes, which is not what the Backpack is sending. Eliminate the "BIN", and the program will work as expected.

    -Phil
  • Martin_HMartin_H Posts: 4,051
    edited 2011-08-03 19:08
    Phil, absolutely fantastic, it worked like a champ! Thank you so much for your help as the inter-microcontroller communication is the thorniest part of my project. I can extend this into what I need.

    Serin is a really powerful command, and I am at survival mode with it. So I generally look for cut and paste reuse with it. Is there some trick to debugging it or is it school of hard knocks to know what to look for?

    For anyone else following this thread who wants to do half duplex single pin communication. Here's the updated code:

    Final Spin:
    CON
      _clkmode      = xtal1 + pll8x
      _xinfreq      = 10_000_000
    
    OBJ
      pst     : "Parallax Serial Terminal" 
      io      : "basic_sio"
    
    PUB start | i, val
      dira[16..17]~~
      io.start 
      pst.Start(115200)    
      pst.str(STRING("I/O TestStart", 13)) 
      repeat
        val := io.in
        pst.Char(val)
        ' Wait 1/10 ms to give the BS a chance to get ready for a serin.
        waitcnt(clkfreq/10000 + cnt)
        io.out(val)  
    

    Final PBasic:
    io     PIN 6           ' Serial I/O pin for Propeller Backpack.
    
    #SELECT $STAMP
      #CASE BS2, BS2E, BS2PE
        baud    CON  84 + 32768
      #CASE BS2SX, BS2P
        baud    CON  240 + 32768
      #CASE BS2PX
        baud    CON  396 + 32768
    #ENDSELECT
    
    message  DATA 39, "This is a demo of the Propeller Backpack"
    
    strCnt  VAR Word ' Counter for stringOut.
    char    VAR Byte ' Character (byte) to send via Serout.
    char2   VAR Byte ' Character (byte) recieved via Serin.
    strAddr VAR Word ' Base address of the string.
    
    '-------[ Program starts here. ]-----------------------------------------------
    DEBUG "Program starts here", CR
    
    LOW io            'Reset the Propeller Backpack
    PAUSE 500
    INPUT io
    
    PAUSE 2000        'Wait for it to come out of reset.
    
    DEBUG "Propeller out of reset", CR
    
    ' Start sending data for the demo.
    strAddr = message
    GOSUB StringOut
    DEBUG CR, "Data sent", CR
    END
    
    StringOut:
      READ strAddr, strCnt       ' Get the number of bytes in the string.
      strAddr = strAddr + 1
      strCnt = strCnt + strAddr  ' Set the endpoint of the string.
      FOR strAddr = strAddr TO strCnt ' For each byte of the string:
        READ strAddr, char            ' put the byte into char
        SEROUT io, baud, [char]       ' and send it out the port.
    
        ' Now catch the echo from the backpack and debug out.
        SERIN io, baud, [char2]
        DEBUG char2
      NEXT
      RETURN
    

    You'll note in the Spin code a small waitcnt is required. I removed that line and the message was garbled, so I kept reducing the waitcnt until it was small enough that I lost interest in optimizing it further. In the real app it will likely be unneeded because processing the command will take the required time.
  • Martin_HMartin_H Posts: 4,051
    edited 2011-08-09 19:08
    I had a big success with this tonight. I merged this code with Phil's TSL1401 line scan camera monitor for the propeller backpack. I have the half duplex code running is a separate cog so the Basic Stamp can send commands to get information about the image. I can also monitor the image on the PC with the simple image monitor, so I can see what the line scan camera is seeing. The Basic Stamp DEBUG's the data it gets from the Propeller, so I can also see what it is getting from the propeller. Now I need to refine my image processing code as it seems to have a few bugs. I can then write BPasic code to act on it.

    I'm fairly sure I would find this sort of thing would be impossible to do on another Microcontroller.
Sign In or Register to comment.