Lost + Found MPU6050 6-Axis Accelerometer/Gyroscope driver library for Raspberry Pi Pico C SDK
  • C 91.6%
  • Python 5.4%
  • CMake 3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Bethany b3029c8481 Add configurable ranges, filtering, reset and gyro calibration
The power-on defaults are the narrowest ranges the part offers, and the
driver hard-coded the matching scale factors, so there was no way to move
off them. Both are a poor fit for anything that moves quickly: 250 deg/s is
an ordinary aircraft aileron roll, and 2 g is exceeded by any real
manoeuvre. A saturated accelerometer is the worse of the two, because it
reads low rather than obviously wrong, so code that sanity-checks the vector
magnitude against 1 g becomes more likely to accept the bad sample.

- lf_mpu6050_init_config() takes gyro range, accel range, DLPF bandwidth and
  sample-rate divider; scale factors are derived and stored on the context,
  so read_data() stays correct at any range.
- Ranges and filtering can also be changed after init.
- Initialization now resets the device before configuring it, which matters
  across a warm boot, and selects the gyro PLL as the clock source instead of
  the internal oscillator the part powers up with.
- lf_mpu6050_calibrate_gyro() populates the gyro_bias fields that the context
  has always had and nothing ever set. Bias is kept in raw counts so it
  survives a range change.
- lf_mpu6050_read_si() reports m/s^2 alongside rad/s. read_data() mixes g
  with rad/s, which is easy to trip over.

lf_mpu6050_init() and read_data() keep their signatures and their behaviour,
so existing callers are unaffected. Verified by building both simquad Pico
firmware targets, which link this driver, against the change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014kuV9nVLjXCNGn8HSsSYNa
2026-09-19 21:52:19 -07:00
include Add configurable ranges, filtering, reset and gyro calibration 2026-09-19 21:52:19 -07:00
src Add configurable ranges, filtering, reset and gyro calibration 2026-09-19 21:52:19 -07:00
CMakeLists.txt Initial commit 2026-08-05 09:55:03 -07:00
conanfile.py Add configurable ranges, filtering, reset and gyro calibration 2026-09-19 21:52:19 -07:00
README.md Add configurable ranges, filtering, reset and gyro calibration 2026-09-19 21:52:19 -07:00

lf-mpu6050

Lost + Found MPU6050 6-Axis Accelerometer/Gyroscope driver library for Raspberry Pi Pico C SDK.

🔌 Hardware Setup

Standard Pin Mapping:

  • SDA: GP4 (Pico Pin 6)
  • SCL: GP5 (Pico Pin 7)
  • Bus: I2C0

📦 Usage

Add this package to your conanfile.txt or CMake setup.

CMake Integration

target_link_libraries(your_project PUBLIC lf-mpu6050)

Driver Instantiation

#include "lf_mpu6050.h"

lf_mpu6050_t mpu;

// Initialize with the power-on ranges (+/-2 g, +/-250 deg/s)
if (lf_mpu6050_init(&mpu, i2c0, LF_MPU6050_DEFAULT_I2C_ADDR)) {
    // Successfully initialized!
}

// Read telemetry
float accel[3], gyro[3], temp;
if (lf_mpu6050_read_data(&mpu, accel, gyro, &temp)) {
    printf("Accel: X=%.2f, Y=%.2f, Z=%.2f g\n", accel[0], accel[1], accel[2]);
    printf("Gyro: X=%.2f, Y=%.2f, Z=%.2f rad/s\n", gyro[0], gyro[1], gyro[2]);
    printf("Temp: %.2f C\n", temp);
}

⚙️ Choosing ranges

The power-on defaults are the narrowest ranges the part offers, which makes them a poor fit for anything that moves quickly:

  • ±250 °/s is exceeded by a hand flick or an ordinary aircraft aileron roll. A clipped gyroscope silently under-reports rotation.
  • ±2 g is exceeded by any real manoeuvre or a decent knock. A saturated accelerometer reads low, which is worse than reading obviously wrong: code that sanity-checks the vector magnitude against 1 g becomes more likely to accept the bad sample, not less.

So pick ranges explicitly:

lf_mpu6050_config_t cfg;
lf_mpu6050_config_defaults(&cfg);
cfg.gyro_range  = LF_MPU6050_GYRO_1000DPS;
cfg.accel_range = LF_MPU6050_ACCEL_8G;
cfg.dlpf        = LF_MPU6050_DLPF_44HZ;  // keep motor vibration out
cfg.sample_rate_div = 0;                 // 1 kHz output with the DLPF on

if (!lf_mpu6050_init_config(&mpu, i2c0, LF_MPU6050_DEFAULT_I2C_ADDR, &cfg)) {
    // sensor did not answer
}

lf_mpu6050_read_data() scales according to whichever ranges are configured, so nothing downstream changes when you widen them. The ranges can also be changed after init with lf_mpu6050_set_gyro_range(), lf_mpu6050_set_accel_range() and lf_mpu6050_set_dlpf().

Filtering

cfg.dlpf sets the on-chip low-pass. LF_MPU6050_DLPF_OFF gives the widest bandwidth and an 8 kHz internal rate; every other setting drops the internal rate to 1 kHz. Some filtering is usually wanted, especially near motors or propellers, because vibration that reaches a derivative term is amplified by it.

SI units

lf_mpu6050_read_data() reports acceleration in g but angular rate in rad/s, which is easy to trip over. lf_mpu6050_read_si() is identical except that acceleration comes back in m/s², so both outputs are SI:

float accel[3], gyro[3];   // m/s^2 and rad/s
lf_mpu6050_read_si(&mpu, accel, gyro, NULL);

Gyroscope calibration

// The device must be completely still: any motion during this is measured
// as bias and subtracted from every later reading.
lf_mpu6050_calibrate_gyro(&mpu, 500);   // ~500 ms

Bias is stored in raw counts, so it stays correct if you change the full-scale range afterwards. Only the gyroscope is calibrated — separating accelerometer bias from gravity needs a multi-orientation procedure that does not belong behind a single call.

Notes on initialization

lf_mpu6050_init_config() issues a device reset before configuring, then selects the gyroscope PLL as the clock source rather than the internal oscillator the part powers up with (the datasheet recommends this; it drifts less). The reset matters across a warm boot: without it the device keeps whatever registers the previous firmware left behind.

lf_mpu6050_init() is unchanged and still applies the power-on ranges, so existing code keeps working and reading identical values.

API

Function Purpose
lf_mpu6050_config_defaults Fill a config with the power-on defaults
lf_mpu6050_init Initialize with the power-on ranges
lf_mpu6050_init_config Initialize with explicit ranges, filter and rate
lf_mpu6050_set_gyro_range Change the gyroscope range
lf_mpu6050_set_accel_range Change the accelerometer range
lf_mpu6050_set_dlpf Change the low-pass bandwidth
lf_mpu6050_ping Check the device answers on the bus
lf_mpu6050_calibrate_gyro Average the gyroscope zero offset
lf_mpu6050_read_raw Raw register counts
lf_mpu6050_read_data Scaled: g and rad/s
lf_mpu6050_read_si Scaled: m/s² and rad/s