ESP32 Turret: Face Tracking + Live Wi-Fi Stream

by gcorica in Circuits > Cameras

173 Views, 2 Favorites, 0 Comments

ESP32 Turret: Face Tracking + Live Wi-Fi Stream

Screenshot 2025-12-30 210200.png
IMG_7718.jpeg

I built a tiny 3D-printed pan-tilt “robot eye” that can stream live video over Wi-Fi and (optionally) track a face by rotating to keep the target centered. It’s powered by two SG90 micro-servos (pan+tilt), an ESP32-CAM for video+detection, and an ESP32 dev board that drives the motion smoothly.

It’s part security camera, part robotics demo, and part why is my desk staring at me? For the web server screenshots, I’m Rick-rolling myself instead of showing my face… because privacy is cool and Rick Astley is eternal.

Make It Spin? The turret’s entire job is spinning, smoothly sweeping left/right while streaming video like a tiny Wi-Fi periscope.

Supplies

IMG_7724.jpeg
IMG_7722.jpeg
IMG_7721.jpeg

Parts

  1. 1x ESP32-CAM (AI Thinker) + MB programmer board
  2. 1x ESP32 dev board (ESP32-WROOM)
  3. 2x SG90 9g micro servos
  4. I used the screws that came with the servos
  5. 2x Micro USB cables
  6. 8x Jumper wires

Tools

  1. Arduino IDE
  2. 3D printer (I used my school’s FlashForge)
  3. Cura (Ultimaker Cura slicer)
  4. PLA filament

3D CAD+Printing the Turret

F7ZWTNWMJOYR4ZC.png
Screenshot 2025-12-30 210238.png
Screenshot 2025-12-30 210338.png
Screenshot 2025-12-30 210419.png

I designed the turret as a modular pan-tilt mount that:

  1. Mounts the double horn of a standard SG90 servo inthe base for pan
  2. A second SG90 mounted on the pan platform
  3. A camera mount, mounted on the single horn of the second servo
  4. camera mount sized for the ESP32-CAM module to slide in with no screws
  5. Everything is designed to be a majority press fit with as little extra hardware as possible

CAD workflow

  1. CAD software: Autodesk Fusion 360
  2. I pulled the servo + ESP32-CAM reference CAD models from Autodesk’s library/community resources (huge time saver and helps the fit be correct).
  3. Then I designed the bracket system around those models (clearances, screw holes, horn alignment).

Printing

  1. Material: PLA
  2. Printer: FlashForge (school printer)
  3. Slicer: Ultimaker Cura
  4. Recommended settings:
  5. 0.2 mm layer height
  6. 15–25% infill
  7. supports only where needed (I used three supports)

Designing around real CAD models makes the build repeatable. Anyone following this can print it and have the electronics fit without hot glue engineering, unless you want the hot glue aesthetic. No judgment, we've all been there.

Mechanical Assembly

  1. Install the pan SG90 onto the base mount
  2. Attach the pan platform to the pan SG90
  3. Install the tilt SG90 into the tilt bracket
  4. Attach the camera mount to the single horn of the tilt SG90
  5. Mount the ESP32-CAM to the camera mount
  6. Make sure the camera has clearance to tilt without hitting the frame
  7. Pass the wires behind to the breadboard
  8. Tip: You can use some tape to secure the wires and have them out of the way

Tip: Before powering anything, gently rotate through the full range to make sure it doesn’t bind.

Wiring (Do This or Servos Will Gaslight You)

IMG_7725.jpeg
IMG_7723.jpeg

Power rules

  1. SG90 servos need 5V power
  2. ESP32 logic is 3.3V
  3. The #1 rule: all grounds must be common

Wiring

Servo power

  1. Servo red --> 5V supply
  2. Servo brown/black --> GND supply

Servo signals ESP32-WROOM

  1. Pan signal --> GPIO 25
  2. Tilt signal --> GPIO 26

ESP32-CAM

  1. Powered via the MB board or 5V input
  2. Used for streaming video + optional detection

Code a - ESP32-CAM

What this code does

  1. Connects the ESP32-CAM to your Wifi.
  2. Starts a simple MJPEG video stream you can open in any browser.
  3. Open with "http://<your ip address>"
  4. Captures frames at QQVGA (160×120) for maximum speed.
  5. Runs face detection a few times per second.
  6. Computes the face center error:
  7. ex = faceX − centerX
  8. ey = faceY − centerY
  9. Applies a small deadband to reduce jitter (ignores tiny motion).
  10. Sends ex/ey/found to the turret over ESP-NOW at a steady update rate.

ESP32-CAM code (Upload using Espressif ESP32 board manager version 1.0.6)

  1. Board Name: AI Thinker ESP32-CAM.
  2. Edits to make: ssid, password, MAC address.

Downloads

Code B: ESP32 WROOM

What this code does:

  1. Connects the ESP32-WROOM to the same wifi as the ESP32-CAM.
  2. Attaches two SG90 servos using hardware.
  3. Listens for ESP-NOW packets containing ex/ey/found from the ESP32-CAM.
  4. Uses a proportional control loop:
  5. panTarget = pan − Kp*ex (mirrored, because you’re facing each other)
  6. tiltTarget = tilt − Kp*ey (can toggle if inverted)
  7. Applies smoothing so motion looks robotic, not twitchy.

ESP32-WROOM code (Upload using Espressif ESP32 board manager version 3.x)

  1. Board Name: your ESP32-WROOM dev board
  2. Important: Servos must have 5V power and a common ground with the ESP32.
  3. Edits to make: ssid, password.


First Boot

Untitled design (7).png

Open:

  1. http://<IP>/ to see video + status
  2. http://<IP>/status to see just the tracking values (great for debugging)

For the screenshot, I pointed the camera at a Rick Astley video instead of my face.

  1. Keeping my privacy :)
  2. Excuse to rickroll my instructable

What to do on first boot:

  1. Power the servos from 5V, not from the ESP32.
  2. Tie servo GND to ESP32 GND (common ground).
  3. Upload Code A to the ESP32-CAM (version 1.0.6).
  4. Upload Code B to the ESP32-WROOM (version 3.x).
  5. Put both devices on the same 2.4GHz hotspot (this keeps ESP-NOW on the same channel).
  6. Open the Serial Monitor for the ESP32-CAM and copy the IP address.
  7. Go to the IP in your browser and confirm the stream loads.

Expected outcomes:

  1. ESP32-CAM Serial Monitor prints:
  2. IP: ...
  3. Wi-Fi Channel: ...
  4. The browser shows the live stream page
  5. /status updates and shows found, ex, ey


Troubleshooting

The turret won’t move at all

  1. Check servo power: SG90s need real 5V current
  2. Check common ground (servo GND and ESP32 GND must connect)
  3. Confirm both boards are on the same hotspot (channel match)

Stream works, but it stays 0

  1. Increase lighting
  2. Move closer to the camera
  3. Reduce JPEG quality number (fewer compression artifacts):
  4. try JPEG_QUALITY_NUM = 18
  5. Ensure mtmn_config.min_face = 40; is set (important at QQVGA)

It tracks but jitters

  1. Increase deadband to 10
  2. Reduce Kp to 0.04
  3. Increase smooth to 0.45


Results and Improvements

IMG_7720.jpeg

Results:

  1. Fully 3D-printed pan-tilt camera turret
  2. Live Wi-Fi video streaming to a browser
  3. Face-centered tracking using ESP32-CAM detection + ESP-NOW control
  4. Mirrored the pan so it behaves correctly when facing you

Improvements / Next Version Ideas:

  1. Add “search mode” (scan until face found)
  2. Add a battery for fully wireless operation
  3. Add cable routing
  4. Upgrade control to PID for smoother motion
  5. Add a “privacy mode” switch