I had no trouble building the circuit. My program is mostly like the example program except the switch puts the robot into “opposite mode” instead of turning it off. Opposite mode makes the robot follow the opposite of the directions that are typed into the serial monitor. I have also created a “dance” function that makes the robot move around randomly. Here is the code:
//the right motor will be controlled by the motor A pins on the motor driver
const int AIN1 = 13; //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
int switchPin = 7; //switch to put the robot into opposite mode
const int driveTime = 20; //this is the number of milliseconds that it takes the robot to drive 1 inch
//it is set so that if you tell the robot to drive forward 25 units, the robot drives about 25 inches
const int turnTime = 8; //this is the number of milliseconds that it takes to turn the robot 1 degree
//it is set so that if you tell the robot to turn right 90 units, the robot turns about 90 degrees
//Note: these numbers will vary a little bit based on how you mount your motors, the friction of the
//surface that your driving on, and fluctuations in the power to the motors.
//You can change the driveTime and turnTime to make them more accurate
String botDirection; //the direction that the robot will drive in (this change which direction the two motors spin in)
String distance; //the distance to travel in each direction
/********************************************************************************/
void setup()
{
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);
Serial.begin(9600); //begin serial communication with the computer
//prompt the user to enter a command
Serial.println("Enter a direction followed by a distance.");
Serial.println("f = forward, b = backward, r = turn right, l = turn left");
Serial.println("Example command: f 50");
}
/********************************************************************************/
void loop()
{
if (Serial.available() > 0) //if the user has sent a command to the RedBoard
{
botDirection = Serial.readStringUntil(' '); //read the characters in the command until you reach the first space
distance = Serial.readStringUntil(' '); //read the characters in the command until you reach the second space
botDirection.trim(); //remove newline character
if (digitalRead(7) == HIGH){ //If the switch is in opposite mode
botDirection = opposite(botDirection); //assign the opposite direction to botDirection
}
//print the command that was just received in the serial monitor
//(or the opposite when in opposite mode)
Serial.print(botDirection);
if(distance != ""){
Serial.print(" ");
Serial.println(distance.toInt());
} else {
Serial.println("");
}
if(botDirection == "f"){ //if the entered direction is forward
forward();
} else if(botDirection == "b"){ //if the entered direction is backward
backward();
} else if(botDirection == "r"){ //if the entered direction is right
right();
} else if(botDirection == "l"){ //if the entered direction is left
left();
} else if (botDirection.equalsIgnoreCase("stop")){
stopMoving();
} else if (botDirection.equalsIgnoreCase("dance")){
dance();
}
}
}
//This function takes a direction as a string
//and returns the opposite direction
String opposite(String oldDirection){
String newDirection;
if(oldDirection == "f"){
newDirection = "b";
} else if(oldDirection == "b"){
newDirection = "f";
} else if(oldDirection == "r"){
newDirection = "l";
} else if(oldDirection == "l"){
newDirection = "r";
} else if(oldDirection.equalsIgnoreCase("dance")){
newDirection = "stop";
} else if(oldDirection.equalsIgnoreCase("stop")){
newDirection = "dance";
}
return newDirection;
}
//This function moves the robot forward
void forward(){
rightMotor(200); //drive the right wheel forward
leftMotor(200); //drive the left wheel forward
delay(driveTime * distance.toInt()); //drive the motors long enough travel the entered distance
stopMoving();
}
//This function moves the robot backward
void backward(){
rightMotor(-200); //drive the right wheel backward
leftMotor(-200); //drive the left wheel backward
delay(driveTime * distance.toInt()); //drive the motors long enough travel the entered distance
stopMoving();
}
//This function turns the robot to the right
void right(){
rightMotor(-200); //drive the right wheel backward
leftMotor(255); //drive the left wheel forward
delay(turnTime * distance.toInt()); //drive the motors long enough turn the entered distance
stopMoving();
}
//This function turns the robot to the left
void left(){
rightMotor(255); //drive the right wheel forward
leftMotor(-200); //drive the left wheel backward
delay(turnTime * distance.toInt()); //drive the motors long enough turn the entered distance
stopMoving();
}
//This function stops the robot
void stopMoving(){
rightMotor(0); //turn the right motor off
leftMotor(0); //turn the left motor off
}
//This function makes the robot move around randomly
void dance(){
int randDirection;
while(Serial.available() < 1){ //while a new command has not been entered in the serial monitor
randomSeed(analogRead(0));
distance = random(20, 80); //set a random distance between 20 and 80
randDirection = random(0, 4); //random number to set the direction
//These if statemtents call the funtion for the direction that was randomly selected
//before calling the function for the opposite direction. This is to ensure that the
//robot does not stray too far from the point where it started dancing.
if(randDirection < 1){
forward();
backward();
} else if(randDirection < 2){
backward();
forward();
} else if(randDirection < 3){
right();
left();
} else if(randDirection < 4){
left();
right();
}
}
}
/********************************************************************************/
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(BIN1, HIGH); //set pin 1 to high
digitalWrite(BIN2, LOW); //set pin 2 to low
}
else if (motorSpeed < 0) //if the motor should drive backward (negative speed)
{
digitalWrite(BIN1, LOW); //set pin 1 to low
digitalWrite(BIN2, 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
}
The setup(), rightMotor(), and leftMotor() functions are exactly the same as in the example program. The loop() function is very similar to the one in the example program. My main changes to the loop() function include omitting the if(digitalRead(7) == LOW) statement at the beginning of the function, and adding the if(digitalRead(7) == HIGH) statement inside the if(Serial.available() > 0) statement. This is to make the switch put the robot into opposite mode instead of making it stop. I also made separate functions for each direction, so the if-statements at the end of the loop() function simply call the function for the entered direction. I also created an opposite() function that takes a direction as a string and returns the opposite direction. This function is called inside the if(digitalRead(7) == HIGH) statement in the loop() function for when the robot is in opposite mode. The dance() function is the last function that I added. It simply makes the robot move around randomly by using the random() function to randomly assign values to the distance variable and randomly select directions. Inside the if-statements in the dance() function, the direction functions are called to make the robot move, but then the opposite direction function is called while the distance variable remains the same. This makes the robot “undo” every motion it makes while dancing, so after every action it then does the opposite action. This is so that the robot does not move too far away from its starting point.
Here is a video of the program in action:
I had one issue while writing this program that is like the issue that I had in Circuit 5A. The issue was that I had not included the statement botDirection.trim() after botDirection=Serial.readStringUntil(' '). Without the call to the trim() function, my “dance” and “stop” commands did not work because a newline character was added to the ends of the strings by the serial monitor. This caused them to be different than the “dance” and “stop” strings that I was comparing them to, and so the if-statements in the loop() function never called the dance() or stop() functions. I fixed this issue by adding the call to the trim() function to remove the newline characters at the ends of the strings. The distance variable also gets a newline character from the serial monitor, but its value is never compared in an if-statement so it does not need to use the trim() function. The distance variable does use the toInt() function, but the toInt() function simply ignores the newline character.
The Landing is a social site for Athabasca University staff, students and invited guests. It is a space where they can share, communicate and connect with anyone or everyone.
Unless you are logged in, you will only be able to see the fraction of posts on the site that have been made public. Right now you are not logged in.
If you have an Athabasca University login ID, use your standard username and password to access this site.
We welcome comments on public posts from members of the public. Please note, however, that all comments made on public posts must be moderated by their owners before they become visible on the site. The owner of the post (and no one else) has to do that.
If you want the full range of features and you have a login ID, log in using the links at the top of the page or at https://landing.athabascau.ca/login (logins are secure and encrypted)
Posts made here are the responsibility of their owners and may not reflect the views of Athabasca University.