Introduction: 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

Step 1: 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.

Step 2: How the Motor Controller Works

Pin NumberPin NameDescription
1Enable 1,2When this is HIGH the left part of the IC will work and when it is low the left part won’t work.
2Input 1When this pin is HIGH the current will flow though output 1
3Output 1This pin should be connected to one of the terminal of motor 1
4GroundGround pin
5GroundGround pin
6Output 2This pin should be connected to one of the terminal of motor 1
7Input 2When this pin is HIGH the current will flow though output 2
8Vcc2Connected to voltage which will be supplied to the motors (4.5V to 36V)
9Enable 3,4When this is HIGH the right part of the IC will work and when it is low the right part won’t work.
10Input 3When this pin is HIGH the current will flow though output 3
11Output 3This pin should be connected to one of the terminal of motor 2
12GroundGround pin
13GroundGround pin
14Output 4This pin should be connected to one of the terminal of motor 2
15Input 4When this pin is HIGH the current will flow though output 4
16Vcc1Connected 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.

Step 3: 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.

Step 4: 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);
}

Step 5: 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.