Tasked to build a robot, using a Mega 2560 Arduino board, that turned in response to obstacles presented to it. I came up with the specimen in the gifs below. A total of about 6 hours was spent wiring, coding, and debugging.
In this gif, the the robot executes a left turn when presented with an object in front of it.
Right Turn
In this gif, the robot executes a right turn when presented with an object to its front and left.
Turning Around
In this gif, the robot executes a backwards movement and a 180 degree turn when presented with an object to its front, left, and right.
Wiring:
In this photo we can observe the physical connections to the Arduino Mega 2560. The servos, left and right, go into PWM ports 9 and 10, respectively. The servo that turns the Parallax Ping Sensor is in PWM port 7 while the actual Parallax Ping Sensor is in PWM port 6.
In this photo the Servo's mounting is displayed. Two arms protrude from the Boebot allowing for its mounting and proper clearance for the Parallax Ping Sensor.
Code:
/* In this program the robot will demonstrate obstacle avoidance using an ultrasonic sensor.
This robot will continue along a path until an object is spotted, stop, turn the sensor
left, if the path is clear it will turn the robot left and continue, if not it will then
turn the sensor to the right, check to see if it is clear and continue, and, finally, if no
clear path is read it will turn around and go forward.
Program written by Korbin Barker on 9/16/2013
Robotic Platform: Boebot
Microcontroller: Arduino MEGA 2560
Servos: 2 Parallax Continuous Rotation Servos
1 Parallax Standard Servo
Sensors: 1 Parallax Ping Sensor
1 Vex Bumper Switch4 Parallax QTI Line Follower Sensors (disabled for this build)
*/
#include <SoftwareSerial.h>
#include <Servo.h>
/* initializes the servos */
Servo rightServo;
Servo leftServo;
Servo sweepServo;
/* initializes all necessary data values and inputs for the ultrasonic sensing */
const int pingPort = 6;
long pongValue = 0;
int distance = 0;
const int leftPos = 180;
const int middlePos = 90;
const int rightPos = 0;
/* initializes all necessary data values and inputs for movement */
const int pos = 180; //sets a turn value
const int stopPos = 90;
const int time = 600;
/* Ping Sensor movement for sensing */
void sweepLeft() //looks for a leftward barrier, senses to see if path is blocked
{
sweepServo.write(leftPos);
delay(1000);
}
void sweepRight() //looks for a rightward barrier, senses to see if path is blocked
{
sweepServo.write(rightPos);
delay(1000);
}
void sweepMiddle() /*looks for a frontal barrier, senses to see if path is blocked (MOST IMPORTANT FUNCTION
IN THE SENSING PROGRAM SET AS ALL OTHER FUNCTIONS BASE
THEMSELVES OFF THIS RESPONSE) */
{
sweepServo.write(middlePos);
delay(1000);
}
void sensDistance()//senses, calculates, and prints distances
{
pinMode(pingPort, OUTPUT); //sets pingPort as an OUTPUT
digitalWrite(pingPort, LOW); //sets pingPort LOW to not produce a sound
delayMicroseconds(2);
digitalWrite(pingPort, HIGH); //sets pingPort HIGH to produce a sound
delayMicroseconds(5);
digitalWrite(pingPort, LOW); //sets pingPort LOW to stop producing a sound
delayMicroseconds(2);
pinMode(pingPort, INPUT); //sets pingPort as an INPUT to read pongValue
pongValue = pulseIn(pingPort, HIGH, 2800); //reads for the HIGH pongValue
if(pongValue == 0)
{
Serial.println("Nothing received"); // if no signal is returned, "Nothing received" is printed in the serial monitor
}
else //for everything else the distance is printed using the calculation contained in this else
{
distance = pongValue/2/74;
Serial.print("Distance:");
Serial.println(distance);
}
delay(1);
}
/* functions for controlling movement of robot */
void forward() //this function makes the robot go forward
{
rightServo.write(-pos);
leftServo.write(pos);
}
void backward() //this function makes the robot go backward
{
rightServo.write(pos);
leftServo.write(-pos);
delay(2*time);
}
void turnAround() //turns robot around (~180 degrees)
{
rightServo.write(-pos);
leftServo.write(-pos);
delay(2*time);
}
void turnLeft() //this function makes the robot turn left 90 degrees
{
rightServo.write(-pos);
leftServo.write(-pos);
delay(time);
}
void turnRight() //this function makes the robot turn right 90 degrees
{
rightServo.write(pos);
leftServo.write(pos);
delay(time);
}
void stopRobot() //this function stops the robot's movement
{
rightServo.write(stopPos);//90 is the servo stop point
leftServo.write(stopPos);
}
/*=======================SETUP STEP=========================*/
void setup()
{
rightServo.attach(10);
leftServo.attach(9);
sweepServo.attach(7);
Serial.begin(9600);
}
/*========================LOOP STEP=========================*/
void loop()
{
if(pongValue == 0 || distance > 6) //reads value, if true the robot continues forward, if false program progresses
{
forward();
sweepMiddle();
sensDistance();
}
else
{
stopRobot();
sweepLeft();
sensDistance();
if(distance > 6 || pongValue == 0) /* reads value after turning the Ping Sensor to sense for a leftward barrier
if true, robot turns left and kicks out to the first if statement, if false
program progresses */
{
turnLeft();
stopRobot();
sweepMiddle();
}
else
{
stopRobot();
sweepRight();
sensDistance();
if(distance > 6 || pongValue == 0) /* reads value after turning the Ping Sensor to sense for a rightward barrier
if true, robot turns right and kicks out to the first if statement, if false
program progresses */
{
turnRight();
stopRobot();
sweepMiddle();
}
else /* if all other conditions above have proved false, then this triggers and the robot
moves backwards, then turns around
the logic behind it is that if there is a barrier left, that condition is false
if a barrier is right, that condition is false, and the frontal barrier has to be
present in order for the other two to happen so the robot would then turn
around and go the other way */
{
sweepMiddle();
backward();
stopRobot();
turnAround();
stopRobot();
sensDistance();
}
}
}
}
Issues:
One of the most important issues I had was getting the proper tiering to work with the functions and condition statements. There was literally no steps taken to solving this in any regard. What basically happened was at around 1:30 a.m. I decided to give the coding one more go, rewrote everything in the void loop() step and it worked. From there I just had to tweak values. Also, another main issue that I encountered was some kind of power issue. There were many times where the robot would shut off or only do a command for a fraction of its intended time. Based on some debugging, (i.e. jiggling the cable that goes to power the robot) I found that it was either an issue with the battery (not retaining a charge), the charger (being faulty and telling me the battery is charged when it isn't), or the cable going from battery to arduino board. Nothing conclusive has otherwise been drawn from this.