Let's Make Robots!

How-to for Thomas

First, lets state our goal:
We want a robot to drive to dark areas while avoiding stuff on the way using various sensors.

As with everything, we break it down into smaller pieces. We test each one individually, record any numbers we get (ADC readings and the like) and then start putting them together. While doing each of these tests individually, it helps us figure out how we are eventually going to put them together.

If someone told me to accomplish the goal above, I would do it just like this:

  • Test of LDR's by themselves. No mapping, raw data. Write these numbers down (dark, light, etc)
  • Code the robot to turn on its center until both LDR readings are identical or within a threshold --then I would play with this code and a flashlight for a while
  • Code the robot to do basically the same thing as above, but go forward this time. See if you can steer to the dark side, see if you can get it to turn proportionally in relation to the difference in readings of the 2 LDR's
  • Forget about the LDR's completely and move on to the sonar sensor
  • Test the sonar sensor all by itself
  • Code the robot to drive forward until it sees an object at a given distance and have it stop 
  • Forget about the sonar sensor completely
  • Code the robot to drive off of its sharp sensors (I assume these are R/L pointing outward) --these can be coded to "scoot" you off of a wall (when you are coming in shallow and your main sonar misses it) Code the robot to drive forward, check its side sensors and make a small correction (just a small correction) to "scoot" off the wall
  • Add your sonar code to your sharp code (still without the LDR's) and have your robot do 2 things --scoot off of the wall, and stop when the main sonar sees something too close

At this point, you will need to stop and think about the actual operation of the bot. Right now, we just stop when we see something and have to reset the bot to make another run. Lets think about what we would want to do instead. We are driving forward, we see something,  --might be good to turn. Which way? Well, as it happens, we have 2 sharp sensors sticking out to the sides, lets ask them and see if either way is better (farther). Our code might look like this:

  • Go forward, check all sensors
  • If sonar is too close, turn. Base turn direction on readings from Sharps
  • If both sharps and sonar are too close --Allstop, goto stuck in corner routine
  • if none of the above is the case, drive forward

Ok, so now we have a robot that reads all 3 navigaion sensors and knows which sensor is more important than the others and drives accordingly. Let's go back to our LDR code.

  • You still have a "read the LDR's" routine left over --great
  • Add to this read the LDR's routine, some code that will figure the "turn request"  I.e. the LDR's want to turn left or want to turn right.
  • Add this "check the LDR's" to your main loop --it can go right next to the code that reads all the other sensors

Now, here's the tricky part:

Add this turn request to the beginning of your navigation code. Now, the navigation routine continues (the stuff we talked about above, scooting off of walls, front sonar etc.) and if any of that happens, it comes after your turn request in the code. --It will "cancel out" the turn request, ignore it, and just do regular navigation. However, lets say the robot is out in the wide open. It runs through the navigation routine (starting with the turn request from the LDR's), but this time its obstacle avoidance is not the priority --there is nothing in front of the bot (or to the sides) and the robot will not correct its path. Thus, it will not "cancel out" your LDR turn request, it will "get through" and be done. Now, we just turned to the dark.

Wow, please tell me at least some of that helped...

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

#include <Servo.h> //include Servo library

 

const int irPin = A1;  //Sharp infrared sensor pin

const int dangerThresh = 276; //threshold for obstacles

const int ledPinstop = 3;       // the pin that the LED is attached to

const int ledPingo = 12;       // the pin that the LED is attached to

 

int rightDistance; //distance away from obstacles on the right

int centerDistance; //distance away from obstacles in the center

int leftDistance;  //distance away from obstacles on the left

int averaging;                // Stores average of distance

int val = 0;

int dist = 0;

 

//declare motors

 

Servo myservo;  

Servo servoleft;     //Left wheel 

Servo servoright;    //Right wheel 

 

 

void setup()

{

 

  pinMode(ledPingo, OUTPUT);  

  pinMode(ledPinstop, OUTPUT);  

  myservo.attach(9);          // head to pin D9

  myservo.write(93);          // set IR sensor pan to center

  servoleft.attach(10);       // Left servo to pin D10

  servoright.attach(11);      // Right servo to pin D11

  servoright.write(90); 

  servoleft.write(90); 

 

}

 

void forward()

 

{

    servoleft.write(0);

    servoright.write(180); //move forward

}

 

void scan_area()

 

{

    servoleft.write(90);

    servoright.write(90);

    delay(100);

    myservo.write(125); 

    delay(300);

    rightDistance = analogRead(irPin); //scan to the left

    delay(100);

    myservo.write(93); //return to center

    delay(300);

    centerDistance = analogRead(irPin); //scan center

    delay(100);

    myservo.write(50);

    delay(300);

    leftDistance = analogRead(irPin); //scan to the right

    delay(100);

    myservo.write(93); //return to center

    delay(300);

    centerDistance = analogRead(irPin); //scan center

    delay(100);

}

int get_avg(int IRpin) //Gets 3 readings from the sensors and averages them to get rid of spikes

{                     

  int total = 0;                

  for(int x = 0; x <=3; x++)    

 

 

  {  

 

    total+=analogRead(IRpin); 

 

  }  

 

  return total/3;

 

}

 

void loop()

 

{

 

  int val = analogRead(irPin); //read IR sensor

  if (val<dangerThresh) //if path is clear

  {

    digitalWrite(ledPingo, HIGH);

    forward();

  }

  else //if path is blocked

  {

    digitalWrite(ledPingo, LOW);

    digitalWrite(ledPinstop, HIGH);

    scan_area();

    compareDistance();

    digitalWrite(ledPinstop, LOW);

  }

}

 

void compareDistance()

{

  if (leftDistance<rightDistance && leftDistance<centerDistance) //if left is less obstructed 

  {

    servoleft.write(180);

    servoright.write(180);  //turn right

    delay(300); 

  }

  else if (rightDistance<leftDistance && rightDistance<centerDistance) //if right is less obstructed

  {

    servoleft.write(0);

    servoright.write(0); //turn left

    delay(300);

  }

  else //if they are equally obstructed

  {

    servoleft.write(180);

    servoright.write(0); //move back

    delay(300);

    servoleft.write(0);

    servoright.write(0);    //turn left

    delay(950);

    scan_area();

    compareDistance();

 

  }

}

 

 

I like the idea of prioritizing the sensors ,never thought of this one . 

A Very explaining and inspiring guide.

 

very helpful i have an idea and would like to sell soon enough hope it will work. sold 4 of my bots so far..

Person to person blogs.....A new digital age has arrived. I guess its good there is an app for that.....

I lurked through the shoutboxing that brought about the need for this post. It makes total sense in that context. This actually could have been a forum post for as helpful as it could be to beginners learning flow, but as a blog it addresses the original request pretty well. I have to admit-I had some flashbacks to an incident involving a donated Picaxe getting fried by a 9v battery.