Shop OBEX P1 Docs P2 Docs Learn Events
S2 Radio-controlled navigation — Parallax Forums

S2 Radio-controlled navigation

Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
edited 2014-02-01 08:38 in Robotics
I don't know why no one has thought of this before, it's so obvious. Maybe they have, and I missed it. My apologies if so. Anyway, it's drop-dead easy to add an RC receiver to an S2 and control it with a transmitter. I added a cheapo ($25 for the full set: transmitter and receiver) 2.4 GHz HobbyKing radio to my S2, hidden inside. It connects to the hacker port via two channels -- one for throttle and one for steering -- which also powers the receiver. Here's a photo of the installation:

attachment.php?attachmentid=104558&d=1382757169

I adhered the receiver in place with double-stick foam tape. Connections to the hacker port were made with servo extension cables. Here's the code I used to control the S2 with the RC transmistter:
CON

  _clkmode      = xtal1 + pll16x
  _xinfreq      = 5_000_000

  STEERING      = 0
  THROTTLE      = 1

  THREV         = 1200
  THOFF         = 1500
  THFWD         = 1800

  STLFT         = 1200
  STCTR         = 1500
  STRGT         = 1800
  
OBJ

  pst   : "Parallax Serial Terminal"
  s2    : "S2"

PUB  start | lftrgt, fwdrev

  pst.start(9600)
  s2.start
  s2.start_motors
  repeat
    lftrgt := ((pulse_in(STEERING) #> STLFT <# STRGT) - STCTR) * 256 / constant(STRGT - STLFT)
    lftrgt &= ||lftrgt > 20
    fwdrev := ((pulse_in(THROTTLE) #> THREV <# THFWD) - THOFF) * 256 / constant(THFWD - THREV)
    fwdrev &= ||fwdrev > 20
    s2.move_now(fwdrev - lftrgt, fwdrev + lftrgt, 0, (||fwdrev #> ||lftrgt >> 1) >> 3, 1)     

PUB pulse_in(pin) | t0, t1

  waitpne(1 << pin, 1 << pin, 0)
  waitpeq(1 << pin, 1 << pin, 0)
  t0 := cnt
  waitpne(1 << pin, 1 << pin, 0)
  t1 := cnt
  return (t1 - t0) / (clkfreq / 1_000_000) 

A full archive is attached.

Of course, you can add more channels if you like. The hacker port will support six total. A simple circuit that ORs all the channels together could conceivably multiplex all channels into one input. I checked my HobbyKing receiver, and there's just enough of a gap between pulses that a PASM program could demultiplex the channels again.

-Phil

Comments

  • bee_manbee_man Posts: 109
    edited 2013-10-26 07:02
    I like to use this OBEX http://obex.parallax.com/object/492. It lets you over ride the robots roaming with your radio control signals.
  • ratronicratronic Posts: 1,451
    edited 2013-10-26 13:03
    Great idea Phil! I'm installing an extra receiver I had for my radio in my S2 now.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-10-26 19:08
    This program works better. It waits for a change in wheel velocities before calling move_now again, thus eliminating extraneous ramping and the resulting intermittent hesitations:
    CON
    
      _clkmode      = xtal1 + pll16x
      _xinfreq      = 5_000_000
    
      STEERING      = 0
      THROTTLE      = 1
    
      THREV         = 1200
      THOFF         = 1500
      THFWD         = 1800
    
      STLFT         = 1200
      STCTR         = 1500
      STRGT         = 1800
      
    OBJ
    
      s2    : "S2"
    
    PUB  start | lftrgt, fwdrev, plftrgt, pfwdrev
    
      s2.start
      s2.start_motors
      repeat
        lftrgt := ((pulse_in(STEERING) #> STLFT <# STRGT) - STCTR) * 256 / constant(STRGT - STLFT)
        lftrgt &= ||lftrgt > 20
        fwdrev := ((pulse_in(THROTTLE) #> THREV <# THFWD) - THOFF) * 256 / constant(THFWD - THREV)
        fwdrev &= ||fwdrev > 20
        if (lftrgt <> plftrgt or fwdrev <> pfwdrev)
          s2.move_now(fwdrev - lftrgt, fwdrev + lftrgt, 0, (||fwdrev #> ||lftrgt >> 1) >> 3, 1)
          plftrgt := lftrgt
          pfwdrev := fwdrev
          
    PUB pulse_in(pin) | t0, t1
    
      waitpne(1 << pin, 1 << pin, 0)
      waitpeq(1 << pin, 1 << pin, 0)
      t0 := cnt
      waitpne(1 << pin, 1 << pin, 0)
      t1 := cnt
      return (t1 - t0) / (clkfreq / 1_000_000)  
    

    -Phil
  • WBA ConsultingWBA Consulting Posts: 2,933
    edited 2013-10-26 20:12
    Very nice Phil!
    Funny, I am working on a few mods for my daughters S2 and was thinking about adding RC control. I hadn't bothered looking on the forums because I figured there would be several threads on it, so I was actually shocked when I read your post about it being the first.
    I am hoping to be able to post the mods I am creating soon as I can't find any evidence of anyone doing what I am doing.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-10-26 20:18
    Andrew,

    Thanks. I'm not sure mine is the first, though; and it would be strange if it were, since it's so obvious. It's just that I don't remember seeing any others.

    -Phil
  • W9GFOW9GFO Posts: 4,010
    edited 2013-10-26 20:32
  • WBA ConsultingWBA Consulting Posts: 2,933
    edited 2013-10-26 20:57
    I remember that, but forgot about the xbee. I should know since it has one of my PowerTwigs in it!
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-10-26 21:49
    I do remember the internal XBee -- very nicely executed! I did an external version awhile back, too:

    I think XBees are great for data, but they're a bit overkill for remote control apps, given the much cheaper prices of available 2.4 GHz RC setups. At one point, I was considering an external S2 plug-in board for RC receivers. But sticking the thing inside is much tidier and obviates the need for a separate PCB to interface to the S2's RS232 port. The only downside is that, without some OR gating, you need one pin for each RC channel.

    -Phil
  • WBA ConsultingWBA Consulting Posts: 2,933
    edited 2013-10-26 23:07
    Phil, That is a very nice module for the S2. Hope that it is still progressing forward. Just like many posts on that thread, I had not seen that before at all. I wonder if that has something to do with not being able to search on the forums directly for 2 character searches, like "S2". In the past 2 months, I have come to really like the S2 as a robotic platform and think that it is actually a good candidate for the younger crowd (like my daughter that is 7). I would like to see some more effort put into S2 curriculum with and without the hacker port and even with C.
  • W9GFOW9GFO Posts: 4,010
    edited 2013-10-27 02:19
    I wonder if that has something to do with not being able to search on the forums directly for 2 character searches, like "S2".

    The search linked to in my sig will allow even one character search terms.
  • Bill HenningBill Henning Posts: 6,445
    edited 2013-10-28 15:21
    Very Cool Phil!

    Now I'll have to order an RC transmitter/receiver set and try it.
  • ercoerco Posts: 20,255
    edited 2013-10-28 20:24
    Both beautiful and worthy remote executions, Rich and PhiPi!

    Rich, great videos on your Youtube channel. Love your Falcon hand glider. LONG ago, I bought a used Eipperformance Rogallo from Kitty Hawk Kites in Nag's Head NC with my paper route money. Best $140 I ever spent! I never went as high as you, maximum a hundred feet or so with that lame 4:1 glide ratio...!
  • ratronicratronic Posts: 1,451
    edited 2014-01-23 18:29
    Phil this program runs completely smooth as it ignores everything except the joystick. I am thinking of using the encoders for some kind of display from the LED's as it is being driven around.

    I Tweaked Kye's pwm2_hbdengine to use with the S2 motor setup and modified your pulse_in routine to return 0 instead of 1500 when the aile/elev stick is centered. The pwm motor driver takes input from -400 to 400 for full reverse to full forward.
    Con                                    'S2 RC receive/operate
                                                                 
      _CLKMODE = XTAL1 + PLL16X                                  
      _XINFREQ = 5_000_000                                       
                                                                 
    Var                                                          
                                                                 
    Obj                                                          
                                                                 
      pwm : "s2motor_driver"                                     
                                                                 
    Pub Main | aile, elev, left, right                           
                                                                 
      pwm.start(4_000)         'start S2 motor driver @ 4000 hert
                                                                 
      repeat                                                     
        aile := pulse_in(0)                                      
        elev := pulse_in(1)                                      
        left := elev - aile                                      
        right := elev + aile                                     
                                                                 
        pwm.leftrightduty(left, right)                           
                                                                 
    PUB pulse_in(pin) | t0, t1                                   
                                                                 
      waitpne(1 << pin, 1 << pin, 0)                             
      waitpeq(1 << pin, 1 << pin, 0)                             
      t0 := cnt                                                  
      waitpne(1 << pin, 1 << pin, 0)                             
      t1 := cnt                                                  
      return (t1 - t0) / (clkfreq / 1_000_000) - 1500
    
  • ratronicratronic Posts: 1,451
    edited 2014-01-25 12:21
    I shouldn't have added the lights I can't get my S2 back from the grandkids! Since I am doing the driving I made up a pasm routine to monitor the encoders and update the LED's on the left/right sides to the state of each encoder with red or green.

    Even if you do not have a rf receiver installed you can use this program to show the encoders output on the LED's by directly turning the wheels.
    Con                                    'S2 RC receive/operate  w/encoders triggering leds
    
      _CLKMODE = XTAL1 + PLL16X
      _XINFREQ = 5_000_000
    
    Var
      
    Obj
        
      pwm : "s2motor_driver"
      
    Pub Main | aile, elev, left, right
      
      pwm.start(4_000)         'start S2 motor driver @ 4000 hertz
      cognew(@entry, 0)        'encoders/leds cog
        
      repeat
        aile := pulse_in(0)
        elev := pulse_in(1)
        left := elev - aile
        right := elev + aile
    
        pwm.leftrightduty (left, right)
            
    Pub pulse_in(pin) | t0, t1                      
                                                
      waitpne(1 << pin, 1 << pin, 0)            
      waitpeq(1 << pin, 1 << pin, 0)            
      t0 := cnt                                 
      waitpne(1 << pin, 1 << pin, 0)            
      t1 := cnt                                 
      return (t1 - t0) / (clkfreq / 1_000_000) - 1500
    
    Dat
                            org 0
    entry                   
                            andn outa, dirmask             
                            mov dira, dirmask
                            mov time, cnt
                            add time, period
    :loop
                            test lftenc, ina        wc
                  if_c      mov lights, #%1001_0000                        
                  if_nc     mov lights, #%1010_0000
                            call #leds
                                      
                            waitcnt time, period
                                                                           
                            test rgtenc, ina        wc
                  if_c      mov lights, #%1000_0100
                  if_nc     mov lights, #%1000_1000
                            call #leds
                            
                            waitcnt time, period
                                    
                            jmp #:loop    
    leds                         
                            mov cntr, #8
    :loop                   shr lights, #1          wc
                            muxc outa, data
                            or outa, clk
                            andn outa, clk
                            djnz cntr, #:loop
    leds_ret                ret                        
                                          
    lftenc        long      1 << 13
    rgtenc        long      1 << 14
    period        long      8_000                        
    data          long      1 << 7
    clk           long      1 << 8
    dirmask       long      $180
    cntr          res       1
    lights        res       1
    time          res       1
    
  • ratronicratronic Posts: 1,451
    edited 2014-02-01 08:38
    Ok to round out the grandkids experience with the radio controlled S2 I added audio record/playback when it is stopped. I swear they have more fun with it than I do.
Sign In or Register to comment.