Skip to content

feat: add MPU-9250 / RAK1905 9-axis sensor support#10556

Open
egorsiniaev wants to merge 6 commits into
meshtastic:developfrom
egorsiniaev:feat/mpu9250-rak1905-magnetometer
Open

feat: add MPU-9250 / RAK1905 9-axis sensor support#10556
egorsiniaev wants to merge 6 commits into
meshtastic:developfrom
egorsiniaev:feat/mpu9250-rak1905-magnetometer

Conversation

@egorsiniaev
Copy link
Copy Markdown

@egorsiniaev egorsiniaev commented May 26, 2026

Summary

Adds support for the InvenSense MPU-9250 (RAK1905 WisBlock module): a 9-axis sensor that combines a 3-axis accelerometer, 3-axis gyroscope, and 3-axis magnetometer in one package. The driver provides tilt-compensated magnetic heading via the existing Fusion library, with hard-iron calibration persisted to flash - matching the BMX160 and ICM-20948 patterns.

Implemented as a minimal direct-I2C driver with no new library dependency. Flash impact on RAK4631: roughly +1 KB.

Motivation

The RAK12034 (BMX160) is end-of-life. RAK's official replacement, RAK12033 (IIM-42652), is 6-axis only and drops the magnetometer entirely. For users who want tilt-compensated compass on a WisBlock-based device, the closest still-in- production option is the RAK1905 (MPU-9250).

Detection

MPU-9250 shares I2C addresses (0x68/0x69) with MPU-6050, ICM-20948, BMX160, BMI270, SEN5X. "ScanI2CTwoWire" now reads WHO_AM_I (0x75) after the existing register-0x00 disambiguation:

  • 0x71 → MPU9250
  • 0x73 → MPU9255 (same driver)
  • otherwise → existing MPU6050 fallback

No regressions to the existing detection paths.

Testing

Verified on a RAK4631 + RAK19007 baseboard + RAK1905:

  • Boot log: "MPU9250 found at address 0x68","MPU9250 init ok (asa=1.17,1.18,1.13)", "AccelerometerThread::init ok"
  • Compass calibration via the existing "Calibrate Compass" menu, persisted across reboots
  • The on-screen N marker tracks magnetic north correctly as the device is rotated flat on a non-magnetic surface — verified against a phone compass app

References

Related WisBlock modules

MPU-9250 chip-level documentation (TDK InvenSense)

Reference implementations

  • wollewald/MPU9250_WE — Arduino library officially recommended by RAK in the RAK1905 quickstart. Confirmed the 0.15 µT/LSB scale factor and the AK8963 init sequence used in this driver.
  • kriswiner/MPU9250 — Canonical reference for the MPU-9250 axis-swap convention (my, mx, -mz to align the AK8963 magnetometer frame with the MPU-6500 accel frame).
  • bolderflight/MPU9250 — Alternative library, well-engineered, considered but not used here to keep zero new dependencies.

🤝 Attestations

  • I have tested that my proposed changes behave as described.
  • I have tested that my proposed changes do not cause any obvious regressions on the following devices:
    • Heltec (Lora32) V3 \ NOT_APPLICABLE
    • LilyGo T-Deck \ NOT_APPLICABLE
    • LilyGo T-Beam \ NOT_APPLICABLE
    • RAK WisBlock 4631
    • Seeed Studio T-1000E tracker card \ NOT_APPLICABLE
    • Other (please specify below) \ NOT_APPLICABLE

Video of testing: https://photos.app.goo.gl/Vkcj1HB4mcSKeKBi8

The RAK12034 (BMX160) WisBlock module is end-of-life. RAK's official
replacement is the 6-axis RAK12033, which drops the magnetometer
entirely. RAK1905 (InvenSense MPU-9250) is the closest 9-axis WisBlock
module still in production and is a natural drop-in for users who want
to keep tilt-compensated compass functionality.

This adds a minimal direct-I2C driver — no new library dependency, ~5KB
flash on rak4631. The MPU-6500 accel/gyro die is driven directly; the
AK8963 magnetometer die is exposed via the MPU's I2C bypass mode and
talked to at 0x0C. Per-axis Fuse-ROM ASA sensitivity factors and ST2
overflow are honored. Hard-iron calibration is persisted to
/prefs/compass_mpu9250.dat, matching the BMX160 / ICM-20948 pattern.

Detection disambiguates MPU-6050 from MPU-9250/9255 by reading
WHO_AM_I (0x75) after the existing register-0x00 fallback path that
already covers ICM-20948 / BMI270 / BMX160 / SEN5X. MPU-6050 paths
are unchanged.
Detection found the chip and set the device type correctly, but
ScanI2C::firstAccelerometer() iterates a hard-coded list that didn't
include MPU9250 — so accelerometer_found stayed unset and the
AccelerometerThread was never constructed for the new sensor.
@github-actions github-actions Bot added the hardware-support Hardware related: new devices or modules, problems specific to hardware label May 26, 2026
@egorsiniaev egorsiniaev marked this pull request as draft May 26, 2026 19:51
Compass-only fusion is stateless, so any dynamic acceleration during
device rotation immediately showed up as overshoot on the displayed
heading. Add a per-axis exponential moving average on the raw accel
and mag samples before tilt compensation. Accel uses alpha=0.15 to
keep the gravity reference stable; mag uses alpha=0.20 for slightly
faster response. Time constant is well under half a second so the
needle still tracks deliberate rotation, but small jitters and
rotation-induced spikes are damped.
FusionCompassCalculateHeading assumes the sensor's Z axis is world-up.
That holds when the WisBlock baseboard is mounted flat, but fails on
cases where the baseboard sits vertical (LCD perpendicular to the
board) — chip Z is then horizontal and tilt-comp becomes unstable.

Add a build-time MPU9250_UP_AXIS selector with five options:
PZ (default, baseboard flat), PX, NX, PY, NY. Implementation rotates
both accel and mag via FusionAxesSwap so the rest of the heading
pipeline still sees Z as up.

The temporary default is PX while testing on a vertical RAK case;
will be reverted to PZ before the PR is marked ready, with vertical
case users opting in via variant.h or build flags.
The previous commit shipped with PX as the default while validating
the remap on a vertical-mount RAK case. PZ matches the assumption
baked into BMX160 / ICM20948 (chip Z = world up), so leaving the
default at PZ keeps existing flat-mount users untouched. Vertical
mount users opt in by setting MPU9250_UP_AXIS in their variant.h or
via build_flags in platformio.ini.
@egorsiniaev egorsiniaev marked this pull request as ready for review May 26, 2026 22:02
@egorsiniaev
Copy link
Copy Markdown
Author

Heads up - opened a design discussion about a related limitation I found while working on this: the existing compass code (here and in the BMX160 / ICM20948 drivers) assumes the sensor chip is mounted with Z = up, which breaks tilt compensation in vertical-mount cases. This PR ships with a build-time workaround (MPU9250_UP_AXIS), but the proper runtime-configurable solution is out of scope for this PR.

Discussion: #10557

Doesn't block review of this PR, just flagging so reviewers know the orientation question is being tracked separately rather than ignored.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

hardware-support Hardware related: new devices or modules, problems specific to hardware

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant