Head-Tracking Camera Gimbal
๐ข Start โ zero knowledge, plain words. ๐ก Hands-on โ building, specifics and tradeoffs. ๐ด Advanced โ the physics and math behind it. โซ Master โ extend it.
Turn your head, and a camera on your desk turns with you. This project needs no drone at all โ it reuses gear you already own if you fly FPV (goggles, radio, an ELRS receiver) plus one small open-source board and two cheap servos. It's the best first project on this site because it exercises the exact same three layers a real quad uses โ sensing, the radio link, and actuation โ in a rig you can debug sitting at a desk instead of chasing across a field.
What you're buildingโ
Two spare channels on your radio carry head orientation instead of stick input. Everything downstream of the radio โ the ELRS link, the receiver, the PWM output โ is identical to what already flies your drone.
๐ข Start โ the idea in plain wordsโ
A gyroscope on your goggles measures how your head is rotating; a small board turns that into two numbers (pan angle, tilt angle) and feeds them to your radio as if they were two extra stick channels. The radio sends them out over the same 2.4 GHz link it already uses for your drone (Module 1 โ Radio & communication links), a receiver on the desk rig picks them up, and two servos physically point a camera the way your head is pointing. No new wireless system, no new protocol to learn โ you're reusing the control link you already have.
๐ก Hands-on โ parts and buildโ
| Part | Choice (example) | Notes |
|---|---|---|
| Head tracker board | (open source: HeadTracker) โ runs on Arduino Nano 33 BLE-class boards | Outputs PPM, SBUS, or CRSF; connects to your radio by wire (trainer port) or Bluetooth on supported EdgeTX radios |
| Mount | 3D-printed or Velcro clip on the goggle strap | Keep it near your head's center of rotation to minimize parallax |
| Radio | Any EdgeTX radio with a free trainer/CRSF input | Mix the two head-tracker channels onto free AUX channels |
| Receiver | Any spare ELRS RX with 2 free PWM outputs | The same kind you already run on a quad |
| Servos | 2ร SG90-class micro servos (pan + tilt) | A cheap pan-tilt bracket (printable) holds them at 90ยฐ to each other |
| Power | 5 V BEC or a small regulated supply | Servos are current-hungry under load โ don't starve them off a USB port |
| Payload | Phone clip, laser pointer, or an actual FPV camera | Start with a laser pointer on a wall โ mistakes are instantly visible and free |
Build order:
- Flash the head-tracker firmware to your board and set its output protocol (start with PPM โ simplest to verify with a servo tester before involving the radio at all).
- Wire the board to your radio's trainer port (or pair it over Bluetooth if your radio supports it) and confirm two channels move in the radio's channel monitor when you turn your head.
- Mix those channels onto two free AUX channels in your radio's model setup.
- Bind an ELRS receiver, wire its two PWM outputs to the pan and tilt servos, and power the rig from the bench supply โ no camera yet.
- Center-trim both servos before they ever hold weight, then mount the payload and test full range of motion slowly, watching for mechanical binding.
If you mix head-tracker channels onto a model profile you also use to fly, double-check those AUX channels aren't already assigned to arm, flight-mode, or failsafe switches on that model. Give this rig its own dedicated model profile on the radio to avoid any chance of cross-wiring a drone's arm switch to a servo mix.
๐ด Advanced โ the mathโ
Orientation estimation. The head tracker runs the same estimation problem as Module 3 โ Sensors & state estimation: a gyroscope integrated over time drifts, an accelerometer is noisy but has no drift, and a complementary filter blends them:
For head tracking, roll is usually ignored (you don't tilt your head much while flying) and yaw/pitch are what drive the two servos.
Angle to servo pulse. A hobby servo's position is set by pulse width, not voltage or PWM duty cycle: 1000 ยตs is one end of travel, 2000 ยตs the other, 1500 ยตs center. Mapping an angle over a servo's usable range to a pulse in microseconds:
Smoothing. Raw head motion is jittery; feeding it straight to a servo produces a twitchy, unpleasant image. The fix is the same one-line exponential filter from Module 9 โ Tuning & flight-test analysis, just applied to a servo setpoint instead of gyro noise:
A small (โ0.1โ0.2) trades responsiveness for smoothness โ the exact same tradeoff as a gyro lowpass filter, just running orders of magnitude slower.
Latency budget. Head movement โ IMU sample โ filter โ radio frame โ ELRS link โ receiver โ servo PWM is a shorter version of the stick-to-motor chain from Module 0 โ Foundations & orientation. Every hop adds a few milliseconds; a sluggish-feeling tracker is almost always over-smoothed (ฮฑ too small), not an RF problem โ the ELRS link itself is normally the fastest link in the whole chain.
โซ Master โ extend itโ
- Swap the laser pointer for a real FPV camera and VTX on the pan-tilt rig: now you're flying-by-head-look at your desk before a single motor spins.
- Add a companion computer running OpenCV so the gimbal tracks a target instead of your head โ this is the same architecture as Module 11 โ Navigation & autonomy's companion-computer diagram, just with a webcam instead of GNSS driving the setpoints.
- Write your own firmware instead of flashing HeadTracker: read a 6-axis IMU over I2C/SPI, run the complementary filter yourself, and output PPM by bit-banging a timer interrupt โ the same "read sensor โ estimate โ command actuator" loop as Module 8 โ Coding the flight controller, just with a servo instead of a motor at the end of it.
- Move the whole rig onto an actual cinematic drone as a real, wearable camera gimbal โ the servo math above doesn't change; only the vibration environment does.
A minimal servo mapper, if you write your ownโ
If you'd rather not flash someone else's firmware, this is the entire control loop in Arduino-flavoured C++ โ read two orientation values however your IMU library gives them to you, smooth them, and drive two servos:
#include <Servo.h>
Servo panServo, tiltServo;
float emaYaw = 0, emaPitch = 0;
const float alpha = 0.15; // smoothing โ see Module 9's PT1 filter
void setup() {
panServo.attach(9);
tiltServo.attach(10);
}
void loop() {
float yaw, pitch;
readOrientation(yaw, pitch); // your IMU + complementary filter (Module 3)
emaYaw += alpha * (yaw - emaYaw);
emaPitch += alpha * (pitch - emaPitch);
panServo.write(mapAngle(emaYaw, -90, 90));
tiltServo.write(mapAngle(emaPitch, -45, 45));
}
int mapAngle(float angle, float lo, float hi) {
angle = constrain(angle, lo, hi);
return (int)((angle - lo) / (hi - lo) * 180.0);
}
Servo::write() takes degrees and handles the microsecond pulse math shown
above internally โ worth reading once from the library source so the
abstraction stops being magic.
Related reading: Module 1 โ Radio & communication links, Module 3 โ Sensors & state estimation, Module 8 โ Coding the flight controller.