Build a Raspberry Pi Pan-Tilt Camera Tracking Rig with OpenCV Face and Motion Tracking
A fixed security or hobby camera only sees what's directly in front of it, but a pan-tilt rig driven by real-time computer vision can follow a face, a moving pet, or any tracked object around a room — the same underlying capability that powers commercial auto-tracking webcams, built here from a Pi, two hobby servos, and a printed bracket. This project builds on our OpenCV machine vision setup guide and Pi Camera Module deep dive, combining both into a closed-loop tracking system: the camera captures a frame, OpenCV finds the target, and two servos adjust pan and tilt angle to keep it centered.
How the Tracking Loop Works
Each control cycle follows the same four steps: capture a frame from the Pi Camera Module, run a detection pass (Haar cascade or a lightweight DNN face detector for face tracking, or simple frame-differencing/color-blob detection for general motion tracking), calculate how far the detected target is from the frame's center in both X and Y, and convert that offset into small pan and tilt servo movements that nudge the target back toward center. Running this loop at even 10-15 frames per second is enough for smooth, responsive tracking of moderately-paced motion — you don't need full video frame rate, and running detection at a lower resolution than the camera's max significantly reduces CPU load on the Pi.
Mechanical Build
PartRole 3D-Printed Pan-Tilt BracketHolds both servos and the camera module; many free designs exist sized for the standard SG90/MG90S servo footprint Pan Servo (base, horizontal rotation)Rotates the whole tilt assembly left/right Tilt Servo (mounted on pan servo's output)Rotates the camera up/down independent of pan Raspberry Pi + Camera ModuleCaptures video and runs the OpenCV tracking loop PCA9685 PWM Servo Driver (recommended)Offloads precise PWM timing from the Pi's software-timed GPIO, avoiding jitter under CPU loadPrint the bracket in PETG rather than PLA if the rig will sit anywhere warm (near a window, a shop with a heater) — PLA servo horns and brackets can creep under the constant light spring-back load a servo puts on its mount. Mount the tilt servo's body to the pan servo's rotating output horn rather than the reverse, so panning carries the tilt assembly and camera together as a unit; this is the standard pan-tilt kinematic layout and keeps wiring simpler since only the tilt servo's leads need to flex with movement.
Wiring
The Pi's software PWM on GPIO pins works for basic servo tests but introduces visible jitter once the Pi is also running a camera capture and OpenCV processing loop, since Linux isn't a hard-real-time OS and PWM timing competes with everything else running. A PCA9685 I2C PWM driver board (the same class of device covered in our I2C wiring guide) generates clean, jitter-free PWM in hardware and is controlled over I2C with just two GPIO pins regardless of how busy the Pi's CPU is, which makes it the right choice for this project rather than driving servos directly from GPIO.
Software: Detection and Servo Control
- Install OpenCV and the PCA9685 Python library (Adafruit's CircuitPython PCA9685 library works well and handles the I2C protocol details) following the setup in our OpenCV guide linked above.
- For face tracking, load OpenCV's built-in Haar cascade classifier (haarcascade_frontalface_default.xml, included with the OpenCV install) as a fast, CPU-friendly starting point — a full deep-learning face detector is more accurate but noticeably slower on a Pi's CPU without a hardware accelerator.
- On each captured frame, run detection, compute the pixel offset between the detected face's center and the frame's center, and convert that pixel offset into a small servo angle adjustment — a simple proportional controller (move the servo a fraction of the offset each frame, rather than jumping straight to a calculated target angle) produces much smoother tracking than snapping directly to a computed position.
- Clamp servo angles to a safe mechanical range in software (typically 0-180 degrees, but check your specific bracket's actual range of motion without binding) so a false detection at the frame's edge can't drive a servo past its mechanical limit.
- Add a "lost target" timeout — if no face is detected for more than a second or two, stop moving and either hold position or slowly sweep to search, rather than continuing to chase the last known offset.
Tuning for Smooth Tracking
The most common first-build problem is oscillation — the rig overshoots the target, corrects too hard the other way, and hunts back and forth instead of settling. This is the same proportional-control tuning problem covered conceptually in our flight controller PID tuning guide, just running at a much slower timescale: reduce the proportional gain (the fraction of pixel offset you convert into servo movement per frame) until the oscillation stops, then increase it slightly until tracking feels responsive without overshoot. Adding a small dead zone around frame center (don't move the servos at all if the target is within a few percent of center) also eliminates the constant small twitching that a strict proportional controller produces on a slightly-moving target.
Extending the Project
Once basic face tracking works reliably, swapping the detector for a color-blob tracker (useful for tracking a specific colored object rather than a face) or a lightweight object-detection model opens up motion-tracking use cases beyond faces — a pet-following camera, a workshop tool-tracking demo, or a base for a more capable security camera that keeps a moving subject framed automatically. The mechanical and control-loop foundation stays the same regardless of what the detection stage is looking for, which is what makes this pan-tilt base a reusable platform rather than a single-purpose build.
Related Guides
- How to Set Up OpenCV Machine Vision on a Raspberry Pi
- How to Control GPIO Pins on Raspberry Pi with Python
- How to Run a Timelapse Camera with Raspberry Pi
- Automated Plant Watering System with Raspberry Pi
- Controlling GPIO Outputs with Python — LED, Relay, and Buzzer
- Raspberry Pi GPIO: Complete Beginner Guide with Python Examples
- Getting Started with ROS2 on Raspberry Pi for Robotics
- Raspberry Pi AI Camera Module (IMX500): On-Sensor Machine Learning Without an Accelerator HAT