With the attached breadboard, you can do more electronics experiments, fool around with different sensors, etc. This project can teach you about electronics, programming, and robotics. It is also a fun toy to entertain younger siblings and pets (just be sure they don't break it!).
Here is a video of what MAEP will do when it is done:
Remove these ads by
Signing UpStep 1: Parts
- Arduino compatible microcontroller. I used an Arduino Uno, so I recommend one if you wish to follow closely along with this tutorial. There are also some Arduino based controllers that are designed specifically for robotics that may be helpful, but you’ll have to find your own method of mounting those. You can buy a copy of the Uno from YourDuino which I believe is completely compatible: http://arduino-direct.com/sunshop/index.php?l=product_detail&p=5
- Breadboard. Make sure it’s not too big, or else it won’t fit. However, we want it to be as big as possible so we have more room for electronics. This is good: http://arduino-direct.com/sunshop/index.php?l=product_detail&p=168
- A standard old 9 volt alkaline battery (which you can probably find at home), as well as a barrel jack connector to hook it up to your Uno easily (not required, but again, easier): http://arduino-direct.com/sunshop/index.php?l=product_detail&p=119
- A power supply for the motors. I don’t believe the power supply I chose is the cheapest or best option, so I’m not going to recommend it to you. I used a 4.8 volt rechargeable NiCad battery, but it’s probably easier to just use a 4 AA battery holder (no need to buy a charger that way)
- A bunch of Boe-Bot hardware for the chassis. Unfortunately, you can’t get this from YourDuino, so look at Parallax, the manufacturer’s website. You can choose either to buy this: http://www.parallax.com/StoreSearchResults/tabid/768/List/0/SortField/4/ProductID/304/Default.aspx?txtSearch=boe+bot+chassis which comes with tons of extra components you don’t need (although may be useful someday), or you can buy all the components in the following list from Parallax and no, I’m not gonna provide a link for each one:
Stock # Quantity Product Name
700-00002 8 Panhead screw, 4/40, 3/8
700-00003 8 4/40 x 3/8" Nut
700-00009 1 Tail Wheel Ball
700-00015 2 #4 Nylon Washer
700-00022 1 Boe-Bot Aluminum Chassis
700-00023 1 Cotter Pin-1/16" Diameter
700-00025 1 Rubber Grommet-13/32" Hole Diameter
700-00028 4 Panhead screw, 4/40, 1/4
700-00060 2 Standoff, threaded aluminum, round 4-40
721-00001 2 Wheel, Plastic, 2.58 Dia, .3 W
721-00002 2 Rubber Band Tire for 721-00001
900-00008 2 Continuous Rotation Servo
- Wire to hook things up will be necessary. Some male-to-male jumpers will do the trick: http://arduino-direct.com/sunshop/index.php?l=product_detail&p=94
- Finally, the PING))) sensor and mounting bracket, so that your robot doesn't kill itself: http://www.parallax.com/StoreSearchResults/tabid/768/List/0/SortField/4/ProductID/563/Default.aspx?txtSearch=ping+sensor+mount
As for tools, all you need is a phillips head screwdriver, a computer, and one of those standard USB printer cables. The Arduino Uno I provided a link for has a cable included.
Now lets get building!












































Visit Our Store »
Go Pro Today »




/*MAEP 2.0 Navigation
by Noah Moroze, aka GeneralGeek
This code has been released under a Attribution-NonCommercial-ShareAlike license, more info at http://creativecommons.org/licenses/
PING))) code by David A. Mellis and Tom Igoe http://www.arduino.cc/en/Tutorial/Ping
*/
#include <Servo.h> //include Servo library
const int RForward = 0;
const int RBackward = 180;
const int LForward = RBackward;
const int LBackward = RForward;
const int RNeutral = 90;
const int LNeutral = 90; //constants for motor speed
const int pingPin = 7;
const int irPin = 0; //Sharp infrared sensor pin
const int dangerThresh = 10; //threshold for obstacles (in cm)
int leftDistance, rightDistance; //distances on either side
Servo panMotor;
Servo leftMotor;
Servo rightMotor; //declare motors
long duration; //time it takes to recieve PING))) signal
void setup()
{
rightMotor.attach(11);
leftMotor.attach(10);
panMotor.attach(6); //attach motors to proper pins
panMotor.write(90); //set PING))) pan to center
}
void loop()
{
int distanceFwd = ping();
if (distanceFwd>dangerThresh) //if path is clear
{
leftMotor.write(LForward);
rightMotor.write(RForward); //move forward
}
else //if path is blocked
{
leftMotor.write(LNeutral);
rightMotor.write(RNeutral);
panMotor.write(0);
delay(500);
rightDistance = ping(); //scan to the right
delay(500);
panMotor.write(180);
delay(700);
leftDistance = ping(); //scan to the left
delay(500);
panMotor.write(90); //return to center
delay(100);
compareDistance();
}
}
void compareDistance()
{
if (leftDistance>rightDistance) //if left is less obstructed
{
leftMotor.write(LBackward);
rightMotor.write(RForward); //turn left
delay(500);
}
else if (rightDistance>leftDistance) //if right is less obstructed
{
leftMotor.write(LForward);
rightMotor.write(RBackward); //turn right
delay(500);
}
else //if they are equally obstructed
{
leftMotor.write(LForward);
rightMotor.write(RBackward); //turn 180 degrees
delay(1000);
}
}
long ping()
{
// Send out PING))) signal pulse
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);
//Get duration it takes to receive echo
pinMode(pingPin, INPUT);
duration = pulseIn(pingPin, HIGH);
//Convert duration into distance
return duration / 29 / 2;
}
Thanks for the great instructable
So am using the link you sent me and making communication between 2 arduinos bt so far no luck :( so i thought of connecting cliff detection to the same Arduino with the Obstacle detection as a back up plan, but for this can u send me the code you used ??
thanks a lot for your help, I really appreciate
/*MAEP 2.0 Navigation
by Noah Moroze, aka GeneralGeek
This code has been released under a Attribution-NonCommercial-ShareAlike license, more info at http://creativecommons.org/licenses/
PING))) code by David A. Mellis and Tom Igoe http://www.arduino.cc/en/Tutorial/Ping
*/
#include //include Servo library
const int RForward = 0;
const int RBackward = 180;
const int LForward = RBackward;
const int LBackward = RForward;
const int RNeutral = 90;
const int LNeutral = 90; //constants for motor speed
const int pingPin = 7;
const int irPin = 0; //Sharp infrared sensor pin
const int dangerThresh = 10; //threshold for obstacles (in cm)
const int minCliff = 350;
const int maxCliff = 470; //thresholds for cliff detection
const int scanPosition[] = {45, 67.5, 90, 112.5, 135};
int cliffVal; //values from analog sensor
int leftDistance, rightDistance; //distances on either side
Servo panMotor;
Servo leftMotor;
Servo rightMotor; //declare motors
long duration; //time it takes to recieve PING))) signal
void setup()
{
rightMotor.attach(11);
leftMotor.attach(10);
panMotor.attach(6); //attach motors to proper pins
panMotor.write(90); //set PING))) pan to center
}
void loop()
{
for(int i=0; i==4; i++)
{
panMotor.write(scanPosition[i]);
delay(1000);
int cliffVal = analogRead(irPin);
if (cliffValmaxCliff)
{
leftMotor.write(LBackward);
rightMotor.write(RBackward);
delay(500);
compareDistance();
}
int distanceFwd = ping();
if (distanceFwd>dangerThresh) //if path is clear
{
leftMotor.write(LForward);
rightMotor.write(RForward);
}
else //if path is blocked
{
compareDistance();
}
}
}
void compareDistance()
{
leftMotor.write(LNeutral);
rightMotor.write(RNeutral);
panMotor.write(0);
delay(500);
rightDistance = ping(); //scan to the right
delay(500);
panMotor.write(180);
delay(700);
leftDistance = ping(); //scan to the left
delay(500);
panMotor.write(90); //return to center
delay(100);
if (leftDistance>rightDistance) //if left is less obstructed
{
leftMotor.write(LBackward);
rightMotor.write(RForward); //turn left
delay(500);
}
else if (rightDistance>leftDistance) //if right is less obstructed
{
leftMotor.write(LForward);
rightMotor.write(RBackward); //turn right
delay(500);
}
else //if they are equally obstructed
{
leftMotor.write(LForward);
rightMotor.write(RBackward); //turn 180 degrees
delay(1000);
}
}
long ping()
{
// Send out PING))) signal pulse
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);
//Get duration it takes to receive echo
pinMode(pingPin, INPUT);
duration = pulseIn(pingPin, HIGH);
//Convert duration into distance
return duration / 29 / 2;
}
I want to thank you so much cs my obstacle detection now works perfectly, so now i will have to add RFID detection and cliff detection for the same robot for it so my project gets completed, however, i found out that i need to add Attiny chip and then use serial ports and send information to my main arduino uno which will be responsible only for the motors directions, but i was thinking if you can help me with this i tried to write some codes and add things together bt so far i have no luck, as i heard in the video u had an extra Infrared sensor for cliff detection, So can you please help me with this ? can u send me the link code or post info abt the obstacle and cliff detection on same robot ?? Or any website that can help me with the serial communication btw Attiny85 and arduino uno ?? Thanx a lot i really appreciate and hope u can help me with that :)
Could you help me with the problem I'm having with my robot PLEASE.
Basically I've used the code you have posted, but it didnt work so I made bit change but still it didnt work, the problem is my the servo with ultrasonic sensor on it keep on spinning left and right constantly even tho there is no obstacle in front.
And also the robot goes few steps forward and again spins the servo with the ultrasonic sensor.
By the way i'm using ultrasonic sensor with 4 pins (HC-SR04)
I would really appreciate, if u could correct it
Cheers
/*MAEP 2.0 Navigation
by Noah Moroze, aka GeneralGeek
This code has been released under a Attribution-NonCommercial-ShareAlike license, more info at http://creativecommons.org/licenses/
PING))) code by David A. Mellis and Tom Igoe http://www.arduino.cc/en/Tutorial/Ping
*/
#include //include Servo library
const int RForward = 0;
const int RBackward = 180;
const int LForward = 0;
const int LBackward = 180;
const int RNeutral = 90;
const int LNeutral = 90; //constants for motor speed
const int trigpin = 7;
const int echopin = 3;
const int dangerThresh = 10; //threshold for obstacles (in cm)
int leftDistance, rightDistance; //distances on either side
Servo panMotor;
Servo leftMotor;
Servo rightMotor; //declare motors
long duration; //time it takes to recieve PING))) signal
void setup()
{
rightMotor.attach(11);
leftMotor.attach(10);
panMotor.attach(6); //attach motors to proper pins
panMotor.write(90); //set PING))) pan to center
}
void loop()
{
int distanceFwd = ping();
if (distanceFwd>dangerThresh) //if path is clear
{
leftMotor.write(LForward);
rightMotor.write(RForward); //move forward
}
else //if path is blocked
{
leftMotor.write(LNeutral);
rightMotor.write(RNeutral);
panMotor.write(0);
delay(500);
rightDistance = ping(); //scan to the right
delay(500);
panMotor.write(180);
delay(700);
leftDistance = ping(); //scan to the left
delay(500);
panMotor.write(90); //return to center
delay(100);
compareDistance();
}
}
void compareDistance()
{
if (leftDistance>rightDistance) //if left is less obstructed
{
leftMotor.write(LBackward);
rightMotor.write(RForward); //turn left
delay(500);
}
else if (rightDistance>leftDistance) //if right is less obstructed
{
leftMotor.write(LForward);
rightMotor.write(RBackward); //turn right
delay(500);
}
else //if they are equally obstructed
{
leftMotor.write(LForward);
rightMotor.write(RBackward); //turn 180 degrees
delay(1000);
}
}
long ping()
{
// Send out PING))) signal pulse
pinMode(trigpin, OUTPUT);
pinMode(echopin,INPUT);
digitalWrite(trigpin, LOW);
delayMicroseconds(2);
digitalWrite(trigpin, HIGH);
delayMicroseconds(10);
digitalWrite(trigpin, LOW);
//Get duration it takes to receive echo
duration = pulseIn(echopin, HIGH);
//Convert duration into distance
return duration / 29 / 2;
}
Just got a quick question, I am not entirely sure about the 5v power rail you mentioned.
So i got the 3 servo motors and the ping sensor that all need 5v.
should i be connecting them all to the battery 5v rail or the arduino 5v rail that you said to connect to the breadboard?
Thanks again !
Wire up the 3 servo motors to power from the separate battery. Motors use up a lot of current, more than the regulator on the Arduino provides, and they can't be powered directly from the 9V battery because 9 volts is too much for them. That's why you have to hook them up to the other battery.
As for the sensor, hook that up to 5V power from the Arduino. It needs the same steady voltage the Arduino is getting in order to give accurate results.
Hope I helped. If things are still unclear, feel free to ask and I'll do my best to fix whatever comes up.
What happens however is that it rotates in a circle with the right motor moving forward and the left moving backward.
when i put my hand in front of the sensor it moves backwards untill all is clear and then continues to move in rotation, also the sensor servo does not operate at all.
I made sure i got all the wires in the right place and also tried swapping the motor wires around but just got more odd movements
here is the code i am using:
/*MAEP 2.0 Navigation
by Noah Moroze, aka GeneralGeek
This code has been released under a Attribution-NonCommercial-ShareAlike license, more info at http://creativecommons.org/licenses/
PING))) code by David A. Mellis and Tom Igoe http://www.arduino.cc/en/Tutorial/Ping
*/
#include //include Servo library
#include
Ultrasonic ultrasonic ( 4, 5);
const int RForward = 0;
const int RBackward = 180;
const int LForward = RBackward;
const int LBackward = RForward;
const int RNeutral = 90;
const int LNeutral = 90; //constants for motor speed
const int irPin = 0; //Sharp infrared sensor pin
const int dangerThresh = 4; //threshold for obstacles (in inches)
int leftDistance, rightDistance; //distances on either side
Servo panMotor;
Servo leftMotor;
Servo rightMotor; //declare motors
void setup()
{
rightMotor.attach(11);
leftMotor.attach(10);
panMotor.attach(6); //attach motors to proper pins
panMotor.write(90); //set PING))) pan to center
leftMotor.write(90);
rightMotor.write(90);
}
void loop()
{
int distanceFwd = ultrasonic.Ranging(INC);
if (distanceFwd>dangerThresh) //if path is clear
{
leftMotor.write(LForward);
rightMotor.write(RForward); //move forward
}
else //if path is blocked
{
leftMotor.write(LNeutral);
rightMotor.write(RNeutral);
panMotor.write(0);
delay(500);
rightDistance = ultrasonic.Ranging(INC); //scan to the right
delay(500);
panMotor.write(180);
delay(700);
leftDistance = ultrasonic.Ranging(INC); //scan to the left
delay(500);
panMotor.write(90); //return to center
delay(100);
compareDistance();
}
}
void compareDistance()
{
if (leftDistance>rightDistance) //if left is less obstructed
{
leftMotor.write(LBackward);
rightMotor.write(RForward); //turn left
delay(500);
}
else if (rightDistance>leftDistance) //if right is less obstructed
{
leftMotor.write(LForward);
rightMotor.write(RBackward); //turn right
delay(500);
}
else //if they are equally obstructed
{
leftMotor.write(LForward);
rightMotor.write(RBackward); //turn 180 degrees
delay(1000);
}
}
const int LForward = RBackward;
const int LBackward = RForward;
To this:
const int LForward = 0;
const int LBackward = 180;
As for your sensor servo, I'm not sure what the problem is. Are you certain this servo works? Try using code from this tutorial to test it - http://arduino.cc/it/Tutorial/Sweep
I was reading up the reason for the odd behavior from all 3 servos and it turns out it was because the servos need to share the ground from both arduino and the battery, i must of missed that part on your tutorial, i just took a lead from from the arduino gnd and connected it to the breadbord gnd rail that you said to link from both sides.
now it responds perfectly! :)
I have now tested out the whole code as i was breaking it down to see how it responded.
everything seems fine except the panmotor still moves all the way to the right at the very start before it even detects an object.
i will do some more tests tomorrow to find out the problem.
i will order a new servo but in the mean time i have simplified the code for a fixed sensor so it simply turns left on detection of obstacles, i have also added a piezo and led to the code, i will make a video to show you my robot :)
it is very simple compared to your robot but for my first robot i am very proud :D
i also had to increase the speed of the right servo as it seems to turn left, i must of designed the balance of the chassis badly.
i also find that when it is heading towards obstacles at an angle it does not pick up on the obstacle and completely gets stuck, but i do have a spare sensor, perhaps i can use 2 on the robot to help this.
well theres plenty of ideas to upgrade my robot :)
I will make the video of my robot very soon, thankyou so much for all your help, you've been amazing and so very helpful :)
I hope you continue with this hobby, it's very fun and I'm incredibly happy to have helped you enter the world of robotics. I recommend you check out letsmakerobots.com, they have a great community of robot builders that give great advice and feedback, and also there are lots of robots there to get inspiration from.
Thankyou so much for all your encouragement and it is because of you i have built my first robot.
I built up a random code from the link you sent me, it works great!
And to add to that i combined the code with something else i found which solves a problem my robot had,
from my last post, simply when the robot came in at an obstacle from an angle it would not detect it and then try and turn too late and it must move forward to make a turn, but when it gets too close to an obstacle it moves backwards then turns.
I have tested the random turning which i really like but i noticed a problem i had not thought of before,
lets say it comes to a corner, and chooses to turn left, it will then immediately meet the other wall and by chance the random code makes it turn right it hit the previous wall again, i have watched it do this quite a few times, but its still quite fun to watch it like this as you said because you never know which turn it will take making things interesting, it always gets it's self out of areas sooner or later anyway hahah
I have bought a new servo for the sensor which should arrive shortly.
Video coming soon! :)
Thanks again!
here is my code if you are interested in seeing it at the moment:
#include //include Servo library
#include
Ultrasonic ultrasonic ( 4, 5);
const int numOfReadings = 1; // number of readings to take/ items in the array
int readings[numOfReadings]; // stores the distance readings in an array
int arrayIndex = 0; // arrayIndex of the current item in the array
int total = 0; // stores the cumlative total
int averageDistance = 0; // stores the average value
int echoPin = 5; // SRF05 echo pin (digital 2)
int initPin = 4; // SRF05 trigger pin (digital 3)
unsigned long pulseTime = 0; // stores the pulse in Micro Seconds
unsigned long distance = 0; // variable for storing the distance (cm
int pinSpeaker = 13;
const int RForward = 0;
const int RBackward = 180;
const int LForward = RBackward;
const int LBackward = RForward;
const int RNeutral = 90;
const int LNeutral = 90; //constants for motor speed
int leftDistance, rightDistance; //distances on either side
Servo leftMotor;
Servo rightMotor; //declare motors
int randNumberSpeed; // variable to store the random speed value
int randNumberDir; // variable to store the random direction value
int x = randNumberDir;
void setup()
{
Serial.begin(9600);
rightMotor.attach(11);
leftMotor.attach(8);
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(pinSpeaker, OUTPUT);
pinMode(4, OUTPUT); // trig init
pinMode(5, INPUT); //echo
// create array loop to iterate over every item in the array
for (int thisReading = 0; thisReading < numOfReadings; thisReading++) {
readings[thisReading] = 0;
randomSeed(millis());
}
}
void loop() {
digitalWrite(initPin, HIGH); // send 10 microsecond pulse
delayMicroseconds(10); // wait 10 microseconds before turning off
digitalWrite(initPin, LOW); // stop sending the pulse
pulseTime = pulseIn(echoPin, HIGH); // Look for a return pulse, it should be high as the pulse goes low-high-low
distance = pulseTime/58; // Distance = pulse time / 58 to convert to cm.
total= total - readings[arrayIndex]; // subtract the last distance
readings[arrayIndex] = distance; // add distance reading to array
total= total + readings[arrayIndex]; // add the reading to the total
arrayIndex = arrayIndex + 1; // go to the next item in the array
// At the end of the array (10 items) then start again
if (arrayIndex >= numOfReadings) {
arrayIndex = 0;
}
averageDistance = total / numOfReadings; // calculate the average distance
delay(10);
// Check the average distance and move accordingly
if (averageDistance <= 10) {
// go backwards
leftMotor.writeMicroseconds(1000);
rightMotor.writeMicroseconds(2000);
digitalWrite(2, HIGH);
digitalWrite(3, LOW);
{
playTone(750, 500);
delay(350);
}
}
if (averageDistance <= 25 && averageDistance > 10 ) {
//turn left
randomSeed(millis());
randNumberDir = random(300); {
if (randNumberDir > 150){
rightMotor.writeMicroseconds(1000);
leftMotor.writeMicroseconds(1500);
digitalWrite(2, LOW);
digitalWrite(3, HIGH);
{
playTone(750, 300);
delay(750);
}
}
else if (randNumberDir < 150){
rightMotor.writeMicroseconds(1500);
leftMotor.writeMicroseconds(2000);
digitalWrite(2, LOW);
digitalWrite(3, HIGH);
{
playTone(750, 400);
delay(750);
}
}
}
}
if (averageDistance > 25) {
// go forward
digitalWrite(2, LOW);
digitalWrite(3, LOW);
delay(1000);
leftMotor.writeMicroseconds(2000);
rightMotor.writeMicroseconds(1100);
}
}
// duration in mSecs, frequency in hertz
void playTone(long duration, int freq) {
duration *= 1000;
int period = (1.0 / freq) * 1000000;
long elapsed_time = 0;
while (elapsed_time < duration) {
digitalWrite(pinSpeaker,HIGH);
delayMicroseconds(period / 2);
digitalWrite(pinSpeaker, LOW);
delayMicroseconds(period / 2);
elapsed_time += (period);
}
}
It simply continues to move in rotation, it seems to be the left motor that is going the wrong way no matter where ever i set it to 0, 180 or 90
And of course it does not stop but rather instead moves backwards when there is an obstacle.
I also tried that code for the sensor servo, it moves it all the way to the right but then nothing else happens, same for the robot code, nothing moves it to the left again.
Its ok if you cant figure this one out, you've been an amazing help with all my questions, i will continue to try and work on it.
Thanks again.
am using S35/STD motors
do u think i should change them, Also, i guess sensors work when motors stop and when motors stop my sensor works, cs it takes a long time to detect an object, how can i change fix this issue?? Or do u think its just motors problem?? I also tried to program my robot to move forward and when it detects sth to stop and then move forward bt it just move forward without detecting anything?? do u have any idea why is this happening ?? Is there a way that u can help me with these inquiries ?? I really need help am working on a big project and these are the first steps of it :(
hope u can help me