IMU Fundamentals: Accelerometer and Gyroscope

Opening post of the Motion Sensing series. Sensors are the window through which embedded systems perceive the physical world, and the IMU (Inertial Measurement Unit) is the most common type. This article skips heavy theory — just how MEMS sensors work, how to wire them, how to read data, and what the numbers actually look like.

IMU Coordinate System

The diagram below defines the three axes of the IMU — all formulas and discussions that follow are based on this coordinate system:

mermaid
flowchart TD
    subgraph Device Coordinate System
        X["X Axis → Roll"]
        Y["Y Axis → Pitch"]
        Z["Z Axis ↑ Yaw"]
    end

    classDef axis fill:#9C27B0,color:#fff
    class X,Y,Z axis

Beyond the diagram above, here’s a 3D rotating coordinate system — red/green/blue for Roll/Pitch/Yaw, rotating to show the spatial relationship of the three axes:

Y → Pitch
X → Roll
Z → Yaw
X → Roll Y → Pitch Z → Yaw

MEMS Accelerometer

An accelerometer measures the acceleration acting on an object, including the gravitational component. Inside a MEMS accelerometer sits a tiny proof mass suspended by silicon cantilever beams between fixed electrodes. When the chip accelerates, the proof mass displaces slightly due to inertia, changing the capacitance on both sides — one increases, the other decreases. By measuring the differential capacitance change, the acceleration can be derived.

One common point of confusion: when resting flat on a desk, the accelerometer reads 1g (about 9.8 m/s²) pointing toward the center of the Earth, not zero. Gravity produces the exact same effect on the proof mass as acceleration — that’s the equivalence principle in action. This means you can use the accelerometer to calculate tilt angle, but only when there’s no linear acceleration干扰.

Tilt Calculation

The accelerometer measures the gravitational components along each axis — using trigonometry we can derive the device’s tilt angle:

$\theta = \text{atan2}(a_x, a_z)$

mermaid
flowchart TD
    A["Device Level<br/>θ=0°"] -->|"az=1g, ax=ay=0"| B["Device Tilted θ°<br/>az=cos(θ)g<br/>ax=sin(θ)g"]
    B --> C["atan2(ax, az)<br/>→ Tilt θ"]

    classDef state fill:#2196F3,color:#fff
    classDef calc fill:#4CAF50,color:#fff
    class A,B state
    class C calc

Parameter explanation:

  • ax: X-axis acceleration reading (g)
  • az: Z-axis acceleration reading (g)
  • atan2: Arc tangent function, automatically handles quadrants (safer than plain atan)

Numerical example: Device tilted 45° → ax=0.707g, az=0.707g → atan2(0.707, 0.707) = 45°

⚠️ Note: Only accurate when stationary! Motion acceleration contaminates the reading.

Watch the device tilt from level to 60° — a_x, a_z, and angle θ update in real-time:

↑ Z
θ = 0.0 °
ax = 0.000 g
az = 1.000 g
θ = atan2(ax, az)

Output Format

Accelerometers output raw X/Y/Z axis values, typically in g or m/s². The datasheet specifies the sensitivity for each range, in LSB/g.

RangeSensitivity
±2g16384 LSB/g
±4g8192 LSB/g
±8g4096 LSB/g
±16g2048 LSB/g

Sensitivity Conversion

Formula for converting raw ADC readings to physical units:

$$a_g = \frac{\text{raw}}{\text{LSB_per_g}}$$

Parameter explanation:

  • raw: ADC raw reading (int16, range -32768~32767)
  • LSB_per_g: Sensitivity, for ±2g range = 16384 LSB/g

Numerical example: raw=8192 → a_g = 8192 / 16384 = 0.5g

💡 Bias drifts with temperature — collect 1000 stationary samples after power-on for zero-bias calibration.

Key Parameters

  • Range: Maximum measurable acceleration. Selection depends on the application — ±2g is enough for handheld devices, while drones or robots may need ±8g or more.
  • Sensitivity: LSBs per g of the digital output. Higher sensitivity means better resolution.
  • Noise Density: Measured in µg/√Hz. Determines the smallest acceleration change you can resolve.
  • Offset (Zero-g Bias): Output value when the sensor experiences 0g. This varies per chip and is usually calibrated out after power-on.

MEMS Gyroscope

A gyroscope measures angular velocity — how fast the object rotates around an axis. The operating principle is a bit more involved than the accelerometer: inside is a continuously vibrating mass (drive mode). When the chip rotates around the sensitive axis, the Coriolis force couples vibrational energy into the sense direction perpendicular to the drive motion, causing displacement that is again measured via capacitance change.

The Coriolis force is proportional to angular velocity, so the measured capacitance change directly reflects the rotation rate.

Output Format

Three-axis angular velocity in °/s (degrees per second) or rad/s. Gyroscopes are also categorized by range:

RangeSensitivity
±250 °/s131 LSB/(°/s)
±500 °/s65.5 LSB/(°/s)
±1000 °/s32.8 LSB/(°/s)
±2000 °/s16.4 LSB/(°/s)

Key Parameters

  • Range: Maximum measurable angular velocity. ±250 °/s is sufficient for handheld devices, but fast-spinning objects need larger ranges.
  • Sensitivity: LSBs per °/s.
  • Bias Stability: The stability of the gyroscope’s output when stationary, measured in °/h (degrees per hour) or °/s. This is the core quality metric — consumer-grade parts range from 5-20 °/h, while industrial-grade can go below 1 °/h.
  • Temperature Drift: Gyroscope bias changes significantly with temperature, one of the most frustrating issues in real projects. Even with the chip perfectly still, the output drifts as temperature changes. The fix is temperature compensation: place a temperature sensor near the IMU on the PCB and build a bias-vs-temperature calibration curve.

Common Sensor Models

Popular consumer-grade IMU chips on the market:

ModelAxesInterfaceNotes
MPU60506-axis (3-axis accel + 3-axis gyro)I2C/SPIMost classic, tons of documentation, built-in DMP fusion
MPU92509-axis (6-axis + AK8963 magnetometer)I2C/SPIMPU6050 upgrade with added magnetometer
ICM-209489-axisI2C/SPIMPU9250 successor, lower power
BMI1606-axisI2C/SPIBosch, extremely low power, ideal for battery devices
LSM6DS36-axisI2C/SPIST product, features a finite state machine for simple gesture recognition

For interfaces, I2C requires the fewest wires (SDA + SCL) but has limited speed — good for low-frequency reads. SPI is faster and suitable for high-output-rate scenarios. The MPU6050 I2C default address is 0x68, and becomes 0x69 when the AD0 pin is pulled high.

Reading Raw Data

Below is the code snippet for reading raw accelerometer and gyroscope values from MPU6050 over I2C. The MPU6050’s registers are laid out sequentially — accelerometer X high byte starts at 0x3B. Reading 14 consecutive bytes gives you all the accelerometer (6B), temperature (2B), and gyroscope (6B) data in one shot.

c
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
// I2C read of MPU6050 accelerometer and gyroscope raw values
#define MPU6050_ADDR  0x68
#define ACCEL_XOUT_H  0x3B
#define GYRO_XOUT_H   0x43

int16_t ax, ay, az, gx, gy, gz;

// Read 14 bytes (accel 6 + temp 2 + gyro 6)
uint8_t buf[14];
i2c_read(MPU6050_ADDR, ACCEL_XOUT_H, buf, 14);

ax = (buf[0] << 8) | buf[1];
ay = (buf[2] << 8) | buf[3];
az = (buf[4] << 8) | buf[5];
// buf[6], buf[7] are temperature
gx = (buf[8] << 8) | buf[9];
gy = (buf[10] << 8) | buf[11];
gz = (buf[12] << 8) | buf[13];

// Convert to physical units (±2g and ±250°/s example)
float ax_g = ax / 16384.0f;  // LSB/g
float gx_dps = gx / 131.0f;  // LSB/(°/s)

The raw values are signed 16-bit integers whose range depends on the configured full-scale setting. To convert to physical units, divide by the sensitivity coefficient for the selected range.

Limitations of Raw Data

Once you have raw data, don’t make the mistake of thinking you can use it directly. Both accelerometers and gyroscopes have their own problems:

Accelerometers are vibration-sensitive. Walking, motor spin-up, even tapping the desk adds significant noise to the readings. If you calculate tilt directly from raw accelerometer data, you get a jittery mess — it must go through a low-pass filter. But filtering introduces latency, so there’s always a trade-off.

Gyroscopes have bias and drift. Even when perfectly still, the gyroscope output isn’t exactly zero — there’s always a small offset. Worse, this offset changes slowly over time (bias instability) and with temperature (thermal drift). When integrating angular velocity to get angle, the bias accumulates — leave it sitting for a minute and the computed angle may have drifted by several degrees.

Integration Drift Problem

mermaid
flowchart TD
    A["Gyro Raw Angular Velocity<br/>ω(t)"] --> B["Integration<br/>θ = ∫ω dt"]
    B --> C["Angle Output"]
    A -.->|"Bias Error Δω"| D["After Integration<br/>Δθ = Δω × t"]
    D --> E["t=60s, Δω=0.01°/s<br/>→ Δθ=0.6° Drift"]
    E --> F["Needs Sensor Fusion<br/>(Next Article)"]

    classDef proc fill:#2196F3,color:#fff
    classDef problem fill:#f44336,color:#fff
    classDef solution fill:#4CAF50,color:#fff
    class A,B,C proc
    class D,E problem
    class F solution

The visualization below shows the bias accumulation process — in 60 seconds of rest, a tiny 0.01 °/s bias integrates into 0.6° of drift:

积分漂移累积 陀螺仪零偏 Δω = 0.01 °/s
0.6°
0.00 °
经时 0 s
漂移 0.00 °
静止 1 分钟,陀螺仪积分漂移可达 0.6°

Because each sensor has its own weaknesses, real projects almost never rely on a single sensor for attitude estimation. Combining the accelerometer’s low-frequency reliability with the gyroscope’s high-frequency responsiveness is what sensor fusion is all about — that gets its own article later in this series.