Skip to content
← All projects

Project / Robotics

Autonomous Desk Vacuum Cleaner

Role
Solo build
Timeline
Add date
Context
Personal project
Tools
Arduino Motor control Robotics

At a glance

Problem
Desks accumulate solder flux residue, component offcuts, and dust. Cleaning by hand is tedious; a small autonomous robot can do it hands-free while you work.
Approach
Differential-drive Arduino robot with two HC-SR04 ultrasonic sensors — one for edge detection, one as a touchless wave-to-activate toggle. Random-bounce navigation keeps the robot on the desk surface for a 2-minute cleaning cycle.
Outcome
Robot navigates a desk surface autonomously, reliably detects and avoids edges, runs its fan while moving, and shuts itself down at the end of each timed cycle.
EK210 team with the desk vacuum project
Fig. 1 — Assembled desk vacuum robot.

Overview

This is a small differential-drive robot built around an Arduino and an L298N dual H-bridge motor driver, designed to autonomously navigate a desk surface and vacuum up debris. The robot drives forward continuously until a downward-facing HC-SR04 ultrasonic sensor detects an edge closer than 10 inches, then stops, reverses for 1.5 seconds, and pivots a random amount before continuing. A second ultrasonic sensor mounted at the front acts as a touchless toggle — waving a hand within 10 cm starts or stops a 2-minute cleaning cycle.

Battery voltage is monitored through a 2.7 kΩ / 1 kΩ resistor divider on the Arduino's analog input and displayed on a 16×2 I2C LCD alongside a countdown timer during operation. The fan is driven through a MOSFET and only powered when the robot is actively moving forward, which extends battery life since suction is unnecessary during reversing and turning maneuvers.

Design decisions

Ultrasonic edge detection

Using an HC-SR04 ultrasonic sensor for edge detection gives a real distance measurement rather than a binary near/far signal from IR. The threshold is set to 10 inches, which provides enough reaction time for the motors to stop before the robot reaches the edge regardless of surface color or lighting — both of which can throw off IR reflectance sensors.

Random-bounce navigation

The navigation algorithm is deliberately simple: go straight until hitting a boundary, then reverse and turn. The turn duration is randomized between 1100 and 1300 ms using Arduino's random() seeded from a floating analog pin, which prevents the robot from tracing the same path repeatedly. The right motor runs at 0.975× the commanded speed to compensate for a small torque mismatch between the two motors that would otherwise cause the robot to drift in a curve during straight-line motion.

Touchless wave-to-activate toggle

A dedicated HC-SR04 sensor handles activation instead of a physical button. The firmware uses rising-edge detection on the proximity signal — a single wave within 10 cm toggles the robot on or off, while sustained proximity does nothing after the initial trigger. This lets the robot be started and stopped without touching it while it's running on a desk that may have work spread across it.

Fan gating

The suction fan is MOSFET-switched and only enabled while the robot is moving forward. During reversing and turning — which together account for roughly 30–40% of active time — the fan is off. In the final three seconds of the run cycle, the motors stop but the fan stays on at full speed to clear any debris that was just reached, then everything shuts down together.

Desk vacuum wiring schematic 1
Fig. 2 — Wiring schematic, sheet 1.
Desk vacuum wiring schematic 2
Fig. 3 — Wiring schematic, sheet 2.
Technical details
Parameter Value Notes
MCU Arduino 5 V, 16 MHz
Motor driver L298N Dual H-bridge, PWM speed control
Drive Differential (2-wheel) Right motor trimmed to 0.975× for straight tracking
Motor speed 69 / 255 PWM ~27% duty cycle
Edge sensor HC-SR04 ultrasonic Stop threshold: 10 in, pins 10 / 11
Toggle sensor HC-SR04 ultrasonic Activation threshold: 10 cm, pins 13 / 12
Fan MOSFET-switched, PWM pin 5 Full speed (255) while moving forward only
Battery 12 V Monitored via 2.7 kΩ / 1 kΩ divider on A0
Display 16×2 I2C LCD Address 0x27, shows countdown + battery %
Runtime 2 min / cycle Auto-shutoff, toggle to restart
Turn duration 1100 – 1300 ms Randomized to avoid repeated paths
Arduino — key snippets

Edge detection + random bounce

void runVacuumBehavior() {
  float distanceIN = getDistanceIN(trigMain, echoMain);

  if (distanceIN < setDistanceIN) {        // no edge — drive forward
    moveForward(motorSpeed);
    analogWrite(fanPin, fanSpeed);
  } else {                                  // edge detected
    stopMotors();
    delay(1000);

    // reverse
    analogWrite(enA, motorSpeed);  digitalWrite(in1, LOW);  digitalWrite(in2, HIGH);
    analogWrite(enB, 0.975 * motorSpeed); digitalWrite(in3, LOW); digitalWrite(in4, HIGH);
    delay(1500);
    stopMotors(); delay(1000);

    // random turn (1100–1300 ms)
    randNumber = random(1100, 1300);
    analogWrite(enA, motorSpeed);  digitalWrite(in1, HIGH); digitalWrite(in2, LOW);
    analogWrite(enB, 0.975 * motorSpeed); digitalWrite(in3, LOW); digitalWrite(in4, HIGH);
    delay(randNumber);
    stopMotors(); delay(1000);
  }
}

Wave-to-activate toggle (rising-edge detection)

if (millis() - lastToggleSample >= US_SAMPLE_INTERVAL) {
  float toggleDist = getDistanceCM(trigToggle, echoToggle);
  bool currentToggleState = (toggleDist > 0 && toggleDist <= toggleThresholdCM);

  // only trigger on rising edge — sustained presence does nothing
  if (currentToggleState && !lastToggleState) {
    active = !active;
    if (active) {
      startTime = millis();
    } else {
      stopMotors();
      analogWrite(fanPin, 15);   // fan off
    }
  }
  lastToggleState = currentToggleState;
  lastToggleSample = millis();
}