Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,27 @@ Use embedded-hal implementation to get SPI, NCS, and delay, then create mpu hand
extern crate mpu9250; // or just use mpu9250; if 2018 edition is used.

// to create sensor with mag support and default configuration:
let mut _imu = Mpu9250::marg_default(spi, ncs, &mut delay)?;
let mut marg = Mpu9250::marg_default(spi, ncs, &mut delay)?;
// to create sensor without mag support and default configuration:
let mut marg = Mpu9250::imu_default(spi, ncs, &mut delay)?;
let mut imu = Mpu9250::imu_default(spi, ncs, &mut delay)?;
// to get all supported measurements:
let all = marg.all()?;
let all = marg.all::<[f32; 3]>()?;
println!("{:?}", all);
```

or use the new expiremntal builder pattern:

```rust
extern crate mpu9250; // or just use mpu9250; if 2018 edition is used.

// to create sensor with mag support and default configuration:
let mut marg = mpu9250::MpuConfig::marg().build(spi, ncs);
marg.init(&mut delay)?;
// to create sensor without mag support and default configuration:
let mut imu = mpu9250::MpuConfig::imu().build(spi, ncs);
imu.init(&mut Delay)?;
// to get all supported measurements:
let all = marg.all::<[f32;3]>()?;
println!("{:?}", all);
```

Expand Down
16 changes: 13 additions & 3 deletions examples/bbblue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,18 @@ use mpu9250::Mpu9250;
fn main() -> io::Result<()> {
let i2c = I2cdev::new("/dev/i2c-2").expect("unable to open /dev/i2c-2");

let mut mpu9250 =
Mpu9250::marg_default(i2c, &mut Delay).expect("unable to make MPU9250");
// Legacy initialisation
let mut mpu9250 = Mpu9250::marg_default(i2c, &mut Delay)
.expect("unable to vreate MPU9250");

// New builder pattern initialisation
// 1. Create a new instance with the desired paramters
// let mut mpu9250 = MpuConfig::marg()
// .gyro_scale(Default::default())
// .gyro_temp_data_rate(Default::default())
// .build(i2c);
// 2. Initialize the hardware only when actually needed
// mpu9250.init(&mut Delay).unwrap();

let who_am_i = mpu9250.who_am_i().expect("could not read WHO_AM_I");
let mag_who_am_i = mpu9250.ak8963_who_am_i()
Expand All @@ -32,7 +42,7 @@ fn main() -> io::Result<()> {
writeln!(&mut stdout,
" Accel XYZ(m/s^2) | Gyro XYZ (rad/s) | Mag Field XYZ(uT) | Temp (C)")?;
loop {
let all = mpu9250.all().expect("unable to read from MPU!");
let all = mpu9250.all::<[f32; 3]>().expect("unable to read from MPU!");
write!(&mut stdout,
"\r{:>6.2} {:>6.2} {:>6.2} |{:>6.1} {:>6.1} {:>6.1} |{:>6.1} {:>6.1} {:>6.1} | {:>4.1} ",
all.accel[0],
Expand Down
14 changes: 11 additions & 3 deletions examples/bbblue_dmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ use std::io::{self, Write};
use hal::sysfs_gpio;
use hal::Delay;
use hal::I2cdev;
use mpu9250::MpuConfig;
use mpu9250::DMP_FIRMWARE;
use mpu9250::{Error, Mpu9250};
use mpu9250::Error;

fn main() {
let i2c = I2cdev::new("/dev/i2c-2").expect("unable to open /dev/i2c-2");
Expand All @@ -30,8 +31,15 @@ fn main() {
let mut stdout = stdout.lock();
writeln!(&mut stdout, " Normalized quaternion").unwrap();

let mut mpu9250 =
Mpu9250::dmp_default(i2c, &mut Delay, &DMP_FIRMWARE).expect("unable to load firmware");
//let mut mpu9250 =
// Mpu9250::dmp_default(i2c, &mut Delay, &DMP_FIRMWARE).expect("unable to load firmware");
let mut mpu9250 = MpuConfig::dmp()
.dmp_rate(mpu9250::DmpRate::_50Hz)
.dmp_features_tap(true)
.dmp_features_gyro_auto_calibrate(true)
.build(i2c);

mpu9250.init(&mut Delay, &DMP_FIRMWARE).unwrap();

loop {
match event.poll(1000).unwrap() {
Expand Down
16 changes: 13 additions & 3 deletions examples/rpi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use std::time::Duration;
use hal::spidev::{self, SpidevOptions};
use hal::sysfs_gpio::Direction;
use hal::{Delay, Pin, Spidev};
use mpu9250::Mpu9250;
use mpu9250::{Mpu9250, MpuConfig};

fn main() {
let mut spi = Spidev::open("/dev/spidev0.0").unwrap();
Expand All @@ -35,8 +35,18 @@ fn main() {
ncs.set_direction(Direction::Out).unwrap();
ncs.set_value(1).unwrap();

// Legacy initialisation
let mut mpu9250 = Mpu9250::marg_default(spi, ncs, &mut Delay).unwrap();

// New builder pattern initialisation
// 1. Create a new instance with the desired paramters
// let mut mpu9250 = MpuConfig::marg()
// .gyro_scale(Default::default())
// .gyro_temp_data_rate(Default::default())
// .build(spi, ncs);
// 2. Initialize the hardware only when actually needed
// mpu9250.init(&mut Delay).unwrap();

let who_am_i = mpu9250.who_am_i().unwrap();
let ak8963_who_am_i = mpu9250.ak8963_who_am_i().unwrap();

Expand All @@ -46,9 +56,9 @@ fn main() {
assert_eq!(who_am_i, 0x71);
assert_eq!(ak8963_who_am_i, 0x48);

println!("{:#?}", mpu9250.all().unwrap());
println!("{:#?}", mpu9250.all::<[f32; 3]>().unwrap());

thread::sleep(Duration::from_millis(100));

println!("{:#?}", mpu9250.all().unwrap());
println!("{:#?}", mpu9250.all::<[f32; 3]>().unwrap());
}
65 changes: 64 additions & 1 deletion src/conf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@ use core::default::Default;
use core::marker::PhantomData;

use super::types;
use super::Mpu9250;

extern crate embedded_hal as hal;
#[cfg(feature = "i2c")]
use hal::blocking::i2c;
#[cfg(not(feature = "i2c"))]
use hal::{blocking::spi, digital::v2::OutputPin};

#[cfg(feature = "i2c")]
use super::device::I2cDevice;
#[cfg(not(feature = "i2c"))]
use super::device::SpiDevice;

/// Controls the gyroscope and temperature sensor data rates and bandwidth.
/// Can be either set to one of two FChoices, or to one of the 8
Expand Down Expand Up @@ -322,7 +334,6 @@ pub struct DmpFeatures {
/// DMP auto calibrate gyro
pub gyro_auto_calibrate: bool,
}
#[cfg(feature = "dmp")]
impl DmpFeatures {
pub(crate) fn packet_size(self) -> usize {
let mut size = 0;
Expand Down Expand Up @@ -647,6 +658,58 @@ impl<MODE> MpuConfig<MODE> {
self.sample_rate_divisor = Some(smplrt_div);
self
}

#[cfg(not(feature = "i2c"))]
/// Build new Mpu9250 from current configuration using the provided device
pub fn build<E, SPI, NCS>(self,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For SPI connected devices we also provide *_with_reinit family of constructors. Although they are a bit ugly, they serve practical need -- maybe worth adding support for reinit to builders?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you give me an example of how you would use *with_reinit() so I can try to design something ergonomic.

spi: SPI,
ncs: NCS)
-> Mpu9250<SpiDevice<SPI, NCS>, MODE>
where SPI: spi::Write<u8, Error = E> + spi::Transfer<u8, Error = E>,
NCS: OutputPin
{
let dev = SpiDevice::new(spi, ncs);
Mpu9250 { dev,
mag_sensitivity_adjustments: [0.0; 3],
raw_mag_sensitivity_adjustments: [0; 3],
gyro_scale: self.gyro_scale.unwrap_or_default(),
accel_scale: self.accel_scale.unwrap_or_default(),
mag_scale: self.mag_scale.unwrap_or_default(),
gyro_temp_data_rate: self.gyro_temp_data_rate
.unwrap_or_default(),
accel_data_rate: self.accel_data_rate.unwrap_or_default(),
sample_rate_divisor: self.sample_rate_divisor,
dmp_configuration: self.dmp_configuration,
packet_size:
self.dmp_configuration
.map_or(0, |cfg| cfg.features.packet_size()),
_mode: PhantomData }
}

#[cfg(feature = "i2c")]
/// Build new Mpu9250 from current configuration using the provided device
pub fn build<E, I2C>(self, i2c: I2C) -> Mpu9250<I2cDevice<I2C>, MODE>
where I2C: i2c::Read<Error = E>
+ i2c::Write<Error = E>
+ i2c::WriteRead<Error = E>
{
let dev = I2cDevice::new(i2c);
Mpu9250 { dev,
mag_sensitivity_adjustments: [0.0; 3],
raw_mag_sensitivity_adjustments: [0; 3],
gyro_scale: self.gyro_scale.unwrap_or_default(),
accel_scale: self.accel_scale.unwrap_or_default(),
mag_scale: self.mag_scale.unwrap_or_default(),
gyro_temp_data_rate: self.gyro_temp_data_rate
.unwrap_or_default(),
accel_data_rate: self.accel_data_rate.unwrap_or_default(),
sample_rate_divisor: self.sample_rate_divisor,
dmp_configuration: self.dmp_configuration,
packet_size:
self.dmp_configuration
.map_or(0, |cfg| cfg.features.packet_size()),
_mode: PhantomData }
}
}

impl MpuConfig<types::Marg> {
Expand Down
39 changes: 39 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,19 @@ impl<E, DEV> Mpu9250<DEV, Imu> where DEV: Device<Error = E>
}
}

/// Init 6DOF Mpu9250
pub fn init<D>(&mut self, delay: &mut D,) -> Result<(), Error<E>>
where D: DelayMs<u8>
{
self.init_mpu(delay)?;
let wai = self.who_am_i()?;
if MpuXDevice::imu_supported(wai) {
Ok(())
} else {
Err(Error::InvalidDevice(wai))
}
}

/// Configures device using provided [`MpuConfig`].
pub fn config(&mut self, config: &mut MpuConfig<Imu>) -> Result<(), E> {
transpose(config.gyro_scale.map(|v| self.gyro_scale(v)))?;
Expand Down Expand Up @@ -679,6 +692,23 @@ impl<E, DEV> Mpu9250<DEV, Marg>
}
}

/// Init 9DOF mpu9250
pub fn init<D>(&mut self, delay: &mut D) -> Result<(), Error<E>>
where D: DelayMs<u8>
{
self.init_mpu(delay)?;
let wai = self.who_am_i()?;
if MpuXDevice::marg_supported(wai) {
self.init_ak8963(delay)?;
self.check_ak8963_who_am_i()?;
Ok(())
} else if wai == MpuXDevice::MPU6500 as u8 {
Err(Error::ModeNotSupported(wai))
} else {
Err(Error::InvalidDevice(wai))
}
}

/// Calculates the average of the at-rest readings of accelerometer and
/// gyroscope and then loads the resulting biases into gyro
/// offset registers. Retunrs either Ok with accelerometer biases, or
Expand Down Expand Up @@ -902,6 +932,15 @@ impl<E, DEV> Mpu9250<DEV, Dmp> where DEV: Device<Error = E>
Ok(mpu9250)
}

/// Init DMP mpu9250
pub fn init<D>(&mut self, delay: &mut D,firmware: &[u8]) -> Result<(), Error<E>>
where D: DelayMs<u8>
{
self.init_mpu(delay)?;
self.init_dmp(delay, firmware)?;
Ok(())
}

/// Logic to init the dmp
fn init_dmp<D>(&mut self,
delay: &mut D,
Expand Down
3 changes: 3 additions & 0 deletions src/types.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
/// Marker trait for mode
pub(crate) trait MpuMode {}
/// Accelerometer + Gyroscope + Temperature Sensor
#[derive(Copy, Clone, Debug)]
pub struct Imu;
impl MpuMode for Imu {}

/// Magnetometer + Accelerometer + Gyroscope + Temperature Sensor
#[derive(Copy, Clone, Debug)]
pub struct Marg;
impl MpuMode for Marg {}

/// Accelerometer + Gyroscope + Dmp
#[cfg(feature = "dmp")]
#[derive(Copy, Clone, Debug)]
pub struct Dmp;
#[cfg(feature = "dmp")]
impl MpuMode for Dmp {}