Auto-Targeting Turret System
A computer vision turret that detects and locks onto a red target in real time using a webcam and servo motor. Python and OpenCV handle the vision and PD control, while an ESP32 drives the hardware over serial - smoothly and without overshoot.
Pipeline · frame → servo
Overview
A real-time auto-targeting turret system that uses a webcam to detect a red object and physically rotate a servo motor to track it. Vision and control logic run entirely in Python, with an ESP32 handling hardware-level servo movement over serial communication.
How It Works
Every frame is converted to HSV. Red sits on both ends of the hue range, so two masks are merged and filtered with morphology. The largest red blob becomes the target. A PD controller measures error and rate of change, then ships a motor angle over serial to the Arduino, which rotates the turret.

Control System · PD loop
Tracking uses a Proportional-Derivative controller instead of a simple follow. P pushes the motor toward the target; D reads the rate of change of error and brakes before the center, preventing overshoot. A hardware slew limiter on the Arduino caps degrees-per-tick for a second layer of smoothness.
Pushes the motor toward the target.
Brakes as error shrinks - no overshoot.
Caps degrees-per-tick in firmware for mechanical smoothness.
Key Features
- Real-time red object detection using dual HSV masking
- Morphological noise filtering before contour detection
- PD controller with tunable gain values for smooth lock-on
- Serial rate-capped at 30Hz to prevent buffer flooding
- Hardware slew limiter on ESP32 for mechanical smoothness
- Exponential decay when target is lost - no sudden snap to center
- Minimum area filter ignores small noise blobs
Challenges & Learnings
Overshoot
ControlEarly on the turret would chase the target and just blow right past it, back and forth, never really settling. The controller had no way to slow itself down as it got close. Once I added a derivative term that brakes based on how fast the error is changing, it stopped oscillating and started locking on smoothly.
Serial flooding
CommsI was sending data every single frame which was way too fast for the Arduino to keep up with. Commands were piling up in the buffer and the turret would lag behind or act on stale data. Capped the serial writes to 30 times per second and it cleared up immediately.
Heap fragmentation
FirmwareThe Arduino kept crashing after running for a while and I couldn't figure out why at first. Turned out the String class constantly allocates and frees memory, and over time that causes instability. Switched to a plain char buffer and the crashes stopped.
Red detection
VisionRed is weird in HSV because it wraps around both ends of the hue range, so one mask wasn't catching everything. Some shades of red were just being ignored. Once I added a second mask for the other end of the range and merged them together, detection became much more consistent.
Hardware
The entire chassis is 3D printed, including base and motor mounts. The base uses an N20 gear motor with a 1:32 ratio for precise rotation. Two Li-ion cells power it. A custom board and the Arduino both connect to the laptop alongside the USB webcam - no Raspberry Pi, everything runs from the laptop.
Software
Vision and control run entirely in Python. OpenCV handles the live feed, colour detection, and on-screen drawing. NumPy powers mask operations and math. PySerial moves commands between the laptop and the Arduino, which drives the motor. Everything talks over serial in real time.