ICM-20948: Complete Guide to TDK’s 9-Axis MEMS MotionTracking Sensor

The ICM-20948 is a 9-axis inertial measurement unit (IMU) manufactured by TDK InvenSense that integrates a 3-axis gyroscope, 3-axis accelerometer, 3-axis magnetometer, and an onboard Digital Motion Processor (DMP) into a single 3 × 3 × 1 mm QFN package. Rated at 2.5 mW of power consumption, it was marketed as the world’s lowest-power 9-axis MotionTracking device at launch. Target applications span drones, wearables, and IoT systems. Note: As of 2024, TDK has transitioned the ICM-20948 to NRND (Not Recommended for New Designs) status due to limited magnetometer wafer availability.

TL;DR / Key Takeaways**
ICM-20948 = 9-axis IMU: accelerometer + gyroscope + magnetometer (AK09916) + DMP
Power consumption: 2.5 mW typical — one-third the power of comparable 9-axis devices
Communication: I2C (400 kHz) and SPI (7 MHz); I2C addresses 0x68 / 0x69
Critical: VDDIO accepts only 1.71–1.95 V — applying 3.3V or 5V damages the IC
NRND status means limited availability — consider alternatives for new production designs
Available libraries: SparkFun (DMP support), ICM20948_WE (Wolle's library, 59 functions)

What Is the ICM-20948?

The ICM-20948 is a 9-axis MEMS (Micro-Electro-Mechanical Systems) motion tracking sensor that combines four distinct sensing elements:

Gyroscope X, Y, Z Measures rotational rate (±250 to ±2000 °/s)
Magnetometer X, Y, Z Measures magnetic field strength (±4900 µT)
Thermometer On-chip temperature sensor

The magnetometer is an AK09916 from AKM, integrated into the package but controlled through the ICM-20948’s auxiliary I2C interface. It is not a native part of the ICM-20948 die — it communicates through a separate bus and has its own register set. This distinction matters when debugging magnetometer issues.

The sensor is controlled via either I2C (up to 400 kHz Fast Mode) or SPI (up to 7 MHz). The I2C address is selectable: 0x68 when the AD0 pin is pulled LOW, and 0x69 when pulled HIGH.

ICM-20948 Specifications

VDD (supply) 1.71 V to 3.6 V
VDDIO (I/O voltage) 1.71 V to 1.95 V
Operating current ~3.1 mA (typical, DMP off)
Power consumption 2.5 mW
Accelerometer ranges ±2g, ±4g, ±8g, ±16g
Accelerometer resolution 16-bit (16384 LSB/g at ±2g)
Gyroscope ranges ±250, ±500, ±1000, ±2000 °/s
Gyroscope data rate 4.4 Hz to 9 kHz
Accelerometer data rate 4.5 Hz to 4.5 kHz
Magnetometer range ±4900 µT
Magnetometer data rate Up to 100 Hz
Digital interfaces I2C (400 kHz), SPI (7 MHz)
Operating temperature -40°C to +85°C
Digital Motion Processor Yes (embedded 3rd gen DMP)

The Digital Motion Processor (DMP) is an onboard coprocessor that offloads sensor fusion calculations from the host microcontroller. It supports 6-axis and 9-axis quaternion output, game rotation vector, and ultra-low-power runtime calibration of all three sensors. The DMP requires 14 KB of program memory on the host — an important consideration for constrained microcontrollers like the ATmega328P.


ICM-20948 vs MPU-9250: What Changed?

The ICM-20948 was designed as the direct successor to the MPU-9250, which reached End of Life (EOL) on December 31, 2018. While they share the same package footprint (3 × 3 × 1 mm QFN) and cover the same sensing axes, several engineering differences matter in practice:

Accelerometer ranges ±2g to ±16g ±2g to ±16g
Magnetometer range ±4900 µT ±4800 µT
DMP fusion **9-axis** **6-axis**
Supply voltage range 1.71–3.6 V (VDD) 2.4–3.6 V (VDD)
Typical current **3.1 mA** 3.7 mA
SPI max speed **7 MHz** 1 MHz
I2C auxiliary bus Yes (controls magnetometer) Yes
NRND / EOL **NRND (since ~2024)** EOL (since 2018)

The most significant practical upgrade is the 9-axis DMP fusion in the ICM-20948 versus the 6-axis fusion in the MPU-9250. With 9-axis fusion, the DMP incorporates magnetometer data into its orientation calculations, producing more accurate heading estimates over time. The ICM-20948 also supports a wider VDD range and lower power consumption.

However, the NRND status of the ICM-20948 is a critical factor for new product designs. TDK recommends evaluating the ICM-42688 (6-axis) or IAM-20680 for new designs requiring motion sensing. The ICM-20648 is a 6-axis alternative that remains active in TDK’s portfolio.


Hardware Overview: Breakout Boards and Module Variants

The ICM-20948 sensor itself operates at 1.8 V on its I/O pins, making direct connection to 5 V Arduino boards dangerous without level shifting. Most hobbyist use comes through breakout boards that add voltage regulation, level shifters, and Qwiic/Stemma QT connectors.

SparkFun 9DoF IMU Breakout (SEN-15335)

The SparkFun breakout is the most popular development board for the ICM-20948. It includes:

  • On-board 1.8 V voltage regulator accepting 1.8–5.5 V input
  • TXS0108 level shifters on all I/O pins (bi-directional, up to 7 MHz SPI)
  • Two Qwiic connectors for daisy-chaining via I2C
  • Onboard power LED (disableable via jumper)
  • I2C address jumper (ADR) — closed = address 0x68, open = 0x69
  • Dual COM headers (I2C and SPI broken out separately)

The SparkFun board accepts 1.8–5.5 V on its VIN pin and handles level shifting internally, making it compatible with Arduino Uno, ESP32, Raspberry Pi, and other popular platforms without additional circuitry.

Generic ICM-20948 Modules (“Version 2”)

Budget modules labeled “v2” or “v2.0” from generic suppliers include voltage regulators but may not include level shifters. These boards typically regulate VIN to 1.8 V but connect VDDIO directly to VIN. On such boards:

  • If VIN = 3.3 V or 5 V, the I/O pins output 3.3 V or 5 V — which exceeds the 1.95 V maximum VDDIO rating
  • You must use external level shifters (e.g., TXS0108E, TXB0108) or a 1.8 V logic microcontroller
  • Some v2 boards include MOSFETs on SDA and SCL but leave CS and INT unprotected

Always verify your module’s pinout and level-shifting capability before connecting it to a 5 V Arduino.

VDDIO: The Most Commonly Missed Detail

The ICM-20948 has two separate power pins: VDD (core supply, 1.71–3.6 V) and VDDIO (I/O supply, 1.71–1.95 V). On many breakout boards, these are tied together internally. If your module connects VDDIO to VDD and you apply 3.3 V, you are operating the I/O at 3.3 V — outside the 1.95 V absolute maximum. This may work temporarily but risks premature failure or erratic behavior.


Connecting ICM-20948 to Arduino, ESP32, and Raspberry Pi

Arduino (I2C)

Parts needed:

  • Arduino Uno/Nano/Mega or ESP32
  • SparkFun 9DoF ICM-20948 breakout (or equivalent with level shifters)
  • Qwiic cable (or 4 dupont wires)

Wiring (Qwiic):

Red (3.3V) 3.3V
Yellow (SDA) A4 (Uno/Nano) / GPIO21 (ESP32)
Blue (SCL) A5 (Uno/Nano) / GPIO22 (ESP32)

Wiring (Dupont, generic module):

GND GND
SDA A4
SCL A5
AD0 GND (→ 0x68) or 3.3V (→ 0x69)

⚠️ **Warning for ESP32 users:** Some 5.1 V power supplies cause voltage spikes that damage the ESP32 Thing Plus. Keep supply cables under 6 feet and use a clean 5 V rail.

Raspberry Pi (I2C via Python)

  1. Enable I2C: sudo raspi-config → Interface Options → I2C → Enable
  2. Install the Pimoroni library: curl https://get.pimoroni.com/icm20948 | bash
  3. Run the example:

import icm20948
from icm20948 import ICM20948
imu = ICM20948()
imu.init()
while True:
    accel = imu.get_accel_data()
    gyro = imu.get_gyro_data()
    mag = imu.get_mag_data()
    print(f"Accel: {accel}, Gyro: {gyro}, Mag: {mag}")
    time.sleep(0.1)

SPI Connection (Advanced)

To use SPI (up to 7 MHz, faster than I2C’s 400 kHz):

SCLK Pin 13
MISO Pin 12
CS Pin 2 (or any digital pin)
VIN 3.3V or 5V
GND GND

In your Arduino sketch, uncomment #define USE_SPI and specify the CS pin.


ICM-20948 Arduino Library Setup and Configuration

Installing the SparkFun Library

  1. Open Arduino IDE
  2. Go to Sketch → Include Library → Manage Libraries
  3. Search for “SparkFun 9DoF IMU Breakout”
  4. Install version 1.2.5 or later

Basic I2C Example (Example1_Basics)


#include "ICM_20948.h"  // http://librarymanager/All#SparkFun_ICM_20948_IMU
#define WIRE_PORT Wire
#define I2C_ADDR ICM_20948_I2C_ADDR_SECONDARY  // 0x69; use PRIMARY (0x68) if AD0 = GND
ICM_20948_I2C myICM;
void setup() {
    WIRE_PORT.begin();
    WIRE_PORT.setClock(400000);  // Fast I2C mode
    Serial.begin(115200);
    myICM.begin(WIRE_PORT, I2C_ADDR);
    if (myICM.status != ICM_20948_Stat_Ok) {
        Serial.println("ICM-20948 not responding — check wiring");
        while (1);
    }
}
void loop() {
    if (myICM.dataReady()) {
        myICM.getAGMT();  // Reads Accelerometer, Gyro, Mag, Temp
        Serial.print("Accel X: "); Serial.print(myICM.accX());
        Serial.print(" Y: ");      Serial.print(myICM.accY());
        Serial.print(" Z: ");      Serial.println(myICM.accZ());
        Serial.print("Gyro X: ");  Serial.print(myICM.gyrX());
        Serial.print(" Y: ");      Serial.print(myICM.gyrY());
        Serial.print(" Z: ");      Serial.println(myICM.gyrZ());
        Serial.print("Mag X: ");   Serial.print(myICM.magX());
        Serial.print(" Y: ");       Serial.print(myICM.magY());
        Serial.print(" Z: ");      Serial.println(myICM.magZ());
        Serial.print("Temp: ");    Serial.println(myICM.temp());
    }
    delay(30);
}

Enabling DMP Support

The DMP is disabled by default in the SparkFun library because it consumes 14 KB of program memory. To enable it:

  1. Navigate to Documents/Arduino/libraries/SparkFun_ICM_20948_ArduinoLibrary/src/util/
  2. Open ICM_20948_C.h
  3. Uncomment line 29: #define ICM_20948_USE_DMP

Library version 1.2.5+ provides an initializeDMP() helper function that automatically downloads DMP firmware and configures registers. Once enabled, DMP outputs include:

  • Raw and calibrated sensor data with accuracy estimates
  • 6-axis and 9-axis quaternion data
  • Game Rotation Vector
  • Ultra-low-power runtime calibration

Alternative: ICM20948_WE Library

For deeper register-level control, Wolle Waldmann’s ICM20948_WE library (available in the Arduino Library Manager) provides 59 public functions across 13 example sketches. This library is ideal for applications that need:

  • Custom DLPF (Digital Low Pass Filter) configurations
  • Precise calibration with manual offset values
  • Low-power cycle mode operation
  • Extended auxiliary I2C bus usage

The library supports both I2C and SPI on any TwoWire port (useful for dual-I2C microcontrollers like the ESP32).


ICM-20948 Calibration: Getting Accurate Readings

Factory-calibrated sensors still exhibit zero-point offsets. For precision applications, run the auto-calibration routine at startup:

Accelerometer and Gyroscope Auto-Offset

Place the ICM-20948 flat (x,y plane horizontal) before calling autoOffsets(). The function:

  • Measures the acceleration vector under gravity
  • Calculates zero-point offsets for each axis
  • Applies corrections to all future readings
  • Also measures and corrects gyroscope drift

Serial.println("Place ICM-20948 flat — calibrating...");
delay(1000);
myIMU.autoOffsets();  // Blocks for ~1 second
Serial.println("Calibration complete.");

Manual Calibration (Advanced)

For non-flat mounting orientations, use setAccOffsets() with pre-measured minimum and maximum raw values:


// Measure raw values at +1g and -1g for each axis, then:
myIMU.setAccOffsets(-16330.0, 16450.0, -16600.0, 16180.0, -16640.0, 16560.0);

This approach corrects both zero-point offset and slope/ratio errors, giving better accuracy at arbitrary angles.

Gyroscope Offset


myIMU.setGyrOffsets(-115.0, 130.0, 105.0);  // Values from your specific module

Store calibration constants in EEPROM if your application requires them to persist across power cycles.


ICM-20948 Digital Low Pass Filter Configuration

The DLPF reduces noise in exchange for reduced bandwidth. Both the accelerometer and gyroscope have independent DLPF settings:

Gyroscope DLPF (lowest noise at DLPF_6):

5 11.6 Hz 1125/(1+GSRD) Hz
6 5.7 Hz 1125/(1+GSRD) Hz
OFF 12106 Hz 9000 Hz

Accelerometer DLPF (lowest noise at DLPF_6):

5 11.5 Hz 1125/(1+ASRD) Hz
6 5.7 Hz 1125/(1+ASRD) Hz
OFF 1209.0 Hz 4500 Hz

For most motion tracking applications, DLPF_6 provides the best balance between noise reduction and response time.


Common Issues and Troubleshooting

ICM-20948 not responding:

  • Verify wiring: SDA → A4, SCL → A5 (Uno/Nano), or correct pins for your board
  • Check that VIN receives 3.3 V or 5 V (not 12 V)
  • Confirm AD0 is connected to either GND (0x68) or 3.3 V (0x69)
  • If using a generic module without level shifters, VDDIO damage may have occurred

Magnetometer reads 0,0,0:

  • The AK09916 magnetometer requires a separate initialization. The SparkFun library handles this automatically in begin().
  • If readings are stuck at zero, try calling myICM.initMagnetometer() explicitly.
  • Magnetic interference from nearby motors, speakers, or ferrous metals distorts readings.

Inaccurate heading from magnetometer:

  • Run manual hard and soft iron calibration (figure-8 motion)
  • The magnetometer must be calibrated in the final product’s environment, not on a bench
  • Keep the ICM-20948 away from DC motors and permanent magnets

DMP quaternion jumps:

  • Ensure DMP firmware download completed successfully (requires ~2 seconds at startup)
  • Disable autoOffsets() if you are using manual calibration — they conflict
  • Check that you are reading the correct quaternion data type (DMP outputs 6-axis or 9-axis quaternions)

Alternatives to the ICM-20948

Given the NRND status, consider these active alternatives:

ICM-42670 6-axis Cost-optimized alternative
MPU-9250 9-axis EOL but widely available in surplus
BNO055 9-axis Integrated sensor fusion, easier to use, 3.3 V only
LSM9DS1 9-axis STM sensor, I2C + SPI, active

The BNO055 from Bosch is the most practical drop-in replacement for projects prioritizing ease of use — it includes automatic sensor fusion without DMP programming. However, it lacks the raw sensor access and configurability of the ICM-20948.


Conclusion

The ICM-20948 remains a capable 9-axis motion tracking sensor for embedded projects, provided its NRND status is factored into supply chain planning. Its key strengths — 2.5 mW power consumption, 9-axis DMP fusion, dual I2C/SPI interface, and compact 3 × 3 × 1 mm package — make it well-suited for drones, wearables, and IoT applications where power budget is constrained. The critical engineering gotchas — VDDIO voltage limits, the AK09916’s auxiliary I2C dependency, and the 14 KB DMP memory footprint — are manageable with proper hardware selection and library configuration. For new designs, evaluate active alternatives like the ICM-42688 or BNO055 unless the specific 9-axis form factor and magnetometer integration are required.

Sources: TDK InvenSense ICM-20948 Product Page, TDK MPU-9250 to ICM-20948 Migration Guide, SparkFun ICM-20948 Arduino Library, Wolles Elektronikkiste ICM-20948 Guide

Please enable JavaScript in your browser to complete this form.

Quick Quote

Info
Click or drag a file to this area to upload.
send me gerber or pcb file,format:7z,rar,zip,pdf

Contact

WellCircuits
More than PCB

Upload your GerberFile(7z,rar,zip)