Inspiration

We wanted to recreate the modern social experience of playing video games with friends by bringing co-op gameplay into the real world! Enter Adventure Bugs; the digital generation's key to collaborative outdoor exploration. The goal was simple: make hardware feel social—a drop-in platform that turns any place into an interactive playground.


What it does

Adventure Bug is a remote-controlled mini rover built on a Seeed Studio XIAO ESP32S3 Sense.

  • Creates its own Wi-Fi network (AP) so it works anywhere (no internet needed).
  • Streams a live camera feed to a webpage.
  • Lets you control movement using WASD / arrow keys (plus on-screen buttons).
  • Drives using differential drive (2× TT motors + DRV8833 motor driver).

The math behind the motion (with every part explained)

1) Differential-drive kinematics

We model the rover as two wheels (left/right) separated by a track width (L).

$$ v=\frac{v_R+v_L}{2}, \qquad \omega=\frac{v_R-v_L}{L} $$

What each symbol means

  • \(v_L\): left wheel linear speed
  • \(v_R\): right wheel linear speed
  • \(v\): robot forward speed
  • \(\omega\): robot angular speed (turn rate)
  • \(L\): distance between wheels (track width)

Intuition

  • If \(v_L=v_R\), the rover goes straight (\(\omega=0\)).

- If \(v_L=-v_R\), the rover spins in place (\(v=0\)).

2) Turning keyboard inputs into motor commands

We turn keys into two control signals:

  • \(u_f \in {-1,0,1}\): forward/back intent

    • \(1\)=forward (W/↑), \(-1\)=back (S/↓), \(0\)=stop
  • \(u_t \in {-1,0,1}\): turning intent

    • \(1\)=right (D/→), \(-1\)=left (A/←), \(0\)=no turn

Then we compute motor targets:

$$ m_L=\operatorname{clip}(u_f-u_t,-1,1), \qquad m_R=\operatorname{clip}(u_f+u_t,-1,1) $$

What each part means

  • \(m_L, m_R\): normalized left/right motor command (range \([-1,1]\))
  • \(\operatorname{clip}(\cdot)\): clamps values so we never exceed safe limits
    Finally, PWM is proportional to command magnitude:

$$ \text{PWM} = P \cdot |m| $$

  • (P): chosen max PWM (sets top speed)
  • (|m|): how hard we drive
  • sign of (m) sets direction (forward vs reverse)

3) Camera stream bandwidth (why resolution/FPS matters)

A simple raw bandwidth estimate is:

$$ R_{\text{raw}}=\text{FPS}\cdot W\cdot H\cdot \text{bpp} $$

  • \(R_{\text{raw}}\): raw bits/sec (before compression)
  • \(\text{FPS}\): frames per second
  • \(W, H\): width/height in pixels
  • \(\text{bpp}\): bits per pixel
    In practice we stream compressed frames, but this explains why higher FPS/resolution can overload the link.

How we built it

Hardware

  • XIAO ESP32S3 Sense (camera + Wi-Fi)
  • DRV8833 dual H-bridge motor driver
  • 2× TT motors + wheels + caster/skid
  • **10V Power supply

Core wiring (XIAO → DRV8833)

XIAO Pin GPIO DRV8833 Pin Motor
D0 GPIO1 AIN1 Left motor
D1 GPIO2 AIN2 Left motor
D2 GPIO3 BIN1 Right motor
D3 GPIO4 BIN2 Right motor
3V3 — VCC Logic power (if needed)
GND — GND Common ground
Battery+ — VM Motor power (3.7V)
Battery- — GND Ground

Important: DRV8833 VM goes directly to the battery, not through the XIAO regulator.


Software

  • Firmware written in Arduino IDE
  • Libraries:

    • ESPAsyncWebServer
    • AsyncTCP

The ESP32 runs:

  • a web server (UI)
  • a WebSocket server (low-latency control)
  • a camera stream server

Expected boot output (Serial @115200)

  • Camera initialized OK
  • AP IP: 192.168.4.1
  • Web server on port 80, stream on 81

Frontend control (browser)

  • Keyboard input (WASD / arrow keys)
  • Mobile-friendly on-screen buttons
  • Sends compact commands like F, B, L, R, S over WebSocket
  • Displays connection status (“Connected”) + live feed

Challenges we ran into

  • Power separation: Buck Converter/motors introduced noise / brown-outs if wiring and grounds aren’t clean.
  • Raspberry Pi SSH + networking issues: direct connection worked, but SSH kept rejecting passwords (“Permission denied”), and some networks block device-to-device traffic.
  • Camera stability: ESP32 camera depends heavily on correct PSRAM settings and stream constraints.
  • Latency tuning: making keypress → WebSocket → motion feel instant required minimal messages and tight handling.

Accomplishments that we're proud of

  • Fully offline control (ESP32 AP mode) — works anywhere.
  • Live camera + real-time driving from a normal browser (no joystick needed).
  • A clear “from scratch” setup flow so others can reproduce it quickly.
  • Smooth differential-drive behavior with a simple, explainable control model.

What we learned

  • How to build an embedded stack: Wi-Fi AP + web UI + WebSockets + camera streaming on ESP32.
  • Why PSRAM configuration is critical for camera-based projects.
  • Real-world debugging: power issues, control systems, faulty connections
  • How lightweight math (clipping + differential drive) makes controls feel reliable.

What's next for Adventure Bugs

  • PID speed control for smoother steering and straighter driving.
  • Battery monitoring + low-voltage cutoff for safety.
  • Gamepad/joystick mode and adjustable sensitivity.
  • Simple autonomy: obstacle avoidance / line following / waypoint moves.
  • Adaptive streaming (auto-adjust FPS/resolution by link quality).
  • Optional spectator mode: one driver, multiple viewers.

Built With

Share this project:

Updates

Submission history