3 releases (breaking)
Uses new Rust 2024
| new 0.3.0 | Mar 2, 2026 |
|---|---|
| 0.2.0 | Feb 8, 2026 |
| 0.1.0 | Feb 4, 2026 |
#218 in Hardware support
260KB
5K
SLoC
LSM9DS0
A platform-agnostic Rust driver for the ST LSM9DS0 9-axis IMU (3D accelerometer, 3D gyroscope, 3D magnetometer).
Built on embedded-hal-async traits for I2C and SPI communication.
Features
- I2C and SPI interface support
- Configurable sensor ranges and data rates
- Temperature sensor
- FIFO support
- Interrupt configuration
no_stdcompatible
Usage
Add the dependency to your Cargo.toml:
[dependencies]
lsm9ds0 = "0.1"
I2C
use lsm9ds0::{
AccelDataRate, GyroDataRate, I2cInterface, Lsm9ds0, Lsm9ds0Config, MagMode,
};
use embassy_time::Delay;
let interface = I2cInterface::init(i2c);
let config = Lsm9ds0Config::new()
.with_gyro_enabled(true)
.with_gyro_data_rate(GyroDataRate::Hz95)
.with_accel_data_rate(AccelDataRate::Hz100)
.with_mag_mode(MagMode::ContinuousConversion)
.with_temperature_enabled(true)
.with_auto_calibration(lsm9ds0::Orientation::ZUp);
let mut imu = Lsm9ds0::new_with_config(interface, config);
imu.init(&mut Delay).await?;
let (gx, gy, gz) = imu.read_gyro().await?; // DegreesPerSecond
let (ax, ay, az) = imu.read_accel().await?; // GForce
let (mx, my, mz) = imu.read_mag().await?; // Gauss
let temp = imu.read_temp().await?; // Celsius
SPI
The LSM9DS0 has separate chip selects for the gyroscope and accelerometer/magnetometer. Provide two SpiDevice instances:
use lsm9ds0::{Lsm9ds0, SpiInterface};
use embassy_time::Delay;
let interface = SpiInterface::init(gyro_spi, accel_mag_spi);
let mut imu = Lsm9ds0::new(interface);
imu.init(&mut Delay).await?;
Configuration
Sensor parameters can be set at initialization or changed at runtime:
use lsm9ds0::{AccelScale, GyroDataRate, GyroScale, MagScale, Orientation};
use embassy_time::Delay;
// At initialization
let config = Lsm9ds0Config::new()
.with_gyro_scale(GyroScale::Dps500)
.with_accel_scale(AccelScale::G4)
.with_mag_scale(MagScale::Gauss8);
// At runtime
imu.set_gyro_scale(GyroScale::Dps2000).await?;
imu.set_accel_data_rate(AccelDataRate::Hz400).await?;
// Calibrate the gyroscope and accelerometer during runtime
imu.calibrate_bias(&mut Delay, Orientation::ZUp).await?;
Blocking I2C / SPI
This driver is built on embedded-hal-async traits, but it works with blocking buses too. The
async methods on the driver still require .await, but if the underlying bus is blocking, they
complete immediately with no executor overhead.
You need two things:
- An adapter that wraps your blocking
embedded_hal::i2c::I2c(orSpiDevice) to satisfy the async trait. The async fn just calls the blocking method and returns — no actual suspension:
struct BlockingI2c<I>(I);
impl<I: embedded_hal::i2c::I2c> embedded_hal::i2c::ErrorType for BlockingI2c<I> {
type Error = I::Error;
}
impl<I: embedded_hal::i2c::I2c> embedded_hal_async::i2c::I2c for BlockingI2c<I> {
async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
self.0.read(address, read)
}
async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
self.0.write(address, write)
}
async fn write_read(&mut self, address: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
self.0.write_read(address, write, read)
}
async fn transaction(&mut self, address: u8, operations: &mut [embedded_hal::i2c::Operation<'_>]) -> Result<(), Self::Error> {
self.0.transaction(address, operations)
}
}
- A trivial executor like
embassy_futures::block_onto run the async code synchronously:
use embassy_futures::block_on;
let interface = I2cInterface::init(BlockingI2c(my_blocking_i2c));
let mut imu = Lsm9ds0::new_with_config(interface, config);
block_on(async {
imu.init(&mut delay).await?;
let (gx, gy, gz) = imu.read_gyro().await?;
});
See the examples/rp2040/src/bin/simple-i2c-blocking.rs example for a complete working implementation.
Default Configuration
The driver's default configuration matches the device's power-on-reset register values from the datasheet, with two exceptions where the actual hardware defaults differ from the documented values:
| Register | Datasheet | Actual |
|---|---|---|
| CTRL_REG7_XM | 0x02 | 0x03 |
| INT_CTRL_REG_M | 0x00 | 0xE8 |
Examples
See the examples/ directory for platform-specific examples, including RP2040.
References
License
Dependencies
~225–690KB
~15K SLoC