Preview build — page text is a draft awaiting human review. Code badges come from real compiles. The flasher is real but not yet hardware-tested; the Playground is still a preview.
Maze-Solving Robot: the finished build
NanoRobotics

Wall-following maze robot with three ultrasonic sensors (Arduino Nano)

Keeps a hand on the left wall — and that’s enough to get out of most mazes.

Difficulty
Hard
Build time
5 h
Parts cost
₹1,940 · $23
Verified — core avr 1.8.8, 3 Nov 2026Compile-only

Community draft — report a mistake

Parts list

PartQtyApprox.Buy
Arduino Nano (CH340, ATmega328P)1₹280Buy Arduino Nano (CH340, ATmega328P)
HC-SR04 ultrasonic sensor3₹270Buy HC-SR04 ultrasonic sensor
TB6612FNG dual motor driver1₹180Buy TB6612FNG dual motor driver
N20 metal gear motors 6 V 300 RPM + brackets + 34 mm wheels2₹600Buy N20 metal gear motors 6 V 300 RPM + brackets + 34 mm wheels
Ball caster1₹40Buy Ball caster
2× 18650 Li-ion cells + holder with switch (7.4 V)1₹350Buy 2× 18650 Li-ion cells + holder with switch (7.4 V)
Small chassis plate (acrylic or PCB, about 12 × 10 cm)1₹120Buy Small chassis plate (acrylic or PCB, about 12 × 10 cm)
Mini breadboard + jumper wires1₹100Buy Mini breadboard + jumper wires
Total₹1,940

Affiliate disclosure: “Buy” links may earn FlashReady a small commission at no extra cost to you. Prices are indicative.

Wiring

Arduino NanoOnly the pins used are shown · 5 V logic2× 18650 Li-ion pack (7.4 V) with switchHC-SR04 ultrasonic sensorHC-SR04 ultrasonic sensor #2HC-SR04 ultrasonic sensor #3TB6612FNG dual DC motor driver+-A1A25VGNDVIND12D11D10D9D8D7D6D5D4D3D2VCCTrigEchoGNDVCCTrigEchoGNDVCCTrigEchoGNDVMVCCGNDA01 → Left motor (+)A02 → Left motor (−)B02 → Right motor (−)B01 → Right motor (+)PWMAAIN2AIN1STBYBIN1BIN2PWMB
Every connection
Arduino NanoPart · pinWireNotes
—TB6612FNG dual DC motor driver · A01—To Left motor (+) (not drawn)
—TB6612FNG dual DC motor driver · A02—To Left motor (−) (not drawn)
—TB6612FNG dual DC motor driver · B01—To Right motor (+) (not drawn)
—TB6612FNG dual DC motor driver · B02—To Right motor (−) (not drawn)
5VHC-SR04 ultrasonic sensor · VCCred
D2HC-SR04 ultrasonic sensor · TrigpurpleLeft sonar
D3HC-SR04 ultrasonic sensor · Echogreen
GNDHC-SR04 ultrasonic sensor · GNDblack
5VHC-SR04 ultrasonic sensor #2 · VCCred
D7HC-SR04 ultrasonic sensor #2 · TrigpurpleFront sonar
D8HC-SR04 ultrasonic sensor #2 · Echogreen
GNDHC-SR04 ultrasonic sensor #2 · GNDblack
5VHC-SR04 ultrasonic sensor #3 · VCCred
A1HC-SR04 ultrasonic sensor #3 · TrigpurpleRight sonar (A1/A2 used as digital pins)
A2HC-SR04 ultrasonic sensor #3 · Echogreen
GNDHC-SR04 ultrasonic sensor #3 · GNDblack
D5TB6612FNG dual DC motor driver · PWMAorangeLeft motor speed
D9TB6612FNG dual DC motor driver · AIN1yellow
D10TB6612FNG dual DC motor driver · AIN2green
D6TB6612FNG dual DC motor driver · PWMBorangeRight motor speed
D11TB6612FNG dual DC motor driver · BIN1blue
D12TB6612FNG dual DC motor driver · BIN2cyan
D4TB6612FNG dual DC motor driver · STBYwhiteHIGH = driver awake
5VTB6612FNG dual DC motor driver · VCCredLogic at 5 V, like the Nano
GNDTB6612FNG dual DC motor driver · GNDblackCommon ground: battery −, driver and Nano
2× 18650 Li-ion pack (7.4 V) with switch · +TB6612FNG dual DC motor driver · VMredMotor supply after the switch
2× 18650 Li-ion pack (7.4 V) with switch · -TB6612FNG dual DC motor driver · GNDblack
VIN2× 18650 Li-ion pack (7.4 V) with switch · +redThe same switched + runs the Nano (VIN, 7–12 V in)

Board quirks: The left-hand rule only works for mazes where every wall connects to the outer wall (“simply connected”). Mazes with islands in the middle — some competition mazes are built that way on purpose — need a mapping algorithm such as flood fill. The 90° turns are timed (<code>TURN_MS</code>), not measured. Tune it on your floor with a charged battery; as the battery drops the turns get shorter. Wheel encoders or an MPU6050 fix this properly. The three sonars fire one after another with a pause between them, so one sensor never hears another’s echo. Li-ion 18650 cells can catch fire if shorted or over-discharged: use a holder with a switch, protected cells, a proper Li-ion charger, and never leave the robot charging unattended.

Code

wall-following-maze-robot.inoArduino C++Open in PlaygroundOpen in PlaygroundFlash
// Wall-following maze robot — Arduino Nano + 3× HC-SR04 + TB6612FNG + 2 N20 gear motors
// Sonars (Trig/Echo): left D2/D3, front D7/D8, right A1/A2, all at 5V.
// TB6612FNG: PWMA D5, AIN1 D9, AIN2 D10 (left), PWMB D6, BIN1 D11, BIN2 D12 (right), STBY D4,
// VCC 5V, VM from the 2S Li-ion pack. It keeps a wall on its LEFT at a set distance (the
// "left-hand rule"): turn left into every opening, go straight if you can, turn right if blocked.
// That solves any maze whose walls are all connected — most school and fest mazes.
constexpr uint8_t L_TRIG = 2, L_ECHO = 3, F_TRIG = 7, F_ECHO = 8, R_TRIG = A1, R_ECHO = A2;
constexpr uint8_t PWMA = 5, AIN1 = 9, AIN2 = 10, PWMB = 6, BIN1 = 11, BIN2 = 12, STBY = 4;
constexpr int WALL_CM = 8;         // distance to keep from the left wall
constexpr int FRONT_STOP_CM = 9;   // wall ahead closer than this → turn right
constexpr int OPENING_CM = 25;     // left reading beyond this = an opening on the left
constexpr int BASE = 150;          // cruising PWM (0–255)
constexpr float KP = 9;            // steering gain: PWM per cm of error
constexpr int TURN_MS = 330;       // time for a 90° pivot at TURN_PWM — tune on your floor
constexpr int TURN_PWM = 170;

void motor(uint8_t pwm, uint8_t a, uint8_t b, int speed) {
  digitalWrite(a, speed > 0 ? HIGH : LOW);
  digitalWrite(b, speed < 0 ? HIGH : LOW);
  analogWrite(pwm, constrain(abs(speed), 0, 255));
}
void drive(int left, int right) {
  motor(PWMA, AIN1, AIN2, left);
  motor(PWMB, BIN1, BIN2, right);
}

// Distance in cm; 100 when nothing echoes within ~1 m (an open side).
int sonar(uint8_t trig, uint8_t echo) {
  digitalWrite(trig, LOW);
  delayMicroseconds(2);
  digitalWrite(trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig, LOW);
  unsigned long us = pulseIn(echo, HIGH, 6000UL);
  delay(8);  // let the echo die out before the next sonar fires (no crosstalk)
  return us ? us / 58 : 100;
}

void pivot(int dir) {  // dir −1 = left, +1 = right, 90° by time
  drive(0, 0);
  delay(60);
  drive(dir * TURN_PWM, -dir * TURN_PWM);
  delay(TURN_MS);
  drive(0, 0);
  delay(60);
}

void setup() {
  Serial.begin(115200);
  const uint8_t outs[] = {L_TRIG, F_TRIG, R_TRIG, PWMA, AIN1, AIN2, PWMB, BIN1, BIN2, STBY};
  for (uint8_t p : outs) pinMode(p, OUTPUT);
  pinMode(L_ECHO, INPUT);
  pinMode(F_ECHO, INPUT);
  pinMode(R_ECHO, INPUT);
  digitalWrite(STBY, HIGH);  // driver awake
  drive(0, 0);
  Serial.println(F("Maze robot: starting in 3 s"));
  delay(3000);
}

void loop() {
  int left = sonar(L_TRIG, L_ECHO), front = sonar(F_TRIG, F_ECHO), right = sonar(R_TRIG, R_ECHO);
  Serial.print(F("L "));
  Serial.print(left);
  Serial.print(F(" F "));
  Serial.print(front);
  Serial.print(F(" R "));
  Serial.print(right);

  if (left > OPENING_CM) {
    // Opening on the left: roll forward so the body clears the corner, then turn into it.
    Serial.println(F(" -> left"));
    drive(BASE, BASE);
    delay(200);
    pivot(-1);
    drive(BASE, BASE);
    delay(250);
  } else if (front < FRONT_STOP_CM) {
    Serial.println(right > OPENING_CM ? F(" -> right") : F(" -> dead end, turn round"));
    pivot(1);
    if (right <= OPENING_CM) pivot(1);  // blocked on three sides: U-turn
  } else {
    // Corridor: steer to hold WALL_CM from the left wall.
    int error = left - WALL_CM;  // positive = drifting away from the wall → steer left
    int steer = constrain((int)(KP * error), -80, 80);
    drive(BASE - steer, BASE + steer);
    Serial.println(F(" -> follow"));
  }
}

Compiled for nano on avr 1.8.8 · 3 Nov 2026

How it works

Put your left hand on the wall at a maze’s entrance and keep it there; you will walk out of any maze whose walls are all joined together. This robot does exactly that with sound instead of a hand. It’s a classic event at school science fairs and college robotics fests, and a good step up from line following: the robot has to steer by distance, not by a black line.

The left-hand rule in code

Every loop the Nano reads three HC-SR04 sonars — left, front and right — and decides:

  1. Opening on the left (left distance over 25 cm): roll forward 200 ms so the body clears the corner, pivot left 90°, and drive into the new corridor.
  2. Wall ahead (front under 9 cm): pivot right. If the right side is closed too, it’s a dead end — pivot right twice (a U-turn).
  3. Otherwise, follow the corridor: a proportional controller compares the left distance with the target 8 cm and steers by the difference — steer = KP × (left − 8), limited to ±80 — slowing one wheel and speeding up the other.

Each decision is printed to Serial with the three distances, which makes tuning on the floor much easier with a long USB cable.

Why these parts

  • HC-SR04 sonars are cheap and measure 2–100 cm well; a maze wall straight beside the robot is an ideal target. The sketch waits at most 6 ms per echo (about 1 m) and treats no echo as “open”.
  • The TB6612FNG loses much less voltage than an L298N and is small enough for a maze robot. Its logic runs at 5 V with the Nano; PWM speed on D5/D6.
  • N20 metal gear motors turn slowly and evenly, which matters for timed turns.

The Nano takes the battery straight into VIN (7–12 V) and its 5 V regulator feeds the three sonars and the driver’s logic — about 60 mA in total.

Building a test maze

Corridors of about 20–25 cm with walls at least 10 cm tall work well — cardboard boxes cut into strips and taped to the floor are enough. Keep the walls smooth and vertical; corrugated edges and gaps confuse the sonars.

Troubleshooting

It zig-zags along the corridor

KP is too high for your robot. Halve it, then raise it slowly until it tracks the wall smoothly.

It turns left in the middle of a corridor

The left sonar sometimes misses the wall (no echo reads as 100 cm = an opening). Mount it level and pointing square at the wall; ultrasound reflects poorly off a wall at an angle.

Turns are too short or too long

Adjust TURN_MS in steps of 20 ms until a pivot is a clean 90° on your surface.

Upgrades

  • Add wheel encoders and turn by counting ticks instead of time.
  • Record the turns and remove dead ends (the classic L-S-R-B shortening) for a faster second run.
  • Replace the HC-SR04s with VL53L0X laser sensors for small micromouse-style mazes.

↑↓ to move · Enter to open