Guide to The Self-Driving Car Prototype: Programming an ESP32 Cam on a 2WD Chassis with MicroPython and TinyYOLO

The Self‑Driving Car Prototype: Programming an ESP32‑Cam on a 2WD Chassis with MicroPython & TinyYOLO

Welcome to this step‑by‑step tutorial guide. You will learn how to turn a simple 2‑wheel‑drive (2WD) chassis into a miniature self‑driving car using an ESP32‑Cam, MicroPython, and the lightweight TinyYOLO object detection model. All code is ready to copy, and each hardware connection is illustrated with clear inline graphics.

Why This Prototype?

The combination of MicroPython and TinyYOLO brings AI inference to the edge with minimal power consumption. By the end of this guide you will have a working autonomous car that can:

  • Capture live video from the ESP32‑Cam.
  • Detect obstacles and lane markings using TinyYOLO.
  • Control motor speed and steering via PWM.
  • Log telemetry to a local SD card.

Materials & Tools

Component Quantity Notes
ESP32‑Cam (AI‑Thinker) 1 128 KB SRAM, OV2640 camera
2WD Chassis Kit 1 Includes motor driver board (L298N)
Micro‑USB to TTL Converter 1 For flashing firmware
MicroSD Card (8 GB) 1 Logs images & telemetry
Jumper Wires, 5 V Power Bank Assorted Male‑to‑female, 20‑30 cm

1. Set Up the Development Environment

  1. Install Python 3.10+ on your workstation.
  2. Open a terminal and run:
    pip install esptool adafruit-ampy
  3. Download the latest MicroPython firmware for ESP32‑Cam from micropython.org (choose esp32‑cam‑v1.20.bin).
  4. Clone the TinyYOLO repository:
    git clone https://github.com/ultralytics/tiny-yolo-v3-micropython.git

2. Flash MicroPython onto the ESP32‑Cam

Connect the ESP32‑Cam to the TTL converter (GND → GND, 3.3 V → VCC, TX → RX, RX → TX). Hold the BOOT button while plugging the USB into your PC. Run the following commands:

# Erase flash
esptool.py --port COM3 erase_flash

# Write MicroPython firmware
esptool.py --chip esp32 --port COM3 --baud 460800 write_flash -z 0x1000 esp32-cam-v1.20.bin

After flashing, press RESET. The ESP32‑Cam now boots into MicroPython REPL.

3. Wire the 2WD Chassis to the ESP32‑Cam

Use the L298N driver to control two DC motors. Keep the wiring tidy to avoid signal noise.

  • ENA → ESP32‑Cam GPIO 14 (PWM for left motor)
  • IN1 → GPIO 12 (direction left)
  • IN2 → GPIO 13 (direction left)
  • ENB → GPIO 27 (PWM for right motor)
  • IN3 → GPIO 26 (direction right)
  • IN4 → GPIO 25 (direction right)
  • Camera SDA/SCL → GPIO 21/22 (optional I2C sensors)
  • SD card slot connects directly to ESP32‑Cam’s SD pins.

💡 Tip: Secure the camera module on the chassis front with double‑sided tape to keep the field of view steady.

4. Load the TinyYOLO Model onto the ESP32‑Cam

MicroPython cannot run full TensorFlow models, but TinyYOLO (v3) is ~30 KB and fits comfortably in the ESP32’s RAM.

  1. Copy tiny_yolo.py and tiny_yolo.weights to the device:
    ampy --port COM3 put tiny_yolo.py
    ampy --port COM3 put tiny_yolo.weights
  2. Verify the files:
    ampy -p COM3 ls

5. Write the Self‑Driving Script

Copy the following script into main.py. It initializes the camera, runs TinyYOLO on each frame, and adjusts motor PWM based on detected objects.

import machine, time, uos
import camera
import tiny_yolo

# ---- Motor pins -------------------------------------------------
LEFT_PWM   = machine.PWM(machine.Pin(14), freq=1000)
RIGHT_PWM  = machine.PWM(machine.Pin(27), freq=1000)
LEFT_DIR1  = machine.Pin(12, machine.Pin.OUT)
LEFT_DIR2  = machine.Pin(13, machine.Pin.OUT)
RIGHT_DIR1 = machine.Pin(26, machine.Pin.OUT)
RIGHT_DIR2 = machine.Pin(25, machine.Pin.OUT)

def set_motor(left_speed, right_speed, left_fwd=True, right_fwd=True):
    # speed: 0‑1023 (0‑100%)
    LEFT_PWM.duty(left_speed)
    RIGHT_PWM.duty(right_speed)
    LEFT_DIR1.value(1 if left_fwd else 0)
    LEFT_DIR2.value(0 if left_fwd else 1)
    RIGHT_DIR1.value(1 if right_fwd else 0)
    RIGHT_DIR2.value(0 if right_fwd else 1)

# ---- Camera setup ------------------------------------------------
camera.init(0, format=camera.JPEG, framesize=camera.FRAME_QVGA)
camera.flip(0)   # adjust orientation if needed

# ---- TinyYOLO model ------------------------------------------------
model = tiny_yolo.YOLO('tiny_yolo.weights', threshold=0.4)

def auto_drive():
    while True:
        buf = camera.capture()
        objs = model.detect(buf)
        # Simple rule: if a person is ahead, stop; else move forward
        stop = any(o['label'] == 'person' and o['conf'] > 0.5 for o in objs)
        if stop:
            set_motor(0, 0)
        else:
            set_motor(700, 700)  # ~70% speed forward
        time.sleep_ms(100)

try:
    auto_drive()
except KeyboardInterrupt:
    set_motor(0, 0)
    camera.deinit()

Upload the script:

ampy -p COM3 put main.py

After reboot, the car starts moving automatically.

6. Test and Calibrate

Place the prototype on a flat surface and observe the following:

  • Steering response: Adjust PWM values (0‑1023) for smoother turns.
  • Detection latency: Typical inference time is ≈180 ms. Reduce framesize if you need faster response.
  • Power stability: A 5 V power bank delivering at least 2 A keeps the motors and camera running without brown‑out.

Use a simple print() debug statement inside the loop to watch object confidence values in the serial monitor.

Troubleshooting

Problem Check

Comments

Popular posts from this blog

Guide to Low-Cost Agricultural Surveying: Designing an Outdoor Rover via APM Rover Firmware and 3D Printed Chassis

Guide to Simulating and Building a Mecanum-Wheel Omnidirectional Robot using FreeRTOS and ESP32

Ready to Start?

Become Part of the ICT Club Community

Many learners are already building the technology skills that improve their daily work performance. Your journey starts today.