Introduction: Arduino Object Avoidance Robot
In this instructable i will describe to you how i built my Object Avoidance Robot. I hope this information will help you to create your own OAR or (maybe) better your own designs.
The materials i used were:
----------------------------------------------------------------------------------------------------------------------------------------------
1 x - Arduino
1 x - Arduino Motor Shield (http://www.adafruit.com/products/81)
male header pins (for breakout's in the motor shield)
female header wires (so i can recycle my parts if i decide to break this project apart)
1 x - Parallax Servo Motor (http://www.radioshack.com/product/index.jsp?productId=12296088)
1 x - Ping))) sensor or HC-SR04 Ultrasonic sensor
1 x - Parallax 5-Position Switch (http://www.radioshack.com/product/index.jsp?productId=12296089)
1 x - RC car with separate back-wheel dc motors
6 x - rechargeable AA batteries (conveniently stored in the RC cars battery housing)
1 x - plastic project box from RadioShack
super glue
double sided tape
and of course
soldering iron
solder
wires
----------------------------------------------------------------------------------------------------------------------------------------------
The materials i used were:
----------------------------------------------------------------------------------------------------------------------------------------------
1 x - Arduino
1 x - Arduino Motor Shield (http://www.adafruit.com/products/81)
male header pins (for breakout's in the motor shield)
female header wires (so i can recycle my parts if i decide to break this project apart)
1 x - Parallax Servo Motor (http://www.radioshack.com/product/index.jsp?productId=12296088)
1 x - Ping))) sensor or HC-SR04 Ultrasonic sensor
1 x - Parallax 5-Position Switch (http://www.radioshack.com/product/index.jsp?productId=12296089)
1 x - RC car with separate back-wheel dc motors
6 x - rechargeable AA batteries (conveniently stored in the RC cars battery housing)
1 x - plastic project box from RadioShack
super glue
double sided tape
and of course
soldering iron
solder
wires
----------------------------------------------------------------------------------------------------------------------------------------------
Step 1: Testing
First section/step is getting all of the parts together and getting them working.
I am not going to write out how to set up the motor shield, the ultrasonic sensor, or the servo. Others have already done so, and did a much nicer job than I could do. So here are a few links I found very useful when unsure of what I was doing.
The Ultrasonic Sensor:
Lets Make Robots
The Motor Shield
Ladyada
At this point I was only concerned with the bare minimum. I wanted to know the ultrasonic sensor was working, the motors in the RC car would spin when i told them to, and the servo would go to the position I set it to go.
I am not going to write out how to set up the motor shield, the ultrasonic sensor, or the servo. Others have already done so, and did a much nicer job than I could do. So here are a few links I found very useful when unsure of what I was doing.
The Ultrasonic Sensor:
Lets Make Robots
The Motor Shield
Ladyada
At this point I was only concerned with the bare minimum. I wanted to know the ultrasonic sensor was working, the motors in the RC car would spin when i told them to, and the servo would go to the position I set it to go.
Step 2: The Build
I started with the entire frame of the RC car, but when a friend told me it looked like a tractor I decided to scrap the front two wheels, and add a scratch plate to keep its balance.
The design was pretty easy for me to decide on since my options were limited. Using the plastic project box from radioshack, I attached the servo to the lid of the box, chucked my Arduino inside, and screwed on some bracket I had laying around to the servo for the ultrasonic sensor. I put a power switch on the side of the box and ran the wires from the battery block of the RC car to the switch and then to the motor shield of my arduino.
The scratch plate is from an old USB postal scale (I'm done selling stuff on ebay anyway), I sanded down the sides of the circled plastic to fit underneath the motors, and with some superglue, its held in place really well.
Soon after it was all put together and running I decided I wanted a parallax 5-position switch. With this I can move the OAR manually and improve on the movement functions.
The design was pretty easy for me to decide on since my options were limited. Using the plastic project box from radioshack, I attached the servo to the lid of the box, chucked my Arduino inside, and screwed on some bracket I had laying around to the servo for the ultrasonic sensor. I put a power switch on the side of the box and ran the wires from the battery block of the RC car to the switch and then to the motor shield of my arduino.
The scratch plate is from an old USB postal scale (I'm done selling stuff on ebay anyway), I sanded down the sides of the circled plastic to fit underneath the motors, and with some superglue, its held in place really well.
Soon after it was all put together and running I decided I wanted a parallax 5-position switch. With this I can move the OAR manually and improve on the movement functions.
Step 3: The Code
I am not big on sharing my code, just because it is personalized for my setup and most likely has no use to you and your unique setup. If you want my code, email me at cgmalantonio@gmail.com and I will gladly send you a copy. I will however describe my work in pseudo-code so you get the idea.
Lets get to it!
First I wanted a function that would use the ultrasonic sensor to get readings while the servo motor turned to 5 different points:
(0 = Left // 45 = Front left // 90 = Front // 135 = Front right // 180 = Right)
Scan{
I used a simple for loop to move the servo in increments of 45, from 0 to 180 (and another to bring it back to 0). Every time it reaches its next point it calls my "LowestNumber" function and adds the value received to an array for the 5 values received (left / left-front / front / right-front / right).
something like this:
for (int i = 0; i < 180; i = i+45){
myservo.write(i);
LowestNumber();
}
for (int i = 180; i > 0; i = i - 45){
myservo.write(i);
LowestNumber();
}
The LowestNumber function takes in 3 readings, spaced 50 milliseconds apart, from the ultrasonic sensor. The 3 readings are then compared against each other, and the lowest value (closest reading) is accepted and is stored into a variable (LowestNumberResult). This number is then stored into an array based on where the servo is positioned. The ultrasonic sensor is a little unpredictable sometimes so I like to check 3 times. And considering I am only worried about it hitting something, I keep the lowest number.
//grab your lowest number
a = ultrasonic.Ranging(INC)
delay(50)
b = ultrasonic.Ranging(INC)
delay(50)
c = ultrasonic.Ranging(INC)
delay(50)
if (a > b)
a = b
if (a > c)
a = c
Once all 5 positions of the servo motor have gathered a distance from the ultrasonic sensor, we then have to handle the positions appropriately.
}
Now we know the distances in front of the OAR's location. We start by finding out which direction is the greatest distance and if some conditions are met, we'll go in that direction.
Handle{
Some of the restrictions were as such:
- are all directions greater than 20 inches
// make sure all paths are clear, can be any number,
// doesn't have to be 20 inches
- if furthest direction is less than the front position + 10 inches (some number), go forward
// favoring the front direction means it wont just turn
// around in circles in the center of your room
// i eventually added a second statement, just like this,
// saying if the front was clear enough, go forward twice
- if furthest direction is Left, make sure left front is clear
-if not clear check right
- if furthest direction is Right, make sure right front is clear
-if not clear check left
- if furthest direction is Left front, make sure left is clear
-if not clear check right
- if furthest direction is Right front, make sure right is clear
-if not clear check left
- if all directions are less than 20 we want to turn the OAR around and try new measurements
}
Extra{
I added some extra features for my 5 position switch.
Power on
Waiting for input
- if you approach the OAR from the front too close, it'll back up and shake its head back and fourth
- if you press a direction, it'll move in that direction
Center click
- starts a query, input 8 directions and it will drive in those directions
Center click again
- drives autonomously and avoids walls/objects
Center click a third time returns menu to start
as well as some head turns of the servo when a direction is picked (as though the OAR is looking where its going to turn)
}
Lets get to it!
First I wanted a function that would use the ultrasonic sensor to get readings while the servo motor turned to 5 different points:
(0 = Left // 45 = Front left // 90 = Front // 135 = Front right // 180 = Right)
Scan{
I used a simple for loop to move the servo in increments of 45, from 0 to 180 (and another to bring it back to 0). Every time it reaches its next point it calls my "LowestNumber" function and adds the value received to an array for the 5 values received (left / left-front / front / right-front / right).
something like this:
for (int i = 0; i < 180; i = i+45){
myservo.write(i);
LowestNumber();
}
for (int i = 180; i > 0; i = i - 45){
myservo.write(i);
LowestNumber();
}
The LowestNumber function takes in 3 readings, spaced 50 milliseconds apart, from the ultrasonic sensor. The 3 readings are then compared against each other, and the lowest value (closest reading) is accepted and is stored into a variable (LowestNumberResult). This number is then stored into an array based on where the servo is positioned. The ultrasonic sensor is a little unpredictable sometimes so I like to check 3 times. And considering I am only worried about it hitting something, I keep the lowest number.
//grab your lowest number
a = ultrasonic.Ranging(INC)
delay(50)
b = ultrasonic.Ranging(INC)
delay(50)
c = ultrasonic.Ranging(INC)
delay(50)
if (a > b)
a = b
if (a > c)
a = c
Once all 5 positions of the servo motor have gathered a distance from the ultrasonic sensor, we then have to handle the positions appropriately.
}
Now we know the distances in front of the OAR's location. We start by finding out which direction is the greatest distance and if some conditions are met, we'll go in that direction.
Handle{
Some of the restrictions were as such:
- are all directions greater than 20 inches
// make sure all paths are clear, can be any number,
// doesn't have to be 20 inches
- if furthest direction is less than the front position + 10 inches (some number), go forward
// favoring the front direction means it wont just turn
// around in circles in the center of your room
// i eventually added a second statement, just like this,
// saying if the front was clear enough, go forward twice
- if furthest direction is Left, make sure left front is clear
-if not clear check right
- if furthest direction is Right, make sure right front is clear
-if not clear check left
- if furthest direction is Left front, make sure left is clear
-if not clear check right
- if furthest direction is Right front, make sure right is clear
-if not clear check left
- if all directions are less than 20 we want to turn the OAR around and try new measurements
}
Extra{
I added some extra features for my 5 position switch.
Power on
Waiting for input
- if you approach the OAR from the front too close, it'll back up and shake its head back and fourth
- if you press a direction, it'll move in that direction
Center click
- starts a query, input 8 directions and it will drive in those directions
Center click again
- drives autonomously and avoids walls/objects
Center click a third time returns menu to start
as well as some head turns of the servo when a direction is picked (as though the OAR is looking where its going to turn)
}
Step 4: Final Project (?)
I seem to have a problem with finishing my projects. I always want to continue updating and bettering my projects as I come up with new ideas or new answers to old problems. However for the sake of this instructable I put together a video of the latest version of my code to show you how my OAR is running. It still has some limitations and bugs to work out but it is a nice collection of successful runs.
Latest Video:
Latest Video: