Skip to content

Repository files navigation

FPV Head Tracking Module

A wireless head tracker that converts head movements into RC radio commands for FPV flying. Pitch, roll, and yaw from your head are sent as a PPM signal to your radio's trainer port β€” no PC required.

πŸ“Ί YouTube build video: Build Video

πŸ“Ί YouTube flight test: Watch on YouTube πŸ–¨οΈ 3D printable case: Thingiverse #7389266


How It Works

Head movement β†’ BNO085 IMU β†’ ESP32-C3 β†’ PPM signal β†’ 3.5mm cable β†’ Radio trainer port β†’ Sim / Aircraft

The head tracker plugs into the trainer port of any EdgeTX/OpenTX radio. A switch on the radio toggles between normal stick control and head-tracker input, so you can always take over manually.


Status

  • βœ… Software emulator with 3D web interface
  • βœ… PPM output via RMT hardware (jitter free)
  • βœ… BNO085 real IMU firmware tested working
  • βœ… Calibration button for zeroing axes
  • βœ… Passive buzzer feedback (startup melody, calibration, errors, battery warnings)
  • βœ… Battery voltage monitoring with low/critical beep warnings
  • βœ… 3D printed case with headset mount and handheld variants β€” Thingiverse
  • βœ… Final assembly complete
  • ⏳ Field testing (see YouTube channel for updates)

Repository Structure

headtracking-module/
β”œβ”€β”€ 01-head_tracker_emulator/       # PPM emulator with WiFi + 3D web UI (test without IMU)
β”œβ”€β”€ 02-bno085_wiring_test/          # Verify BNO085 wiring and axis directions
β”œβ”€β”€ 03-buzzer_test/                 # Test buzzer patterns and find resonant frequency
β”œβ”€β”€ 04-battery_wifi_test/           # Battery voltage monitor with web UI for calibration
β”œβ”€β”€ 05-head_tracker_bno085/         # Main firmware β€” IMU + PPM + buzzer + battery
β”œβ”€β”€ images/
β”‚   └── wiring_diagram.svg          # Wiring schematic
β”œβ”€β”€ ppm_demo.html                   # Interactive visualisation of PPM signal
β”œβ”€β”€ README.md
β”œβ”€β”€ WIRING.md                       # Detailed wiring guide
└── LICENSE

The sketches are numbered in the recommended build order β€” flash and test each one to verify each subsystem before moving to the main firmware.


Hardware

Part Details
ESP32-C3 SuperMini Main controller
TENSTAR BNO085 9-axis IMU, VR/AR optimised
1S Li-ion / LiPo battery Power (any 3.7V battery works)
TP4056 module Battery charging via USB-C
Slider switch Power on/off
6x6mm momentary button IMU calibration
Passive buzzer Audio feedback (~2kHz resonant)
2x 10kΞ© resistors Battery voltage divider
PJ-341 3.5mm TRS jack Panel mount in case
Vention 3.5mm TRS cable 1.5m PPM signal to radio
Perfboard 4x6cm Switch/button mounting
Velcro straps Goggle mounting

See WIRING.md for the complete wiring diagram and pin assignments. 3D printable case files on Thingiverse.


Software Setup

Arduino IDE

  1. Add ESP32 board URL in File β†’ Preferences β†’ Additional Board Manager URLs:
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
  1. Install esp32 by Espressif Systems via Board Manager

  2. Select board: ESP32C3 Dev Module

  3. Set USB CDC On Boot β†’ Enabled

  4. Install libraries via Library Manager:

    • WebSockets by Markus Sattler (needed for 01-head_tracker_emulator and 04-battery_wifi_test)
    • Adafruit BNO08x (needed for BNO085 firmware)
    • Adafruit Unified Sensor (dependency)
    • Adafruit BusIO (dependency)

Build Order (Recommended)

The numbered folders correspond to the recommended build sequence. Flash and verify each one before moving to the next:

Step Sketch What to verify
1 01-head_tracker_emulator PPM output reaches radio, channels respond in EdgeTX channel monitor
2 02-bno085_wiring_test I2C communication works, all 3 axes respond to tilt
3 03-buzzer_test Buzzer sounds, find loudest frequency for your specific buzzer
4 04-battery_wifi_test Calibrate voltage divider against multimeter reading
5 05-head_tracker_bno085 Main firmware with your calibrated values

Main Firmware Usage

  1. Wire all components per WIRING.md
  2. Adjust calibration values in 05-head_tracker_bno085.ino:
    • DIVIDER_RATIO β€” from your resistor measurements
    • ADC_CORRECTION and BATT_CALIB β€” from battery test sketch
    • INVERT_PITCH/ROLL/YAW β€” from BNO085 axis test
  3. Flash to ESP32-C3
  4. Power on β€” listen for the startup melody (4 ascending notes)
  5. Connect 3.5mm cable to radio trainer port
  6. In EdgeTX: Model β†’ Trainer β†’ Master/PPM, assign enable switch
  7. Put on headset, look forward, press calibration button (1 beep confirms)
  8. Fly!

Beep patterns

Sound Meaning
4 ascending notes (C-E-G-C) Startup β€” board ready
1 beep Calibration confirmed
2 spaced beeps Battery LOW (<3.5V) β€” every 30s
5 fast beeps Battery CRITICAL (<3.3V) β€” every 5s
1 long beep (looping) BNO085 not found

Emulator Usage

For testing without hardware (just ESP32 + 3.5mm cable β€” no IMU needed):

  1. Flash 01-head_tracker_emulator.ino to ESP32
  2. Connect to WiFi: HeadTracker / password: flyfpv123
  3. Open browser: http://192.168.4.1
  4. Drag 3D head to control axes

Web UI controls:

Input Axis
Left drag horizontal Yaw
Left drag vertical Pitch
Right drag horizontal Roll
Q / E keys Roll left / right
Arrow keys Pitch + Yaw
RESET CENTER button Zero all axes

PPM Channel Mapping

Channel Axis Range
CH1 Roll (lean left/right) Β±45Β°
CH2 Pitch (nod up/down) Β±45Β°
CH3 β€” center β€”
CH4 Yaw (turn left/right) Β±90Β°
CH5–8 β€” center β€”
  • PPM pulse width: 300Β΅s (matches Radiomaster default)
  • PPM frame: 22,500Β΅s

See ppm_demo.html for an interactive visualisation of the PPM signal.


Radio Setup (RadioMaster TX16S)

  1. Connect 3.5mm TRS cable to trainer port on top of the radio
  2. Model Settings β†’ Trainer β†’ Master/PPM
  3. Map channels: CH1=Roll, CH2=Pitch, CH4=Yaw
  4. Assign trainer enable switch (SD or SH recommended for momentary override)
  5. Flip switch to activate head tracking, flip back for full stick control

Works with any EdgeTX/OpenTX radio that has a 3.5mm PPM trainer port.


Technical Details

PPM Implementation

Uses the ESP32 RMT (Remote Control Transceiver) hardware peripheral via a dedicated FreeRTOS task β€” pulse timing is handled in hardware, immune to WiFi stack interruptions.

Key details:

  • rmtSetEOT(PPM_PIN, 1) keeps pin HIGH between frames (prevents CH1 jitter)
  • Channel values updated atomically (locals computed first, then assigned)
  • Exponential smoothing on all axes

Battery Monitoring

The ESP32-C3 ADC needs some care:

  • Use GPIO 0 for the battery ADC input β€” GPIO 2 has a hardware pullup that pollutes readings
  • Firmware includes ADC_CORRECTION to compensate for ADC nonlinearity at 11dB attenuation
  • The 04-battery_wifi_test sketch helps calibrate all three values (divider ratio, ADC correction, offset) via a live web interface

Tuning

Axis inversion

In 05-head_tracker_bno085.ino, flip flags if an axis is backwards for your mount:

#define INVERT_PITCH  false
#define INVERT_ROLL   false
#define INVERT_YAW    true

Sensitivity

Adjust deflection range:

#define PITCH_RANGE   45.0f   // Β±45Β° = full stick deflection
#define ROLL_RANGE    45.0f
#define YAW_RANGE     90.0f

Smoothing

#define SMOOTH 0.5f  // 0.1 = very smooth, 1.0 = no smoothing

Battery calibration

Determined empirically using 04-battery_wifi_test:

#define DIVIDER_RATIO  2.077f   // (R1 + R2) / R2
#define ADC_CORRECTION 0.886f   // ESP32-C3 ADC nonlinearity fix
#define BATT_CALIB     -0.13f   // fine-tune offset

Compatible Radios

Any radio with a 3.5mm PPM trainer port and EdgeTX/OpenTX:

  • RadioMaster TX16S βœ… (tested)
  • RadioMaster Pocket ELRS
  • RadioMaster Zorro
  • RadioMaster Boxer
  • Any EdgeTX/OpenTX radio with trainer port

Credits & Links


License

MIT β€” see LICENSE

About

Fly FPV drones with your head. A DIY wireless head tracker using ESP32-C3 + BNO085 IMU that plugs into any EdgeTX radio trainer port.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages