|
#include <Adafruit_MotorShield.h> |
|
#include <Servo.h> |
|
#include <Wire.h> |
|
|
|
// Pin constants for the Ultrasonic sensor. |
|
const int pingPinOut = 8; |
|
const int pingPinIn = 8; |
|
// Constant Definitions |
|
const unsigned slowSpeed = 400; |
|
const unsigned fastSpeed = 800; |
|
const unsigned openSpace = 7; |
|
const unsigned turnTime = 1000; |
|
|
|
Adafruit_MotorShield AFMS = Adafruit_MotorShield(); |
|
// Declares the left motor on the Adafruit M3 and right motor on M4. |
|
// Declares the Ultrasonic sensor as "myLooker". |
|
Adafruit_DCMotor *lMotor = AFMS.getMotor(2); |
|
Adafruit_DCMotor *rMotor = AFMS.getMotor(3); |
|
Servo myLooker; |
|
|
|
|
|
void setup() |
|
{ |
|
Serial.begin(9600); |
|
// Declares the servo motor that the ultrasonic sensor is on to pin 9. |
|
myLooker.attach(9); |
|
AFMS.begin(); |
|
} |
|
|
|
void loop() |
|
{ |
|
delay(2000); |
|
bool found = SolveMaze(); |
|
|
|
// If the goal of the maze was found, the robot will do a happy dance. |
|
if (found == true) |
|
{ |
|
goLeft(100); |
|
goRight(100); |
|
goLeft(100); |
|
goRight(100); |
|
} |
|
} |
|
|
|
bool SolveMaze() |
|
{ |
|
// Begins infinite loop to look for the maze goal. |
|
for (;;) |
|
{ |
|
// Declares the step counter "i" and the character path array "path". |
|
unsigned i = 0; |
|
char path[50]; |
|
|
|
// Assigns the variable "cm" to the distance to the wall that is calculated by the function "DistancePing". |
|
long cm = DistancePing(); |
|
long x = cm; |
|
|
|
// Begins loop to move forward and put the letter "F" into the path array. |
|
// This continues for a preset distance. |
|
LookForward(); |
|
path[i++] = 'F'; |
|
goForward(slowSpeed); |
|
|
|
while (cm >= x - 15) |
|
{ |
|
goForward(slowSpeed); |
|
cm = DistancePing(); |
|
} |
|
|
|
// Determines if either the left or right direction is open. |
|
bool left = LookLeft(); |
|
bool right = LookRight(); |
|
|
|
// If Both are left and right are open the robot will determine if it is at the goal. |
|
if (left == true && right == true) |
|
{ |
|
bool end = ChckForEnd(); |
|
if (end == true) |
|
{ |
|
// If it is at the goal it will begin to shorten the path array. |
|
char sPath[50]; |
|
char one, two, three; |
|
unsigned index; |
|
|
|
for (index = 0; index <= i; index++) |
|
{ |
|
one = path[index]; |
|
two = path[index + 1]; |
|
three = path[index + 2]; |
|
|
|
if (one == 'L' && two == 'B' && three == 'R') |
|
sPath[index] = 'B'; |
|
else if (one == 'L' && two == 'B' && three == 'F') |
|
sPath[index] = 'R'; |
|
else if (one == 'R' && two == 'B' && three == 'L') |
|
sPath[index] = 'B'; |
|
else if (one == 'F' && two == 'B' && three == 'L') |
|
sPath[index] = 'R'; |
|
else if (one == 'F' && two == 'B' && three == 'F') |
|
sPath[index] == 'B'; |
|
else if (one == 'L' && two == 'B' && three == 'L') |
|
sPath[index] == 'F'; |
|
else |
|
sPath[index] = path[index]; |
|
} |
|
|
|
// The robot will then return to the start of the maze. |
|
for (unsigned a = index; a >= 0; a--) |
|
{ |
|
char step; |
|
step = sPath[a]; |
|
|
|
if (step == 'F') |
|
goBack(slowSpeed); |
|
else if (step == 'R') |
|
goLeft(slowSpeed); |
|
else if (step == 'L') |
|
goRight(slowSpeed); |
|
|
|
} |
|
|
|
// The robot will wait and begin its speed run through the maze. |
|
delay(5000); |
|
for (unsigned b = 0; b <= index; b++) |
|
{ |
|
if (sPath[b] == 'F') |
|
goForward(fastSpeed); |
|
else if (sPath[b] == 'L') |
|
goLeft; |
|
else if (sPath[b] == 'R') |
|
goRight(fastSpeed); |
|
else |
|
break; |
|
} |
|
return true; |
|
} |
|
} |
|
|
|
// If the robot is not at the goal and the left path is open, it will go left. |
|
// Otherwise if right is open it will go right. |
|
// If neither are open, it will turn around and go back. |
|
if (left == true) |
|
{ |
|
goLeft(slowSpeed); |
|
path[i++] = 'L'; |
|
} |
|
else if (right == true) |
|
{ |
|
goRight(slowSpeed); |
|
path[i++] = 'R'; |
|
} |
|
else |
|
{ |
|
goBack(slowSpeed); |
|
path[i++] = 'B'; |
|
|
|
} |
|
} |
|
} |
|
|
|
/*-------------- g o F o r w a r d ( ) ---------------------- |
|
Purpose: To move the robot in the forward direction. |
|
*/ |
|
void goForward(int speed) |
|
{ |
|
delay(1000); |
|
lMotor->setSpeed(speed); |
|
rMotor->setSpeed(speed); |
|
lMotor->run(FORWARD); |
|
rMotor->run(FORWARD); |
|
delay(turnTime); |
|
lMotor->run(RELEASE); |
|
rMotor->run(RELEASE); |
|
} |
|
|
|
/*-------------- g o L e f t ( ) ------------------------- |
|
Purpose: To turn the robot left. |
|
*/ |
|
void goLeft(int speed) |
|
{ |
|
delay(1000); |
|
lMotor->setSpeed(speed); |
|
rMotor->setSpeed(speed); |
|
lMotor->run(BACKWARD); |
|
rMotor->run(FORWARD); |
|
delay(turnTime); |
|
lMotor->run(RELEASE); |
|
rMotor->run(RELEASE); |
|
} |
|
|
|
/*---------------------- g o R i g h t ( ) --------------------- |
|
Purpose: To turn the robot right |
|
*/ |
|
void goRight(int speed) |
|
{ |
|
delay(1000); |
|
lMotor->setSpeed(speed); |
|
rMotor->setSpeed(speed); |
|
lMotor->run(FORWARD); |
|
rMotor->run(BACKWARD); |
|
delay(turnTime); |
|
lMotor->run(RELEASE); |
|
rMotor->run(RELEASE); |
|
} |
|
|
|
/*---------------------- g o B a c k ( ) ---------------------- |
|
Purpose: to turn the robot 180 degrees |
|
*/ |
|
void goBack(int speed) |
|
{ |
|
delay(1000); |
|
lMotor->setSpeed(speed); |
|
rMotor->setSpeed(speed); |
|
lMotor->run(FORWARD); |
|
rMotor->run(BACKWARD); |
|
delay(turnTime); |
|
delay(turnTime); |
|
lMotor->run(RELEASE); |
|
rMotor->run(RELEASE); |
|
} |
|
|
|
/*-------------- D i s t a n c e P i n g ( ) --------------------------- |
|
Purpose: To determine the distance to the wall using the ultrasonic sensor. |
|
*/ |
|
long DistancePing() |
|
{ |
|
long duration, cm; |
|
|
|
// Pings a test pulse, then the measured one. |
|
pinMode(pingPinOut, OUTPUT); |
|
digitalWrite(pingPinOut, LOW); |
|
delayMicroseconds(2); |
|
digitalWrite(pingPinOut, HIGH); |
|
delayMicroseconds(10); |
|
digitalWrite(pingPinOut, LOW); |
|
|
|
// Read in the time it takes for the signal to travel and return. |
|
pinMode(pingPinIn, INPUT); |
|
duration = pulseIn(pingPinIn, HIGH); |
|
|
|
return (cm / 29 / 2); |
|
} |
|
|
|
/*----------------------- L o o k F o r w a r d ( ) ------------------------- |
|
Purpose: Turns the servo so that the sensor is facing forward. |
|
*/ |
|
void LookForward() |
|
{ |
|
delay(1000); |
|
int x = 90; |
|
myLooker.write(x); |
|
} |
|
|
|
/*------------------------ L o o k L e f t ( ) ---------------------------- |
|
Purpose: Determines if the left side of the robot is open. |
|
*/ |
|
bool LookLeft() |
|
{ |
|
delay(1000); |
|
long cM; |
|
|
|
myLooker.write(0); |
|
cM = DistancePing(); |
|
|
|
if (cM >= openSpace) |
|
return true; |
|
else |
|
return false; |
|
} |
|
|
|
/*--------------------- L o o k R i g h t ( )------------------------------ |
|
Purpose: Determines if the right side of the robot is open. |
|
*/ |
|
bool LookRight() |
|
{ |
|
delay(1000); |
|
long centiM; |
|
|
|
myLooker.write(180); |
|
centiM = DistancePing(); |
|
|
|
if (centiM >= openSpace) |
|
return true; |
|
else |
|
return false; |
|
} |
|
|
|
/*----------------------- C h c k F o r E n d ( ) --------------------------- |
|
Purpose: Determines if the robot is at the goal of the maze. |
|
*/ |
|
bool ChckForEnd() |
|
{ |
|
delay(1000); |
|
long leftCenti, rightCenti; |
|
|
|
myLooker.write(135); |
|
rightCenti = DistancePing(); |
|
myLooker.write(45); |
|
leftCenti = DistancePing(); |
|
|
|
if (rightCenti >= openSpace && leftCenti >= openSpace) |
|
return true; |
|
else |
|
return false; |
|
} |