ActivityBot -- SIRC control + whiskers

twm47099twm47099 Posts: 538
There are sometimes questions about how to combine different lessons in the C-Learning Tutorials. The program below combines ActivityBot using the Sony IR remote control with Navigating by touch.

The hardware setup is the same as in the 2 tutorials. My wiring using the overlay board is here:
http://forums.parallax.com/discussion/comment/1337873/#Comment_1337873

There are 2 potentially tricky changes.
1. Since there is up to 1 second delay if no remote control button is pushed, and we want the response to hitting an object to be immediate, I run the whisker function in its own cog.

.
2. The SIRC command codes are based on my remote control (Sony RMT-DSLR1). If you are using a different remote, use the program in the SIRC tutorial
http://learn.parallax.com/propeller-c-simple-devices/ir-receiver-and-remote
to determine the codes your remote uses for the keys you want to use for each command. Then change the number in the remote control aliases define statements.

Note: that I've added a new version a few posts down that changes the codes to those used in a standard Sony TV remote.

Here's the code:

/*
SIRC Remote control new a.c  for overlay board

This worked - There is no delay between whisker touching and bot stopping.
Before using separate cog for whiskers, there was a noticible delay, and whisker fully
compressed before bot would stop.
This version stops, backs up, turns 90 deg from obstacle and stops.
Must press remote key to restart motion.  Consider changes to allow continuing motion wo
need to press remote key.

Use multiple cogs - new cog to handle whiskers

Connect 38 kHz IR receiver to Propeller P10
Decodes button presses on Sony-compatible IR remote
Commands Activitybot to move straight, pivot 45 deg, move in a curve,
increase or decrease speed and curve radius, and stop.
Also has whisker code for obstacle avoidance.
This has ramping to speed.  Increment = 4 ticks per 1/50 sec (4/0.020 sec).
To get from 0 to 100 takes 25 increments = 0.5 sec
Future: add code for autonomous movement selectable from remote,

Load EEProm and Run
*/

#include "simpletools.h"                      // Libraries included
#include "sirc.h"
#include "abdrive.h"                          // abdrive library

// ***** Remote control aliases -- uses Sony camera remote RMT-DSLR1 *****

#define fwd 58       //  up arrow  -- forward
#define stp 57       //  center -- stop
#define rvs 59       //  down arrow -- reverse
#define pl 62        //  left arrow -- pivot left
#define pr 63        //  right arrow -- pivot right
#define cvl 56       //  menu -- curve left
#define cvr 61       //  trash can -- curve right
#define ispd 74      //  plus rocker -- increase speed
#define dspd 75      //  minus rocker -- decrease speed

// ***** Pin Defines *****
#define spkrpin 3       // speaker pin for overlay board
#define SIRCpin 10      // SIRC input pin
#define Rwpin 8         // Right whisker pin
#define Lwpin 7         // Left whisker pin

int *cogwhisker;      // pointers to cog IDs

void whisker();       // monitors whiskers, if hit: stops, backs away, turns away, runs in separate cog

volatile int bumpflg;
int Lspd, Rspd = 0;   // Left and Right command wheel speeds

int main()                // **** main function ****
{
int spd = 50;           //  initial speed once fwd command given
int dflg = 0;         // flag: -1=fwd or rev, 0=stopped, 1=curve left, 2=curve right, 3=pivot L or R
drive_speed(0, 0);
sirc_setTimeout(1000);                  // -1 if no remote code in 1 sec
bumpflg = 0;                            // Gives control to remote
cogwhisker = cog_run(whisker, 100);     // start monitoring whiskers
freqout(spkrpin,1000, 3000);            // Speaker tone: 1 s, 3 kHz

while(1)                                // Repeat indefinitely
{

int button = sirc_button(SIRCpin);    //  get code from SIRC remote


switch(button)                        //  decode signal from SIRC and calc drive command
{
case stp :      //  Center button - Q
Lspd = 0;     //  stop
Rspd = 0;
dflg = 0;
break;

case fwd :        //  Top Arrow - M
Lspd = spd;     //  forward
Rspd = spd;
dflg = -1;
break;

case rvs :        //  Down Arrow
Lspd = -spd;    //  reverse
Rspd = -spd;
dflg = -1;
break;

case pr :          //    Right Arrow - N
Lspd = 13;
Rspd = -13;     //  Pivot Right 45 deg & stop
dflg = 3;
break;

case pl :         //  Left Arrow - P
Lspd = -13;
Rspd = 13;      //  Pivot Left 45 deg & stop
dflg = 3;
break;

case cvr :              //  Curve Right - L
if (spd < 25) spd=25;
Lspd = spd;
Rspd = spd-20;
dflg = 2;
break;

case cvl :               //  Curve Left  - K
if (spd < 25) spd=25;
Lspd = spd-20;
Rspd = spd;
dflg = 1;
break;

case ispd :              //  Up-Rocker - H -- Increase speed
if (dflg == 1)          // curving left - increase spd and move in curve at new spd
{
spd=spd+5;
if (spd > 100) spd = 100;
Lspd = spd-20;
Rspd = spd;
}
else if (dflg == 2)     // curving right - increase spd and move in curve at new spd
{
spd=spd+5;
if (spd > 100) spd = 100;
Lspd = spd;
Rspd = spd-20;
}
else if (dflg == -1)      // straight ahead - increase spd and move at new spd
{
spd=spd+5;
if (spd > 100) spd = 100;
Lspd = spd;
Rspd = spd;
}
else
{
spd=spd+5;
if (spd > 100) spd = 100;
}
break;                // Finish Up-Rocker

case dspd :          //  Down-Rocker -- decrease spd
if (dflg == 1)      // curving left - decrease spd and move at new spd
{
spd=spd-5;
if (spd < 25) spd = 25;
Lspd = spd-20;
Rspd = spd;
}
else if (dflg == 2)      // curving right - decrease spd and move at new spd
{
spd=spd-5;
if (spd < 25) spd = 25;
Lspd = spd;
Rspd = spd-20;
}
else if (dflg == -1)      // straight ahead - decrease spd and move at new spd
{
spd=spd-5;
if (spd < 0) spd = 0;
Lspd = spd;
Rspd = spd;
}
else                       //  stopped
{
spd=spd-5;
if (spd < 0) spd = 0;
}
break;                   // Finish Down-Rocker
default :
break;
}       // end switch

if(dflg == 3)           // execute pivot
{
if( ! bumpflg) drive_ramp(0,0);         // stop for pivot, whiskers not controlling movement
if( ! bumpflg)                          // whiskers not controlling movement
{
drive_ramp(Lspd, Rspd);     // now pivot 45 deg
pause(1000);
Lspd = 0;                   // and stop, executed with other drive cmds below
Rspd = 0;
dflg = 0;
}
}
if( ! bumpflg) drive_ramp(Lspd, Rspd);  // execute drive comnd, whiskers not cntrling movement
}     // end while
}       // end main


void whisker()       // If whisker pressed, stop & move away from obstacle:
// 1. disable SIRC control, 2. stop bot, 3. back up, 4. turn away from obstacle,
// 5. stop, 6. restore SIRC control
{
while(1)
{
// If whisker pressed, avoid obstacle.
// First just right whisker - input(8) is 0 if whisker is pressed

if(! input(Rwpin))
{
bumpflg = 1;                               // Set flag so main will not give conflicting drive commands
drive_speed(0,0);
drive_ramp(-60, -60);                  // Back up 0.5 seconds
pause(500);
drive_ramp(0,0);
drive_speed(-26, 26);                   // Turn left 1 seconds -- 90 deg
pause(1000);
drive_ramp(0, 0);                             //  stop
}

// Just left whisker - input(7)

else if(! input(Lwpin))
{
bumpflg = 1;
drive_speed(0,0);
drive_ramp(-60, -60);                  // Back up 0.5 seconds
pause(500);
drive_ramp(0,0);
drive_speed(26, -26);                   // Turn right 1 seconds -- 90 deg
pause(1000);
drive_ramp(0,0);                         // stop
}
bumpflg = 0;                                //  clear flag, allow main to have control
}
}



I hope you enjoy it.

Tom

Comments

  • 3 Comments sorted by Date Added Votes
  • twm47099twm47099 Posts: 538
    edited July 2015 Vote Up0Vote Down
    Trying again to post the code:  Not sure what happened.  When I originally posted, the code cut off half way.  When I edited the original post and just saved it, The full code reappeared.  So I'm deleting the reposted code below???






    Tom
  • twm47099twm47099 Posts: 538
    edited August 2015 Vote Up0Vote Down


    I just noticed that in the program posted above all of the "<" and ">" operators had been changed to a combination of & lt and ; for < and similar for > probably during one of the forum upgrades.

    I've fixed them in the program above.

    Tom
  • I've made a few modifications to this program:
    1. It now uses a standard Sony TV remote. Previously I was using a Sony DSLR camera remote. The change was made by simply changing the values in the #DEFINE statements.

    2. The "whisker" code now uses 'waitpne' instead of looping to check each whisker. waitpne halts the 'whisker' cog until there is a change in either pin that the whiskers are connected to.
    /*
      SIRC TV Remote control 9.c  for overlay board
    
      This worked - There is no delay between whisker touching and bot stopping.  
        Before using separate cog for whiskers, there was a noticible delay, and whisker fully 
        compressed before bot would stop.
      This version stops, backs up, turns 90 deg from obstacle and stops.  
        Must press remote key to restart motion.  Consider changes to allow continuing motion wo 
        need to press remote key.
        
      Use multiple cogs - new cog to handle whiskers
      
      Connect 38 kHz IR receiver to Propeller P10
      Decodes button presses on Sony-compatible IR TV remote 
      Commands Activitybot to move straight, pivot 45 deg, move in a curve,
       increase or decrease speed and curve radius, and stop. 
      Also has whisker code for obstacle avoidance.  
      This has ramping to speed.  Increment = 4 ticks per 1/50 sec (4/0.020 sec).  
      To get from 0 to 100 takes 25 increments = 0.5 sec
        Future: add code for autonomous movement selectable from remote, 
    
      Load EEProm and Run
    */
    
    #include "simpletools.h"                      // Libraries included
    #include "sirc.h"
    #include "abdrive.h"                          // abdrive library
    
    // ***** Remote control aliases -- uses Sony TV remote  *****
    
    #define fwd 2       //  #2  -- forward
    #define stp 5       //  #5 -- stop        
    #define rvs 8       //  #8 -- reverse
    #define pl 4        //  #4 -- pivot left
    #define pr 6        //  #6 -- pivot right
    #define cvl 1       //  #1 -- curve left
    #define cvr 3       //  #3 -- curve right
    #define ispd 18      //  plus volume -- increase speed
    #define dspd 19      //  minus volume -- decrease speed
    
    // ***** Pin Defines *****
    #define spkrpin 3       // speaker pin for overlay board
    #define SIRCpin 10      // SIRC input pin
    #define Rwpin 8         // Right whisker pin -- must be 1 pin number higher than Lwpin
    #define Lwpin 7         // Left whisker pin
    
    int *cogwhisker;      // pointers to cog IDs
    
    void whisker();       // monitors whiskers, if hit: stops, backs away, turns away, runs in separate cog
    
    volatile int bumpflg;
    int Lspd, Rspd = 0;   // Left and Right command wheel speeds
    
    int main()                // **** main function ****
    {
      int spd = 50;           //  initial speed once fwd command given
      int dflg = 0;         // flag: -1=fwd or rev, 0=stopped, 1=curve left, 2=curve right, 3=pivot L or R
      drive_speed(0, 0);
      sirc_setTimeout(1000);                  // -1 if no remote code in 1 sec
      bumpflg = 0;                            // Gives control to remote
      cogwhisker = cog_run(whisker, 100);     // start monitoring whiskers
      freqout(spkrpin,1000, 3000);            // Speaker tone: 1 s, 3 kHz
    
      while(1)                                // Repeat indefinitely
      { 
                                            
        int button = sirc_button(SIRCpin);    //  get code from SIRC remote
        
    
        switch(button)                        //  decode signal from SIRC and calc drive command
        {
        case stp :      //  Center button - Q    
          Lspd = 0;     //  stop
          Rspd = 0;
          dflg = 0;
          break;
    
        case fwd :        //  Top Arrow - M
          Lspd = spd;     //  forward
          Rspd = spd;
          dflg = -1;
          break;
    
        case rvs :        //  Down Arrow 
          Lspd = -spd;    //  reverse
          Rspd = -spd;
          dflg = -1;
          break;
    
       case pr :          //    Right Arrow - N
          Lspd = 13;
          Rspd = -13;     //  Pivot Right 45 deg & stop
          dflg = 3;
          break;
    
        case pl :         //  Left Arrow - P
          Lspd = -13;
          Rspd = 13;      //  Pivot Left 45 deg & stop
          dflg = 3;
          break;
    
        case cvr :              //  Curve Right - L
          if (spd<25) spd=25;
          Lspd = spd;
          Rspd = spd-20;
          dflg = 2;
          break;
    
       case cvl :               //  Curve Left  - K
          if (spd<25) spd=25;
          Lspd = spd-20;
          Rspd = spd;
          dflg = 1;
          break;
    
       case ispd :              //  Up-Rocker - H -- Increase speed
            if (dflg == 1)          // curving left - increase spd and move in curve at new spd
            {
              spd=spd+5;                 
              if (spd > 100) spd = 100;
              Lspd = spd-20;
              Rspd = spd;
              }
            else if (dflg == 2)     // curving right - increase spd and move in curve at new spd
             {
              spd=spd+5;   
              if (spd > 100) spd = 100;
              Lspd = spd;
              Rspd = spd-20;
              }
            else if (dflg == -1)      // straight ahead - increase spd and move at new spd
             {
              spd=spd+5;       
              if (spd > 100) spd = 100;
              Lspd = spd;
              Rspd = spd;
              }
            else 
             {
              spd=spd+5;               
              if (spd > 100) spd = 100;
              }                                          
            break;                // Finish Up-Rocker
    
       case dspd :          //  Down-Rocker -- decrease spd
            if (dflg == 1)      // curving left - decrease spd and move at new spd
            {
              spd=spd-5;          
              if (spd < 25) spd = 25; 
              Lspd = spd-20;
              Rspd = spd;
              }
           else if (dflg == 2)      // curving right - decrease spd and move at new spd
            {
              spd=spd-5;               
              if (spd < 25) spd = 25;
              Lspd = spd;
              Rspd = spd-20;
              }
            else if (dflg == -1)      // straight ahead - decrease spd and move at new spd
             {
              spd=spd-5;                 
              if (spd <0) spd = 0;
              Lspd = spd;
              Rspd = spd;
              }
            else                       //  stopped
             {
              spd=spd-5;                  
              if (spd <0) spd = 0;
              }  
            break;                   // Finish Down-Rocker 
       default :
            break;
          }       // end switch
    
            if(dflg == 3)           // execute pivot 
            {
              if( ! bumpflg) drive_ramp(0,0);         // stop for pivot, whiskers not controlling movement 
              if( ! bumpflg)                          // whiskers not controlling movement
              {
                drive_ramp(Lspd, Rspd);     // now pivot 45 deg
                pause(1000);
                Lspd = 0;                   // and stop
                Rspd = 0;
                dflg = 0;
              }
            }
              if( ! bumpflg) drive_ramp(Lspd, Rspd);  // execute drive comnd, whiskers not cntrling movement    
      }     // end while
    }       // end main
    
    
    void whisker()       // If whisker pressed, stop & move away from obstacle:
                          // 1. stop bot, 2. disable SIRC control, 3. back up, 4. turn away from obstacle,
                          // 5. stop, 6. restore SIRC control 
    {
    //   uses waitpne(wstate, wmask) 
      int wmask = 1 << Rwpin | 1 << Lwpin;  // build 32 bit int mask with whisker pin numbers
      int wstate = wmask;           // in normal running both pins are high, hit whisker pin drops to low
    
      int RLval;
      while(1)        // runs continuously
      {
        waitpne(wstate, wmask);                 //stop cog until a whisker is pressed
        RLval = get_states(Rwpin, Lwpin);       // get whisker pin values
        bumpflg = 1;                            // Set flag so main will not give conflicting drive commands
        drive_speed(0,0);                       // stop
        drive_ramp(-60, -60);                   // Back up 0.5 seconds
        pause(500);
        drive_ramp(0,0);                        // and stop
    
      //  ***** Check direction to turn *****
         switch(RLval)                    //  decode whiskers 0b00=both, 0b01=right, 0b10=left, 0b11=neither
        {
          case 0 :                        // *** both whiskers hit, turn right
          drive_speed(26, -26);           // Turn right 1 seconds -- 90 deg
          break;
    
          case 1 :                        // *** Right whisker hit, turn left
          drive_speed(-26, 26);           // Turn left 1 seconds -- 90 deg
          break;
    
          case 2 :                        // *** Left whisker hit, turn right
          drive_speed(26, -26);           // Turn right 1 seconds -- 90 deg
          break;
    
          case 3 :                        // *** Neither whisker hit, don't turn
          break;
        }     // end switch
                                          // now do the 1 second delay for the 90 degree turn
          pause(1000);
          drive_ramp(0, 0);               //  and stop
          Lspd = 0;                       // prevents bot from resuming last movement command in main
          Rspd = 0;
          bumpflg = 0;                    //  clear flag, allow main to have control
      }   // end while
    }     // end whisker function
    
    
    
Sign In or Register to comment.