Maze-Solving Robot (MPU6050 + PID Control)

An autonomous maze-solving robot built with Arduino, utilizing three ultrasonic sensors for spatial awareness and an MPU6050 IMU for precise directional control. The robot employs a wall-following algorithm combined with a dual-PID system to maintain stability and accuracy. This robot competed in INSAT Robolympix 4.0 in the autonomous challenge.

๐Ÿ“ฆ Libraries & Initialization

The MPU6050 IMU handles all orientation tracking. These libraries are essential for I2C communication and gyro data processing:

#include <Wire.h>
#include <MPU6050_tockn.h>

MPU6050 mpu6050(Wire);  // Initialize the IMU

๐Ÿ”Œ Pin Mapping

ComponentPinFunction
Left MotorPWM 6 (Fwd), 3 (Bwd)Locomotion
Right MotorPWM 5 (Fwd), 9 (Bwd)Locomotion
Ultrasonic FrontTrig 12 / Echo 13Obstacle detection
Ultrasonic LeftTrig 4 / Echo 10Wall detection
Ultrasonic RightTrig 7 / Echo 8Wall detection
MPU6050I2C (SDA/SCL)Gyroscopic heading
Start Button2Calibration & launch
LED11Status indicator

๐Ÿ“ก Ultrasonic Sensor Reading

Each sensor reading is averaged over multiple samples to reduce noise. The pulseIn() timeout prevents infinite blocking:

long readSensor(int trig, int echo) {
  digitalWrite(trig, LOW);
  delayMicroseconds(2);
  digitalWrite(trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig, LOW);
  long duration = pulseIn(echo, HIGH, 30000);
  if (duration == 0) return sensorMax;
  long dist = duration * 0.034 / 2;
  return constrain(dist, sensorMin, sensorMax);
}

๐ŸŽฎ Motor Control Functions

Simple abstractions for driving, stopping, and differential movement:

void stopMotors() {
  analogWrite(in1, 0); analogWrite(in2, 0);
  analogWrite(in3, 0); analogWrite(in4, 0);
}

void driveForward(int spd) {
  analogWrite(in1, spd); analogWrite(in2, 0);
  analogWrite(in3, spd); analogWrite(in4, 0);
}

void setMotors(int l, int r) {
  analogWrite(in1, constrain(l, 0, 255)); analogWrite(in2, 0);
  analogWrite(in3, constrain(r, 0, 255)); analogWrite(in4, 0);
}

๐Ÿง  PID Control โ€” Straight Line Walking

When moving forward, the robot uses a full PID loop to ensure perfectly straight travel, correcting for motor inconsistencies or physical bumps.

void pidStep() {
  mpu6050.update();
  float error = sleft() - sright();  // Keep centered between walls
  integral += error;
  integral = constrain(integral, -100, 100);
  derivative = error - preverror;
  float correction = Kp * error + Ki * integral + Kd * derivative;
  int l = constrain(basespeed + correction, minspeed, maxspeed);
  int r = constrain(basespeed - correction, minspeed, maxspeed);
  setMotors(l, r);
  preverror = error;
}

๐Ÿ”„ Pivot PID โ€” Precise Turns

Precise 90ยฐ turns are difficult with simple timers due to battery voltage fluctuations. This PD controller handles it:

void pivotToAngle(float target_angle) {
  t = millis();
  while (true) {
    mpu6050.update();
    float current_yaw = mpu6050.getAngleZ();
    float turn_error = target_angle - current_yaw;
    
    if (abs(turn_error) < 5) { stopMotors(); break; }
    if (millis() - t > 2500) { break; }
    
    float turn_diff = turn_error - last_turn_error;
    float turn_correction = (p_turn * turn_error) + (d_turn * turn_diff);
    last_turn_error = turn_error;
    int motor_pwm = constrain(turn_base_speed + abs(turn_correction), 0, max_pwm);
    
    if (turn_error > 0) {
      // Turn LEFT
      analogWrite(in1, motor_pwm); analogWrite(in2, 0);
      analogWrite(in3, 0); analogWrite(in4, motor_pwm);
    } else {
      // Turn RIGHT
      analogWrite(in1, 0); analogWrite(in2, motor_pwm);
      analogWrite(in3, motor_pwm); analogWrite(in4, 0);
    }
  }
  tangle = target_angle;
  integral = 0; preverror = 0;
}

โ†ช๏ธ U-Turn Function

Two consecutive 78ยฐ pivots (since 90ยฐ was overshooting in testing):

void uTurn() {
  pivotToAngle(78);
  delay(100);
  pivotToAngle(78);
}

๐Ÿƒ The Algorithm โ€” Right-Hand Rule

The robot implements the Right-Hand Rule (wall follower). This is an "uninformed" maze-solving algorithm where the robot keeps the right wall at a constant relative distance.

Decision Priority:

  1. Turn Right: If right sensor detects an opening (dist > 24cm), move forward slightly, then execute -79ยฐ pivot.
  2. Drive Forward: If right turn not possible but front path clear, continue forward using PID stabilization.
  3. Turn Left: If right AND front blocked but left open, execute +79ยฐ pivot.
  4. U-Turn (Dead End): If all three sides blocked, perform ~165ยฐ pivot to backtrack.
void loop() {
  pidStep();
  if(right()){
    driveForward(basespeed);
    delay(50); stopMotors(); delay(150);
    pivotToAngle(tangle - 79);
    stopMotors(); delay(150);
    // Drive into new cell
    t = millis();
    while(millis() - t < 650) { pidStep(); }
  }
  else if(left() && !forward() && !right()){
    driveForward(basespeed);
    delay(50); stopMotors(); delay(150);
    pivotToAngle(tangle + 79);
    stopMotors(); delay(100);
    t = millis();
    while(millis() - t < 650) { pidStep(); }
  }
  else if(!left() && !forward() && !right()){
    pivotToAngle(tangle - 165);  // U-turn
    delay(50);
  }
}

โš™๏ธ PID Tuning Parameters

These values were calibrated specifically for the robot's weight, motor response, and maze surface:

// Walking PID
float Kp = 15;
float Ki = 0.05;
float Kd = 0.1;

// Turn PID
float p_turn = 40.0; 
float d_turn = 3;

// Speed limits
int basespeed = 180;
int maxspeed  = 255;
int minspeed  = 100;
int turn_base_speed = 30;
int max_pwm = 70;

๐Ÿš€ Setup & Calibration

On power-up, the robot waits for the start button. During this time, the MPU6050 calculates gyro offsets โ€” the robot must stay perfectly still. The LED blinks to indicate waiting state:

void setup() {
  Wire.begin();
  mpu6050.begin();
  // ... pinModes ...
  
  mpu6050.calcGyroOffsets(true);
  
  while (digitalRead(startButton) == LOW) {
    digitalWrite(led, (millis() / 500) % 2);  // Blink LED
    delay(50);
  }
}

๐ŸŽฏ Key Takeaways


๐Ÿ† Competed in INSAT Robolympix 4.0 โ€” Autonomous Challenge

This project taught me more about control theory than any textbook ever could. Breaking the PID loop, watching the robot oscillate, tuning Kp until it screamed down the straightaway โ€” that's real engineering.

โ† back to all posts