A platform agnostic driver to interface with LSM9DS1 3D accelerometer, 3D gyroscope, 3D magnetometer sensor module.
This library is work in progress. Not all features are implemented yet. Contributions are welcome.
- SPI communication with Accelerometer/Gyroscope
- SPI communication with Magnetometer
- SPI communication with Temperature Sensor
- I2C communication with Accelerometer/Gyroscope
- I2C communication with Magnetometer
- I2C communication with Temperature Sensor
- Custom sensor settings
- Sensor reading (Accel, Gyro, Mag, Temperature)
- Raw Sensor reading (Accel, Gyro, Mag) See
read_sensor_raw()
. - Calibration
- Interrupt
- FIFO Mode
- Configure sensor settings with
LSM9DS1Init
. - Initialize a communication interface: either
SpiInterface
orI2cInterface
. - Initialize
LSM9DS1
driver with the interface of your choice. - Start the sensors.
- Get the sensors' readings.
This driver uses LSM9DS1Init
struct to set sensor configuration.
pub struct LSM9DS1Init {
pub accel: AccelSettings,
pub gyro: GyroSettings,
pub mag: MagSettings,
}
You can find each sensor's default settings in accel.rs
, gyro.rs
and mag.rs
.
impl Default for AccelSettings {
fn default() -> Self {
AccelSettings {
enable_x: true,
enable_y: true,
enable_z: true,
sample_rate: ODR::_119Hz,
scale: Scale::_2G,
bandwidth_selection: BandwidthSelection::ByODR,
bandwidth: Bandwidth::_408Hz,
high_res_bandwidth: HighRes::Disabled,
}
}
}
impl Default for GyroSettings {
fn default() -> Self {
GyroSettings {
enable_x: true,
enable_y: true,
enable_z: true,
flip_x: false,
flip_y: false,
flip_z: false,
scale: Scale::_245DPS,
sample_rate: ODR::_952Hz,
bandwidth: Bandwidth::LPF_0,
int_selection: GyroIntSelection::SEL_0,
out_selection: GyroOutSelection::SEL_0,
low_power_mode: LowPowerMode::Disabled,
hpf_mode: HpFilter::Disabled,
hpf_cutoff: HpFilterCutoff::HPCF_1,
latch_interrupt: LatchInterrupt::Disabled,
}
}
}
impl Default for MagSettings {
fn default() -> Self {
MagSettings {
temp_compensation: TempComp::Disabled,
x_y_performance: OpModeXY::Low,
sample_rate: ODR::_10Hz,
scale: Scale::_4G,
i2c_mode: I2cMode::Enabled,
system_op: SysOpMode::Continuous,
low_power: LowPowerMode::Disabled,
spi_mode: SpiMode::RW,
z_performance: OpModeZ::Low,
}
}
}
If you want to use the default settings, initialize LSM9DS1Init
this way.
LSM9DS1Init {
..Default::default()
}
If you want a custom configuration, modify the fields that are different from the default values.
LSM9DS1Init {
accel: accel::AccelSettings {
scale: accel::Scale::_16G, // custom setting
..Default::default() // the rest of the fields are the default values.
},
..Default::default() // gyro and mag use the default settings.
}
LSM9DS1 supports SPI and I2C communication. Create an instance of SpiInterface
or I2cInterface
and pass it to LSM9DS1Init
's with_interface()
method to create an instance of LSM9DS1
driver.
// Create SPI interface
let spi_interface = SpiInterface::init(spi, ag_cs, m_cs);
// Init LSM9DS1 driver with settings and SPI interface
let mut lsm9ds1 = LSM9DS1Init {
..Default::default()
}
.with_interface(spi_interface);
Turn on sensors.
lsm9ds1.begin_accel().unwrap();
lsm9ds1.begin_gyro().unwrap();
lsm9ds1.begin_mag().unwrap();
Get readings
let temp = lsm9ds1.read_temp().unwrap(); // temperature reading in celsius
let (x, y, z) = lsm9ds1.read_accel().unwrap();
let (x, y, z) = lsm9ds1.read_gyro().unwrap();
let (x, y, z) = lsm9ds1.read_mag().unwrap();
This code shows how to read sensor values with SPI interface. (Error handling is omitted for brevity.)
//! Target board: STM32F3DISCOVERY
#![no_std]
#![no_main]
extern crate panic_semihosting;
pub use cortex_m::{asm::bkpt, iprint, iprintln, peripheral::ITM};
use cortex_m_rt::entry;
use embedded_hal::spi::MODE_0;
use stm32f3xx_hal as hal;
use hal::prelude::*;
use hal::spi::Spi;
use hal::stm32;
use lsm9ds1::interface::SpiInterface;
use lsm9ds1::{accel, gyro, mag, LSM9DS1Init};
#[entry]
fn main() -> ! {
let cp = cortex_m::Peripherals::take().unwrap();
let mut itm = cp.ITM;
let dp = stm32::Peripherals::take().unwrap();
let mut flash = dp.FLASH.constrain();
let mut rcc = dp.RCC.constrain();
// Accelerometer/Gyroscope Chip Select
let mut gpiob = dp.GPIOB.split(&mut rcc.ahb);
let mut ag_cs = gpiob
.pb5
.into_push_pull_output(&mut gpiob.moder, &mut gpiob.otyper);
ag_cs.set_high().unwrap();
// Magnetometer Chip Select
let mut m_cs = gpiob
.pb4
.into_push_pull_output(&mut gpiob.moder, &mut gpiob.otyper);
m_cs.set_high().unwrap();
// SPI
let mut gpioa = dp.GPIOA.split(&mut rcc.ahb);
let clocks = rcc.cfgr.freeze(&mut flash.acr);
// Configure pins for SPI
let sck = gpioa.pa5.into_af5(&mut gpioa.moder, &mut gpioa.afrl);
let miso = gpioa.pa6.into_af5(&mut gpioa.moder, &mut gpioa.afrl);
let mosi = gpioa.pa7.into_af5(&mut gpioa.moder, &mut gpioa.afrl);
let spi = Spi::spi1(
dp.SPI1,
(sck, miso, mosi),
MODE_0,
1.mhz(),
clocks,
&mut rcc.apb2,
);
// Create SPI interface
let spi_interface = SpiInterface::init(spi, ag_cs, m_cs);
// Init LSM9DS1 with default settings and attach SPI interface
let mut lsm9ds1 = LSM9DS1Init {
..Default::default()
}
.with_interface(spi_interface);
// start sensors
lsm9ds1.begin_accel().unwrap();
lsm9ds1.begin_gyro().unwrap();
lsm9ds1.begin_mag().unwrap();
loop {
// read sensors
let temp = lsm9ds1.read_temp().unwrap();
iprintln!(&mut itm.stim[0], "temp: {}", temp);
let (x, y, z) = lsm9ds1.read_accel().unwrap();
iprintln!(&mut itm.stim[0], "xl: {}, {}, {}", x, y, z);
let (x, y, z) = lsm9ds1.read_gyro().unwrap();
iprintln!(&mut itm.stim[0], "gy: {}, {}, {}", x, y, z);
let (x, y, z) = lsm9ds1.read_mag().unwrap();
iprintln!(&mut itm.stim[0], "mg: {}, {}, {}", x, y, z);
cortex_m::asm::delay(8_000_000);
}
}