Robotics Mechanical 2024

Autonomous Rover
Prototype

A four-wheeled ground rover capable of basic obstacle avoidance using ultrasonic sensors. The chassis was designed in SolidWorks and 3D-printed; navigation logic runs on an Arduino Uno.

Arduino C++ SolidWorks 3D Printing Ultrasonics
// The Problem & Solution

Mechanical Design

The challenge was to build a rover that could navigate an obstacle course entirely on its own, without any remote input. I needed a compact chassis stiff enough to handle uneven surfaces, yet light enough that two small DC motors could propel it at a usable speed.

Starting in SolidWorks, I modelled every structural component — the base plate, motor mounts, and sensor arm — as a parametric assembly so dimensions could be tweaked quickly. After a few FEA checks for stress at the motor mounts, I exported the parts for FDM 3D printing in PLA. Tolerances were dialled in over three print iterations until the wheel fit was snug with no slop.

The final chassis weighs just 340 g, runs on a 7.4 V LiPo pack, and has a ground clearance of 12 mm — plenty for indoor testing on carpet and tile.

// The Code & Electronics

Software & Sensing

An HC-SR04 ultrasonic sensor sits on a pan servo at the front. The Arduino Uno fires 40 kHz pulses every 60 ms and measures the echo return time. If an obstacle is detected within 25 cm, the rover halts, sweeps the servo left and right to compare distances, then steers toward the clearer path.

Motor speed is handled via PWM through an L298N H-bridge, giving independent control of each side. A simple PD correction loop keeps the rover tracking straight on open ground.

C++ · Arduino rover_nav.ino
// Measure distance via HC-SR04
long getDistance() {
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  long duration = pulseIn(ECHO_PIN, HIGH);
  return duration * 0.034 / 2; // cm
}

void loop() {
  long dist = getDistance();

  if (dist < OBSTACLE_THRESHOLD) {
    stopMotors();
    int leftDist  = scanSide(-60);
    int rightDist = scanSide( 60);

    (leftDist > rightDist) ? turnLeft() : turnRight();
  } else {
    driveForward();
  }
}

What I Learned

📡

Sensor Noise & Filtering

Raw ultrasonic readings are surprisingly noisy — stray echoes from walls and carpet fibres caused the rover to brake erratically. I implemented a five-sample rolling-median filter which cut false positives by ~80% and made steering decisions far more stable.

Motor Speed Calibration

No two DC motors are identical — even from the same pack, one side ran ~12% faster. I measured the open-loop RPM of each motor and offset the PWM duty cycle accordingly. Future iterations will use encoders for closed-loop speed matching.

🖨️

Iterative 3D Printing

Tolerances that looked fine in SolidWorks didn't survive the printer's dimensional variance. I learned to design 0.3 mm of clearance into every press-fit joint and to prototype moving parts at 20% infill first before committing to structural prints.

// Explore Further

See It in Action

The full source code is on GitHub. A demo video walkthrough is on YouTube.