loading
Hello,

This is a step by step guide to build an autonomous navigation robot. We use the Arduino microcontroller to control this robot. We have two different programs for this robot. The first enables the robot to drive around and avoid anything that gets in its way. This avoiding obstacles program uses two ultrasonic sensors. Our other program uses 2-D arrays to map out the surrounding area. Based on the values we input into the 2-D array, the robot knows where things around it are. Both programs are included.

Step 1: Materials

We used vex as the frame for our robot, but you can use anything you want to make the structure. In fact, we recommend making the frame from scratch. We also use Vex sensors and vex motors, but even if you use other sensors and motors, (which we recommend that you do) it will work almost exactly the same way.

- (2) ultrasonic sensors (4 for further mapping ability or just to have fun :) )
- (4) servos (5 for funsies)
- Arduino (we used Uno)
- Perf board (we used Radio Shack 276-150: http://www.radioshack.com/product/index.jsp?productId=2102845)
- Lots of Wires
- (2) 9.6 V Batteries (we used Vex batteries: http://www.vexrobotics.com/276-2220.html)
- (1) 9V Battery (to power the Arduino)
- (4) wheels (5” diameter)
- assorted hardware (nuts, bolts, etc.)
- duct tape is also quite helpful

This tutorial has three more steps.
The first section is about the mechanical aspect.
The second section is about the electronic aspect.
The third section is about the programming.

Step 2: Mechanical

First, we need to build a solid base. We have attached pictures here, but you can make it pretty much however you want. We made three different prototypes of this robot. We will discuss the first two here. Mark I had a truck-like shape. It was pretty big, but that also made it slower and harder to turn. Also, for our purposes, the size was pretty much unnecessary. Therefore, in our second model, we made it much smaller and more compact.

Next, we need to add the servos underneath the base so that there is enough space on the outside to attach wheels. We used a four wheel drive. Depending on how strong your servos are, you can use two wheel drive if you want. However, there must be enough space on top of the base to fit the Arduino, PCB, and battery.

Next, add the wheels onto the servos, we added reinforcements outside the wheels to secure the other side of the shaft and keep them from coming off. The two extra wheels at the front are elevated so that if the robot runs into a curb or step, it will be able to climb on top of it. We put duct tape on the back two wheels to reduce the friction so that it turns easier.

Next, we added a battery holder. For us, it was easy to take a Vex battery charger and hack it so that it transmits power to the wheels instead of charging the batteries. Take out the circuit board inside and desolder the positive and negative leads that go to the charging port. Next you solder together the black wires from the two battery terminals and solder together the red wires as well. Next, solder a wire each to the red and black wire. This can plug straight into your PCB. Pictures of this battery holder are under the electronics section.

Next, make a mount at the front of the robot for the ultrasonic sensors. If you want to go above and beyond, you can make a mount in the center for a rotating ultrasonic sensor.

We have included pictures of our Mark II design which is a standard four wheel drive as well as our Mark III design which features a crab wheel design. Crab wheel is more complicated to program, but it enables holonomic drive.

Step 3: Electronics

The electronics for this robot are not that hard. If you use the battery holder idea from above, your 9.6 should be connected in parallel. If you aren’t using that idea, connect your batteries in parallel. Then, follow the picture of the circuit board posted here. However, be careful because depending on the size of your base, your servo wires may not be able to reach the circuit board. We are using the same signal wire for servos 1 and 2 and a different signal wire for servos 3 and 4. This is because servos 1 and 2 should always have the same signal while servos 3 and 4 should always have the same signal (because they are on the same side).

If you want to add another sensor or another servo just follow the same pattern as shown in the picture connecting signal to an Arduino pin, 5V to red, and ground to black. Remember that the ground on motors has to be connected to both the Arduino black and the battery black.

We include a rotary encoder on one of our motors just to measure how far it turned. But, this is completely optional.

Step 4: Programming

We are using the Arduino Uno programming language. It is based off of Java.
Here is our sample code for navigation using 2D arrays. Inside the 2D array grid, we input either a 0 or a 1. A 1 represents an object or an obstacle. A 0 represents free space. The robot travels through the 0’s.

Grid navigation:

//   THIS IS A PROGRAM TO MAP OUT AN AREA WITH 2D ARRAYS AND THEN NAVIGATE ONLY THROUGH THE
//   ZEROS PRESENT. ULTRASONIC SENSORS ARE NOT USED ALTHOUGH THEY ARE INITIALIZED.
//   THE ENCODERS ARE ALSO NOT USED BUT ARE INITIALIZED

//  @author Pranav

#include "Servo.h"

// Motors
Servo motor1;
Servo motor2;

// Rotary Encoders
int encoderAPin = 4;              //Left      // pin for the rotary encoderA
int encoderBPin = 2;              //Right     // pin for the rotary encoderB
int encoderAPosition = 0;                     // position counter for encoderA
int encoderBPosition = 0;                     // position counter for encoderB
int signalAInput1;                             // signal input 1 for encoderA
int signalAInput2;                             // signal input 2 for encoderA
int signalBInput1;                             // signal input 1 for encoderB
int signalBInput2;                             // signal input 2 for encoderB



// robot location service
// 0 is up
// 1 is right
// 2 is down
// 3 is left
int robotDirection = 2;

// this is the coordinates in the grid of where the robot is
// it is also the x and y indexes in the array.
// remember that the array starts at index 0.
int xcoordinate = 2;
int ycoordinate = 1;

// ultrasonic pins
const int Trig_pin =  5;  // pin for triggering pulse    INPUT
const int Echo_pin = 6;   // pin for recieving echo      OUPUT
long duration;            // how long it takes for the sound to rebound


// motor pins
const int Motor1Pin = 9;  // Left side
const int Motor2Pin = 10; // right side

// the array that it tracks with
// this can be an array of any size
// just make sure that the robot has a free space to move to from its initial position.
int arraything [6] [6] =

  {    1,1,1,1,1,1    }
  ,
  {    1,1,0,1,0,1    }
  ,
  {    1,1,0,1,0,1    }
  ,
  {    1,1,0,1,0,1    }
  ,
  {    1,1,0,1,1,1    }
  ,
  {    1,1,1,0,1,1    }
};



void setup () {
  // Rotary encoder
  pinMode (encoderAPin, INPUT);
  pinMode (encoderBPin, INPUT);
  Serial.begin(9600);
  Serial.println ("Starting now...");
  \
 
  // ultrasonic
  //  pinMode(Trig_pin, OUTPUT);        // initialize the pulse pin as output:
  //  pinMode(Echo_pin, INPUT);       // initialize the echo_pin pin as an input:


  // motorsmmmmmmmmm
  motor1.attach(Motor1Pin);
  motor2.attach(Motor2Pin);

}


// In English, this program sees if there is something in front of it.
// If no, it moves straight. If yes, it checks its Right.
// If its Right is free, it turns that way, or else, it checks its Left.
// If its Left is free, it turns that way, or else, it just turns 180 degrees
// and goes back the way it came.
//
// Next to do is to encorporate beginning and destination as well as optimum path finding
//
// Last is to use the ultrasonic with the grid.

void loop () {

  while (1==1){
    if (isFrontOpen() == true) {
      moveForward();
      delay (2000);
    }
    else
      if (isRightOpen() == true) {
      turnRight();
      delay (2000);
    }
    else
      if (isLeftOpen() == true) {
        turnLeft();
        delay (2000);
      } 
      else {
        turnAround();
        delay (2000);
      }
  }
}


// Checks if there is something right in front of it using Grids
boolean isFrontOpen () {
  int nextNumber = getFrontNumber();
  if (nextNumber == 0){
    return true;
  }
  else {
    return false;
  }
}

// Checks if there is something to the Right of it using Grids
boolean isRightOpen(){
  int nextNumber = getRightNumber();
  if (nextNumber == 0){
    return true;
  }
  else {
    return false;
  }
}

// Checks if there is something to the Left of it using Grids
boolean isLeftOpen(){
  int nextNumber = getLeftNumber();
  if (nextNumber == 0){
    return true;
  }
  else {
    return false;
  }
}


// Moves straight forward.
void moveForward () {
  motor1.write(180);
  motor2.write(0);

  Serial.println("Forward");
  if (robotDirection == 0)
    ycoordinate = ycoordinate - 1;
  if (robotDirection == 1)
    xcoordinate = xcoordinate + 1;
  if (robotDirection == 2)
    ycoordinate = ycoordinate + 1;
  if (robotDirection == 3)
    xcoordinate = xcoordinate - 1;
  delay (100);
  /*Serial.print("  xcoordinate " );
   Serial.print(xcoordinate);
   delay (500);
   Serial.print(" ycoordinate ");
   Serial.print(ycoordinate);
   delay (500);
   Serial.print("  robot direction: ");
   Serial.print(robotDirection);
   delay(500);
   Serial.println ();
   delay(1000);
  
   */
  delay(800);
}

// Turns 90 degrees to the Right
void turnRight () {
  motor1.write (60);
  motor2.write (60);
  delay(178);
  motor2.write(95) ;
  delay(65) ;
  motor1.write(90);
  Serial.println("Right");
  if (robotDirection == 0)
    robotDirection = 1;
  else if (robotDirection == 1)
    robotDirection = 2;
  else if (robotDirection == 2)
    robotDirection = 3;
  else if (robotDirection == 3)
    robotDirection = 0;
  delay (500);
  Serial.print("  xcoordinate " );
  Serial.print(xcoordinate);
  delay (500);
  Serial.print(" ycoordinate ");
  Serial.print(ycoordinate);
  delay (500);
  Serial.print("  robot direction: ");
  Serial.print(robotDirection);
  delay (500);
  Serial.println();

  delay(1000);
}


// Turns 90 degrees to the Left
void turnLeft () {
  motor1.write(120);
  motor2.write(120);
  delay(325);
  motor2.write(95) ;
  delay(65) ;
  motor1.write(90);
  Serial.println("Left");
  if (robotDirection == 0)
    robotDirection = 3;
  else if (robotDirection == 1)
    robotDirection = 0;
  else if (robotDirection == 2)
    robotDirection = 1;
  else if (robotDirection == 3)
    robotDirection = 2;
  delay (500);
  Serial.print("  xcoordinate " );
  Serial.print(xcoordinate);
  delay (500);
  Serial.print(" ycoordinate ");
  Serial.print(ycoordinate);
  delay (500);
  Serial.print("  robot direction: ");
  Serial.print(robotDirection);
  delay(500);
  Serial.println();
  delay(1000);
}


// Turns 180 degrees
void turnAround () {
  //  delay(1000);
  Serial.println("Around");
  if (robotDirection == 0)
    robotDirection = 2;
  else if (robotDirection == 1)
    robotDirection = 3;
  else if (robotDirection == 2)
    robotDirection = 0;
  else if (robotDirection == 3)
    robotDirection = 1;
  delay (500);
  Serial.print("  xcoordinate " );
  Serial.print(xcoordinate);
  delay (500);
  Serial.print(" ycoordinate ");
  Serial.print(ycoordinate);
  delay (500);
  Serial.print("  robot direction: ");
  Serial.print(robotDirection);
  delay(500);
  Serial.println();

  delay(1000);
}


// Gets the number on the Grid of the space right in front of it.
int getFrontNumber() {
  if (robotDirection == 0) {
    return arraything  [ycoordinate - 1][xcoordinate];
  }
  if (robotDirection == 1)  {
    return arraything  [ycoordinate][xcoordinate + 1];
  }
  if (robotDirection == 2) {
    return arraything [ycoordinate + 1][xcoordinate] ;
  }
  if (robotDirection == 3) {
    return arraything  [ycoordinate][xcoordinate - 1];
  }
}


// Gets the number on the Grid of the space to the Right of it.
int getRightNumber() {
  if (robotDirection == 0) {
    return arraything [ycoordinate][xcoordinate + 1] ;

  }
  if (robotDirection == 1)  {
    return arraything  [ycoordinate + 1][xcoordinate];

  }
  if (robotDirection == 2) {
    return arraything  [ycoordinate][xcoordinate - 1];
  }
  if (robotDirection == 3) {
    return arraything  [ycoordinate - 1][xcoordinate];
  }
}


// Gets the number on the Grid of the Space to the Left of it.
int getLeftNumber() {
  if (robotDirection == 0) {
    return arraything [ycoordinate][xcoordinate - 1] ;
  }
  if (robotDirection == 1)  {
    return arraything  [ycoordinate - 1][xcoordinate];
  }
  if (robotDirection == 2) {
    return arraything [ycoordinate][xcoordinate + 1] ;
  }
  if (robotDirection == 3) {
    return arraything  [ycoordinate + 1][xcoordinate];
  }
}



Here is a sample program for the ultrasonic sensors. This program will just avoid anything and everything that gets in the way.
Included in the program is programming for an extra servo simply spinning back and forth on the top of the robot. If you aren’t doing this on your robot, ignore that part of the code, it should have no effect on your program.



//  THIS CODE AVOIDS OBSTACLES
//  IT CAN EITHER ENCOUNTER AN OBSTACLE ON THE RIGHT OR THE LEFT SIDE
//  THEREFORE, WE PROGRAMMED IT TO TURN TO THE LEFT IF IT ENCOUNTERED AN OBSTACLE ON THE RIGHT
//  AND RIGHT IF WE ENCOUNTERED IT ON THE LEFT

//  @author: Pranav


/*
UltraSonic 1
Pin 5 Triggers the Pulse (Yellow lead)
Pin 6 Recieves the Echo  (Orange lead)

UltraSonic 2
Pin 7 Triggers the Pulse (Yellow lead)
Pin 8 Recieves the Echo  (Orange lead)
*/

#include "Servo.h"
Servo motorR;
Servo motorL;
Servo motorS;

// ultrasonic pins
// ultrasonic Right
const int Trig1_pin =  5;  // pin for triggering pulse    INPUT
const int Echo1_pin = 6;   // pin for recieving echo      OUPUT
long duration1;           // how long it takes for the sound to rebound

// ultrasonic Left
const int Trig2_pin = 7;
const int Echo2_pin = 8;
long duration2;

// motor pins
const int MotorLPin = 2;    // Left
const int MotorRPin = 13;    // Right

// spinning ultrasonic motor
const int MotorSpinPin = 3;
int spinCounter = 0;

// sensing or not
boolean isARightWallThere = false;
boolean isALeftWallThere = false;

// which way to turn
boolean Right = true;


void setup() {
  Serial.begin(9600);
  Serial.println ("Starting");
  // ultrasonic 1
  pinMode(Trig1_pin, OUTPUT);        // initialize the pulse pin as output:
  pinMode(Echo1_pin, INPUT);         // initialize the echo_pin pin as an input:
  //ultrasonic 2
  pinMode(7, OUTPUT);        // initialize the pulse pin as output:
  pinMode(Echo2_pin, INPUT);         // initialize the echo_pin pin as an input:
  // motors
  motorR.attach(MotorRPin);
  motorL.attach(MotorLPin);
  motorS.attach(MotorSpinPin);



}


void loop(){
  while (1==1)  {

    if (spinCounter < 2) {
      motorS.write(160);
    }
    else {
      motorS.write(20);
    }
    if (spinCounter >= 3) {
      spinCounter = 0;
    }

    spinCounter ++;

    checkTheRightWall(); 
    checkTheLeftWall();

    if (isARightWallThere == false && isALeftWallThere == false) {
      motorR.write(120);
      motorL.write(72);


    }
    else {

      if (isARightWallThere == true && isALeftWallThere == true){

        motorR.write(0);
        motorL.write(180);
        delay(300);
        motorR.write(80);
        motorL.write(80);
        delay(500);
        motorR.write(0);
        motorL.write(180);

      }

      else {
        if (isARightWallThere == false && isALeftWallThere == true) {

          motorR.write(50);
          motorL.write(90);

        } 
        else {
          if (isARightWallThere == true && isALeftWallThere == false) {

            motorR.write(90);
            motorL.write(140);
          }

        }

      }



    }

  }
}





void checkTheRightWall () {
  digitalWrite(Trig1_pin, LOW);
  delayMicroseconds(2);
  digitalWrite(Trig1_pin, HIGH);
  delayMicroseconds(10);
  digitalWrite(Trig1_pin, LOW);
  duration1 = pulseIn(Echo1_pin,10);
  Serial.println("Duration1:  ");
  Serial.println(duration1, DEC);



  if ((duration1 > 4000 || duration1 == 0)) {
    isARightWallThere = false; 
  }
  else {
    isARightWallThere = true;
  }


}


void checkTheLeftWall() {
  digitalWrite(7, LOW);
  delayMicroseconds(2);
  digitalWrite(7, HIGH);
  delayMicroseconds(10);
  digitalWrite(7, LOW);
  duration2 = pulseIn(Echo2_pin,10);
  Serial.println("Duration2:  ");
  Serial.println(duration2, DEC);


  if ((duration2 > 4000 || duration2 == 0)) {
    isALeftWallThere = false; 
  }
  else {
    isALeftWallThere = true;
  }

}



If you have the time, check out one of my friend's pages. He is the one who did all the programming for us.
Here's the link to his page: https://www.instructables.com/member/praznav/

The end,
Spark Industries,
<p>If this is in the instructable and I missed it, I apologize -- but how is the size in each block of the grid determined? For example, how do I know how big a 10 x 10 grid is in the real world?</p>
<p>&quot;We are using the Arduino Uno programming language. It is based off of Java.&quot;</p><p>You realize this is very clearly C, it even starts with an #include directive.</p>
<p>Yes, you are right. Arduino is C haha.</p><p>I didn't know that at the time that I wrote this though.</p>
<p>I came down looking for this comment, though I prefer java, arduino is C based</p>
<p>Java is also C based.</p>
<p>Please tell which servos are u using in this project?</p>
<p>We are using vex servos.</p><p>I believe we had the servo kit with some parts and gears.</p>
hello there... I would like to make a Two wheeled mapper robot using two servos...but I can see that u have used four wheels...what are the changes that I should make in the codings??
<p>Is there a video of this thing in action ? </p>
How can I instruct my robot to go from one point to another in the map
How can I instruct my robot to go from one point to another in the map
Can I put my home map in it input
How would I implement a gps navigation system so the robot follows way points?
<p>If you have a GPS with a serial output (RS-232, NOT USB), it's possible.. But, as Praznav said, use the algorithm.. You'll be following decimal geodesic coordinates, but even those will be +/- 8 feet at best.. I tried using output from an old ETREX Classic (Plain yellow, no WAAS), on a similar design, but it never really worked too well... There are GPS modules out there, with TTL-Level Serial (Again, RS-232 format, but +5V/0 (TTL) instead of -15/+15 )</p>
<p>You can make a graphical representation of every path the robot can take. I would look up Djikstras algorithm if I were you. I think it can be very helpful. <br>Create a graphical representation of the field and then use djikstras to find the shortest path from one waypoint to the next.<br><a href="http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm" rel="nofollow">http://en.wikipedia.org/wiki/Dijkstra%27s_algorith...</a></p><p>good luck!</p>
<p>Actually i'm using DC motors rather than Servo motors, since my DC motor works at 12V, can u just help me how to run that motors when they got output from Arduino??? </p>
<p>DC are not the best unless using gears, I would recommend servos or geared dc motors,</p>
<p>Highly concur, DC motors require that little extra Direction &amp; speed control, while most servos are all 1-package, only needing Signal/Pwr/GND per motor. The Motor Modules for VEX (seeing this is the platform frame) ran VERY Close to plain RC-Servos, using +5V Pwr, the Arduino Servo.h library (0 (Full Reverse) - 90 (Stop) - 179 (Full Forward)) ran perfect with it. Most RC Servos can also be modified to constant rotation (Other instructables here on this site, I recommend Futaba S3004's for light-drive, but easiest to modify. (remove Potentiometer, and replace with 2X 2.2K resistors in a &quot;W&quot; across the old pot pin holes (put in series, and feeding the outer connections to the outer holes, and the center to the wiper hole.) , Then carefully whittle the stop tab on the main drive gear, off.) (worked replacing two drive motors on a Parallax B.O.E.-Bot that the motors failed.)</p>
<p>If you are going to use a 12V DC motor, you probably need a motor controller for it as well. It is a little bit different from how we did it.</p><p>gluck and ask any questions you have here</p>
<p>Sir please help me out with the mapping process generated by the ultrasonic sensor.</p>
<p>Sir I am going to build same type of robot but i have some doubt regarding connections and motors you have use. Please help me. My mail id is moinaksaha@ymail.com. If possible give me your phone no.</p>
<p>I going to implement a compass for continuous calibration.</p>
<p>hi i want ur number or any other sources to contact u urgently </p>
<p>you can also use it as a security system</p>
<p>Yea definitely! In fact, one of the projects that I worked on later involved using a Kinect sensor to create a security system. However, this was a stationary system and didn't move around like our robot above.</p><p>love the username &lt;3</p>
<p>hi my name is krishna can u help me in making this bot </p>
<p>Hi Krishna,</p><p>What do you need help with?</p><p>Mechanically, this robot is extremely simple. If you are having trouble with the electronics or programming, you might want to start with using a Vex or NXT system which is much simpler to use.</p><p>I was the programmer for our team, but feel free to post any questions you might have; I'll do my best!</p>
<p>hi my name is krishna can u help me in making this bot </p>
<p>you can also use it as a security system</p>
<p>you can also use it as a security system</p>
<p>hey dude..!<br>ur robot seems cool..!</p><p>im on building one myself..</p><p>but it just struck me last night..</p><p>dat..wai is the robot supposed to do if its autonavigation robot ?</p><p>i mean..<br>wat is the main purpose of building a robot which can detect things nd move around without doin ny other things which rbots are meant to do..<br>please help me..<br>give me ny idea..</p><p>please..</p>
<p>You can make an autonavigation robot that also does other things.<br>Or, it can just navigate and transport items from one place to another.</p>
This project looks great. <br>I have a question, where is the mapping displayed? is this project able to produce a 2D image on a computer?
We never actually tried using the ultrasonic sensors to create a 2D map. <br>It was the idea, but we really just ended up inputting an map we created ourselves and having the robot navigate itself through it. <br>We also had the ultrasonic help the robot avoid objects that might not be in the map such as people. <br>Usually, when we ran the robot, it was not connected to a computer or anything. However, I do think its possible to attach an LCD screen and have a map on it update as the robot moves around. <br>If you make a similar project, keep us posted! <br>
just had a couple of question about the 2d array code. do I have to manually input the array grid with 1's and 0's? or does the ultrasonic sensor map it for me?..is it possible to map objects and walls in a room?
sorry for the late response, <br>The idea behind the design is that either works. <br>So, we simply inputted a 2D array ourselves. However, we eventually wanted to use the sensors to have the robot map out the 2D array itself. Its definitely possible, but we had to take the robot apart before we were able to make that part. Then, we never got around to doing it. <br>If you try it, tell me how it goes!
can u help us in clarifying the doubts regarding the code ...mail ur id to this id nikhilsharma3523@gmail.com so that we contact u nd clarify our doubts
praznav can i get ur contact no ..i have some doubts regarding the code , so wanted to clarify it with u ...it would be a lot of help fr us if i can contact u sir
awsome work..im going this try this code. thank you for this instructable!!
Hello, <br> <br>This is a great navigation bot. But how does it map an area (for example a room) without any storage capabilities? Also will this autonavigation bot be able to move around a previously navigated area without the need to map the area again? <br> <br>Thank you.
We used an Arduino which means we could store a 2D array in the program. <br>The 2D array was filled with 1s and 0s. <br>0's were empty spaces and 1's were walls. <br>This created a map for the Arduino to follow. <br>The ideal is to have the robot move around and use the ultrasonic sensors to create a map.

About This Instructable

122,372views

117favorites

License:

More by astarkfuture:Autonomous Autonavigation Robot (Arduino) 
Add instructable to: