Roomba Maze Navigator Robot
This was a project where the goal was to navigate a maze that would be set up with certain conditions. Some of these conditions included 50cm distance between walls, reduction in points for hitting walls, and only the using the components provided.
Supplies
Materials Needed:
- Aluminum Sheet
- 2 Wheels
- 3 Ultrasonic Sensors
- 1500mAh 11.1V Battery (Need 11.1V for the motors used)
- 2 DC Geared Motors with Encoders (SPG-30E-XXXK)
- L293D Dual Motor Controller Module
- Arduino Mega 2560 (Other Arduinos work to)
- Breadboard
- Wires
- Mounts and covers (3D printed)
- 2 Ball bearings and casing
Equipment Needed:
- 3D Printer
- Manual metal bending machine
- Drill press
- Vertical Milling Machine
Create the Chasis
The chassis fabrication began with a precise cut using a vertical milling machine, shaping it to the desired form. Then, the edges were folded at 90-degree angles allowing there to be mounts for the sensors. After shaping, the sensor and ball bearing holes were drilled using a drill press, followed by cleaning up the edges with a file for safety. Finally, individual screw holes were created using a drill to secure different components in place.
Alternatively, for weight reduction, the chassis could be produced using 3D printed filament like PLA or ABS depending on individual needs.
Downloads
How the Motor Controller Works
Pin Number | Pin Name | Description |
---|---|---|
1 | Enable 1,2 | When this is HIGH the left part of the IC will work and when it is low the left part won’t work. |
2 | Input 1 | When this pin is HIGH the current will flow though output 1 |
3 | Output 1 | This pin should be connected to one of the terminal of motor 1 |
4 | Ground | Ground pin |
5 | Ground | Ground pin |
6 | Output 2 | This pin should be connected to one of the terminal of motor 1 |
7 | Input 2 | When this pin is HIGH the current will flow though output 2 |
8 | Vcc2 | Connected to voltage which will be supplied to the motors (4.5V to 36V) |
9 | Enable 3,4 | When this is HIGH the right part of the IC will work and when it is low the right part won’t work. |
10 | Input 3 | When this pin is HIGH the current will flow though output 3 |
11 | Output 3 | This pin should be connected to one of the terminal of motor 2 |
12 | Ground | Ground pin |
13 | Ground | Ground pin |
14 | Output 4 | This pin should be connected to one of the terminal of motor 2 |
15 | Input 4 | When this pin is HIGH the current will flow though output 4 |
16 | Vcc1 | Connected to +5V to enable IC function |
- The enable pins are used to turn on and off the output pins for each side
- The input pins are connected to the Arduino board and are either set to HIGH or LOW
- The output pins are connected to the positive or negative terminals of the motors
- Ground pins are connected to the ground of the board and battery, not all pins need to be connected as they are internally connected
Below are documentation on pulse width modulation used to control the speed of the motor and the data sheet for the L293 motor controller.
Create Circuit Diagram
For this project the encoders on the motors were not used as they were unnecessary. Above shows how the electronic components of the design were implemented. It is key to make sure the 5V is attached to Vcc1 on the top right of the L293D integrated circuit and the battery of 11.1V or above is attached to Vcc2 on the bottom left. If these are flipped the circuit will be damaged and need to be replaced.
Code
The code below is for Arduino and written in the simplified version of C++. The pins that have been set can be changed from the values assigned below as long as they connect to a digital pin:
#include <NewPing.h>
// Ultrasonic sensor pins
int triggerL = 10; // Trigger pin for left sensor
int echoL = 9; // Echo pin for left sensor
int triggerR = 47; // Trigger pin for right sensor
int echoR = 45; // Echo pin for right sensor
int triggerC = 35; // Trigger pin for center sensor
int echoC = 33; // Echo pin for center sensor
NewPing sonarL(triggerL, echoL); // Left sensor object
NewPing sonarR(triggerR, echoR); // Right sensor object
NewPing sonarC(triggerC, echoC); // Center sensor object
// Motor pins
int in1 = 3; // Motor pin 1
int in2 = 4; // Motor pin 2
int en = 2; // Motor enable pin (left)
int in3 = 5; // Motor pin 3
int en2 = 6; // Motor enable pin (right)
int in4 = 7; // Motor pin 4
// Previous distance variables for comparison
int pDL = 0; // Previous left distance
int pDR = 0; // Previous right distance
int pDC = 0; // Previous center distance
void setup() {
// Initialize pin modes
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
pinMode(en, OUTPUT);
pinMode(in3, OUTPUT);
pinMode(in4, OUTPUT);
pinMode(en2, OUTPUT);
// Initialize serial communication
Serial.begin(9600);
delay(1000); // Delay to stabilize
}
void loop() {
// Read distances from sensors
int dL = sonarL.ping_cm(); // Left distance
int dR = sonarR.ping_cm(); // Right distance
int dC = sonarC.ping_cm(); // Center distance
// Print sensor readings
Serial.print("Left distance: ");
Serial.print(dL);
Serial.print(" cm, Right distance: ");
Serial.print(dR);
Serial.print(" cm, Center distance: ");
Serial.print(dC);
Serial.print(" cm");
// Obstacle avoidance logic
if ((dC < 15 || dR < 6 || dL < 6) && (pDC < 15 || pDR < 15 || pDL < 15)) {
backUp(180, 150); // Reverse
Serial.println(", reverse");
delay(250); // Delay for stability
}
else {
// Forward motion or turning based on sensor readings
if ((pDR + 90 < dR) || (pDL + 90 < dL)) {
forward(220); // Forward using past data
Serial.println(", forward using past");
}
// Additional conditional statements for different scenarios
else if (dL <= dR && dR >= 10 && dR < 35) {
turn(225, 230); // Turn slight right
Serial.println(", turning slight right");
}
else if (dR <= dL && dL >= 10 && dL < 35) {
turn(210, 230); // Turn slight left
Serial.println(", turning slight left");
}
// Additional conditions for cornering
else if (dC <= 35 && dL >= 30 && dL > dR) {
turn(70, 220); // Corner left
Serial.println(", corner left new");
}
else if (dC <= 35 && dR >= 30 && dR > dL) {
turn(220, 70); // Corner right
Serial.println(", corner right new");
}
// Additional conditions for sharper turns
else if (dR >= 50 && dR > dL) {
turn(220, 70); // Corner right
Serial.println(", corner right");
}
else if (dL >= 50 && dL > dR) {
turn(70, 220); // Corner left
Serial.println(", corner left");
}
// Default action: move forward
else {
forward(220); // Forward
Serial.println(", forward");
}
}
// Update previous distances
pDR = dR;
pDC = dC;
pDL = dL;
delay(50); // Delay for stability
}
// Function to move forward
void forward(int speed) {
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);
analogWrite(en, speed);
analogWrite(en2, speed);
}
// Function to turn left
void turn(int sL, int sR) {
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);
analogWrite(en, sL);
analogWrite(en2, sR);
}
// Function to reverse
void backUp(int sL, int sR) {
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);
analogWrite(en, sL);
analogWrite(en2, sR);
}
// Function for ending condition (example)
void endCondition(int sL, int sR) {
// Back up
backUp(sL, sR);
delay(500);
// Spin
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);
analogWrite(en, sL);
analogWrite(en2, sR);
delay(10000);
}
Put It All Together
This design allowed me and my group to achieve a time of 14 seconds to reach the ending. This won first place by about 1 second.
If there is anything I can add to make this better please leave a comment, more than happy to hear any and all feedback.