Friday, December 14, 2012

Basic roaming bot w/t ultrasonic object avoidance

Hope you enjoy this tutorial, if interested please check out my latest project/website. It's an attempt at creating an artificial neural network for predicting stock directions. As always, any feedback is appreciated  www.mspann.com

Now back to the robot...

This simple roaming bot uses an ultrasound sensor to avoid objects in its path...Once assembly is complete, the bot's performance is only limited by your creativity when programming the sketch.  I will include a simple sketch program which gets the bot moving and pings the sonar sensor to determine if objects are in it's path.


Parts List

  • Arduino Uno U3 - Ordered this through Amazon.com for about $20.00
  • Arduino Motor Shield L293D -  Also on Amazon.com about $16.00
  • Ultrasonic Sensor HC-SR04 - Amazon.com about $4.00          
  • RC Car (used for motors battery pack)- Picked up a  cheap $10.00 car at my local Duane Reade, and it came with 2 DC motors...hard to beat that deal.                                 
  • 9 V battery connector (to power Arduino board when not plugged into usb) - Radio Shack.
  • Soldering Iron 
  • Mini Tools (screw driver, wire cutter, etc.) - These are needed to unscrew RC car parts 
  • Jumper cables

Open up the RC car

Now that we have all the parts we will need, lets begin by taking the RC car apart to see what we're working with.  RC car parts will vary but most low end ones will have either 2 DC motors or 1 DC and one Servo motor. The 2 DC motor setup would mean one motor powers the left wheel and one powers the right wheel so you can have the car go forward, back and turns are handled by having one motor forward while the other goes back.   The 1 DC and 1 servo motor setup would work by having 2 tires connected to the DC motor this would control forward and back. The servo motor would then be connected to the steering wheels turning them left or right.  

This RC car has 2 DC motors, each connected to one rear wheel.

If you look at the 3rd picture the wires leading from the DC motors of the rear wheels are red and black for the top wheel and white and yellow for the bottom wheel.

Those two shiny metal strips with a screw holding them in place, are the power connected to the battery pack which is directly underneath the metal strips and next to the motors.  This top is negative and the bottom is positive...this car uses 4 AA batteries at 1.5 v each that's a total of 6 v.  That means we will not have enough power for 2 motors and the Arduino board, we will need a secondary power source to supply the Arduino. This will come from your USB cable when plugged into the computer for programming and from the 9 v battery when the bot is disconnected from the USB and out roaming.

We don't need the RC cars controll board, so lets go ahead and clip all the wires connecting to it.

You see that red wire leading into that piece in the middle, that's the on off switch for the RC car. We will use this switch later.


Arduino and Motor Shield

We are almost ready for testing, first you will need to attach the Motor Shield L293D to the Arduino Uno board.  Align the pins and piggyback the Motor Shield to the top of the Arduino.



+=

Testing the Motors

The Arduino and Motor shield are ready for testing.
Connect one of the DC Motor's to the M1 screw pins on the Motor Shield.


In this picture it's the red and black wires going into the top right 2 screw pins...The top of the board has 5 screw pins, use the top 2 on the right for M1 the top 2 on the left are for M2 (yellow white wires) we will use that later.

Download and install the Motor Shield's library library download
Rename the folder to AFMotor place it along with all sub folders and files in your
My Documents/Arduino /libraries folder.
The Arduino IDE will need to started before the library is recognized, if the IDE is already open, simply quit and re-open.

Use the following code to run your test. This will run the motor forward 1 second, back 1 second and stop 1 second...Then the it will repeat (infinitely).

Sketch code - motor test


#include <AFMotor.h>
AF_DCMotor motor(1, MOTOR12_64KHZ); // create motor #1, 64KHz pwm
void setup() 
{
motor.setSpeed(200); // set the speed to 200/255
}
void loop() 
{
motor.run(FORWARD); // turn it on going forward
delay(1000);

motor.run(BACKWARD); // the other way
delay(1000);

motor.run(RELEASE); // stopped
delay(1000);
}

Once you created your sketch using the code above, connect the Arduino to the PC using the USB cable and upload your sketch.  The code above will begin executing and the motors should begin to run forward, back, stop...repeat.


Test the Sensor

Now we, want to test the ultrasonic sensor.
You will need to solder 4 jumper cables to the sensor's pins.














Connect the Sensor's wires to the Arduino Motor shield.

The 2 red wires go to the shield's 5V and GND pins.The white(echo) and green (trig) connect to the shield's 2 and 3 pins.

Don't worry about the cardboard box for the sensor, I just added that because it will be part of the finished bot, but you don't need it at this testing stage.

After the sensor is connected, we are ready to test.




Use the code below to test the ultrasonic range finder.

Sketch code - ultrasonic test


#define trigPin 3
#define echoPin 2

void setup() 
{
  Serial.begin (9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
}

int CheckDistance()
{
  long duration, distance;
  digitalWrite(trigPin, LOW);  // Added this line
  delayMicroseconds(2); // Added this line

  digitalWrite(trigPin, HIGH);
//  delayMicroseconds(1000); - Removed this line
  delayMicroseconds(10); // Added this line
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration/2) / 29.1;
  
  return distance;
}

void loop() 
{
   int testDistance = CheckDistance(); /// get object distance using ping
   
   /// if object is more than 50 cm away it is out of range
    if (testDistance >= 50 || testDistance <= 0) /// if object is more than 50 cm away it is out of range
    {
    Serial.println("Out of range");
    }
    else /// object is closer than 50cm, prit distance
    {
    Serial.print(testDistance);
    Serial.println(" cm");
    }
   
  delay(500); ///wait half a sec before next ping
}

Connect the Arduino to the PC using your USB cable and upload the above sketch.  To see the ping distance results go to Tools, Serial Monitor in the IDE while the sketch is running, here the ping distance values will be printed.


Assemble the bot

Lets connect all the motors and sensor to the Arduino so we can test the entire bot. Some of these wire connections may need soldering, to keep them fastened securely to the motor shield.

  • Connect the 2 DC motors to M1 and M3 on the Motor shield. The white and yellow wires did not reach up to the M3 pins so I extended them with some red wire...don't forget to cover the connection point of the 2 wires with electrical tape.

  • Connect the power from the RC car's positive battery (it's the black wire on the RC car's bottom metal strip) to the motor shield's PWR pin screw.  If you don't know which battery metal strip is positive, open up the battery case and check which side of the AA battery touches that piece of the metal strip where the wire connects.
  • Connect the ground (black wire) from the RC car's on/off switch to the GND pin screw on the motor shield.
  • Connect the ultrasound sensor's wires to the motor shield.  The 2 red wires go to the shield's 5V and GND pins.The white(echo) and green (trig, looks blue in the pic but it's green) connect to the shield's 2 and 3 pins.




  • Connect the external 9v battery power to the Arduino board.  This is so we will no longer need the USB to power the Arduino.

 


  • Finally, upload your sketch and run one last test.

Sketch code - roaming bot test


This sketch will have the robot ping to find if there is an object within range.  If no objects are within range it will continue forward a small distance then ping again.  If an object is found it will perform a sequence of commands to try and avoid the object (move back, turn, etc.).  Then the whole process repeats in an infinite a loop.

#include <AFMotor.h>
#define trigPin 3
#define echoPin 2
AF_DCMotor motor1(1, MOTOR12_8KHZ); // create motor #1, 8KHz pwm
AF_DCMotor motor3(3, MOTOR34_8KHZ); // create motor #3, 8KHz pwm

void setup() {
  Serial.begin (9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  motor1.setSpeed(255); // set the speed to 200/255
  motor3.setSpeed(255); // set the speed to 200/255
}

int CheckDistance()
{
  long duration, distance;
  digitalWrite(trigPin, LOW);  // Added this line
  delayMicroseconds(2); // Added this line

  digitalWrite(trigPin, HIGH);
//  delayMicroseconds(1000); - Removed this line
  delayMicroseconds(10); // Added this line
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration/2) / 29.1;
  
  return distance;
}

void MotorForward(int delaytime)
{
  motor1.run(FORWARD);
  motor3.run(FORWARD);
  delay(delaytime);
}
void MotorBackward(int delaytime)
{
  motor1.run(BACKWARD);
  motor3.run(BACKWARD);
  delay(delaytime);
}
void MotorRelease()
{
  motor1.run(RELEASE);
  motor3.run(RELEASE);
  delay(1000);
}

void MotorLeft()
{
  motor1.run(FORWARD);
  motor3.run(BACKWARD);
  delay(600);
}

void MotorRight()
{
  motor1.run(BACKWARD);
  motor3.run(FORWARD);
  delay(500);
}

void loop() 
{
  int testDistance = CheckDistance();
  
   Serial.print(testDistance);
   Serial.println(" test");
   
  if (testDistance >= 30 || testDistance <= 0){
    Serial.println("Out of range");
    //go forward and check range again
    MotorForward(700);
    MotorRelease();
  }
  else 
  {
    Serial.print(testDistance);
    Serial.println(" cm");
    //object in path, reverse and turn to avoid
    MotorBackward(600);
    MotorRelease();
    MotorRight();
    MotorRelease();
    MotorForward(600);
    MotorRelease();
    MotorLeft();
    MotorRelease();
    
  }
   
  delay(500);
}

*** Pro tips 
  • I settled on the sketch code above after a lot of trial and error.  My previous sketches would work fine in testing but not once the completed bot was set free. My main problems were, I had the DC motors running at the same time I was trying to ping, this caused interference in the circuitry and resulted in bogus ping readings, which in turn resulted in the robot malfunctioning...The above sketch resolves this issue by making sure all motors are off (released) when the ping occurs.
  • The frequency of the DC motors declared in your sketch may be different from the one I used here, basically your options would be either: MOTOR12_64KHZ, KHZMOTOR12_8KHZ or MOTOR12_1KHZ  Test a few of these out to see which freq your motors respond best to. I believe the default would be 1khz.
  • When I dismantled the RC car, some of the joints supporting the RC car's battery contacts loosened.  I noticed this during testing when I squeezed my hand against the car's battery door, the motor speed would increase.  I tightened these connections and this resolved the power leak issue.

Now with our final systems testing completed, we can attach the outer shell to the bot for aesthetics and let it run around.



Robot Shell

With our testing complete, it's time to think about the robot's appearance.  Feel free to get really creative with this part.  I decided to use what I had laying around, some cardboard I scrapped from a box one of the Arduino boards were shipped in. One of the cardboard pieces had this 'V3' printed on it, so I thought it would look cool to have that on the front of the bot.




I cut out some pieces and came up with the rough design of what the bot will look like. I loosely placed the shell parts on the robot to see how they fit, there is a bit of trial and error here so don't worry if it doesn't look good right away.

Once satisfied with the shell, go ahead and attach it to the bot.  I mostly used scotch tape and twist ties to attach the cardboard pieces to the frame of the old RC car.  Since I didn't attach a switch for the 9v battery, I cut out a hole in the back for the battery  to be able to disconnect the 9v battery wires whenever it wasn't being used.

 


It's Alive!

Now that everything was tested and assembled, it's time to let this little bot roam free and see what it does...enjoy!



As you can see from the video, the sketch definitely needs more tweaking...but the basics are there...It went forward, detected an object then reversed and tried to turn (probably should increase the turning time). Hope you enjoyed this tutorial and please feel free to post any questions or comments below.