Landing : Athabascau University
  • Blogs
  • Circuit 5C: Autonomous Robot

Circuit 5C: Autonomous Robot

I had no issues while building the circuit. My program is very similar to the example program. Instead of only turning left when sensing an object, my program chooses a random direction for the robot to drive in. I also programmed the robot to slow down before stopping when it senses that it is getting close to an object. Here is the code:

//the right motor will be controlled by the motor A pins on the motor driver
const int AIN1 = 4; //control pin 1 on the motor driver for the right motor
const int AIN2 = 12; //control pin 2 on the motor driver for the right motor
const int PWMA = 11; //speed control pin on the motor driver for the right motor
//the left motor will be controlled by the motor B pins on the motor driver
const int PWMB = 10; //speed control pin on the motor driver for the left motor
const int BIN2 = 9; //control pin 2 on the motor driver for the left motor
const int BIN1 = 8; //control pin 1 on the motor driver for the left motor

//distance variables
const int trigPin = 6;
const int echoPin = 5;
int switchPin = 7; //switch to turn the robot on and off
float distance = 0; //variable to store the distance measured by the distance sensor
//robot behaviour variables
int backupTime = 500; //amount of time that the robot will back up when it senses an object
/********************************************************************************/
void setup()
{
pinMode(trigPin, OUTPUT); //this pin will send ultrasonic pulses out from the distance sensor
pinMode(echoPin, INPUT); //this pin will sense when the pulses reflect back to the distance sensor
pinMode(switchPin, INPUT_PULLUP); //set this as a pullup to sense whether the switch is flipped
//set the motor control pins as outputs
pinMode(AIN1, OUTPUT);
pinMode(AIN2, OUTPUT);
pinMode(PWMA, OUTPUT);
pinMode(BIN1, OUTPUT);
pinMode(BIN2, OUTPUT);
pinMode(PWMB, OUTPUT);
}
/********************************************************************************/
void loop()
{
//DETECT THE DISTANCE READ BY THE DISTANCE SENSOR
distance = getDistance();
if (digitalRead(switchPin) == LOW) { //if the on switch is flipped
if (distance < 5) { //if an object is detected
//stop for a moment
stopMoving();
delay(200);
//back up
backUp();
delay(backupTime);
//turn
randomTurn();
} else if (distance < 10){ //if an object is detected but its still far away
//slow down
slowDown();
} else { //if no obstacle is detected drive forward
goForward();
}
} else { //if the switch is off then stop
//stop the motors
stopMoving();
}
}
//This function turns the robot in a random direction.
void randomTurn(){
randomSeed(analogRead(0));
int turnDirection = random(0, 2);
int turnTime = random(200, 1500);
if(turnDirection == 0){
//turn left for a random amount of time
turnLeft();
delay(turnTime);

} else {
//turn right for a random amount of time
turnRight();
delay(turnTime);
}
}
void stopMoving(){
rightMotor(0);
leftMotor(0);
}
void goForward(){
rightMotor(200);
leftMotor(200);
}
void backUp(){
rightMotor(-200);
leftMotor(-200);
}
void slowDown(){
rightMotor(100);
leftMotor(100);
}
void turnLeft(){
rightMotor(255);
leftMotor(-200);
}
void turnRight(){
leftMotor(255);
rightMotor(-200);
}
/********************************************************************************/
void rightMotor(int motorSpeed) //function for driving the right motor
{
if (motorSpeed > 0) //if the motor should drive forward (positive speed)
{
digitalWrite(AIN1, HIGH); //set pin 1 to high
digitalWrite(AIN2, LOW); //set pin 2 to low
}
else if (motorSpeed < 0) //if the motor should drive backward (negative speed)
{
digitalWrite(AIN1, LOW); //set pin 1 to low
digitalWrite(AIN2, HIGH); //set pin 2 to high
}
else //if the motor should stop
{
digitalWrite(AIN1, LOW); //set pin 1 to low
digitalWrite(AIN2, LOW); //set pin 2 to low
}
analogWrite(PWMA, abs(motorSpeed)); //now that the motor direction is set, drive it at the entered speed
}
/********************************************************************************/
void leftMotor(int motorSpeed) //function for driving the left motor
{
if (motorSpeed > 0) //if the motor should drive forward (positive speed)
{
digitalWrite(BIN2, HIGH); //set pin 1 to high
digitalWrite(BIN1, LOW); //set pin 2 to low
}
else if (motorSpeed < 0) //if the motor should drive backward (negative speed)
{
digitalWrite(BIN2, LOW); //set pin 1 to low
digitalWrite(BIN1, HIGH); //set pin 2 to high
}
else //if the motor should stop
{
digitalWrite(BIN1, LOW); //set pin 1 to low
digitalWrite(BIN2, LOW); //set pin 2 to low
}
analogWrite(PWMB, abs(motorSpeed)); //now that the motor direction is set, drive it at the entered speed
}
/********************************************************************************/
//RETURNS THE DISTANCE MEASURED BY THE HC-SR04 DISTANCE SENSOR
float getDistance()
{
float echoTime; //variable to store the time it takes for a ping to bounce off an object
float calculatedDistance; //variable to store the distance calculated from the echo time
//send out an ultrasonic pulse that's 10ms long
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
echoTime = pulseIn(echoPin, HIGH); //use the pulsein command to see how long it takes for the
//pulse to bounce back to the sensor
calculatedDistance = echoTime / 148.0; //calculate the distance of the object that reflected the pulse (half the bounce time multiplied by the speed of sound)
return calculatedDistance; //send back the distance that was calculated
}

My code is based on the code in the example program. I have decided to omit the calls to the serial functions for printing data to the serial monitor in my program because I do not like the LED on the RedBoard that blinks very quickly when data is being sent to the serial monitor and it is not useful to send data to the serial monitor when the robot is not connected to the USB cable anyway. Aside from the removal of the serial monitor functions, the setup(), getDistance(), leftMotor, and rightMotor() functions are almost exactly the same as in the example program. The loop() function is also mostly the same as in the example program, except instead of calling the rightMotor() and leftMotor() functions directly from the loop() function, I have added the goForward(), slowdown(), stopMoving(), randomTurn(), and backUp() functions which call the rightMotor() and leftMotor() functions. The randomTurn() function randomly selects either left or right, and then turns the robot in that direction for a random amount of time by calling the leftTurn() or rightTurn() functions, which in turn call the rightMotor() and leftMotor() functions. In the loop() function I also added another if-statement to make the robot slow down as it gets close to an object.

Here is a video of the program in action:  Autonomous Robot

I had one issue while writing the program. Initially, the two wheels drove in different directions when the robot was meant to be driving straight. This is because I connected the red and black wires from one of the motors in the wrong order, causing the motor to spin the wrong way. Instead of adjusting the wires, I decided to swap the BIN1 and BIN2 variables in the leftMotor() function. Another way to fix this issue would have been to swap the values of the variables where they are initialized at the top of the sketch.

Another issue that I had was that after a day had passed since I built the circuit and I turned it on again, it started backing up and turning even when there was no object in front of it. I used the serial monitor to check the value of the distance variable and found that it would often be less than 1 even when there were no objects near the distance sensor. This issue was fixed after I replaced all the jumper wires that were connected to the distance sensor, and upon inspection of the replaced wires I found small marks and kinks in some of them, leading me to believe that our cats may have been chewing on them.