Obstacle Avoidance

Thread Starter

ActivePower

Joined Mar 15, 2012
155
Hi,

I am currently working on developing my first bot which I expect to function as a humble obstacle-dodging machine. I call it "dodging" because unlike the machines which avoid an obstacle and change their course altogether, I wish it to keep to (return to) the straight path it was set on even after it encounters an obstacle.

I have two 38 kHz IR proximity sensor modules (purchased ready-made as I didn't wish to have any hassles the first time around) but I guess I'll employ just one in the bot this time around.

I have visualized a circular form factor for the chassis with the sensor and the breadboard circuit mounted. The wheels are run by two 300 rpm DC Geared motors.

I have the following algorithm in mind (and partially implemented) for the purpose:

#1. Check (front) sensor status.
#2. If High (No obstacle) move straight ahead.
#3. If Low (Obstacle Detected):
3a. Generate pseudo-random boolean value for switching
3b. Use an if-else/Switch statement to turn right/left.
3c. Delay for some time (to be determined by trial and error?)
3d. Call the complementary motor function i.e. if turned left earlier then turn right.
3e. Delay for the same time.
//Assuming bot comes back on course
#4. Resume free run.

I am currently working on the C code for the same but figured any additional inputs/criticisms/suggestions would be great before I get my hands dirty!

Thanks!
 

John P

Joined Oct 14, 2008
2,026
It seems to me that you need more than this. I'd imagine a series of course changes that would be turn (let's say left), travel a certain distance, turn right twice as much as the first turn, travel the same distance as before, turn left the same amount as the first turn, resume course. In other words, after zigging you have to zag.
 

Thread Starter

ActivePower

Joined Mar 15, 2012
155
Just realized that such a mechanism of dodging objects would require me to estimate the object distance too so that the vehicle can bend around it. I do not believe that I have such a proficiency right now in PIC programming, though. Is there any way out or any possible solution?

Thanks!
 

DumboFixer

Joined Feb 10, 2009
217
sideways looking sensor for detecting when you are past the obstacle ?

Or just turn the robot and if the obstacle is still there then turn it back and move forward a bit more - not very elegant though.
 

Thread Starter

ActivePower

Joined Mar 15, 2012
155
It is not the estimating when I am past the obstacle that bothers me but the angle I need to turn the bot so that it just escapes the obstacle. Is it really possible to build an object avoiding bot with one proximity sensor though?
 

BMorse

Joined Sep 26, 2009
2,675
It is not the estimating when I am past the obstacle that bothers me but the angle I need to turn the bot so that it just escapes the obstacle. Is it really possible to build an object avoiding bot with one proximity sensor though?

yes it is, I have built a couple before utilizing 2 different schemes, 1 I used an Ultrasonic ranger attached to a servo that I panned back and forth to detect obstacles and "plan" for a different route to take around the obstacles.... another one I used a laser pointer and a spinning mirror to project a laser line ahead of the bot, and sampled the reflection of the laser to determine if there were objects in its path.... the first one is pretty easy to do, does not require more than an ultrasonic ranger and an RC Servo.... but if you already have some IR rangers, use those instead of an Ultrasonic ranger..... basically just mount the sensor on a servo, and pan it back and forth while you take readings.... or, just for the heck of it, have the bot "pan" itself to map the area.....


I built this "light seeking" photopopper, it basically navigates around obstacles that block its path to the brightest point in the room.... only using transistor logic..... http://www.morse-code.com/36f40f00.jpg
 
Last edited:

John P

Joined Oct 14, 2008
2,026
Think of a robot that might find a wastebasket in its path, or might be facing the Great Wall of China...

In the one case, a quick deviation in course. In the other, better have plenty of battery power.
 

Thread Starter

ActivePower

Joined Mar 15, 2012
155
basically just mount the sensor on a servo, and pan it back and forth while you take readings.... or, just for the heck of it, have the bot "pan" itself to map the area.....
That does seem to be possible! I have an additional query in this regard, though. What could be the differential turning mechanism? I am awfully ignorant in this regard.

I feel it can be done by switching off one motor and running the other as well as running both motors but in opposite directions.
However, the first method would cause some translation in addition to the rotation and thus I am inclined to choose the latter for the 'panning' purpose. But just to confirm my thoughts: could 'single motor running' be the preferred turning method in any application? (or this, for that matter?)

Thanks!

EDIT: I am working on the code right now and would post it as soon as it is done. It would be great if anyone could check it and let me know if anything is terribly wrong in there.
 

BMorse

Joined Sep 26, 2009
2,675
I think running both motors would work better, you would get a "better" reading, and you would not have to loose the position you were originally at, of course you will have to have a way to track your wheels also, so that way you know how much each one turned so you can return them to the original position.... some black and white stripes in the inside of the wheels with an IR LED and IR Phototransistor would work good for a basic wheel encoder...
 

Thread Starter

ActivePower

Joined Mar 15, 2012
155
Rich (BB code):
void init()				//initialize major registers and variables
{
	
}

/*	DRIVE FUNCTIONS  */

void Free_Run()			//No obstacle in path; free run
{
	LM_Pos=1;
	LM_Neg=0;			//run LM
	RM_Pos=1;
	RM_Neg=0;			//run RM
}

void Right_Turn()		//differential drive; turn right motor back and left motor forward
{
   LM_Pos=1;
   LM_Neg=0;		//LM forward
   RM_Pos=0;
   RM_Neg=1;		//RM reverse
}

void Left_Turn()		//differential drive; turn right motor forward and left motor back; rotate left
{
   LM_Pos=0;
   LM_Neg=1;			//LM reverse
   RM_Pos=1;
   RM_Neg=0;		//RM forward
}

void Stop()				//standstill
{
   LM_Pos=0;
   LM_Neg=0;		
   RM_Pos=0;
   RM_Neg=0;		
}


void main()
{
	TRISB0=0;		//POST LED pin configured as output
	POST=1;			//switch ON LED to signal MCU power-up
	TRISC=0b01000010;		//configure PORTC; sensor inputs at RC1 and RC6 and remaining digital motor drive outputs
	TRISB1=1;		//configure two-way switch input
	while(1)
	{
		while(Switch)		//if switch is turned ON to power
		{
			while(Sense)		//no obstacle in path
			{
				Free_Run();
			}
			
			while(!Sense)		//if obstacle in path
			{
				Right_Turn();
			}
			
		}	
	}
}

This is just the crude alpha version of the code and there may be several errors in it (I am quite sure of some) and I need your help in sorting them out (if present ;)). I realize that the left turn and standstill functions have not been used but I wrote them just in case I happen to make any improvements in the rough draft later. I'd be really happy if anyone could suggest any improvements in the algorithm.

@BMorse: Is this a valid 'panning' algorithm? :)
 

BMorse

Joined Sep 26, 2009
2,675
@BMorse: Is this a valid 'panning' algorithm? :)

Actually it is really crude to where you do not know how many "steps" or revolutions your wheels have moved, if you are strictly going to go off some sort of "timing", using gearboxes will reduce the accuracy quite a bit, plus the amount of "code" steps to make will also affect your timing.... you will definitely need to use some sort of H-Bridge to drive the motors, this will simplify the code quite a bit, plus definitely some sort of encoder for the wheels, the you can run the motor and count how many steps it has taken, then you can make sure that both wheels are traveling at the same rate and speed, so using some H-Bridges and PWM speed control, you can alter the speed of each motor to "sync" them together to make sure your bot is traveling in a "straight" line when you need it to, then you can also specify angles for specific turn radius', etc.

Then you can start writing a "real" algorithm for running the motors and always knowing exactly where they are in relation to position and each other, and be able to compensate for travel off the planned path if the bot encounters an obstacle..... and also, look into possibly adding some sort of electronic compass (such as this one >> http://www.morse-code.com/id32.htm), so the bot has a heading indicator....
 

BMorse

Joined Sep 26, 2009
2,675
here is a basic example of how a bot should react when encountering an object in its path...sampl algorithim.jpg

If you would notice that the "bot" determined which side of it is blocked than the other, this way, the bot can take the shortest distance to maneuver around the obstacle, and have to spend less time and power to navigate its surroundings......
 

Markd77

Joined Sep 7, 2009
2,806
Your project has many similarities with a "wall follower" robot, you just need to add the ability to keep track of it's position. Here's a video (there are many) which shows the advantage of being able to turn while moving forward instead of stopping and turning (it still does that when it detects an obstacle directly in front of it).
http://www.youtube.com/watch?v=Ww1cJ7ALuwE&feature=related
Have you got the datasheet of the sensors you have?
Using stepper motors could work as an alternative to DC motors and rotary encoders.
 

BMorse

Joined Sep 26, 2009
2,675
which shows the advantage of being able to turn while moving forward instead of stopping and turning (it still does that when it detects an obstacle directly in front of it).
Using stepper motors could work as an alternative to DC motors and rotary encoders.

I agree, there are advantages to turning while moving, that is why I suggested PWM control of his DC Gear motors, so he can essentially speed up one motor faster than the other (or slow one down) etc.

And depending on the size of his robot, RC servo's modified for full rotation would work better than Steppers(and all the complicated circuits and controlling code required to run a stepper) Or H-Bridge driven DC Gear motors with rotary encoders....:rolleyes:
 

Thread Starter

ActivePower

Joined Mar 15, 2012
155
Sorry for the late follow-up on this thread. I have been travelling a bit and was caught up on schoolwork and other projects.

I admit that I should have made it clear that it is my very first attempt at building something autonomous and I wish to just get it up and running the first time around with additional features added in later iterations.

As it stands I worked on the algorithm and attempted writing one with two sensors just to simplify the code.

Here's how it goes:

Rich (BB code):
//Main.c
//Main drive software for Cain, an obstacle avoiding bot

/* 
   Device: PIC16F877A
*/

#include<htc.h>
#define _XTAL_FREQ 20000000				//20 MHz oscillator

//set PORT aliases
#define POST RB0 				//Power On Self Test LED
#define Switch RB1 				//Switch control (ON/OFF)
#define Enable RD1
#define LM_Pos RC2 
#define LM_Neg RC3 //Pins for controlling wheel motors; go to corresponding driver pins
#define RM_Pos RD3 
#define RM_Neg RD2 
#define L_Sense RC1 				//left IR proximity sensor
#define R_Sense RC6				//right IR proximity sensor


//set config word

__CONFIG (FOSC_XT & CPD_OFF & CP_OFF & LVP_ON & PWRTE_OFF & BOREN_OFF & DEBUG_OFF & WDTE_OFF);


void init()				//initialize major registers and variables
{
	TRISB0=0;		//POST LED pin configured as output
	TRISB1=1;		//configure two-way switch input
	TRISD=0b00000000;		//D-pins out
	TRISC=0b01000010;		//configure PORTC; sensor inputs at RC1 and RC6 and remaining digital motor drive outputs
	Enable=1;
}

/*	DRIVE FUNCTIONS  */

void Free_Run()			//No obstacle in path; free run
{
	LM_Pos=1;
	LM_Neg=0;			//run LM
	RM_Pos=1;
	RM_Neg=0;			//run RM
}

void Right_Turn()		//differential drive; turn right motor back and left motor forward
{
   LM_Pos=1;
   LM_Neg=0;		//LM forward
   RM_Pos=0;
   RM_Neg=1;		//RM reverse
}

void Left_Turn()		//differential drive; turn right motor forward and left motor back; rotate left
{
   LM_Pos=0;
   LM_Neg=1;			//LM reverse
   RM_Pos=1;
   RM_Neg=0;		//RM forward
}

void Reverse()				//standstill
{
   LM_Pos=0;
   LM_Neg=1;		
   RM_Pos=0;
   RM_Neg=1;		
}


void main()
{
	init();
	POST=1;			//switch ON LED to signal MCU power-up
	while(1)
				//if switch is turned ON to power
		{
			if((~L_Sense)&&(~R_Sense))		//no obstacle in path
				Free_Run();
			else if((~L_Sense)&&(R_Sense))		//if obstacle on the right
				Left_Turn();
			else if((~R_Sense)&&(L_Sense))		//if obstacle on the left
				Right_Turn();
			else if ((R_Sense)&&(L_Sense))
			{
				Reverse();
				__delay_ms(200);
				Left_Turn();
				__delay_ms(500);			
			}
				
			
			
		}	
	
}

The code builds alright and I have checked it a couple of times through the debugger (MPLAB SIM) setting various port pins to see the effect and it works as expected (I think).

However, on the hardware side of things, the motors seem to be running in the "free run" mode irrespective of the sensor inputs. After some (small) tweaks to the code (this is the final tweaked version) I could not get the PIC to make the if-else decisions.

My first guess was the input pins for the sensors were not working properly. But then, if the program enters the free run mode it must have entered the if statement and this should imply that the sensor inputs have been read, right?

Am I missing something obvious/subtle or is there some fault with the code?
I'll post the breadboard prototype asap.

And thanks for the awesome suggestions and ideas! I do look forward to incorporate those features in my future projects.

Thanks!
 

crazyengineer

Joined Dec 29, 2010
156
I have a quick suggestion.

I don't see anything in you're code referring the the 38khz IR reciever. In order for the IR reciever to properly work, the IR LED has to be pusled at 38hz. I would control them using some sort of timer interrupt on the pic microcontroller.
 

BMorse

Joined Sep 26, 2009
2,675
The sensors are packaged with the control circuitry built in as far as I know. The usual (no obstacle signal) is 0V which goes high once it detects an obstacle. The range is variable from 10 cm-12 cm.

Here's the link:

http://robokits.co.in/shop/index.php?main_page=product_info&cPath=11&products_id=330.

Am I missing something?
I don't believe you are, I believe he was assuming that you were using an IR receiver module such as the ones in televisions, etc. those are modulated....

But one suggestion though, I would put some kind of opaque or dark colored baffle in between the IR transmitter/receiver LED's..... this will block any interference from the emitter right at the PCB, if anything I would cut short pieces of a dark colored plastic pen or something similar and place the "tubes" around each LED...... and if you want to make the receiver LED less sensitive to ambient light, place a piece of developed film negative on the end of the tube, this will help block out most ambient light but will let the IR through....
 

BMorse

Joined Sep 26, 2009
2,675
You have only 2 cm room to detect an object? wow... are you sure that is enough?
Why don't you use an ultrasonic range finder?

By the way, here's my obstacle avoidance robot: http://www.youtube.com/watch?v=L3Dpe1v6G-w
He could get more distance if he used some lenses on the IR LED pair...... and apparently those modules were designed for more of a collision detection, rather than collision avoidance, ;)....
 
Top