> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/opentrack/opentrack/llms.txt
> Use this file to discover all available pages before exploring further.

# HATire (Arduino)

> Connect Arduino-based IMU devices for inertial head tracking

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.

<Info>
  HATire supports rotational tracking (yaw, pitch, roll) and can optionally include positional tracking if your IMU has magnetometer or additional sensors.
</Info>

## 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)

<Note>
  Total hardware cost is typically \$5-30 depending on your choices. This is one of the most affordable head tracking options.
</Note>

## Setup Instructions

<Steps>
  <Step title="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.

    <Warning>
      Some 3.3V IMUs can be damaged by 5V. Check your sensor's voltage rating and use appropriate voltage level.
    </Warning>
  </Step>

  <Step title="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
    ```
  </Step>

  <Step title="Configure Serial Protocol">
    HATire supports multiple data formats. Configure your Arduino sketch to output:

    **Simple format:**

    ```cpp theme={null}
    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
  </Step>

  <Step title="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
  </Step>

  <Step title="Map Axes">
    Configure which Arduino output maps to which head movement:

    ```yaml theme={null}
    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:

    ```yaml theme={null}
    Enable Roll: true
    Invert Roll: false (flip if backwards)
    # Repeat for other axes
    ```
  </Step>

  <Step title="Set Commands (Optional)">
    Configure commands to send to Arduino:

    ```yaml theme={null}
    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.
  </Step>

  <Step title="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

    <Info>
      Keep the IMU as close to your head's rotation center as possible for best accuracy.
    </Info>
  </Step>
</Steps>

## Configuration Options

### Serial Port Settings

| Option               | Default | Description                         |
| -------------------- | ------- | ----------------------------------- |
| **Serial Port Name** | -       | COM port (COM3, /dev/ttyUSB0, etc.) |
| **Baud Rate**        | 115200  | Communication speed                 |
| **Data Bits**        | 8       | Bits per byte                       |
| **Parity**           | None    | Error checking                      |
| **Stop Bits**        | OneStop | End of byte marker                  |
| **Flow Control**     | None    | Hardware flow control               |
| **DTR**              | false   | Data Terminal Ready signal          |

### Axis Mapping

| Option         | Default | Description              |
| -------------- | ------- | ------------------------ |
| **Roll Axis**  | 1       | Which data channel (0-5) |
| **Pitch Axis** | 2       | Which data channel       |
| **Yaw Axis**   | 0       | Which data channel       |
| **X/Y/Z Axis** | 0       | Position channels        |

### Axis Control

| Option           | Default | Description          |
| ---------------- | ------- | -------------------- |
| **Enable Roll**  | true    | Use roll data        |
| **Enable Pitch** | true    | Use pitch data       |
| **Enable Yaw**   | true    | Use yaw data         |
| **Enable X/Y/Z** | false   | Use position data    |
| **Invert Roll**  | false   | Flip roll direction  |
| **Invert Pitch** | false   | Flip pitch direction |
| **Invert Yaw**   | false   | Flip yaw direction   |

### Commands

| Option             | Default | Description                |
| ------------------ | ------- | -------------------------- |
| **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

| Option             | Default | Description              |
| ------------------ | ------- | ------------------------ |
| **Init Delay**     | 0ms     | Wait after init command  |
| **Start Delay**    | 0ms     | Wait after start command |
| **Sequence Delay** | 0ms     | Wait after each command  |

### Advanced

| Option             | Default | Description                    |
| ------------------ | ------- | ------------------------------ |
| **Big Endian**     | false   | Byte order for binary protocol |
| **Enable Logging** | false   | Log serial data for debugging  |

## Example Arduino Sketches

### Basic MPU6050 Example

```cpp theme={null}
#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
}
```

<Warning>
  This is a simplified example. For production use, implement proper sensor fusion (DMP, complementary filter, or Kalman filter) to get stable orientation.
</Warning>

### Using MPU6050 DMP

```cpp theme={null}
// 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

| Sensor        | Cost    | Axes   | Features        | Difficulty |
| ------------- | ------- | ------ | --------------- | ---------- |
| **MPU6050**   | \$2-5   | 6-axis | Gyro+Accel, DMP | Easy       |
| **MPU9250**   | \$5-10  | 9-axis | +Magnetometer   | Medium     |
| **BNO055**    | \$20-30 | 9-axis | Built-in fusion | Easy       |
| **LSM6DS3**   | \$5-8   | 6-axis | Low power       | Medium     |
| **ICM-20948** | \$10-15 | 9-axis | Newer MPU9250   | Medium     |

<Info>
  **Recommended for beginners**: BNO055 (easier) or MPU6050 with DMP (cheaper)
</Info>

## Advantages and Limitations

<CardGroup cols={2}>
  <Card title="Advantages" icon="check">
    * 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
  </Card>

  <Card title="Limitations" icon="exclamation">
    * 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
  </Card>
</CardGroup>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Serial port not detected">
    * 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)
  </Accordion>

  <Accordion title="No data received">
    * 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
  </Accordion>

  <Accordion title="Tracking drifts over time">
    * 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
  </Accordion>

  <Accordion title="Jittery or noisy data">
    * 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
  </Accordion>

  <Accordion title="Wrong axis orientation">
    * 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
  </Accordion>

  <Accordion title="I2C communication errors">
    * 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
  </Accordion>
</AccordionGroup>

## Advanced Topics

### Sensor Fusion

For stable tracking, implement sensor fusion:

1. **Complementary Filter**: Simple, fast
   ```cpp theme={null}
   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

<CardGroup cols={2}>
  <Card title="Arduino Sketches" icon="code">
    * EDTracker project
    * OpenTrack forums
    * GitHub repositories
    * Arduino forums
  </Card>

  <Card title="3D Printable Cases" icon="cube">
    * Thingiverse
    * Printables
    * Custom designs
    * Mounting brackets
  </Card>
</CardGroup>

## Comparison with Other Trackers

| Feature          | HATire            | PointTracker      | NeuralNet       |
| ---------------- | ----------------- | ----------------- | --------------- |
| Tracking type    | Rotation only     | 6DOF              | 6DOF            |
| Hardware cost    | Very Low (\$5-30) | Low-Medium        | Very Low        |
| DIY required     | Yes               | Some              | No              |
| Setup difficulty | Medium-Hard       | Medium            | Easy            |
| Drift            | Yes (gyro drift)  | No                | No              |
| Line of sight    | Not required      | Required          | Required        |
| Latency          | Low (\~20ms)      | Very Low (\~10ms) | Medium (\~50ms) |
| Accuracy         | Medium            | Excellent         | Good            |

## 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

* [FreePIE UDP](/trackers/freepie-udp) - Alternative for wireless IMU setups
* [PointTracker](/trackers/pointtracker) - For 6DOF position tracking
* [Hardware Guide](/trackers/hardware) - General hardware information
