Shop OBEX P1 Docs P2 Docs Learn Events
XBee Remote Controller for S2 Robot — Parallax Forums

XBee Remote Controller for S2 Robot

Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
edited 2012-05-13 19:27 in Robotics
I wanted to test my S2 XBee adapter in a "practical" application, so I cobbled together a remote control for it, using a MoBoStamp-pe, a Parallax 2-Axis Joystick mounted to a Proto-DB, and an XBee-DB (as yet unreleased). All of this is mounted to a RadioShack 4 x AAA Battery Holder, which is wired to the MoBo via a MoBo power cable. I really love the little RadioShack battery-holder boxes. They're dirt cheap and even include an on/off switch. Here's a photo of the remote:

attachment.php?attachmentid=92359&d=1336594033

I installed an S2 Marauder rubber band gun on the S2 and added a push button switch to the remote (visible in the above photo) to control it. Here's a photo of the whole setup:

attachment.php?attachmentid=92360&d=1336594034

The BASIC Stamp 2pe program on the MoBo reads the two joystick axes by means of the AVR coprocessor's ADC, along with the switch on/off state and continuously sends the raw data to the S2 via the XBee module. Here's the program:
' {$STAMP BS2pe}
' {$PBASIC 2.5}

Owio    PIN 10
Switch  PIN 9
XbOut   PIN 5

LftRgt  VAR Byte
FwdRev  VAR Byte
Busy    VAR Bit

DO
 OWOUT Owio, 0, [%00011010]
 DO : OWIN Owio, 4, [Busy] : LOOP WHILE Busy
 OWIN Owio, 0, [FwdRev]
 OWOUT Owio, 0, [%00001010]
 DO : OWIN Owio, 4, [Busy] : LOOP WHILE Busy
 OWIN Owio, 0, [LftRgt]
 SEROUT XbOut, 84, [0, LftRgt MIN 1, FwdRev MIN 1, Switch + "0"]
 DEBUG 1, DEC3 LftRgt, " ", DEC3 FwdRev, " ", DEC Switch
LOOP

The program running in the S2 receives the raw data from the XBee object and converts it into motion commands for the S2 object and fire commands for the rubber band gun. Here's the code:
CON

  _clkmode      = xtal1 + pll16x
  _xinfreq      = 5_000_000

  FIRE_PIN      = 0

OBJ

  xb    : "xbee"
  s2    : "s2"

VAR

  long  time
  byte LftRgt, FwdRev, Switch, pSwitch, index

PUB start | ch

  xb.start(31, 30, 9600)
  s2.start
  s2.start_motors
  stop
  dira[FIRE_PIN]~~
  case s2.reset_button_count
  
    0:                                                  'Starts here on power-up.
      s2.button_mode(false, true)                       'Allow button to reset S2.
      repeat
        if (cnt - time) > clkfreq                       'Stop if haven't received data for one second.
          stop
        if (xb.rxbytes)
          ifnot (ch := xb.rx)                           'Synchronize to zero byte that precedes each message.
            index~
          else
            LftRgt[index++] := ch                       'Fill three-byte buffer with data.
            if (index == 3)
              move                                      'Perform motion when entire message has been received.
        
    1:                                                  'Starts here on one button press.
      repeat
        if s2.button_press                              'For each button press, cycle the escpament once.
          fire                                          'Can be used to test fire or reload.
          repeat while s2.button_press

PUB stop

  index~
  s2.stop_now
  pSwitch := "1"
  time := cnt

PUB move | lr, fr

  {{ Fire a rubber band if the button has just been pushed.
     Move proportionally to the FwdRev and LftRgt joystick values.
  }}

  index~
  if (Switch == "0" and pSwitch == "1")
    fire
  pSwitch := Switch
  LftRgt &= LftRgt <> 255       'Joystick has an endpoint glitch.
  lr := LftRgt - 128
  lr &= ||lr > 20               'Accommodate a center dead zone.
  fr := FwdRev - 128
  fr &= ||fr > 20               'Accommodate a center dead zone.
  s2.move_now(fr - lr, fr + lr, 0, (||fr #> ||lr >> 1) >> 3, 1)
  time := cnt

PUB fire

{{ This method causes the escapement mechanism to cyle once.
   It can be used for firing or loading s single rubber band.
}}

  repeat 10
    pulsout(FIRE_PIN, 1100)
    waitms(20)
  repeat 10
    pulsout(FIRE_PIN, 1900)
    waitms(20)

PRI pulsout(pin, us)

{{ Pulse pin high for us microseconds.
}}

  outa[pin]~~
  waitus(us)
  outa[pin]~

PRI waitms(ms)

{{ Pause for ms milliseconds.
}}

  waitcnt(ms * 80_000 + cnt)

PRI waitus(us)

{{ Pause for us microseconds.
}}

  waitcnt(us * 80 + cnt)

Here's a little demo video I made that ties everything together:

[video=vimeo;41867887]

-Phil
523 x 379 - 58K
648 x 486 - 77K

Comments

  • W9GFOW9GFO Posts: 4,010
    edited 2012-05-09 15:20
    Is that a raccoon rug?
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-05-09 15:54
    Yes, it's a raccoon rug, received as a gift. Browser loves it!

    attachment.php?attachmentid=92366&d=1336604042

    He's not nearly as fond of the live ones, though!

    -Phil
    903 x 526 - 143K
  • ZootZoot Posts: 2,227
    edited 2012-05-09 16:09
    Great project; elegant in its simplicity. I want to see you shooting rubberbands into the raccoon mouth.
  • TtailspinTtailspin Posts: 1,326
    edited 2012-05-13 19:27
    +1 for shooting rubberbands at the raccoon, (+10 for shooting rubberbands at the Cat..)

    Thats the coolest homebuilt Joystick ever. :thumb:
    Will you be making the XBee-DP adaptor available to the general public?

    -Tommy

Sign In or Register to comment.