 • Blogs
• Circuit 5B: Remote-Controlled Robot

## Circuit 5B: Remote-Controlled Robot

• Public
By Adam Kroeker August 14, 2022 - 12:45pm

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 driverconst int AIN1 = 13; //control pin 1 on the motor driver for the right motorconst int AIN2 = 12; //control pin 2 on the motor driver for the right motorconst 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 driverconst int PWMB = 10; //speed control pin on the motor driver for the left motorconst int BIN2 = 9; //control pin 2 on the motor driver for the left motorconst 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 directionString 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 forwardvoid 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 backwardvoid 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 rightvoid 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 leftvoid 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 robotvoid stopMoving(){ rightMotor(0); //turn the right motor off leftMotor(0); //turn the left motor off}`
`//This function makes the robot move around randomlyvoid 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. 