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