← All work
Project 002 · 2026

Sunny the 4WD Robot

An Arduino 4WD rover that steers itself with a hand-rolled PID loop on gyro yaw data, with gains tunable live over Bluetooth. In build.

RoboticsArduinoPIDControl Theory
ControllerELEGOO UNO R3 + V4.0 IO shield
Drive4WD, 4× 1:48 DC gear motors
Motor driverDRV8835
IMUGY-521 / MPU-6050, I2C
RangingHC-SR04 on SG90 servo gimbal
LinkHC-06 Bluetooth UART
Power7.4 V 2000 mAh LiPo
Firmware6 classes, hand-rolled PID
HEADING θ · GREEN = TOLERANCE BAND

The idea: Robotics fundamentals with no library doing the work

Sunny is a four-wheel-drive autonomous platform built on an Arduino Uno from the ground up. The point of it was to work through robotics fundamentals — motor control, sensor integration, obstacle avoidance, communication protocols, control systems and software architecture — without leaning on pre-built libraries or frameworks.

It is the furthest along of the three builds in this series, and the one where the most has been decided.

The approach: One class per job

The firmware is organised as six classes rather than one loop:

Class Job
Motor_Control Low-level 4WD driving and degree-based turning
Sensors Ultrasonic distance reading, smoothing and averaging
Obstacle_Avoidance Servo sweep and the “find the open path” decision
MPU650_MotionTracking I2C comms with the gyro, calibration, live motion data
PID Proportional/integral/derivative correction
BlueTooth UART command parsing over the HC-06

Obstacle avoidance uses an HC-SR04 on a servo gimbal: the sensor sweeps from 0° to 180°, the firmware picks the clearest open direction, and the robot turns that way.

The build: A PID controller written out longhand

The steering controller is not a library. It takes yaw rate from the gyro as its process variable and trims left and right motor PWM to hold a heading. The integral accumulator, derivative-on-error and Δt handling are all written from scratch, with Δt computed from millis().

The sign of the yaw reading decides which side gets trimmed: drift right and the left motor is slowed by the correction value; drift left and the right motor is slowed instead. The gains are live-editable — sending p, i or d followed by a value over Bluetooth updates the corresponding gain on the fly and echoes the new value back, so tuning needs no recompile and no tether.

The same serial link doubles as manual control mode: single-character F / B / L / R commands drive the car, V sets speed from 0 to 255, and any unrecognised command falls through to a stop.

What broke: The camera module never made it

The original ambition was larger than the robot is now. Line following, with an ESP32 camera for FPV tracking, was part of the plan and is now shelved. The ESP32-WROVER camera module (OV2640) bought for that job is destroyed.

The board was trouble in its own right. It is a third-party module from a lesser-known company, and getting the host computer to talk to it took considerable time. Even once the driver was detected, the upload still required manually flashing the device mid-upload.

So the scope narrowed. Full autonomy and line-following are out of the current plan, and PID steering is what is being worked on now.

The result: What runs today

  • 4WD motor control — forward, backward, left, right, plus timed precision turns on the DRV8835
  • Ultrasonic obstacle avoidance with the 0°–180° servo sweep
  • MPU-6050 gyro integration over I2C, including a calibration routine to zero out drift and the conversion from raw gyro data to turn angles
  • PID steering correction — implemented; the work now is tuning the gains and hardening the serial command parsing
  • Live Bluetooth PID tuning and Bluetooth remote-control mode
  • Class-based firmware architecture

There are no heading-accuracy or drift figures yet, so none are quoted here.

What’s next

  • Tune the PID gains and harden the BlueTooth command parsing
  • Machine-learning perception once the control loop is dialled in
  • Line following and camera FPV tracking stay shelved, not abandoned

What we learned: The bit-level detail is the real curriculum

Getting the MPU-6050 talking over I2C was the learning curve. Each read comes back as a 16-bit packet — the first 8 bits are the register address, the second 8 bits are the actual data — and working out that bit and byte mapping was the moment the rest of the gyro code made sense.