Skip to main content
HATire (Head Arduino Tracker Interface) connects to Arduino-based IMU (Inertial Measurement Unit) devices via serial port. This tracker is perfect for DIY head tracking projects using affordable IMU sensors like the MPU6050, MPU9250, or BNO055.

How It Works

An Arduino microcontroller reads data from an IMU sensor (gyroscope and accelerometer) and sends the orientation data over serial USB to OpenTrack. The HATire tracker parses this data and converts it to head tracking coordinates.
HATire supports rotational tracking (yaw, pitch, roll) and can optionally include positional tracking if your IMU has magnetometer or additional sensors.

Requirements

Hardware

  • Arduino board: Arduino Nano, Uno, Pro Micro, or compatible
  • IMU sensor: One of:
    • MPU6050 (gyro + accel, $2-5)
    • MPU9250 (gyro + accel + mag, $5-10)
    • BNO055 (9-axis with fusion, $20-30)
    • GY-521/GY-85/GY-86 breakout boards
  • Connecting wires: For I2C or SPI connection
  • USB cable: To connect Arduino to PC
  • Mounting: Headset, cap, or headband to wear Arduino + IMU

Software

  • Arduino IDE for programming the Arduino
  • HATire Arduino sketch (available in OpenTrack or DIY community)
  • USB serial drivers (usually automatic)
Total hardware cost is typically $5-30 depending on your choices. This is one of the most affordable head tracking options.

Setup Instructions

1

Build the Hardware

Connect your IMU to the Arduino:For MPU6050 (I2C):
MPU6050 VCC  -> Arduino 5V (or 3.3V)
MPU6050 GND  -> Arduino GND
MPU6050 SCL  -> Arduino A5 (or SCL)
MPU6050 SDA  -> Arduino A4 (or SDA)
For other IMUs: Check the sensor’s datasheet for pinout.
Some 3.3V IMUs can be damaged by 5V. Check your sensor’s voltage rating and use appropriate voltage level.
2

Program the Arduino

  1. Download HATire Arduino sketch
  2. Install required libraries (e.g., MPU6050 library from Jeff Rowberg)
  3. Open sketch in Arduino IDE
  4. Select your Arduino board and COM port
  5. Upload the sketch
  6. Open Serial Monitor to verify data output
The Arduino should output formatted data like:
Roll:123 Pitch:45 Yaw:67
3

Configure Serial Protocol

HATire supports multiple data formats. Configure your Arduino sketch to output:Simple format:
Serial.print("Roll:");
Serial.print(roll);
Serial.print(" Pitch:");
Serial.print(pitch);
Serial.print(" Yaw:");
Serial.println(yaw);
Binary format (more efficient):
  • Send data as binary struct
  • Configure frame start/end markers
  • See HATire protocol documentation
4

Configure in OpenTrack

In OpenTrack tracker settings:
  1. Serial Port: Select Arduino’s COM port
  2. Baud Rate: Match Arduino (typically 115200)
  3. Data Bits: 8
  4. Parity: None
  5. Stop Bits: 1
  6. Flow Control: None
5

Map Axes

Configure which Arduino output maps to which head movement:
Roll Axis: Which data channel is roll (0-5)
Pitch Axis: Which channel is pitch
Yaw Axis: Which channel is yaw
X/Y/Z Axis: Position channels (if available)
Enable/disable and invert axes as needed:
Enable Roll: true
Invert Roll: false (flip if backwards)
# Repeat for other axes
6

Set Commands (Optional)

Configure commands to send to Arduino:
Init Command: Send on startup (e.g., "Init")
Start Command: Send when tracking starts (e.g., "S")
Stop Command: Send when tracking stops (e.g., "s")  
Reset Command: Send to reset IMU (e.g., "R")
Center Command: Send to recenter view (e.g., "C")
Your Arduino sketch must handle these commands.
7

Mount on Head

Secure the Arduino + IMU setup:
  • Use a small project box to protect electronics
  • Mount on headset strap or cap
  • Ensure IMU orientation is consistent
  • Route USB cable to minimize movement
Keep the IMU as close to your head’s rotation center as possible for best accuracy.

Configuration Options

Serial Port Settings

OptionDefaultDescription
Serial Port Name-COM port (COM3, /dev/ttyUSB0, etc.)
Baud Rate115200Communication speed
Data Bits8Bits per byte
ParityNoneError checking
Stop BitsOneStopEnd of byte marker
Flow ControlNoneHardware flow control
DTRfalseData Terminal Ready signal

Axis Mapping

OptionDefaultDescription
Roll Axis1Which data channel (0-5)
Pitch Axis2Which data channel
Yaw Axis0Which data channel
X/Y/Z Axis0Position channels

Axis Control

OptionDefaultDescription
Enable RolltrueUse roll data
Enable PitchtrueUse pitch data
Enable YawtrueUse yaw data
Enable X/Y/ZfalseUse position data
Invert RollfalseFlip roll direction
Invert PitchfalseFlip pitch direction
Invert YawfalseFlip yaw direction

Commands

OptionDefaultDescription
Init Command""Sent during initialization
Start Command""Sent when tracking starts
Stop Command""Sent when tracking stops
Reset Command""Sent to reset IMU
Center Command""Sent to recenter view
Zero Command""Sent to zero position

Timing

OptionDefaultDescription
Init Delay0msWait after init command
Start Delay0msWait after start command
Sequence Delay0msWait after each command

Advanced

OptionDefaultDescription
Big EndianfalseByte order for binary protocol
Enable LoggingfalseLog serial data for debugging

Example Arduino Sketches

Basic MPU6050 Example

#include <Wire.h>
#include <MPU6050.h>

MPU6050 mpu;

void setup() {
  Serial.begin(115200);
  Wire.begin();
  mpu.initialize();
  mpu.setFullScaleGyroRange(MPU6050_GYRO_FS_250);
  mpu.setFullScaleAccelRange(MPU6050_ACCEL_FS_2);
}

void loop() {
  int16_t ax, ay, az;
  int16_t gx, gy, gz;
  
  mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  
  // Calculate angles (simplified - use DMP or complementary filter in practice)
  float roll = atan2(ay, az) * 180 / PI;
  float pitch = atan2(-ax, sqrt(ay*ay + az*az)) * 180 / PI;
  float yaw = 0; // Needs magnetometer or gyro integration
  
  // Send to OpenTrack
  Serial.print("Roll:");
  Serial.print(roll);
  Serial.print(" Pitch:");
  Serial.print(pitch);
  Serial.print(" Yaw:");
  Serial.println(yaw);
  
  delay(20); // ~50Hz update rate
}
This is a simplified example. For production use, implement proper sensor fusion (DMP, complementary filter, or Kalman filter) to get stable orientation.

Using MPU6050 DMP

// Use Jeff Rowberg's I2Cdevlib for MPU6050 DMP
// DMP provides fused quaternion output
// Convert quaternion to Euler angles
// See examples in I2Cdevlib library

IMU Sensor Comparison

SensorCostAxesFeaturesDifficulty
MPU6050$2-56-axisGyro+Accel, DMPEasy
MPU9250$5-109-axis+MagnetometerMedium
BNO055$20-309-axisBuilt-in fusionEasy
LSM6DS3$5-86-axisLow powerMedium
ICM-20948$10-159-axisNewer MPU9250Medium
Recommended for beginners: BNO055 (easier) or MPU6050 with DMP (cheaper)

Advantages and Limitations

Advantages

  • Very low cost ($5-30)
  • No line-of-sight required
  • Works in any lighting
  • Rotational tracking only (no marker)
  • DIY-friendly and customizable
  • Educational/learning opportunity
  • Low latency (~20ms)
  • Lightweight on head

Limitations

  • Rotation only (no position tracking)
  • Gyro drift over time
  • Requires DIY assembly
  • Programming knowledge helpful
  • Magnetometer affected by metal
  • Sensor calibration needed
  • Wired connection (USB cable)
  • Less accurate than optical tracking

Troubleshooting

  • Install USB drivers for Arduino (CH340, FTDI, etc.)
  • Check Device Manager (Windows) or ls /dev/tty* (Linux)
  • Try different USB port
  • Verify Arduino is powered (LED should light)
  • Check USB cable (some are charge-only)
  • Open Arduino Serial Monitor to verify output
  • Check baud rate matches in OpenTrack and Arduino
  • Verify serial format matches expectations
  • Check enable logging in HATire settings
  • Look for parse errors in logs
  • This is normal for gyro-only tracking
  • Implement complementary or Kalman filter
  • Add magnetometer for yaw stability
  • Use sensor fusion (DMP, Madgwick, Mahony)
  • Recenter view regularly
  • Calibrate IMU properly
  • Enable low-pass filter in IMU configuration
  • Increase averaging/smoothing in Arduino code
  • Use sensor fusion algorithm
  • Enable filtering in OpenTrack
  • Check for loose connections
  • Shield from electrical interference
  • Check axis mapping in HATire settings
  • Try inverting problematic axes
  • Verify IMU mounting orientation
  • Adjust coordinate system in Arduino code
  • Use debug mode to see raw values
  • Check wiring connections
  • Add pull-up resistors if needed (4.7kΩ)
  • Reduce I2C clock speed in Arduino
  • Keep wires short (<15cm ideal)
  • Check for loose connections

Advanced Topics

Sensor Fusion

For stable tracking, implement sensor fusion:
  1. Complementary Filter: Simple, fast
    angle = 0.98 * (angle + gyro * dt) + 0.02 * accel;
    
  2. Madgwick Filter: Better accuracy
    • Use Madgwick library
    • Provides quaternion output
    • Moderate computational cost
  3. DMP (Digital Motion Processor): MPU6050/9250
    • Hardware sensor fusion
    • Best accuracy for MPU chips
    • Use I2Cdevlib library

Wireless Options

Make your tracker wireless:
  • Bluetooth: HC-05/HC-06 modules
  • ESP32: WiFi + Bluetooth built-in
  • nRF24L01: 2.4GHz wireless
  • Battery power: LiPo battery + charging circuit

Position Tracking

Add limited position tracking:
  • Double integrate accelerometer (accumulates error)
  • Use ultrasonic sensors for distance
  • Add magnetometer for absolute reference
  • Combine with camera tracking for hybrid system

Community Resources

Arduino Sketches

  • EDTracker project
  • OpenTrack forums
  • GitHub repositories
  • Arduino forums

3D Printable Cases

  • Thingiverse
  • Printables
  • Custom designs
  • Mounting brackets

Comparison with Other Trackers

FeatureHATirePointTrackerNeuralNet
Tracking typeRotation only6DOF6DOF
Hardware costVery Low ($5-30)Low-MediumVery Low
DIY requiredYesSomeNo
Setup difficultyMedium-HardMediumEasy
DriftYes (gyro drift)NoNo
Line of sightNot requiredRequiredRequired
LatencyLow (~20ms)Very Low (~10ms)Medium (~50ms)
AccuracyMediumExcellentGood

Tips for Best Results

  1. Sensor Choice: Start with BNO055 for easiest setup, or MPU6050 for lowest cost
  2. Calibration: Properly calibrate your IMU (follow sensor datasheet)
  3. Sensor Fusion: Use DMP or complementary filter for stable output
  4. Mounting: Mount IMU rigid and close to head rotation center
  5. Update Rate: 50-100Hz is sufficient, faster uses more power
  6. Filtering: Enable both Arduino-side and OpenTrack filtering
  7. Cable Management: Use flexible cable, strain relief at connections

See Also