embedded_sensors/mpu6500/
mod.rs

1use core::marker::PhantomData;
2
3use embedded_hal::blocking::{delay, i2c};
4use nalgebra::Vector3;
5
6use self::{
7    config::Config,
8    register::Register,
9    result::{Error, Result},
10};
11
12pub mod config;
13mod register;
14pub mod result;
15
16pub const I2C_ADDR_AL: u8 = 0x68;
17pub const I2C_ADDR_AH: u8 = 0x69;
18
19pub const DEV_ID_MPU6500: u8 = 0x70;
20pub const DEV_ID_MPU9250: u8 = 0x71;
21pub const DEV_ID_MPU9255: u8 = 0x73;
22
23// const CALIB_GYRO_SENSITIVITY: u16 = 131; // LSB/deg/s
24const CALIB_ACCEL_SENSITIVITY: u16 = 16384; // LSB/g
25
26const DEG_TO_RAD: f32 = 0.01745329252;
27
28pub struct Mpu6500<I2C>
29where
30    I2C: i2c::Read + i2c::Write,
31{
32    addr: u8,
33    cfg: Config,
34    pub(crate) acceleration: Vector3<f32>,
35    pub(crate) angular_velocity: Vector3<f32>,
36    pub(crate) temperature: f32,
37    accel_bias: Vector3<f32>,
38    gyro_bias: Vector3<f32>,
39    accel_resolution: f32,
40    gyro_resolution: f32,
41    _i2c: PhantomData<I2C>,
42}
43
44impl<I2C, I2cError> Mpu6500<I2C>
45where
46    I2C: i2c::Read<Error = I2cError> + i2c::Write<Error = I2cError>,
47{
48    pub fn new<DELAY>(addr: u8, delay: &mut DELAY, i2c: &mut I2C) -> Result<Self, I2cError>
49    where
50        DELAY: delay::DelayMs<u16>,
51    {
52        Self::with_configuration(addr, i2c, delay, Config::default())
53    }
54
55    pub fn with_configuration<DELAY>(
56        addr: u8,
57        i2c: &mut I2C,
58        delay: &mut DELAY,
59        cfg: Config,
60    ) -> Result<Self, I2cError>
61    where
62        DELAY: delay::DelayMs<u16>,
63    {
64        let dev_id = Self::who_am_i(addr, i2c)?;
65
66        if dev_id != DEV_ID_MPU6500 && dev_id != DEV_ID_MPU9250 && dev_id != DEV_ID_MPU9255 {
67            return Err(Error::InvalidDevice(dev_id));
68        }
69
70        let mut mpu = Self {
71            addr,
72            acceleration: Vector3::default(),
73            angular_velocity: Vector3::default(),
74            temperature: 0.0,
75            accel_bias: Vector3::default(),
76            gyro_bias: Vector3::default(),
77            accel_resolution: cfg.accel_fs_sel.get_resolution(),
78            gyro_resolution: cfg.gyro_fs_sel.get_resolution(),
79            cfg,
80            _i2c: PhantomData::default(),
81        };
82
83        mpu.init(i2c, delay)?;
84
85        Ok(mpu)
86    }
87
88    fn init<DELAY>(&mut self, i2c: &mut I2C, delay: &mut DELAY) -> Result<(), I2cError>
89    where
90        DELAY: delay::DelayMs<u16>,
91    {
92        Self::pwr_mgmt_1(self.addr, i2c, false, false, false, false, false, 0x00)?;
93        delay.delay_ms(100);
94
95        Self::pwr_mgmt_1(self.addr, i2c, false, false, false, false, false, 0x01)?;
96        delay.delay_ms(200);
97
98        Self::config(self.addr, i2c, false, self.cfg.gyro_dlpf_cfg)?;
99        Self::sample_rate_div(self.addr, i2c, self.cfg.fifo_sample_rate)?;
100
101        Self::gyro_cfg(self.addr, i2c, self.cfg.gyro_fs_sel, self.cfg.gyro_fchoice)?;
102
103        Self::accel_cfg(self.addr, i2c, self.cfg.accel_fs_sel)?;
104        Self::accel_cfg_2(
105            self.addr,
106            i2c,
107            (self.cfg.accel_fchoice & 0x01) == 1,
108            self.cfg.accel_dlpf_cfg,
109        )?;
110        Self::int_pin_bypass_enable_interrupt_cfg(
111            self.addr, i2c, false, false, false, false, false, false, true,
112        )?;
113        Self::enable_interrupt(self.addr, i2c, false, false, false, true)?;
114        delay.delay_ms(100);
115
116        Ok(())
117    }
118
119    pub(crate) fn read_imu(&mut self, i2c: &mut I2C) -> Result<(), I2cError> {
120        let mut buf = [0; 14];
121        Self::read_register(self.addr, i2c, Register::ACCEL_XOUT_H, &mut buf)?;
122
123        self.acceleration = Vector3::new(
124            i16::from_be_bytes([buf[0], buf[1]]) as f32 * self.accel_resolution,
125            i16::from_be_bytes([buf[2], buf[3]]) as f32 * self.accel_resolution,
126            i16::from_be_bytes([buf[4], buf[5]]) as f32 * self.accel_resolution,
127        );
128
129        self.temperature = i16::from_be_bytes([buf[6], buf[7]]) as f32 / 333.87 + 21.0;
130
131        self.angular_velocity = Vector3::new(
132            i16::from_be_bytes([buf[8], buf[9]]) as f32 * self.gyro_resolution * DEG_TO_RAD,
133            i16::from_be_bytes([buf[10], buf[11]]) as f32 * self.gyro_resolution * DEG_TO_RAD,
134            i16::from_be_bytes([buf[12], buf[13]]) as f32 * self.gyro_resolution * DEG_TO_RAD,
135        );
136
137        Ok(())
138    }
139
140    pub fn read(&mut self, i2c: &mut I2C) -> Result<(), I2cError> {
141        self.read_imu(i2c)?;
142
143        Ok(())
144    }
145
146    pub fn calibrate<DELAY>(&mut self, i2c: &mut I2C, delay: &mut DELAY) -> Result<(), I2cError>
147    where
148        DELAY: delay::DelayMs<u16>,
149    {
150        Self::pwr_mgmt_1(self.addr, i2c, false, false, false, false, false, 0x01)?;
151        Self::pwr_mgmt_2(self.addr, i2c, false, false, false, false, false, false)?;
152        delay.delay_ms(200);
153
154        Self::enable_interrupt(self.addr, i2c, false, false, false, false)?;
155        Self::fifo_enable(
156            self.addr, i2c, false, false, false, false, false, false, false, false,
157        )?;
158        Self::pwr_mgmt_1(self.addr, i2c, false, false, false, false, false, 0x00)?;
159        Self::i2c_mst_ctrl(self.addr, i2c, false, false, false, false, 0x00)?;
160        Self::user_ctrl(self.addr, i2c, false, false, false, false, false, false)?;
161        Self::user_ctrl(self.addr, i2c, false, false, true, true, false, false)?;
162        delay.delay_ms(15);
163
164        Self::config(self.addr, i2c, false, config::GyroDlpfCfg::Dlpf184Hz)?;
165        Self::sample_rate_div(self.addr, i2c, config::FifoSampleRate::Smpl1000Hz)?;
166        Self::gyro_cfg(self.addr, i2c, config::GyroFullScaleSelect::Dps250, 0x00)?;
167        Self::accel_cfg(self.addr, i2c, config::AccelFullScaleSelect::G2)?;
168
169        Self::user_ctrl(self.addr, i2c, true, false, false, false, false, false)?;
170        Self::fifo_enable(
171            self.addr, i2c, false, true, true, true, true, false, false, false,
172        )?;
173        delay.delay_ms(40);
174
175        Self::fifo_enable(
176            self.addr, i2c, false, false, false, false, false, false, false, false,
177        )?;
178
179        let fifo_count = Self::fifo_count_h(self.addr, i2c)?;
180        let packet_count = fifo_count / 12;
181
182        for _ in 0..packet_count {
183            let (accel, gyro) = Self::fifo_read(self.addr, i2c)?;
184
185            self.accel_bias.x += accel.x as f32;
186            self.accel_bias.y += accel.y as f32;
187            self.accel_bias.z += accel.z as f32;
188
189            self.gyro_bias.x += gyro.x as f32;
190            self.gyro_bias.y += gyro.y as f32;
191            self.gyro_bias.z += gyro.z as f32;
192        }
193
194        if packet_count != 0 {
195            self.accel_bias /= packet_count as f32;
196            self.gyro_bias /= packet_count as f32;
197
198            if self.accel_bias.z > 0.0 {
199                self.accel_bias.z -= CALIB_ACCEL_SENSITIVITY as f32;
200            } else {
201                self.accel_bias.z += CALIB_ACCEL_SENSITIVITY as f32;
202            }
203        }
204
205        let mut accel_offset = Self::read_accel_offset(self.addr, i2c)?;
206        let mut mask_bit = Vector3::new(1, 1, 1);
207
208        // x
209
210        if accel_offset.x % 2 != 0 {
211            mask_bit.x = 0;
212        }
213
214        accel_offset.x -= (self.accel_bias.x as i16) >> 3;
215
216        if mask_bit.x != 0 {
217            accel_offset.x &= !mask_bit.x;
218        } else {
219            accel_offset.x |= 0b1;
220        }
221
222        // y
223
224        if accel_offset.y % 2 != 0 {
225            mask_bit.y = 0;
226        }
227
228        accel_offset.y -= (self.accel_bias.y as i16) >> 3;
229
230        if mask_bit.y != 0 {
231            accel_offset.y &= !mask_bit.y;
232        } else {
233            accel_offset.y |= 0b1;
234        }
235
236        // z
237
238        if accel_offset.z % 2 != 0 {
239            mask_bit.z = 0;
240        }
241
242        accel_offset.z -= (self.accel_bias.z as i16) >> 3;
243
244        if mask_bit.z != 0 {
245            accel_offset.z &= !mask_bit.z;
246        } else {
247            accel_offset.z |= 0b1;
248        }
249
250        let gyro_offset = Vector3::new(
251            -self.gyro_bias.x as i16 / 4,
252            -self.gyro_bias.y as i16 / 4,
253            -self.gyro_bias.z as i16 / 4,
254        );
255
256        Self::write_accel_offset(self.addr, i2c, accel_offset)?;
257        Self::write_gyro_offset(self.addr, i2c, gyro_offset)?;
258
259        delay.delay_ms(100);
260
261        self.init(i2c, delay)?;
262
263        Ok(())
264    }
265
266    pub fn acceleration(&self) -> Vector3<f32> {
267        self.acceleration
268    }
269
270    pub fn angular_velocity(&self) -> Vector3<f32> {
271        self.angular_velocity
272    }
273
274    /// Registers 19 to 24 – Gyro Offset Registers
275    fn write_gyro_offset(
276        addr: u8,
277        i2c: &mut I2C,
278        gyro_offset: Vector3<i16>,
279    ) -> Result<(), I2cError> {
280        let x = gyro_offset.x.to_be_bytes();
281        Self::write_register(addr, i2c, Register::XG_OFFSET_H, x[0])?;
282        Self::write_register(addr, i2c, Register::XG_OFFSET_L, x[1])?;
283
284        let y = gyro_offset.y.to_be_bytes();
285        Self::write_register(addr, i2c, Register::YG_OFFSET_H, y[0])?;
286        Self::write_register(addr, i2c, Register::YG_OFFSET_L, y[1])?;
287
288        let z = gyro_offset.z.to_be_bytes();
289        Self::write_register(addr, i2c, Register::ZG_OFFSET_H, z[0])?;
290        Self::write_register(addr, i2c, Register::ZG_OFFSET_L, z[1])?;
291
292        Ok(())
293    }
294
295    /// Register 25 – Sample Rate Divider
296    fn sample_rate_div(
297        addr: u8,
298        i2c: &mut I2C,
299        smplrt_div: config::FifoSampleRate,
300    ) -> Result<(), I2cError> {
301        Self::write_register(addr, i2c, Register::SMPLRT_DIV, smplrt_div as u8)
302    }
303
304    /// Register 26 – Configuration
305    fn config(
306        addr: u8,
307        i2c: &mut I2C,
308        fifo_mode: bool,
309        dlpf_cfg: config::GyroDlpfCfg,
310    ) -> Result<(), I2cError> {
311        Self::write_register(
312            addr,
313            i2c,
314            Register::CONFIG,
315            (fifo_mode as u8) << 6 | (dlpf_cfg as u8) << 0,
316        )
317    }
318
319    /// Register 27 – Gyroscope Configuration
320    fn gyro_cfg(
321        addr: u8,
322        i2c: &mut I2C,
323        gyro_fs_sel: config::GyroFullScaleSelect,
324        fchoice_b: u8,
325    ) -> Result<(), I2cError> {
326        let mut c = [0; 1];
327        Self::read_register(addr, i2c, Register::GYRO_CONFIG, &mut c)?;
328
329        Self::write_register(
330            addr,
331            i2c,
332            Register::GYRO_CONFIG,
333            c[0] & 0b11100111 | (gyro_fs_sel as u8) << 3 | (fchoice_b & 0b11) << 0,
334        )
335    }
336
337    /// Register 28 – Accelerometer Configuration
338    fn accel_cfg(
339        addr: u8,
340        i2c: &mut I2C,
341        accel_fs_sel: config::AccelFullScaleSelect,
342    ) -> Result<(), I2cError> {
343        let mut c = [0; 1];
344        Self::read_register(addr, i2c, Register::ACCEL_CONFIG_2, &mut c)?;
345
346        Self::write_register(
347            addr,
348            i2c,
349            Register::ACCEL_CONFIG,
350            c[0] & 0b11100111 | (accel_fs_sel as u8) << 3,
351        )
352    }
353
354    /// Register 29 – Accelerometer Configuration 2
355    fn accel_cfg_2(
356        addr: u8,
357        i2c: &mut I2C,
358        accel_fchoice_b: bool,
359        a_dlpf_cfg: config::AccelDlpfCfg,
360    ) -> Result<(), I2cError> {
361        let mut c = [0; 1];
362        Self::read_register(addr, i2c, Register::ACCEL_CONFIG_2, &mut c)?;
363
364        Self::write_register(
365            addr,
366            i2c,
367            Register::ACCEL_CONFIG_2,
368            c[0] & 0b11110000 | (accel_fchoice_b as u8) << 3 | (a_dlpf_cfg as u8) << 0,
369        )
370    }
371
372    /// Register 35 – FIFO Enable
373    fn fifo_enable(
374        addr: u8,
375        i2c: &mut I2C,
376        temp_out: bool,
377        gyro_xout: bool,
378        gyro_yout: bool,
379        gyro_zout: bool,
380        accel: bool,
381        slv_2: bool,
382        slv_1: bool,
383        slv_0: bool,
384    ) -> Result<(), I2cError> {
385        Self::write_register(
386            addr,
387            i2c,
388            Register::FIFO_EN,
389            (temp_out as u8) << 7
390                | (gyro_xout as u8) << 6
391                | (gyro_yout as u8) << 5
392                | (gyro_zout as u8) << 4
393                | (accel as u8) << 3
394                | (slv_2 as u8) << 2
395                | (slv_1 as u8) << 1
396                | (slv_0 as u8) << 0,
397        )
398    }
399
400    /// Register 36 – I2C Master Control
401    fn i2c_mst_ctrl(
402        addr: u8,
403        i2c: &mut I2C,
404        mult_mst_en: bool,
405        wait_for_es: bool,
406        slv_3_fifo_en: bool,
407        i2c_mst_p_nsr: bool,
408        i2c_mst_clk: u8,
409    ) -> Result<(), I2cError> {
410        Self::write_register(
411            addr,
412            i2c,
413            Register::I2C_MST_CTRL,
414            (mult_mst_en as u8) << 7
415                | (wait_for_es as u8) << 6
416                | (slv_3_fifo_en as u8) << 5
417                | (i2c_mst_p_nsr as u8) << 4
418                | (i2c_mst_clk & 0b1111) << 0,
419        )
420    }
421
422    /// Register 55 – INT Pin / Bypass Enable Configuration
423    fn int_pin_bypass_enable_interrupt_cfg(
424        addr: u8,
425        i2c: &mut I2C,
426        actl: bool,
427        open: bool,
428        latch_int_en: bool,
429        int_anyrd_2clear: bool,
430        actl_fsync: bool,
431        fsync_int_mode_en: bool,
432        bypass_en: bool,
433    ) -> Result<(), I2cError> {
434        Self::write_register(
435            addr,
436            i2c,
437            Register::INT_PIN_CFG,
438            (actl as u8) << 7
439                | (open as u8) << 6
440                | (latch_int_en as u8) << 5
441                | (int_anyrd_2clear as u8) << 4
442                | (actl_fsync as u8) << 3
443                | (fsync_int_mode_en as u8) << 2
444                | (bypass_en as u8) << 1,
445        )
446    }
447
448    /// Register 56 – Interrupt Enable
449    fn enable_interrupt(
450        addr: u8,
451        i2c: &mut I2C,
452        wom_en: bool,
453        fifo_overflow_en: bool,
454        fsync_int_en: bool,
455        raw_rdy_en: bool,
456    ) -> Result<(), I2cError> {
457        Self::write_register(
458            addr,
459            i2c,
460            Register::INT_ENABLE,
461            (wom_en as u8) << 6
462                | (fifo_overflow_en as u8) << 4
463                | (fsync_int_en as u8) << 3
464                | (raw_rdy_en as u8) << 0,
465        )
466    }
467
468    /// Register 106 – User Control
469    fn user_ctrl(
470        addr: u8,
471        i2c: &mut I2C,
472        fifo_en: bool,
473        i2c_mst_en: bool,
474        i2c_if_dis: bool,
475        fifo_rst: bool,
476        i2c_mst_rst: bool,
477        sig_cond_rst: bool,
478    ) -> Result<(), I2cError> {
479        Self::write_register(
480            addr,
481            i2c,
482            Register::USER_CTRL,
483            (fifo_en as u8) << 6
484                | (i2c_mst_en as u8) << 5
485                | (i2c_if_dis as u8) << 4
486                | (fifo_rst as u8) << 2
487                | (i2c_mst_rst as u8) << 1
488                | (sig_cond_rst as u8) << 0,
489        )
490    }
491
492    /// Register 107 – Power Management 1
493    fn pwr_mgmt_1(
494        addr: u8,
495        i2c: &mut I2C,
496        h_reset: bool,
497        sleep: bool,
498        cycle: bool,
499        gyro_standby: bool,
500        pd_ptat: bool,
501        clksel: u8,
502    ) -> Result<(), I2cError> {
503        Self::write_register(
504            addr,
505            i2c,
506            Register::PWR_MGMT_1,
507            (h_reset as u8) << 7
508                | (sleep as u8) << 6
509                | (cycle as u8) << 5
510                | (gyro_standby as u8) << 4
511                | (pd_ptat as u8) << 3
512                | (clksel & 0b111) << 0,
513        )
514    }
515
516    // Register 108 – Power Management 2
517    fn pwr_mgmt_2(
518        addr: u8,
519        i2c: &mut I2C,
520        disable_xa: bool,
521        disable_ya: bool,
522        disable_za: bool,
523        disable_xg: bool,
524        disable_yg: bool,
525        disable_zg: bool,
526    ) -> Result<(), I2cError> {
527        Self::write_register(
528            addr,
529            i2c,
530            Register::PWR_MGMT_2,
531            (disable_xa as u8) << 5
532                | (disable_ya as u8) << 4
533                | (disable_za as u8) << 3
534                | (disable_xg as u8) << 2
535                | (disable_yg as u8) << 1
536                | (disable_zg as u8) << 0,
537        )
538    }
539
540    /// Register 114 – FIFO Count High
541    fn fifo_count_h(addr: u8, i2c: &mut I2C) -> Result<u16, I2cError> {
542        let mut buf = [0; 2];
543        Self::read_register(addr, i2c, Register::FIFO_COUNTH, &mut buf)?;
544        Ok(u16::from_be_bytes(buf))
545    }
546
547    /// Register 116 – FIFO Read Write
548    fn fifo_read(addr: u8, i2c: &mut I2C) -> Result<(Vector3<i16>, Vector3<i16>), I2cError> {
549        let mut buf = [0; 12];
550        Self::read_register(addr, i2c, Register::FIFO_R_W, &mut buf)?;
551        Ok((
552            Vector3::new(
553                i16::from_be_bytes([buf[0], buf[1]]),
554                i16::from_be_bytes([buf[2], buf[3]]),
555                i16::from_be_bytes([buf[4], buf[5]]),
556            ),
557            Vector3::new(
558                i16::from_be_bytes([buf[6], buf[7]]),
559                i16::from_be_bytes([buf[8], buf[9]]),
560                i16::from_be_bytes([buf[10], buf[11]]),
561            ),
562        ))
563    }
564
565    /// Register 117 – Who Am I
566    fn who_am_i(addr: u8, i2c: &mut I2C) -> Result<u8, I2cError> {
567        let mut buf = [0; 1];
568        Self::read_register(addr, i2c, Register::WHO_AM_I, &mut buf)?;
569        Ok(buf[0])
570    }
571
572    /// Registers 119, 120, 122, 123, 125, 126 – Accelerometer Offset Registers
573    fn read_accel_offset(addr: u8, i2c: &mut I2C) -> Result<Vector3<i16>, I2cError> {
574        let mut buf = [0; 2];
575        Self::read_register(addr, i2c, Register::XA_OFFSET_H, &mut buf)?;
576        let x = i16::from_be_bytes(buf);
577
578        let mut buf = [0; 2];
579        Self::read_register(addr, i2c, Register::YA_OFFSET_H, &mut buf)?;
580        let y = i16::from_be_bytes(buf);
581
582        let mut buf = [0; 2];
583        Self::read_register(addr, i2c, Register::ZA_OFFSET_H, &mut buf)?;
584        let z = i16::from_be_bytes(buf);
585
586        Ok(Vector3::new(x, y, z))
587    }
588
589    /// Registers 119, 120, 122, 123, 125, 126 – Accelerometer Offset Registers
590    fn write_accel_offset(
591        addr: u8,
592        i2c: &mut I2C,
593        accel_offset: Vector3<i16>,
594    ) -> Result<(), I2cError> {
595        let x = accel_offset.x.to_be_bytes();
596        Self::write_register(addr, i2c, Register::XA_OFFSET_H, x[0])?;
597        Self::write_register(addr, i2c, Register::XA_OFFSET_L, x[1])?;
598
599        let y = accel_offset.y.to_be_bytes();
600        Self::write_register(addr, i2c, Register::YA_OFFSET_H, y[0])?;
601        Self::write_register(addr, i2c, Register::YA_OFFSET_L, y[1])?;
602
603        let z = accel_offset.z.to_be_bytes();
604        Self::write_register(addr, i2c, Register::ZA_OFFSET_H, z[0])?;
605        Self::write_register(addr, i2c, Register::ZA_OFFSET_L, z[1])?;
606
607        Ok(())
608    }
609
610    fn read_register(
611        addr: u8,
612        i2c: &mut I2C,
613        reg: Register,
614        buf: &mut [u8],
615    ) -> Result<(), I2cError> {
616        match i2c.write(addr, &[reg as u8]) {
617            Ok(()) => {}
618            Err(e) => return Err(Error::I2cError(e)),
619        }
620
621        match i2c.read(addr, buf) {
622            Ok(()) => Ok(()),
623            Err(e) => Err(Error::I2cError(e)),
624        }
625    }
626
627    fn write_register(addr: u8, i2c: &mut I2C, reg: Register, cmd: u8) -> Result<(), I2cError> {
628        match i2c.write(addr, &[reg as u8, cmd]) {
629            Ok(()) => Ok(()),
630            Err(e) => Err(Error::I2cError(e)),
631        }
632    }
633}