Obstacle Avoidance

Discussion in 'Embedded Systems and Microcontrollers' started by ActivePower, Jul 22, 2012.

  1. ActivePower

    Thread Starter Active Member

    Mar 15, 2012

    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!

  2. John P

    AAC Fanatic!

    Oct 14, 2008
    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.
  3. ActivePower

    Thread Starter Active Member

    Mar 15, 2012
    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?

  4. DumboFixer

    Active Member

    Feb 10, 2009
    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.
  5. ActivePower

    Thread Starter Active Member

    Mar 15, 2012
    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?
  6. BMorse

    AAC Fanatic!

    Sep 26, 2009

    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: Jul 23, 2012
  7. John P

    AAC Fanatic!

    Oct 14, 2008
    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.
  8. ActivePower

    Thread Starter Active Member

    Mar 15, 2012
    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?)


    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.
  9. BMorse

    AAC Fanatic!

    Sep 26, 2009
    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...
  10. ActivePower

    Thread Starter Active Member

    Mar 15, 2012
    Code ( (Unknown Language)):
    3. void init()             //initialize major registers and variables
    4. {
    6. }
    8. /*  DRIVE FUNCTIONS  */
    10. void Free_Run()         //No obstacle in path; free run
    11. {
    12.     LM_Pos=1;
    13.     LM_Neg=0;           //run LM
    14.     RM_Pos=1;
    15.     RM_Neg=0;           //run RM
    16. }
    18. void Right_Turn()       //differential drive; turn right motor back and left motor forward
    19. {
    20.    LM_Pos=1;
    21.    LM_Neg=0;        //LM forward
    22.    RM_Pos=0;
    23.    RM_Neg=1;        //RM reverse
    24. }
    26. void Left_Turn()        //differential drive; turn right motor forward and left motor back; rotate left
    27. {
    28.    LM_Pos=0;
    29.    LM_Neg=1;            //LM reverse
    30.    RM_Pos=1;
    31.    RM_Neg=0;        //RM forward
    32. }
    34. void Stop()             //standstill
    35. {
    36.    LM_Pos=0;
    37.    LM_Neg=0;       
    38.    RM_Pos=0;
    39.    RM_Neg=0;       
    40. }
    43. void main()
    44. {
    45.     TRISB0=0;       //POST LED pin configured as output
    46.     POST=1;         //switch ON LED to signal MCU power-up
    47.     TRISC=0b01000010;       //configure PORTC; sensor inputs at RC1 and RC6 and remaining digital motor drive outputs
    48.     TRISB1=1;       //configure two-way switch input
    49.     while(1)
    50.     {
    51.         while(Switch)       //if switch is turned ON to power
    52.         {
    53.             while(Sense)        //no obstacle in path
    54.             {
    55.                 Free_Run();
    56.             }
    58.             while(!Sense)       //if obstacle in path
    59.             {
    60.                 Right_Turn();
    61.             }
    63.         }  
    64.     }
    65. }

    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? :)
  11. BMorse

    AAC Fanatic!

    Sep 26, 2009

    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....
  12. BMorse

    AAC Fanatic!

    Sep 26, 2009
    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......
  13. Markd77

    Senior Member

    Sep 7, 2009
    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).
    Have you got the datasheet of the sensors you have?
    Using stepper motors could work as an alternative to DC motors and rotary encoders.
  14. BMorse

    AAC Fanatic!

    Sep 26, 2009

    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:
  15. ActivePower

    Thread Starter Active Member

    Mar 15, 2012
    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:

    Code ( (Unknown Language)):
    1. //Main.c
    2. //Main drive software for Cain, an obstacle avoiding bot
    4. /*
    5.    Device: PIC16F877A
    6. */
    8. #include<htc.h>
    9. #define _XTAL_FREQ 20000000             //20 MHz oscillator
    11. //set PORT aliases
    12. #define POST RB0                //Power On Self Test LED
    13. #define Switch RB1              //Switch control (ON/OFF)
    14. #define Enable RD1
    15. #define LM_Pos RC2
    16. #define LM_Neg RC3 //Pins for controlling wheel motors; go to corresponding driver pins
    17. #define RM_Pos RD3
    18. #define RM_Neg RD2
    19. #define L_Sense RC1                 //left IR proximity sensor
    20. #define R_Sense RC6             //right IR proximity sensor
    23. //set config word
    28. void init()             //initialize major registers and variables
    29. {
    30.     TRISB0=0;       //POST LED pin configured as output
    31.     TRISB1=1;       //configure two-way switch input
    32.     TRISD=0b00000000;       //D-pins out
    33.     TRISC=0b01000010;       //configure PORTC; sensor inputs at RC1 and RC6 and remaining digital motor drive outputs
    34.     Enable=1;
    35. }
    37. /*  DRIVE FUNCTIONS  */
    39. void Free_Run()         //No obstacle in path; free run
    40. {
    41.     LM_Pos=1;
    42.     LM_Neg=0;           //run LM
    43.     RM_Pos=1;
    44.     RM_Neg=0;           //run RM
    45. }
    47. void Right_Turn()       //differential drive; turn right motor back and left motor forward
    48. {
    49.    LM_Pos=1;
    50.    LM_Neg=0;        //LM forward
    51.    RM_Pos=0;
    52.    RM_Neg=1;        //RM reverse
    53. }
    55. void Left_Turn()        //differential drive; turn right motor forward and left motor back; rotate left
    56. {
    57.    LM_Pos=0;
    58.    LM_Neg=1;            //LM reverse
    59.    RM_Pos=1;
    60.    RM_Neg=0;        //RM forward
    61. }
    63. void Reverse()              //standstill
    64. {
    65.    LM_Pos=0;
    66.    LM_Neg=1;       
    67.    RM_Pos=0;
    68.    RM_Neg=1;       
    69. }
    72. void main()
    73. {
    74.     init();
    75.     POST=1;         //switch ON LED to signal MCU power-up
    76.     while(1)
    77.                 //if switch is turned ON to power
    78.         {
    79.             if((~L_Sense)&&(~R_Sense))      //no obstacle in path
    80.                 Free_Run();
    81.             else if((~L_Sense)&&(R_Sense))      //if obstacle on the right
    82.                 Left_Turn();
    83.             else if((~R_Sense)&&(L_Sense))      //if obstacle on the left
    84.                 Right_Turn();
    85.             else if ((R_Sense)&&(L_Sense))
    86.             {
    87.                 Reverse();
    88.                 __delay_ms(200);
    89.                 Left_Turn();
    90.                 __delay_ms(500);           
    91.             }
    95.         }  
    97. }

    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.

  16. crazyengineer


    Dec 29, 2010
    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.
  17. ActivePower

    Thread Starter Active Member

    Mar 15, 2012
  18. BMorse

    AAC Fanatic!

    Sep 26, 2009
    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....
  19. CVMichael

    AAC Fanatic!

    Aug 3, 2007
    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
  20. BMorse

    AAC Fanatic!

    Sep 26, 2009
    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, ;)....