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
23const CALIB_ACCEL_SENSITIVITY: u16 = 16384; const 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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}