Skip to content

mpu6886

InvenSense MPU6886 — 6-axis IMU.

The part on the M5Stack Atom Matrix. Layer 3: it knows the device, not the chip driving it, and talks through a [BusHandle].

Readings come back as raw i16 counts, with conversions to milli-g and milli-degrees-per-second done in integer arithmetic. No f32 anywhere.

That is a deliberate choice for a driver in an RTOS. A float in a device driver is a float in whatever context calls it — including, eventually, an interrupt handler — and on Xtensa that means the FPU registers join the set that a context switch has to save. Milli-units carry more precision than this part’s noise floor, so nothing is lost.

The part needs pauses during its reset sequence. How to wait belongs to the RTOS, not this driver — so [Mpu6886::bring_up] takes the wait as a closure and owns only the durations (the datasheet’s 10 ms minimums):

dev.bring_up(api::task::sleep_ms)?; // reset, wait, wake, wait, configure

The individual steps (reset, wake, configure) stay public for a caller that must interleave something else; each says how long to wait after it. The 10 ms figures are the datasheet’s minimum, not a recommendation for your board — a board on a slowly-settling rail passes a longer-waiting closure.

From M5Stack’s own MPU6886.cpp, the driver that runs this exact part on this exact board — including the configuration values, which are choices rather than datasheet constants.

struct Axes {
pub x: i16,
pub y: i16,
pub z: i16,
}

A three-axis reading, in raw counts.

Implements: Clone, Copy, Debug, Default, Eq, PartialEq, StructuralPartialEq

struct Mpu6886<'a> { /* private fields */ }

An MPU6886 on a bus.

const ADDR: u8;

I2C address with AD0 low, which is how the Atom Matrix wires it.

const REG_WHO_AM_I: u8;

WHO_AM_I, and the value that identifies this part.

const WHO_AM_I: u8;

The MPU6886’s identity. A BMI270 in the same socket answers 0x24 from a different register — see the bmi270 driver.