Master Robotics with GalaxyRVR Rover
Table of Contents
Master Robotics:
Master Robotics with GalaxyRVR- SunFounder’s GalaxyRVR Rover is not just a toy, but it’s a full kit for you and your kids to Master robotics. With the GalaxyRVR Mars Rover, you get 23 lesson codes. You can run these codes on the robot and even change them as you like.
Learn how to make a Wall Climbing Robot.
I have already written an article; on how to build and test this robot.
Today, we will cover the Motors, IR sensors, Ultrasonic sensor, Servo motor, and RGB LED.
Amazon Links:
*Disclosure: These are affiliate links. As an Amazon Associate I earn from qualifying purchases.
Master Robotics Lesson 1: Motors
The GalaxyRVR Rover has 6 motors. There are 3 motors on the right side and 3 motors on the left side. These motors are divided into two groups: left side motors and right side motors.
You cannot individually control any motor on the left side and the same goes for the motors on the right side. If you send a signal to turn ON a motor on the right side, all the motors on that side will turn ON, and if you adjust the speed; all the motors will change speed at the same time.
Think of these 6 motors as just 2 motors, one on the left side and one on the right side.
All these motors are connected to a motor driver. Using only 4 pins (2, 3, 4, and 5) on the Arduino Uno, you can control the speed and direction.
So, let’s start with our first example.
GalaxyRVR Move Forward Program:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#include <SoftPWM.h> // Define the pins of motors const int in1 = 2; const int in2 = 3; const int in3 = 4; const int in4 = 5; void setup() { // Initialize SoftPWM SoftPWMBegin(); } void loop() { // Set the left motors rotate counterclockwise SoftPWMSet(in1, 255); // Full speed SoftPWMSet(in2, 0); // Stop // Set the right motors rotate clockwise SoftPWMSet(in3, 0); // Stop SoftPWMSet(in4, 255); // Full speed } |
Explanation:
First, you will need to download the SoftPWM library which allows us to control the speed and direction of the motors.
To install this library, simply copy the library name “SoftPWM”, then go to the sketch menu, then to Include Library, and click on the Manage Libraries.
Paste the Library name in the search box.
You can see I have already installed this library. You also need to install the same exact library.
Next, we define pins for the motors.
We are telling the controller which pins on the Arduino are going to be used to control two groups of motors” Right Side motors and Left Side Motors”.
in1 is connected to pin 2.
in2 is connected to pin 3.
in3 is connected to pin 4.
in4 is connected to pin 5.
1 |
void setup() { } |
The setup function runs once when the program starts. Here, we start the SoftPWM library with SoftPWMBegin().
1 |
void loop() { } |
The loop function runs over and over again. In this loop:
We set the left motors to rotate counterclockwise. Using the pulse width modulation or PWM to sit the in1 to its full speed and we sit the in2 to 0 which means stop.
1 2 3 |
SoftPWMSet(in1, 255); SoftPWMSet(in2, 0); |
And we do the opposite thing to the right side motors. It have set the right motors to rotate clockwise.
We set the right motors to rotate clockwise:
1 2 3 |
SoftPWMSet(in3, 0); SoftPWMSet(in4, 255); |
In simple terms, this code makes the left motors spin in one direction and the right motors spin in the opposite direction, both at full speed.
To upload this program,
- first connect the USB cable.
- Next, select the Arduino Uno from the Boards list.
- Next, select the communication port.
- Finally, click on the upload button.
Turn ON the power switch and you will see the GalaxyRVR will start moving in the forward direction forever.
Let’s modify the code.
I want the GalaxyRVR to move forward for 3 seconds, then I want it to stop for 2 seconds, and then I want it to move in the reverse direction, again it stops for 2 seconds, and then this repeats again and again.
Motors Speed Control Program:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
#include <SoftPWM.h> // Define the pins of motors const int in1 = 2; const int in2 = 3; const int in3 = 4; const int in4 = 5; void setup() { // Initialize SoftPWM SoftPWMBegin(); } void loop() { // Forward SoftPWMSet(in1, 255); // Full speed SoftPWMSet(in2, 0); // Stop SoftPWMSet(in3, 0); // Stop SoftPWMSet(in4, 255); // Full speed delay(3000); //Stop SoftPWMSet(in1, 0); // Stop SoftPWMSet(in2, 0); // Stop SoftPWMSet(in3, 0); // Stop SoftPWMSet(in4, 0); // Stop delay(2000); //Reverse SoftPWMSet(in1, 0); // Full speed SoftPWMSet(in2, 255); // Stop SoftPWMSet(in3, 255); // Stop SoftPWMSet(in4, 0); // Full speed delay(3000); //stop SoftPWMSet(in1, 0); // Stop SoftPWMSet(in2, 0); // Stop SoftPWMSet(in3, 0); // Stop SoftPWMSet(in4, 0); // Stop delay(2000); } |
As you can see, I have modified the code. First, the robot moves forward for 3 seconds.
To stop the robot, I have set all the pins to 0.
For reverse direction, I have set in1 and in4 to 0, and in2 and in3 to 255 for full speed. Then, there is a 3-second delay. So, the robot will go in reverse for 3 seconds and then stop for 2 seconds.
Upload the above program and you will see the Motors on the GalaxyRVR rotating at their full speed.
You can also control the motor speed very easily. You need to remember, 0 means stop and 255 means full speed. So, to control the speed, you can use any value between 0 and 255.
Modify the above program, to reduce the speed, this time, you can replace 255 with 100. After making the necessary changes, again upload the program, and this time you will see decrease in the motors speed.
Motors Left Right control:
You can control the robot’s left-right movement using different techniques. For example, if you turn off the motors on the right side and turn on the motors on the left side, the robot will turn right. If you turn off the motors on the left side and turn on the motors on the right side, the robot will turn left.
If you want the robot to turn quickly, you can make the motors on both sides rotate in opposite directions.
If you want the robot to turn slowly, you can simply reduce the speed. Let’s take a look at the modified code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
#include <SoftPWM.h> // Define the pins of motors const int in1 = 2; const int in2 = 3; const int in3 = 4; const int in4 = 5; void setup() { // Initialize SoftPWM SoftPWMBegin(); } void loop() { //*********Normal****** // right side SoftPWMSet(in1, 255); // Full speed SoftPWMSet(in2, 0); // Stop SoftPWMSet(in3, 0); // Stop SoftPWMSet(in4, 0); // Full speed delay(1000); //Stop SoftPWMSet(in1, 0); // Stop SoftPWMSet(in2, 0); // Stop SoftPWMSet(in3, 0); // Stop SoftPWMSet(in4, 0); // Stop delay(2000); // Left side SoftPWMSet(in1, 0); // Full speed SoftPWMSet(in2, 0); // Stop SoftPWMSet(in3, 0); // Stop SoftPWMSet(in4, 255); // Full speed delay(1000); //Stop SoftPWMSet(in1, 0); // Stop SoftPWMSet(in2, 0); // Stop SoftPWMSet(in3, 0); // Stop SoftPWMSet(in4, 0); // Stop delay(2000); //******** fast********* // right side SoftPWMSet(in1, 255); // Full speed SoftPWMSet(in2, 0); // Stop SoftPWMSet(in3, 255); // Stop SoftPWMSet(in4, 0); // Full speed delay(1000); //Stop SoftPWMSet(in1, 0); // Stop SoftPWMSet(in2, 0); // Stop SoftPWMSet(in3, 0); // Stop SoftPWMSet(in4, 0); // Stop delay(2000); // Left side SoftPWMSet(in1, 0); // Full speed SoftPWMSet(in2, 255); // Stop SoftPWMSet(in3, 0); // Stop SoftPWMSet(in4, 255); // Full speed delay(1000); //Stop SoftPWMSet(in1, 0); // Stop SoftPWMSet(in2, 0); // Stop SoftPWMSet(in3, 0); // Stop SoftPWMSet(in4, 0); // Stop delay(2000); //*********Slow****** // right side SoftPWMSet(in1, 100); // Full speed SoftPWMSet(in2, 0); // Stop SoftPWMSet(in3, 0); // Stop SoftPWMSet(in4, 0); // Full speed delay(1000); //Stop SoftPWMSet(in1, 0); // Stop SoftPWMSet(in2, 0); // Stop SoftPWMSet(in3, 0); // Stop SoftPWMSet(in4, 0); // Stop delay(2000); // Left side SoftPWMSet(in1, 0); // Full speed SoftPWMSet(in2, 0); // Stop SoftPWMSet(in3, 0); // Stop SoftPWMSet(in4, 100); // Full speed delay(1000); //Stop SoftPWMSet(in1, 0); // Stop SoftPWMSet(in2, 0); // Stop SoftPWMSet(in3, 0); // Stop SoftPWMSet(in4, 0); // Stop delay(2000); } |
To turn the robot to the right side, I simply set the in1 to 255 and all the other pins to 0. Then the robot stops for 2 seconds. For the left side movement I set the in4 to 255, and all the other pins to 0. Again the robot stops for 2 seconds.
For the quick movement we turn ON the motors on both sides.
For the slow movement, we simply reduce the PWM value.
Robot Moves Forward and Left_Right:
You can define your own functions for the robot’s movements. This will make your code more organized, and you can easily make changes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
#include <SoftPWM.h> // Define the pins of motors const int in1 = 2; const int in2 = 3; const int in3 = 4; const int in4 = 5; void setup() { // Initialize SoftPWM SoftPWMBegin(); } void loop() { moveForward(200); // Move the Rover forward delay(1000); moveBackward(200); // Move the Rover backward delay(1000); turnLeft(200); // Turn the Rover to the left delay(1000); turnRight(200); // Turn the Rover to the right delay(1000); stopMove(); // Stop the Rover delay(5000); } void moveForward(int speed) { // Set the left motors rotate counterclockwise SoftPWMSet(in1, speed); SoftPWMSet(in2, 0); // Set the right motors rotate clockwise SoftPWMSet(in3, 0); SoftPWMSet(in4, speed); } void moveBackward(int speed) { // Set the left motors rotate clockwise SoftPWMSet(in1, 0); SoftPWMSet(in2, speed); // Set the right motors rotate counterclockwise SoftPWMSet(in3, speed); SoftPWMSet(in4, 0); } void turnLeft(int speed) { // Set al motors to rotate clockwise SoftPWMSet(in1, 0); SoftPWMSet(in2, speed); SoftPWMSet(in3, 0); SoftPWMSet(in4, speed); } void turnRight(int speed) { // Set all motors to rotate counterclockwise SoftPWMSet(in1, speed); SoftPWMSet(in2, 0); SoftPWMSet(in3, speed); SoftPWMSet(in4, 0); } void stopMove() { // Stop all the motors SoftPWMSet(in1, 0); SoftPWMSet(in2, 0); SoftPWMSet(in3, 0); SoftPWMSet(in4, 0); } |
As you can see, to move the robot forward, we have the function moveForward(). This is a user-defined function. It has no return type and takes only one value as an argument, which is the speed. Now you don’t need to go into the function body to change the speed; you can just change the value inside the parenthesis in the main loop() function.
The same thing applies to all the other functions. You can set any speed you want.
Upload the program and make necessary changes as per your requirements.
Master Robotics, Lesson 1 Video:
Master Robotics Lesson 2: IR Sensors
After controlling the motors forward, reverse, left, and right movements, now we will cover IR sensors. The GalaxyRVR Rover has two IR sensors; one on the right side and one on the left side.
The right IR sensor is connected to pin 7 on the Arduino Uno, and the left IR sensor is connected to pin 8.
- First, you need to set the alignment of these two sensors.
- Next, you need to set their detection range.
To do this, first turn on the GalaxyRVR Rover, then use your hand or an object to check if both sensors are detecting properly. If the distance is too short or too long, you can adjust the range using the potentiometers on the IR sensors.
After setting the alignment and range of the IR sensors, now we can start with the programming.
Reading IR Sensors:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
// Define the pins for the IR modules #define IR_RIGHT 7 #define IR_LEFT 8 void setup() { // Set the IR module pins as inputs pinMode(IR_RIGHT, INPUT); pinMode(IR_LEFT, INPUT); // Begin serial communication Serial.begin(9600); } void loop() { // Read the values from the IR modules int rightValue = digitalRead(IR_RIGHT); int leftValue = digitalRead(IR_LEFT); // Print the values to the serial monitor Serial.print("Right IR: "); Serial.println(rightValue); Serial.print("Left IR: "); Serial.println(leftValue); // Wait a bit for readability delay(200); } |
First, we define the two pins our IR sensors are connected to. There are certain rules when it comes to defining variables, I have already covered it in my Arduino Course, it’s completely free.
I am sure you already know about the setup() function; it’s a special function that executes only once when the Arduino board is powered up or reset.
Since we are going to use IR Sensors for detecting objects and humans so that’s why we need to set the IR Sensor pins to “INPUT” mode, meaning they will receive the signals.
Next, you will need to activate the Serial communication, if you want to send messages to the computer and get them printed on the Serial monitor. We want to check if the IR Sensors detect objects.
1 |
Serial.begin(9600); |
Anyway, inside the parenthesis, you can see this number 9600, it’s the Baud Rate.
Loop() is also a special function like the setup() function. But, the loop() function runs repeatedly over and over again.
Since, the IR sensors on the GalaxyRVR Rover, we are using are digital; so, that’s why we are using digitalRead() functions). If we were using analog IR sensors, then we would use analogRead() functions.
So, we use the digitalRead() function to check if the IR sensor is blocked by any object or human. Let me tell you, when there is nothing in front of the IR sensor you get 1, and when it detects anything then it gives 0.
Anyway, after reading the IR sensors, then we print it on the Serial monitor.
Output:
Both the IR sensors, successfully detected my hands. You can see 0s; it means both the IR sensors detected my hands.
Now, let’s turn the GalaxyRVR in an obstacle avoidance robot.
Obstacle Avoidance Robot programming:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
#include <SoftPWM.h> // Define the pins of motors const int in1 = 2; const int in2 = 3; const int in3 = 4; const int in4 = 5; // Define the pins for the IR modules #define IR_RIGHT 7 #define IR_LEFT 8 void setup() { // Initialize SoftPWM SoftPWMBegin(); // Set the IR module pins as inputs pinMode(IR_RIGHT, INPUT); pinMode(IR_LEFT, INPUT); } void loop() { // Read values from IR sensors int rightValue = digitalRead(IR_RIGHT); int leftValue = digitalRead(IR_LEFT); // Based on IR sensor readings, control rover's movements if (rightValue == 0 && leftValue == 1) { // Right path blocked backRight(150); } else if (rightValue == 1 && leftValue == 0) { // Left path blocked backLeft(150); } else if (rightValue == 0 && leftValue == 0) { // Both paths blocked moveBackward(150); } else { // Paths clear moveForward(150); } delay(100); } // Function to move the rover backward void moveBackward(int speed) { // Set the left motors to rotate clockwise SoftPWMSet(in1, 0); // Stop SoftPWMSet(in2, speed); // Full speed // Set the right motors to rotate counterclockwise SoftPWMSet(in3, speed); // Full speed SoftPWMSet(in4, 0); // Stop } void moveForward(int speed) { // Set the left motors rotate counterclockwise SoftPWMSet(in1, speed); SoftPWMSet(in2, 0); // Set the right motors rotate clockwise SoftPWMSet(in3, 0); SoftPWMSet(in4, speed); } // Function to turn to the back right void backRight(int speed) { SoftPWMSet(in1, 0); SoftPWMSet(in2, speed); SoftPWMSet(in3, 0); SoftPWMSet(in4, 0); } // Function to turn to the back left void backLeft(int speed) { SoftPWMSet(in1, 0); SoftPWMSet(in2, 0); SoftPWMSet(in3, speed); SoftPWMSet(in4, 0); } |
We are going to use the same library and the same pins on the Arduino to control all the 6 motors. We can’t change these pins because of the Hardware limitations. They have already defined the connections. So, you will have to use the same pins when it comes to controlling the motors on the GalaxyRVR Rover.
The IR sensors pins definitions and code inside the setup() function remains exactly the same. The softPWMBegin() is for the PWM. If, you remember we used it in the first lesson.
Inside the loop() function, first we check the IR Sensors, and store the pins status in the variables rightValue and leftValue.
Next, we use if conditions to check if only one IR Sensor is blocked or both the IR sensors are blocked. 0 means there is something in front of the IR Sensor and 1 means there is nothing.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
if (rightValue == 0 && leftValue == 1) { // Right path blocked backRight(150); } else if (rightValue == 1 && leftValue == 0) { // Left path blocked backLeft(150); } else if (rightValue == 0 && leftValue == 0) { // Both paths blocked moveBackward(150); } else { // Paths clear moveForward(150); } |
Take a look at the first condition; we are telling the controller to backRight, if there is something in front of the right IR sensor.
Then in the 2nd condition we are telling the controller to backLeft, if there is something in front of the Left IR sensor.
And in third condition, we are telling the controller to move the robot backward, you can also stop the robot.
else
If there is nothing in front of both the IR Sensors, then the controller moves the GalaxyRVR in the forward direction.
Master Robotics, Lesson 2 Video:
Master Robotics Lesson 3: Ultrasonic Sensor
After covering the IR sensors; next, we are going to start with the HC-SR04 Ultrasonic Sensor, installed on the front of the GalaxyRVR Rover.
I won’t talk about its technical specification and how it works; because I have already used in several projects.
Anyway, the Ultrasonic Sensor is connected to the Arduino pin 10. So, let’s first read this Ultrasonic Sensor and afterwards we will do some interesting projects.
Reading the Ultrasonic Sensor:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
// Define the pin for the ultrasonic module #define ULTRASONIC_PIN 10 void setup() { // Start the serial communication Serial.begin(9600); } void loop() { // A 4ms delay is required, otherwise the reading may be 0 delay(4); //Set to OUTPUT to send signal pinMode(ULTRASONIC_PIN, OUTPUT); // Clear the trigger pin digitalWrite(ULTRASONIC_PIN, LOW); delayMicroseconds(2); // Trigger the sensor by sending a high pulse for 10us digitalWrite(ULTRASONIC_PIN, HIGH); delayMicroseconds(10); // Set the trigger pin back to low digitalWrite(ULTRASONIC_PIN, LOW); //Set to INPUT to read pinMode(ULTRASONIC_PIN, INPUT); // pulseIn returns the duration of the pulse on the pin float duration = pulseIn(ULTRASONIC_PIN, HIGH); // Calculate the distance (in cm) based on the speed of sound (340 m/s or 0.034 cm/us) float distance = duration * 0.034 / 2; // Print the distance to the serial monitor Serial.print("The distance is: "); Serial.print(distance); Serial.println(" cm"); // Delay a bit to let the sensor settle before the next measurement delay(200); } |
First, define a pin for the Ultrasonic Sensor. As I said, the ultrasonic sensor is connected to the Arduino pin 10.
In the setup() function, we simply activated the Serial communication and we are using 9600 baud rate.
In the loop() function that runs repeatedly, we started off by adding a delay of 4ms, otherwise the reading may be 0.
We set the Ultrasonic_pin to output to send a singal.
Then we clear the trigger pin.
Then we trigger the Ultrasonic Sensor by sending a high pulse for 10us.
Next, we set the trigger pin back to low.
Then we set it to INPUT to read the signal.
The PulseIn returns the duration of the pulse on the pin.
Then we calculate the distance in cm based on the speed of sound 340 m/s or 0.034 cm/us. And don’t forget to divide it by 2.
Finally we the distance value to the serial monitor.
Now, let’s turn this into an obstacle avoidance robot using the Ultrasonic Sensor.
Obstacle Avoidance using Ultrasonic Sensor:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
#include <SoftPWM.h> // Define the pin for the ultrasonic module #define ULTRASONIC_PIN 10 // Define the pins of motors const int in1 = 2; const int in2 = 3; const int in3 = 4; const int in4 = 5; void setup() { // Initialize SoftPWM SoftPWMBegin(); //Serial.begin(9600); } void loop() { // Read distance from ultrasonic sensor float distance = readSensorData(); //Serial.println(distance); // Output distance for debugging // Control rover based on distance reading if (distance > 50) { // If it's safe to move forward moveForward(200); } else if (distance < 15 && distance > 1) { // If there's an obstacle close moveBackward(200); delay(500); // Wait for a while before attempting to turn backLeft(150); delay(1000); } else { // For distances in between, proceed with caution moveForward(150); } } float readSensorData() { // A 4ms delay is required, otherwise the reading may be 0 delay(4); //Set to OUTPUT to send signal pinMode(ULTRASONIC_PIN, OUTPUT); // Clear the trigger pin digitalWrite(ULTRASONIC_PIN, LOW); delayMicroseconds(2); // Trigger the sensor by sending a high pulse for 10us digitalWrite(ULTRASONIC_PIN, HIGH); delayMicroseconds(10); // Set the trigger pin back to low digitalWrite(ULTRASONIC_PIN, LOW); //Set to INPUT to read pinMode(ULTRASONIC_PIN, INPUT); // pulseIn returns the duration of the pulse on the pin float duration = pulseIn(ULTRASONIC_PIN, HIGH); // Calculate the distance (in cm) based on the speed of sound (340 m/s or 0.034 cm/us) float distance = duration * 0.034 / 2; return distance; } void moveForward(int speed) { // Set the left motors rotate counterclockwise SoftPWMSet(in1, speed); SoftPWMSet(in2, 0); // Set the right motors rotate clockwise SoftPWMSet(in3, 0); SoftPWMSet(in4, speed); } void moveBackward(int speed) { // Set the left motors to rotate clockwise SoftPWMSet(in1, 0); // Stop SoftPWMSet(in2, speed); // Full speed // Set the right motors to rotate counterclockwise SoftPWMSet(in3, speed); // Full speed SoftPWMSet(in4, 0); // Stop } // Function to turn to the back left void backLeft(int speed) { SoftPWMSet(in1, 0); SoftPWMSet(in2, 0); SoftPWMSet(in3, speed); SoftPWMSet(in4, 0); } |
Again we are using the same library for the motors.
The same pins definitions for the Ultrasonic Sensor and motors pins.
Inside the setup() function, we simply activated the SoftPWM library.
Rest of the program is pretty straightforward. First we read the ultrasonic sensor. readSensorData() is a user-defined function and its return type is float. You can see it consist of the same set of instructions, I explained in example number1. This time it calculates the distance and then return the final calculated distance.
Then we use some if conditions to control the GalaxyRVR Rover based on the distance reading.
The first condition checks if the distance is greater than 50 then we call the moveForward() function.
And if the distance is less than 15 and greater than 1 then move the rover backward for half a second.
Next we turn the rover by calling the backLeft function.
moveForward(), moveBackward(), and backLeft(), these are user-defined functions; used for controlling the motors. I have already explained all these functions in Lesson 1.
I have talked in much detail about how to control the speed and direction of motors.
Right now, it can only sense objects that are in front of the Ultrasonic sensor. It totally ignores objects on the left and right sides. So, next we are going to use the Ultrasonic Sensor and IR sensors to make the smartest obstacle avoidance system. So, let’s do it
Obstacle avoidance Robot using Ultrasonic & IR Sensors:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
#include <SoftPWM.h> // Define the pin for the ultrasonic module #define ULTRASONIC_PIN 10 // Define the pins for the IR modules #define IR_RIGHT 7 #define IR_LEFT 8 // Define the pins of motors const int in1 = 2; const int in2 = 3; const int in3 = 4; const int in4 = 5; void setup() { // Initialize serial communication for debugging Serial.begin(9600); // Initialize SoftPWM SoftPWMBegin(); // Set the IR module pins as inputs pinMode(IR_RIGHT, INPUT); pinMode(IR_LEFT, INPUT); } void loop() { // Read values from IR sensors int rightValue = digitalRead(IR_RIGHT); int leftValue = digitalRead(IR_LEFT); // Based on IR sensor readings, control rover's movements if (rightValue == 0 && leftValue == 1) { // Right ir module blocked backRight(150); } else if (rightValue == 1 && leftValue == 0) { // Left ir module blocked backLeft(150); } else if (rightValue == 0 && leftValue == 0) { // Both modules blocked moveBackward(150); } else { // Paths clear handleForwardMovement(); } } void handleForwardMovement() { // Read distance from ultrasonic sensor float distance = readSensorData(); //Serial.println(distance); // Output distance for debugging // Control rover based on distance reading if (distance > 30) { // If it's safe to move forward moveForward(200); } else if (distance < 15 && distance > 1) { // If there's an obstacle close moveBackward(200); delay(500); // Wait for a while before attempting to turn backLeft(150); delay(1000); } else { // For distances in between, proceed with caution moveForward(150); } } float readSensorData() { // A 4ms delay is required, otherwise the reading may be 0 delay(4); //Set to OUTPUT to send signal pinMode(ULTRASONIC_PIN, OUTPUT); // Clear the trigger pin digitalWrite(ULTRASONIC_PIN, LOW); delayMicroseconds(2); // Trigger the sensor by sending a high pulse for 10us digitalWrite(ULTRASONIC_PIN, HIGH); delayMicroseconds(10); // Set the trigger pin back to low digitalWrite(ULTRASONIC_PIN, LOW); //Set to INPUT to read pinMode(ULTRASONIC_PIN, INPUT); // pulseIn returns the duration of the pulse on the pin float duration = pulseIn(ULTRASONIC_PIN, HIGH); // Calculate the distance (in cm) based on the speed of sound (340 m/s or 0.034 cm/us) float distance = duration * 0.034 / 2; return distance; } // Function to move the rover forward void moveForward(int speed) { // Set the left motors rotate counterclockwise SoftPWMSet(in1, speed); SoftPWMSet(in2, 0); // Set the right motors rotate clockwise SoftPWMSet(in3, 0); SoftPWMSet(in4, speed); } // Function to move the rover backward void moveBackward(int speed) { // Set the left motors to rotate clockwise SoftPWMSet(in1, 0); // Stop SoftPWMSet(in2, speed); // Full speed // Set the right motors to rotate counterclockwise SoftPWMSet(in3, speed); // Full speed SoftPWMSet(in4, 0); // Stop } // Function to turn to the back right void backRight(int speed) { SoftPWMSet(in1, 0); SoftPWMSet(in2, speed); SoftPWMSet(in3, 0); SoftPWMSet(in4, 0); } // Function to turn to the back left void backLeft(int speed) { SoftPWMSet(in1, 0); SoftPWMSet(in2, 0); SoftPWMSet(in3, speed); SoftPWMSet(in4, 0); } |
This program is just the combination of two projects. The ultrasonic avoidance that you just saw and the IR avoidance system that I explained in lesson 2. You can clearly see, the same set of instructions are used. So, I think there is no need for me to explain anything.
Now, it can not only detect objects on the front side, but also on the right and left sides of the rover.
Now, let’s make the GalaxyRVR Rover to follow an object.
Robot follows an Object:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
#include <SoftPWM.h> // Define the pin for the ultrasonic module #define ULTRASONIC_PIN 10 // Define the pins for the IR modules #define IR_RIGHT 7 #define IR_LEFT 8 // Define the pins of motors const int in1 = 2; const int in2 = 3; const int in3 = 4; const int in4 = 5; void setup() { // Initialize serial communication for debugging Serial.begin(9600); // Initialize SoftPWM SoftPWMBegin(); // Set the IR module pins as inputs pinMode(IR_RIGHT, INPUT); pinMode(IR_LEFT, INPUT); } void loop() { float distance = readSensorData(); // Read values from IR sensors int rightValue = digitalRead(IR_RIGHT); int leftValue = digitalRead(IR_LEFT); if (distance > 8 && distance < 30) { moveForward(150); } // Based on IR sensor readings, control rover's movements else if (rightValue == 0 && leftValue == 1) { // Right ir module blocked turnRight(150); } else if (rightValue == 1 && leftValue == 0) { // Left ir module blocked turnLeft(150); } else { // Paths clear stopMove(); } } float readSensorData() { // A 4ms delay is required, otherwise the reading may be 0 delay(4); //Set to OUTPUT to send signal pinMode(ULTRASONIC_PIN, OUTPUT); // Clear the trigger pin digitalWrite(ULTRASONIC_PIN, LOW); delayMicroseconds(2); // Trigger the sensor by sending a high pulse for 10us digitalWrite(ULTRASONIC_PIN, HIGH); delayMicroseconds(10); // Set the trigger pin back to low digitalWrite(ULTRASONIC_PIN, LOW); //Set to INPUT to read pinMode(ULTRASONIC_PIN, INPUT); // pulseIn returns the duration of the pulse on the pin float duration = pulseIn(ULTRASONIC_PIN, HIGH); // Calculate the distance (in cm) based on the speed of sound (340 m/s or 0.034 cm/us) float distance = duration * 0.034 / 2; return distance; } void moveForward(int speed) { // Set the left motors rotate counterclockwise SoftPWMSet(in1, speed); SoftPWMSet(in2, 0); // Set the right motors rotate clockwise SoftPWMSet(in3, 0); SoftPWMSet(in4, speed); } void moveBackward(int speed) { // Set the left motors rotate clockwise SoftPWMSet(in1, 0); SoftPWMSet(in2, speed); // Set the right motors rotate counterclockwise SoftPWMSet(in3, speed); SoftPWMSet(in4, 0); } void turnLeft(int speed) { // Set al motors to rotate clockwise SoftPWMSet(in1, 0); SoftPWMSet(in2, speed); SoftPWMSet(in3, 0); SoftPWMSet(in4, speed); } void turnRight(int speed) { // Set all motors to rotate counterclockwise SoftPWMSet(in1, speed); SoftPWMSet(in2, 0); SoftPWMSet(in3, speed); SoftPWMSet(in4, 0); } void stopMove() { // Stop all the motors SoftPWMSet(in1, 0); SoftPWMSet(in2, 0); SoftPWMSet(in3, 0); SoftPWMSet(in4, 0); } |
You can see this is the same exact program with some minor changes, this time instead of avoiding any object, it follows that object.
Master Robotics, Lesson 3 Video:
Master Robotics Lesson 4: Servo Motor
After covering the Ultrasonic Sensor, next, we are going to start with this Micro Servo which is used to control the position of the ESP32 Camera module.
Its range is from 0 to 180 degrees. A Servo is one of the most popular and most commonly used components. It is used in applications where precise movement and control are required. As you can see, on the GalaxyRVR Rover, we use it to control the position of this camera. You can also use it in RC Vehicles, in RC planes for controlling the ailerons and Rudder. You can also use it in automated manufacturing systems, and so on. And let me also tell you this servo is connected to the Arduino Uno pin 6.
Now, let’s start with a very basic program; we are going to control the position of this camera.
Servo Angle control:
1 2 3 4 5 6 7 8 9 10 11 |
#include <Servo.h> Servo myServo; // create a servo object void setup() { myServo.attach(6); // attaches the servo on pin 6 } void loop() { myServo.write(45); // tell servo to go to 45 degrees } |
First we add the Servo library which contains the code to control a servo.
Next, we create a servo object with the name myServo. You can define multiple Servo objects, if you need to control multiple Servo motors.
In the setup() function, we tell the controller that Servo is connected to pin 6 on the Arduino.
In the loop() function, we set the camera position at 45 degrees using myServo.write() function.
Upload the program; and then keep changing this values inside the parenthesis.
1 |
myServo.write(45); |
Upload the program; each time you change the angle.
Isn’t it so boring, changing the angle, and uploading the program again and again. Let’s use a loop.
Servo with for loop:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#include <Servo.h> Servo myServo; // create a servo object void setup() { myServo.attach(6); // attaches the servo on pin 6 } void loop() { for (int i = 0; i <= 130; i++) { // loop from 0 to 130 degrees myServo.write(i); // control the servo to move to the current angle delay(100); // delay for 100 milliseconds } } |
I slightly modified this program, you can see this time I added this for loop, to automatically increment the angle from 0 to 130. You might be wondering, why not 180? Because, I have practically tested it, the camera can only go to 130 degrees, otherwise the camera may get damaged by the body.
Upload this program and you will see the Servo; starting from 0 and then moves all the way to 130 degrees.
You can change the speed; by changing the delay value, currently its 100ms, to make it faster you can change this to a lower value let’s say 20ms. Try different values and you will get the idea.
Now, let’s control its position using Ultrasonic Sensor.
By default, I want the camera at zero degree, and when the ultrasonic Sensor detects an object, I want the camera to change its position towards the front. Let’s do it.
Servo and Ultrasonic Sensor:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
#include <SoftPWM.h> #include <Servo.h> // Define the pin for the ultrasonic module #define ULTRASONIC_PIN 10 Servo myServo; // create a servo object // Define the pins of motors const int in1 = 2; const int in2 = 3; const int in3 = 4; const int in4 = 5; void setup() { // Initialize SoftPWM SoftPWMBegin(); myServo.attach(6); // attaches the servo on pin 6 } void loop() { // Read distance from ultrasonic sensor float distance = readSensorData(); //Serial.println(distance); // Output distance for debugging // Control rover based on distance reading if (distance <= 50) { myServo.write(100); delay(1000); } if(distance > 50){ myServo.write(0); delay(1000); } } float readSensorData() { // A 4ms delay is required, otherwise the reading may be 0 delay(4); //Set to OUTPUT to send signal pinMode(ULTRASONIC_PIN, OUTPUT); // Clear the trigger pin digitalWrite(ULTRASONIC_PIN, LOW); delayMicroseconds(2); // Trigger the sensor by sending a high pulse for 10us digitalWrite(ULTRASONIC_PIN, HIGH); delayMicroseconds(10); // Set the trigger pin back to low digitalWrite(ULTRASONIC_PIN, LOW); //Set to INPUT to read pinMode(ULTRASONIC_PIN, INPUT); // pulseIn returns the duration of the pulse on the pin float duration = pulseIn(ULTRASONIC_PIN, HIGH); // Calculate the distance (in cm) based on the speed of sound (340 m/s or 0.034 cm/us) float distance = duration * 0.034 / 2; return distance; } |
This code is the combination of the Servo first example and the Ultrasonic Sonic based Avoidance system.
I only added these two conditions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
if (distance <= 50) { myServo.write(100); delay(1000); } if(distance > 50){ myServo.write(0); delay(1000); } |
If the distance is less than or equal to 50 then move the Servo to 100 degrees.
and if the distance is greater than 50, or if there is nothing in front of the Ultrasonic Sensor then move the camera to its default position. Rest of the program is exactly the same.
You can see, it’s working perfectly, but when I touch the robot body; it starts to act in an abnormal way. It may be due to, when I touch the robot body might introduce electrical noise or static electricity, which interferes with the ultrasonic sensor and servo control signals. Or it may be due to the grounding issues. The same thing I also noticed with the IR sensors. To avoid such issues, just keep your hands off the robot.
Master Robotics, Lesson 4 Video:
Master Robotics Lesson 5: Battery and RGB LED Strips
After covering the Servo Motor, next, we are going to start with the RGB LED strips and battery voltage monitoring.
Let’s first start with the two RGB LED strips attached underneath the robot body. And let me tell you, the two LED strips share the same pins (11, 12, and 13) on the Arduino Uno. Let’s start with our first example which is about turning the LED strips ON and OFF.
RGB LED strip Light up:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#include <SoftPWM.h> // Define the pin numbers for the RGB strips const int bluePin = 11; const int redPin = 12; const int greenPin = 13; void setup() { // Initialize software-based PWM on all pins SoftPWMBegin(); } void loop() { // Set the color to red by turning the red LED on and the others off SoftPWMSet(redPin, 0); // 255 is the maximum brightness SoftPWMSet(greenPin, 0); // 0 is off SoftPWMSet(bluePin, 255); // 0 is off delay(1000); // Wait for 1 second } |
As usual for the PWM we have added the SoftPWM library. This is the same library for controlling the speed of all 6 motors.
1 2 3 4 5 |
const int bluePin = 11; const int redPin = 12; const int greenPin = 13; |
These are the pins our LED strips are connected to.
In the setup() function, we activate the SoftPWM library.
Now, the actual code is in the loop function that runs repeatedly.
1 |
SoftPWMSet(redPin, 0); // 255 is the maximum brightness |
This instruction lights up the RED LEDs with full brightness. While all the other LEDs are OFF.
With this program, we can only turn ON the Red, Green, or Blue LEDs on the strips. To generate any color of our choice, for this, we will need to make some changes in this code.
Generate different colors using LED RGB strips:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
#include <SoftPWM.h> // Include the SoftPWM library // Define the pin numbers for the RGB strips const int bluePin = 11; const int redPin = 12; const int greenPin = 13; void setup() { SoftPWMBegin(); // Initialize software-based PWM on all pins } void loop() { // Set different colors with a delay of 1 second (1000 ms) in between setColor(255, 0, 0); // Set the color to red delay(1000); setColor(255, 128, 0); // Set the color to orange delay(1000); setColor(255, 255, 0); // Set the color to yellow delay(1000); setColor(0, 255, 0); // Set the color to green delay(1000); setColor(0, 0, 255); // Set the color to blue delay(1000); setColor(0, 255, 255); // Set the color to lightblue delay(1000); setColor(255, 0, 255); // Set the color to purple delay(1000); setColor(255, 255, 255); // Set the color to white delay(1000); } // Define a function to set color void setColor(int red, int green, int blue) { SoftPWMSet(redPin, red); // Set red component of color SoftPWMSet(greenPin, green); // Set green component of color SoftPWMSet(bluePin, blue); // Set blue component of color } |
This time we are going to use the setColor function to generate any color of our choice. Its just a user-defined function and it takes three inputs as the arguments. Its job is to mix these color, and it’s done by changing the Red, Green, and Blue color values.
Now; let’s control these RGB LED Strips using the Ultrasonic Sensor.
I want the Arduino to turn ON the RED Leds; when there is an obstacle in front of the Ultrasonic Sensor. And I want the Arduino to turn ON the Green LEDs when there is nothing in front of the Ultrasonic Sensor. So, let’s go ahead and take a look at the program.
RGB LED Strips and Ultrasonic Sensor:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
#include <SoftPWM.h> // Include the SoftPWM library // Define the pin numbers for the RGB strips const int bluePin = 11; const int redPin = 12; const int greenPin = 13; // Define the pin for the ultrasonic module #define ULTRASONIC_PIN 10 void setup() { SoftPWMBegin(); // Initialize software-based PWM on all pins } void loop() { // Read distance from ultrasonic sensor float distance = readSensorData(); if (distance > 50) { // If it's safe to move forward setColor(0, 255, 0); // Set the color to green delay(1000); } else if (distance < 15 && distance > 1) { // If there's an obstacle close setColor(255, 0, 0); // Set the color to red delay(1000); } else { // For distances in between, proceed with caution setColor(0, 255, 0); // Set the color to green delay(1000); } } // Define a function to set color void setColor(int red, int green, int blue) { SoftPWMSet(redPin, red); // Set red component of color SoftPWMSet(greenPin, green); // Set green component of color SoftPWMSet(bluePin, blue); // Set blue component of color } float readSensorData() { // A 4ms delay is required, otherwise the reading may be 0 delay(4); //Set to OUTPUT to send signal pinMode(ULTRASONIC_PIN, OUTPUT); // Clear the trigger pin digitalWrite(ULTRASONIC_PIN, LOW); delayMicroseconds(2); // Trigger the sensor by sending a high pulse for 10us digitalWrite(ULTRASONIC_PIN, HIGH); delayMicroseconds(10); // Set the trigger pin back to low digitalWrite(ULTRASONIC_PIN, LOW); //Set to INPUT to read pinMode(ULTRASONIC_PIN, INPUT); // pulseIn returns the duration of the pulse on the pin float duration = pulseIn(ULTRASONIC_PIN, HIGH); // Calculate the distance (in cm) based on the speed of sound (340 m/s or 0.034 cm/us) float distance = duration * 0.034 / 2; return distance; } |
This program is the combination of Ultrasonic Avoidance example and the RGB Led strip example. We simply measure the distance using the ultrasonic sensor and then use some if conditions to check the distance and then accordingly control the LED strips. Rest of the code, you can see, is exactly the same.
By default, when there is nothing in front of the Ultrasonic Sensor; the Green LEDs are turned ON.
And when the Ultrasonic Sensor detects any object then the Red LEDs are turned ON.
Now, let’s go ahead and measure the battery voltage.
Robot Battery Voltage Monitoring:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
#define BATTERY_PIN A3 // This pin reads the voltage of the battery // This function reads the battery voltage float batteryGetVoltage() { // Reads the analog value from the battery pin int adcValue = analogRead(BATTERY_PIN); // Converts the analog value to voltage float adcVoltage = adcValue / 1023.0 * 5 * 2; // Rounds the voltage to two decimal places float batteryVoltage = int(adcVoltage * 100) / 100.0; return batteryVoltage; } // This function calculates the battery percentage based on its voltage uint8_t batteryGetPercentage() { float voltage = batteryGetVoltage(); // Gets the battery voltage // Maps the voltage to a percentage. int16_t temp = map(voltage, 6.6, 8.4, 0, 100); // Ensures the percentage is between 0 and 100 uint8_t percentage = max(min(temp, 100), 0); return percentage; } void setup() { Serial.begin(115200); pinMode(BATTERY_PIN, INPUT); // Sets the battery pin as an input } void loop() { // Prints the calculated battery voltage Serial.print(" Voltage:"); Serial.print(batteryGetVoltage()); // Prints the calculated battery percentage Serial.print(" Percentage:"); Serial.println(batteryGetPercentage()); delay(1000); } |
For the battery voltage monitoring we have this program. You can see the battery pin is connected to the Arduino Analog pin A3.
Then we have this user-defined function batteryGetVoltage(), its return type is float, and it doesn’t take any argument as the input.
We read the battery pin using the analogRead() function and then store the value in variable adcValue.
Next, we convert this value into voltage.
Next, we round the voltage value to two decimal places.
And then finally; we return the batteryVoltage.
We have another user-defined function to calculate the battery percentage based on its voltage.
First, we store the battery voltage in variable voltage.
Next, we map the voltage to a percentage and store it in the variable temp. 6.6 is the minimum battery voltage when it’s fully discharged, and 8.4 is the maximum battery voltage when the battery is fully charged.
This line of code ensures that the variable percentage is within the range of 0 to 100. If temp is less than 0, percentage will be set to 0. If temp is greater than 100, percentage will be set to 100. Otherwise, percentage will be set to the value of temp. You can read more about the min() and max() functions in the article.
1 |
min(temp, 100): |
This part of the code compares the value of temp with 100.
The min function returns the smaller of the two values.
If temp is greater than 100, min(temp, 100) will return 100.
If temp is less than or equal to 100, min(temp, 100) will return temp.
1 |
max(min(temp, 100), 0): |
This part of the code takes the result from min(temp, 100) and compares it with 0.
The max function returns the larger of the two values.
If the result from min(temp, 100) is less than 0, max(min(temp, 100), 0) will return 0.
If the result from min(temp, 100) is greater than or equal to 0, max(min(temp, 100), 0) will return that result.
Finally, we return the percentage.
Inside the setup(), I have activated the serial communication and this time I am using 115200 as the baud rate.
Using the pinMode(), I have set the BATTERY_PIN as the INPUT.
And then in the loop() function, we send the battery actual voltage and percentage to the Serial monitor.
Master Robotics, Lesson 5 Video: