PX4 Firmware
PX4 Autopilot Software http://px4.io
MPU6000.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2012-2015 PX4 Development Team. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name PX4 nor the names of its contributors may be
16  * used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  ****************************************************************************/
33 
34 #include "MPU6000.hpp"
35 
36 /*
37  list of registers that will be checked in check_registers(). Note
38  that MPUREG_PRODUCT_ID must be first in the list.
39  */
40 constexpr uint8_t MPU6000::_checked_registers[MPU6000_NUM_CHECKED_REGISTERS];
41 
42 MPU6000::MPU6000(device::Device *interface, enum Rotation rotation, int device_type) :
43  ScheduledWorkItem(MODULE_NAME, px4::device_bus_to_wq(interface->get_device_id())),
44  _interface(interface),
45  _device_type(device_type),
46  _px4_accel(_interface->get_device_id(), (_interface->external() ? ORB_PRIO_MAX : ORB_PRIO_HIGH), rotation),
47  _px4_gyro(_interface->get_device_id(), (_interface->external() ? ORB_PRIO_MAX : ORB_PRIO_HIGH), rotation),
48  _sample_perf(perf_alloc(PC_ELAPSED, "mpu6k_read")),
49  _bad_transfers(perf_alloc(PC_COUNT, "mpu6k_bad_trans")),
50  _bad_registers(perf_alloc(PC_COUNT, "mpu6k_bad_reg")),
51  _reset_retries(perf_alloc(PC_COUNT, "mpu6k_reset")),
52  _duplicates(perf_alloc(PC_COUNT, "mpu6k_duplicates"))
53 {
54  switch (_device_type) {
55  default:
59  break;
60 
64  break;
65 
69  break;
70 
74  break;
75  }
76 }
77 
79 {
80  /* make sure we are truly inactive */
81  stop();
82 
83  /* delete the perf counter */
89 }
90 
91 int
93 {
94  /* probe again to get our settings that are based on the device type */
95  int ret = probe();
96 
97  /* if probe failed, bail now */
98  if (ret != OK) {
99  PX4_DEBUG("probe init failed");
100  return ret;
101  }
102 
103  if (reset() != OK) {
104  return ret;
105  }
106 
107  return ret;
108 }
109 
111 {
112  // if the mpu6000 is initialized after the l3gd20 and lsm303d
113  // then if we don't do an irqsave/irqrestore here the mpu6000
114  // frequently comes up in a bad state where all transfers
115  // come as zero
116  uint8_t tries = 5;
117  irqstate_t state;
118 
119  while (--tries != 0) {
120  state = px4_enter_critical_section();
121 
122  // Hold off sampling for 60 ms
123  _reset_wait = hrt_absolute_time() + 60000;
124 
126  up_udelay(10000);
127 
128  // Wake up device and select GyroZ clock. Note that the
129  // MPU6000 starts up in sleep mode, and it can take some time
130  // for it to come out of sleep
132  up_udelay(1000);
133 
134  // Enable I2C bus or Disable I2C bus (recommended on data sheet)
137 
138  px4_leave_critical_section(state);
139 
141  break;
142  }
143 
145  px4_usleep(2000);
146  }
147 
148  // Hold off sampling for 30 ms
149 
150  state = px4_enter_critical_section();
151  _reset_wait = hrt_absolute_time() + 30000;
152  px4_leave_critical_section(state);
153 
155  return -EIO;
156  }
157 
158  px4_usleep(1000);
159 
160  // SAMPLE RATE
161  _set_sample_rate(1000);
162  px4_usleep(1000);
163 
165 
166  if (is_icm_device()) {
168  }
169 
170  px4_usleep(1000);
171  // Gyro scale 2000 deg/s ()
173  px4_usleep(1000);
174 
175  // correct gyro scale factors
176  // scale to rad/s in SI units
177  // 2000 deg/s = (2000/180)*PI = 34.906585 rad/s
178  // scaling factor:
179  // 1/(2^15)*(2000/180)*PI
180  _px4_gyro.set_scale(0.0174532f / 16.4f);//1.0f / (32768.0f * (2000.0f / 180.0f) * M_PI_F);
181 
183 
184  px4_usleep(1000);
185 
186  // INT CFG => Interrupt on Data Ready
187  write_checked_reg(MPUREG_INT_ENABLE, BIT_RAW_RDY_EN); // INT: Raw data ready
188  px4_usleep(1000);
189  write_checked_reg(MPUREG_INT_PIN_CFG, BIT_INT_ANYRD_2CLEAR); // INT: Clear on any read
190  px4_usleep(1000);
191 
192  if (is_icm_device()) {
194  }
195 
196  // Oscillator set
197  // write_reg(MPUREG_PWR_MGMT_1,MPU_CLK_SEL_PLLGYROZ);
198  px4_usleep(1000);
199  return OK;
200 }
201 
202 int
204 {
205  uint8_t whoami = read_reg(MPUREG_WHOAMI);
206  uint8_t expected = 0;
207  bool unknown_product_id = true;
208 
209  switch (_device_type) {
210 
211  default:
213  expected = MPU_WHOAMI_6000;
214  break;
215 
217  expected = ICM_WHOAMI_20602;
218  break;
219 
221  expected = ICM_WHOAMI_20608;
222  break;
223 
225  expected = ICM_WHOAMI_20689;
226  break;
227  }
228 
229  if (whoami != expected) {
230  PX4_DEBUG("unexpected WHOAMI 0x%02x", whoami);
231  return -EIO;
232  }
233 
234  /* look for a product ID we recognize */
236 
237  // verify product revision
238  switch (_product) {
239  case MPU6000ES_REV_C4:
240  case MPU6000ES_REV_C5:
241  case MPU6000_REV_C4:
242  case MPU6000_REV_C5:
243  case MPU6000ES_REV_D6:
244  case MPU6000ES_REV_D7:
245  case MPU6000ES_REV_D8:
246  case MPU6000_REV_D6:
247  case MPU6000_REV_D7:
248  case MPU6000_REV_D8:
249  case MPU6000_REV_D9:
250  case MPU6000_REV_D10:
251  case ICM20608_REV_FF:
252  case ICM20689_REV_FE:
253  case ICM20689_REV_03:
254  case ICM20689_REV_04:
255  case ICM20602_REV_01:
256  case ICM20602_REV_02:
257  case MPU6050_REV_D8:
258  unknown_product_id = false;
259  }
260 
262 
263  PX4_DEBUG("ID 0x%02x", _product);
264 
265  if (unknown_product_id) {
266 
267  PX4_WARN("unexpected ID 0x%02x %s", _product, is_icm_device() ? "accepted" : "exiting!");
268 
269  if (is_mpu_device()) {
270  return -EIO;
271  }
272  }
273 
274  return OK;
275 }
276 
277 /*
278  set sample rate (approximate) - 1kHz to 5Hz, for both accel and gyro
279 */
280 void
281 MPU6000::_set_sample_rate(unsigned desired_sample_rate_hz)
282 {
283  if (desired_sample_rate_hz == 0) {
284  desired_sample_rate_hz = MPU6000_GYRO_DEFAULT_RATE;
285  }
286 
287  uint8_t div = 1000 / desired_sample_rate_hz;
288 
289  if (div > 200) {
290  div = 200;
291  }
292 
293  if (div < 1) {
294  div = 1;
295  }
296 
298  _sample_rate = 1000 / div;
299 }
300 
301 /*
302  set the DLPF filter frequency. This affects both accel and gyro.
303  */
304 void
305 MPU6000::_set_dlpf_filter(uint16_t frequency_hz)
306 {
307  uint8_t filter = MPU_GYRO_DLPF_CFG_2100HZ_NOLPF;
308 
309  /*
310  choose next highest filter frequency available
311  */
312  if (frequency_hz == 0) {
314 
315  } else if (frequency_hz <= 5) {
316  filter = MPU_GYRO_DLPF_CFG_5HZ;
317 
318  } else if (frequency_hz <= 10) {
319  filter = MPU_GYRO_DLPF_CFG_10HZ;
320 
321  } else if (frequency_hz <= 20) {
322  filter = MPU_GYRO_DLPF_CFG_20HZ;
323 
324  } else if (frequency_hz <= 42) {
325  filter = MPU_GYRO_DLPF_CFG_42HZ;
326 
327  } else if (frequency_hz <= 98) {
328  filter = MPU_GYRO_DLPF_CFG_98HZ;
329 
330  } else if (frequency_hz <= 188) {
331  filter = MPU_GYRO_DLPF_CFG_188HZ;
332 
333  } else if (frequency_hz <= 256) {
335  }
336 
338 }
339 
340 void
341 MPU6000::_set_icm_acc_dlpf_filter(uint16_t frequency_hz)
342 {
343  uint8_t filter = ICM_ACC_DLPF_CFG_1046HZ_NOLPF;
344 
345  /*
346  choose next highest filter frequency available
347  */
348  if (frequency_hz == 0) {
350 
351  } else if (frequency_hz <= 5) {
352  filter = ICM_ACC_DLPF_CFG_5HZ;
353 
354  } else if (frequency_hz <= 10) {
355  filter = ICM_ACC_DLPF_CFG_10HZ;
356 
357  } else if (frequency_hz <= 21) {
358  filter = ICM_ACC_DLPF_CFG_21HZ;
359 
360  } else if (frequency_hz <= 44) {
361  filter = ICM_ACC_DLPF_CFG_44HZ;
362 
363  } else if (frequency_hz <= 99) {
364  filter = ICM_ACC_DLPF_CFG_99HZ;
365 
366  } else if (frequency_hz <= 218) {
367  filter = ICM_ACC_DLPF_CFG_218HZ;
368 
369  } else if (frequency_hz <= 420) {
370  filter = ICM_ACC_DLPF_CFG_420HZ;
371  }
372 
374 }
375 
376 #ifndef CONSTRAINED_FLASH
377 /*
378  perform a self-test comparison to factory trim values. This takes
379  about 200ms and will return OK if the current values are within 14%
380  of the expected values (as per datasheet)
381  */
382 int
384 {
385  _in_factory_test = true;
386  uint8_t saved_gyro_config = read_reg(MPUREG_GYRO_CONFIG);
387  uint8_t saved_accel_config = read_reg(MPUREG_ACCEL_CONFIG);
388  const uint16_t repeats = 100;
389  int ret = OK;
390 
391  // gyro self test has to be done at 250DPS
393 
394  struct MPUReport mpu_report {};
395  float accel_baseline[3] {};
396  float gyro_baseline[3] {};
397  float accel[3] {};
398  float gyro[3] {};
399  float accel_ftrim[3] {};
400  float gyro_ftrim[3] {};
401 
402  // get baseline values without self-test enabled
403  for (uint8_t i = 0; i < repeats; i++) {
404  up_udelay(1000);
406  sizeof(mpu_report));
407 
408  accel_baseline[0] += int16_t_from_bytes(mpu_report.accel_x);
409  accel_baseline[1] += int16_t_from_bytes(mpu_report.accel_y);
410  accel_baseline[2] += int16_t_from_bytes(mpu_report.accel_z);
411  gyro_baseline[0] += int16_t_from_bytes(mpu_report.gyro_x);
412  gyro_baseline[1] += int16_t_from_bytes(mpu_report.gyro_y);
413  gyro_baseline[2] += int16_t_from_bytes(mpu_report.gyro_z);
414  }
415 
416 #if 1
422 
423  // accel 8g, self-test enabled all axes
424  write_reg(MPUREG_ACCEL_CONFIG, saved_accel_config | 0xE0);
425 #endif
426 
427  up_udelay(20000);
428 
429  // get values with self-test enabled
430  for (uint8_t i = 0; i < repeats; i++) {
431  up_udelay(1000);
433  sizeof(mpu_report));
434 
435  accel[0] += int16_t_from_bytes(mpu_report.accel_x);
436  accel[1] += int16_t_from_bytes(mpu_report.accel_y);
437  accel[2] += int16_t_from_bytes(mpu_report.accel_z);
438  gyro[0] += int16_t_from_bytes(mpu_report.gyro_x);
439  gyro[1] += int16_t_from_bytes(mpu_report.gyro_y);
440  gyro[2] += int16_t_from_bytes(mpu_report.gyro_z);
441  }
442 
443  for (uint8_t i = 0; i < 3; i++) {
444  accel_baseline[i] /= repeats;
445  gyro_baseline[i] /= repeats;
446  accel[i] /= repeats;
447  gyro[i] /= repeats;
448  }
449 
450  // extract factory trim values
451  uint8_t trims[4];
452  trims[0] = read_reg(MPUREG_TRIM1);
453  trims[1] = read_reg(MPUREG_TRIM2);
454  trims[2] = read_reg(MPUREG_TRIM3);
455  trims[3] = read_reg(MPUREG_TRIM4);
456  uint8_t atrim[3];
457  uint8_t gtrim[3];
458 
459  atrim[0] = ((trims[0] >> 3) & 0x1C) | ((trims[3] >> 4) & 0x03);
460  atrim[1] = ((trims[1] >> 3) & 0x1C) | ((trims[3] >> 2) & 0x03);
461  atrim[2] = ((trims[2] >> 3) & 0x1C) | ((trims[3] >> 0) & 0x03);
462  gtrim[0] = trims[0] & 0x1F;
463  gtrim[1] = trims[1] & 0x1F;
464  gtrim[2] = trims[2] & 0x1F;
465 
466  // convert factory trims to right units
467  for (uint8_t i = 0; i < 3; i++) {
468  accel_ftrim[i] = 4096 * 0.34f * powf(0.92f / 0.34f, (atrim[i] - 1) / 30.0f);
469  gyro_ftrim[i] = 25 * 131.0f * powf(1.046f, gtrim[i] - 1);
470  }
471 
472  // Y gyro trim is negative
473  gyro_ftrim[1] *= -1;
474 
475  for (uint8_t i = 0; i < 3; i++) {
476  float diff = accel[i] - accel_baseline[i];
477  float err = 100 * (diff - accel_ftrim[i]) / accel_ftrim[i];
478  ::printf("ACCEL[%u] baseline=%d accel=%d diff=%d ftrim=%d err=%d\n",
479  (unsigned)i,
480  (int)(1000 * accel_baseline[i]),
481  (int)(1000 * accel[i]),
482  (int)(1000 * diff),
483  (int)(1000 * accel_ftrim[i]),
484  (int)err);
485 
486  if (fabsf(err) > 14) {
487  ::printf("FAIL\n");
488  ret = -EIO;
489  }
490  }
491 
492  for (uint8_t i = 0; i < 3; i++) {
493  float diff = gyro[i] - gyro_baseline[i];
494  float err = 100 * (diff - gyro_ftrim[i]) / gyro_ftrim[i];
495  ::printf("GYRO[%u] baseline=%d gyro=%d diff=%d ftrim=%d err=%d\n",
496  (unsigned)i,
497  (int)(1000 * gyro_baseline[i]),
498  (int)(1000 * gyro[i]),
499  (int)(1000 * (gyro[i] - gyro_baseline[i])),
500  (int)(1000 * gyro_ftrim[i]),
501  (int)err);
502 
503  if (fabsf(err) > 14) {
504  ::printf("FAIL\n");
505  ret = -EIO;
506  }
507  }
508 
509  write_reg(MPUREG_GYRO_CONFIG, saved_gyro_config);
510  write_reg(MPUREG_ACCEL_CONFIG, saved_accel_config);
511 
512  _in_factory_test = false;
513 
514  if (ret == OK) {
515  ::printf("PASSED\n");
516  }
517 
518  return ret;
519 }
520 #endif
521 
522 /*
523  deliberately trigger an error in the sensor to trigger recovery
524  */
525 void
527 {
528  _in_factory_test = true;
529  // deliberately trigger an error. This was noticed during
530  // development as a handy way to test the reset logic
531  uint8_t data[sizeof(MPUReport)] {};
533  PX4_WARN("error triggered");
534  print_registers();
535  _in_factory_test = false;
536 }
537 
538 uint8_t
539 MPU6000::read_reg(unsigned reg, uint32_t speed)
540 {
541  uint8_t buf{};
542  _interface->read(MPU6000_SET_SPEED(reg, speed), &buf, 1);
543  return buf;
544 }
545 
546 uint16_t
547 MPU6000::read_reg16(unsigned reg)
548 {
549  uint8_t buf[2] {};
550 
551  // general register transfer at low clock speed
552  _interface->read(MPU6000_LOW_SPEED_OP(reg), &buf, arraySize(buf));
553  return (uint16_t)(buf[0] << 8) | buf[1];
554 }
555 
556 int
557 MPU6000::write_reg(unsigned reg, uint8_t value)
558 {
559  // general register transfer at low clock speed
560  return _interface->write(MPU6000_LOW_SPEED_OP(reg), &value, 1);
561 }
562 
563 void
564 MPU6000::modify_reg(unsigned reg, uint8_t clearbits, uint8_t setbits)
565 {
566  uint8_t val = read_reg(reg);
567  val &= ~clearbits;
568  val |= setbits;
569  write_reg(reg, val);
570 }
571 
572 void
573 MPU6000::write_checked_reg(unsigned reg, uint8_t value)
574 {
575  write_reg(reg, value);
576 
577  for (uint8_t i = 0; i < MPU6000_NUM_CHECKED_REGISTERS; i++) {
578  if (reg == _checked_registers[i]) {
579  _checked_values[i] = value;
580  }
581  }
582 }
583 
584 int
585 MPU6000::set_accel_range(unsigned max_g_in)
586 {
587  // workaround for bugged versions of MPU6k (rev C)
588  if (is_mpu_device()) {
589  switch (_product) {
590  case MPU6000ES_REV_C4:
591  case MPU6000ES_REV_C5:
592  case MPU6000_REV_C4:
593  case MPU6000_REV_C5:
596  return OK;
597  }
598  }
599 
600  uint8_t afs_sel;
601  float lsb_per_g;
602  //float max_accel_g;
603 
604  if (max_g_in > 8) { // 16g - AFS_SEL = 3
605  afs_sel = 3;
606  lsb_per_g = 2048;
607  //max_accel_g = 16;
608 
609  } else if (max_g_in > 4) { // 8g - AFS_SEL = 2
610  afs_sel = 2;
611  lsb_per_g = 4096;
612  //max_accel_g = 8;
613 
614  } else if (max_g_in > 2) { // 4g - AFS_SEL = 1
615  afs_sel = 1;
616  lsb_per_g = 8192;
617  //max_accel_g = 4;
618 
619  } else { // 2g - AFS_SEL = 0
620  afs_sel = 0;
621  lsb_per_g = 16384;
622  //max_accel_g = 2;
623  }
624 
625  write_checked_reg(MPUREG_ACCEL_CONFIG, afs_sel << 3);
626 
627  _px4_accel.set_scale(CONSTANTS_ONE_G / lsb_per_g);
628 
629  return OK;
630 }
631 
632 void
634 {
635  /* make sure we are stopped first */
636  uint32_t last_call_interval = _call_interval;
637  stop();
638  _call_interval = last_call_interval;
639 
640  ScheduleOnInterval(_call_interval - MPU6000_TIMER_REDUCTION, 1000);
641 }
642 
643 void
645 {
646  ScheduleClear();
647 
648  /* reset internal states */
649  memset(_last_accel, 0, sizeof(_last_accel));
650 }
651 
652 void
654 {
655  /* make another measurement */
656  measure();
657 }
658 
659 void
661 {
662  /*
663  we read the register at full speed, even though it isn't
664  listed as a high speed register. The low speed requirement
665  for some registers seems to be a propgation delay
666  requirement for changing sensor configuration, which should
667  not apply to reading a single register. It is also a better
668  test of SPI bus health to read at the same speed as we read
669  the data registers.
670  */
671  uint8_t v;
672 
673  // the MPUREG_ICM_UNDOC1 is specific to the ICM20608 (and undocumented)
676  }
677 
680  /*
681  if we get the wrong value then we know the SPI bus
682  or sensor is very sick. We set _register_wait to 20
683  and wait until we have seen 20 good values in a row
684  before we consider the sensor to be OK again.
685  */
687 
688  /*
689  try to fix the bad register value. We only try to
690  fix one per loop to prevent a bad sensor hogging the
691  bus.
692  */
693  if (_register_wait == 0 || _checked_next == MPU6000_CHECKED_PRODUCT_ID_INDEX) {
694  // if the product_id is wrong then reset the
695  // sensor completely
697  // after doing a reset we need to wait a long
698  // time before we do any other register writes
699  // or we will end up with the mpu6000 in a
700  // bizarre state where it has all correct
701  // register values but large offsets on the
702  // accel axes
703  _reset_wait = hrt_absolute_time() + 10000;
704  _checked_next = 0;
705 
706  } else {
707  write_reg(_checked_registers[_checked_next], _checked_values[_checked_next]);
708  // waiting 3ms between register writes seems
709  // to raise the chance of the sensor
710  // recovering considerably
711  _reset_wait = hrt_absolute_time() + 3000;
712  }
713 
714  _register_wait = 20;
715  }
716 
717  _checked_next = (_checked_next + 1) % MPU6000_NUM_CHECKED_REGISTERS;
718 }
719 
720 int
722 {
723  if (_in_factory_test) {
724  // don't publish any data while in factory test mode
725  return OK;
726  }
727 
728  if (hrt_absolute_time() < _reset_wait) {
729  // we're waiting for a reset to complete
730  return OK;
731  }
732 
733  struct MPUReport mpu_report;
734 
735  struct Report {
736  int16_t accel_x;
737  int16_t accel_y;
738  int16_t accel_z;
739  int16_t temp;
740  int16_t gyro_x;
741  int16_t gyro_y;
742  int16_t gyro_z;
743  } report;
744 
745  /* start measuring */
747 
748  /*
749  * Fetch the full set of measurements from the MPU6000 in one pass.
750  */
751 
752  // sensor transfer at high clock speed
753 
754  const hrt_abstime timestamp_sample = hrt_absolute_time();
755 
757  (uint8_t *)&mpu_report, sizeof(mpu_report))) {
758 
759  return -EIO;
760  }
761 
762  check_registers();
763 
764  /*
765  see if this is duplicate accelerometer data. Note that we
766  can't use the data ready interrupt status bit in the status
767  register as that also goes high on new gyro data, and when
768  we run with BITS_DLPF_CFG_256HZ_NOLPF2 the gyro is being
769  sampled at 8kHz, so we would incorrectly think we have new
770  data when we are in fact getting duplicate accelerometer data.
771  */
772  if (!_got_duplicate && memcmp(&mpu_report.accel_x[0], &_last_accel[0], 6) == 0) {
773  // it isn't new data - wait for next timer
776  _got_duplicate = true;
777  return OK;
778  }
779 
780  memcpy(&_last_accel[0], &mpu_report.accel_x[0], 6);
781  _got_duplicate = false;
782 
783  /*
784  * Convert from big to little endian
785  */
786 
787  report.accel_x = int16_t_from_bytes(mpu_report.accel_x);
788  report.accel_y = int16_t_from_bytes(mpu_report.accel_y);
789  report.accel_z = int16_t_from_bytes(mpu_report.accel_z);
790 
791  report.temp = int16_t_from_bytes(mpu_report.temp);
792 
793  report.gyro_x = int16_t_from_bytes(mpu_report.gyro_x);
794  report.gyro_y = int16_t_from_bytes(mpu_report.gyro_y);
795  report.gyro_z = int16_t_from_bytes(mpu_report.gyro_z);
796 
797  if (report.accel_x == 0 &&
798  report.accel_y == 0 &&
799  report.accel_z == 0 &&
800  report.temp == 0 &&
801  report.gyro_x == 0 &&
802  report.gyro_y == 0 &&
803  report.gyro_z == 0) {
804 
805  // all zero data - probably a SPI bus error
808 
809  // note that we don't call reset() here as a reset()
810  // costs 20ms with interrupts disabled. That means if
811  // the mpu6k does go bad it would cause a FMU failure,
812  // regardless of whether another sensor is available,
813  return -EIO;
814  }
815 
816  if (_register_wait != 0) {
817  // we are waiting for some good transfers before using
818  // the sensor again, don't return any data yet
819  _register_wait--;
820  return OK;
821  }
822 
823 
824  /*
825  * Swap axes and negate y
826  */
827  int16_t accel_xt = report.accel_y;
828  int16_t accel_yt = ((report.accel_x == -32768) ? 32767 : -report.accel_x);
829 
830  int16_t gyro_xt = report.gyro_y;
831  int16_t gyro_yt = ((report.gyro_x == -32768) ? 32767 : -report.gyro_x);
832 
833  /*
834  * Apply the swap
835  */
836  report.accel_x = accel_xt;
837  report.accel_y = accel_yt;
838  report.gyro_x = gyro_xt;
839  report.gyro_y = gyro_yt;
840 
841  // report the error count as the sum of the number of bad
842  // transfers and bad register reads. This allows the higher
843  // level code to decide if it should use this sensor based on
844  // whether it has had failures
845 
846  const uint64_t error_count = perf_event_count(_bad_transfers) + perf_event_count(_bad_registers);
847  _px4_accel.set_error_count(error_count);
848  _px4_gyro.set_error_count(error_count);
849 
850  /*
851  * 1) Scale raw value to SI units using scaling from datasheet.
852  * 2) Subtract static offset (in SI units)
853  * 3) Scale the statically calibrated values with a linear
854  * dynamically obtained factor
855  *
856  * Note: the static sensor offset is the number the sensor outputs
857  * at a nominally 'zero' input. Therefore the offset has to
858  * be subtracted.
859  *
860  * Example: A gyro outputs a value of 74 at zero angular rate
861  * the offset is 74 from the origin and subtracting
862  * 74 from all measurements centers them around zero.
863  */
864 
865  float temperature = 0.0f;
866 
867  if (is_icm_device()) { // if it is an ICM20608
868  temperature = (report.temp / 326.8f + 25.0f);
869 
870  } else { // If it is an MPU6000
871  temperature = (report.temp / 340.0f + 35.0f);
872  }
873 
874  _px4_accel.set_temperature(temperature);
875  _px4_gyro.set_temperature(temperature);
876 
877  _px4_accel.update(timestamp_sample, report.accel_x, report.accel_y, report.accel_z);
878  _px4_gyro.update(timestamp_sample, report.gyro_x, report.gyro_y, report.gyro_z);
879 
880  /* stop measuring */
882  return OK;
883 }
884 
885 void
887 {
893 
896 }
897 
898 void
900 {
901  PX4_INFO("registers");
902 
903  for (uint8_t reg = MPUREG_PRODUCT_ID; reg <= 108; reg++) {
904  uint8_t v = read_reg(reg);
905  printf("%02x:%02x ", (unsigned)reg, (unsigned)v);
906 
907  if ((reg - (MPUREG_PRODUCT_ID - 1)) % 13 == 0) {
908  printf("\n");
909  }
910  }
911 
912  printf("\n");
913 }
virtual int probe()
Definition: MPU6000.cpp:203
#define BIT_INT_ANYRD_2CLEAR
Definition: icm20948.h:139
#define ICM_ACC_DLPF_CFG_99HZ
Definition: MPU6000.hpp:176
#define MPU_GYRO_DLPF_CFG_98HZ
Definition: MPU6000.hpp:138
#define MPU6000_REV_D8
Definition: MPU6000.hpp:217
perf_counter_t _reset_retries
Definition: MPU6000.hpp:347
uint8_t _checked_next
Definition: MPU6000.hpp:373
#define MPUREG_INT_STATUS
Definition: icm20948.h:82
#define DRV_ACC_DEVTYPE_ICM20608
Definition: drv_sensor.h:84
void write_checked_reg(unsigned reg, uint8_t value)
Write a register in the MPU6000, updating _checked_values.
Definition: MPU6000.cpp:573
measure the time elapsed performing an event
Definition: perf_counter.h:56
static enum @74 state
#define MPU6050_REV_D8
Definition: MPU6000.hpp:220
void print_status()
#define MPUREG_TRIM1
Definition: MPU6000.hpp:132
#define MPU6000ES_REV_D7
Definition: MPU6000.hpp:211
#define ICM20602_REV_02
Definition: MPU6000.hpp:193
#define MPU_GYRO_DLPF_CFG_10HZ
Definition: MPU6000.hpp:141
bool is_mpu_device()
is_mpu_device
Definition: MPU6000.hpp:395
void update(hrt_abstime timestamp, float x, float y, float z)
#define MPU6000_SET_SPEED(r, s)
Definition: MPU6000.hpp:261
int write_reg(unsigned reg, uint8_t value)
Write a register in the MPU6000.
Definition: MPU6000.cpp:557
#define ICMREG_ACCEL_CONFIG2
Definition: MPU6000.hpp:173
int _device_type
Definition: MPU6000.hpp:334
#define MPUREG_CONFIG
Definition: icm20948.h:54
int factory_self_test()
Test behaviour against factory offsets.
Definition: MPU6000.cpp:383
#define ICM_ACC_DLPF_CFG_21HZ
Definition: MPU6000.hpp:178
#define MPUREG_ICM_UNDOC1_VALUE
Definition: MPU6000.hpp:187
#define MPU6000_LOW_BUS_SPEED
Definition: MPU6000.hpp:257
int measure()
Fetch measurements from the sensor and update the report buffers.
Definition: MPU6000.cpp:721
uint8_t _product
Definition: MPU6000.hpp:335
#define DRV_ACC_DEVTYPE_ICM20689
Definition: drv_sensor.h:86
#define MPU6000ES_REV_D6
Definition: MPU6000.hpp:210
#define MPU6000_REV_C5
Definition: MPU6000.hpp:214
#define BIT_I2C_IF_DIS
Definition: icm20948.h:147
static constexpr int MPU6000_NUM_CHECKED_REGISTERS
Definition: MPU6000.hpp:357
perf_counter_t _sample_perf
Definition: MPU6000.hpp:344
bool is_icm_device()
is_icm_device
Definition: MPU6000.hpp:391
count the number of times an event occurs
Definition: perf_counter.h:55
#define MPU_GYRO_DLPF_CFG_42HZ
Definition: MPU6000.hpp:139
#define MPU_GYRO_DLPF_CFG_20HZ
Definition: MPU6000.hpp:140
unsigned _sample_rate
Definition: MPU6000.hpp:342
void _set_icm_acc_dlpf_filter(uint16_t frequency_hz)
Definition: MPU6000.cpp:341
#define MPUREG_PRODUCT_ID
Definition: MPU6000.hpp:131
void set_device_type(uint8_t devtype)
static constexpr float CONSTANTS_ONE_G
Definition: geo.h:51
void set_error_count(uint64_t error_count)
#define MPUREG_ACCEL_CONFIG
Definition: icm20948.h:56
#define MPUREG_TRIM3
Definition: MPU6000.hpp:134
#define ICM_ACC_DLPF_CFG_420HZ
Definition: MPU6000.hpp:181
#define MPU6000_DEFAULT_ONCHIP_FILTER_FREQ
Definition: MPU6000.hpp:228
#define MPUREG_WHOAMI
Definition: icm20948.h:52
#define MPUREG_SMPLRT_DIV
Definition: icm20948.h:53
PX4Accelerometer _px4_accel
Definition: MPU6000.hpp:339
#define DRV_GYR_DEVTYPE_ICM20608
Definition: drv_sensor.h:85
void update(hrt_abstime timestamp, float x, float y, float z)
static constexpr uint8_t _checked_registers[MPU6000_NUM_CHECKED_REGISTERS]
Definition: MPU6000.hpp:359
uint8_t _register_wait
Definition: MPU6000.hpp:350
void perf_count(perf_counter_t handle)
Count a performance event.
bool _got_duplicate
Definition: MPU6000.hpp:381
Report conversation within the mpu, including command byte and interrupt status.
Definition: icm20948.h:311
void perf_free(perf_counter_t handle)
Free a counter.
#define MPU_WHOAMI_6000
Definition: MPU6000.hpp:166
#define ICM_ACC_DLPF_CFG_1046HZ_NOLPF
Definition: MPU6000.hpp:174
#define ICM_ACC_DLPF_CFG_5HZ
Definition: MPU6000.hpp:180
volatile bool _in_factory_test
Definition: MPU6000.hpp:377
uint16_t _last_accel[3]
Definition: MPU6000.hpp:380
#define MPUREG_INT_ENABLE
Definition: icm20948.h:81
#define DRV_ACC_DEVTYPE_ICM20602
Definition: drv_sensor.h:82
void set_temperature(float temperature)
#define ICM_ACC_DLPF_CFG_10HZ
Definition: MPU6000.hpp:179
perf_counter_t _bad_registers
Definition: MPU6000.hpp:346
#define MPUREG_INT_PIN_CFG
Definition: icm20948.h:80
#define MPU6000ES_REV_C4
Definition: MPU6000.hpp:208
#define perf_alloc(a, b)
Definition: px4io.h:59
#define DRV_ACC_DEVTYPE_MPU6000
Definition: drv_sensor.h:67
#define MPUREG_PWR_MGMT_1
Definition: icm20948.h:106
Rotation
Enum for board and external compass rotations.
Definition: rotation.h:51
#define MPU6000_HIGH_BUS_SPEED
Definition: MPU6000.hpp:258
uint8_t * data
Definition: dataman.cpp:149
#define BITS_GYRO_ST_X
Definition: icm20948.h:117
#define ICM20689_REV_04
Definition: MPU6000.hpp:203
#define BITS_GYRO_ST_Z
Definition: icm20948.h:119
#define DRV_GYR_DEVTYPE_MPU6000
Definition: drv_sensor.h:71
#define DRV_GYR_DEVTYPE_ICM20689
Definition: drv_sensor.h:87
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
Definition: integration.cpp:8
int reset()
Reset chip.
Definition: MPU6000.cpp:110
perf_counter_t _bad_transfers
Definition: MPU6000.hpp:345
#define ICM_WHOAMI_20689
Definition: MPU6000.hpp:169
void test_error()
Definition: MPU6000.cpp:526
#define MPU_GYRO_DLPF_CFG_5HZ
Definition: MPU6000.hpp:142
#define ICM_ACC_DLPF_CFG_218HZ
Definition: MPU6000.hpp:175
void start()
Start automatic measurement.
Definition: MPU6000.cpp:633
void set_error_count(uint64_t error_count)
#define MPU6000_REV_C4
Definition: MPU6000.hpp:213
void perf_end(perf_counter_t handle)
End a performance event.
int set_accel_range(unsigned max_g)
Set the MPU6000 measurement range.
Definition: MPU6000.cpp:585
#define ICM_ACC_DLPF_CFG_44HZ
Definition: MPU6000.hpp:177
#define MPU_GYRO_DLPF_CFG_256HZ_NOLPF2
Definition: MPU6000.hpp:136
#define BITS_GYRO_ST_Y
Definition: icm20948.h:118
PX4Gyroscope _px4_gyro
Definition: MPU6000.hpp:340
void modify_reg(unsigned reg, uint8_t clearbits, uint8_t setbits)
Modify a register in the MPU6000.
Definition: MPU6000.cpp:564
#define MPU6000_LOW_SPEED_OP(r)
Definition: MPU6000.hpp:263
__BEGIN_DECLS typedef uint64_t hrt_abstime
Absolute time, in microsecond units.
Definition: drv_hrt.h:58
virtual int write(unsigned address, void *data, unsigned count)
Write directly to the device.
Definition: Device.hpp:115
uint8_t _checked_values[MPU6000_NUM_CHECKED_REGISTERS]
Definition: MPU6000.hpp:372
#define err(eval,...)
Definition: err.h:83
#define MPU6000_REV_D9
Definition: MPU6000.hpp:218
#define ICM_WHOAMI_20602
Definition: MPU6000.hpp:167
void set_scale(float scale)
#define MPU_CLK_SEL_PLLGYROZ
Definition: MPU6000.hpp:151
#define MPU6000_REV_D10
Definition: MPU6000.hpp:219
void check_registers(void)
Definition: MPU6000.cpp:660
virtual int init()
Definition: MPU6000.cpp:92
void set_temperature(float temperature)
#define MPU6000_TIMER_REDUCTION
Definition: MPU6000.hpp:273
virtual ~MPU6000()
Definition: MPU6000.cpp:78
#define ICM20608_REV_FF
Definition: MPU6000.hpp:197
uint16_t read_reg16(unsigned reg)
Definition: MPU6000.cpp:547
uint64_t _reset_wait
Definition: MPU6000.hpp:351
perf_counter_t _duplicates
Definition: MPU6000.hpp:348
#define arraySize(a)
#define MPU6000ES_REV_C5
Definition: MPU6000.hpp:209
MPU6000(device::Device *interface, enum Rotation rotation, int device_type)
Definition: MPU6000.cpp:42
void perf_print_counter(perf_counter_t handle)
Print one performance counter to stdout.
uint64_t perf_event_count(perf_counter_t handle)
Return current event_count.
#define BIT_H_RESET
Definition: icm20948.h:114
#define MPU6000_REV_D7
Definition: MPU6000.hpp:216
#define MPU6000ES_REV_D8
Definition: MPU6000.hpp:212
Fundamental base class for all physical drivers (I2C, SPI).
Definition: Device.hpp:65
#define MPUREG_GYRO_CONFIG
Definition: icm20948.h:55
Definition: bst.cpp:62
#define BIT_RAW_RDY_EN
Definition: icm20948.h:138
void stop()
Stop automatic measurement.
Definition: MPU6000.cpp:644
#define MPUREG_TRIM2
Definition: MPU6000.hpp:133
void print_info()
Diagnostics - print some basic information about the driver.
Definition: MPU6000.cpp:886
#define MPU6000_GYRO_DEFAULT_RATE
Definition: MPU6000.hpp:225
static constexpr int MPU6000_CHECKED_PRODUCT_ID_INDEX
Definition: MPU6000.hpp:356
#define DRV_GYR_DEVTYPE_ICM20602
Definition: drv_sensor.h:83
void print_registers()
Definition: MPU6000.cpp:899
device::Device * _interface
Definition: MPU6000.hpp:326
#define MPU6000_ACCEL_DEFAULT_RANGE_G
Definition: MPU6000.hpp:222
#define OK
Definition: uavcan_main.cpp:71
#define ICM20689_REV_FE
Definition: MPU6000.hpp:201
#define MPU6000_REV_D6
Definition: MPU6000.hpp:215
#define MPUREG_TRIM4
Definition: MPU6000.hpp:135
int16_t int16_t_from_bytes(uint8_t bytes[])
Converts a signed 16 bit integer from big endian to little endian.
Definition: conversions.c:46
#define ICM20602_REV_01
Definition: MPU6000.hpp:192
void set_scale(float scale)
DeviceBusType get_device_bus_type() const
Return the bus type the device is connected to.
Definition: Device.hpp:168
void set_device_type(uint8_t devtype)
#define MPU_GYRO_DLPF_CFG_2100HZ_NOLPF
Definition: MPU6000.hpp:143
#define MPUREG_USER_CTRL
Definition: icm20948.h:105
#define MPUREG_ICM_UNDOC1
Definition: MPU6000.hpp:186
#define ICM_WHOAMI_20608
Definition: MPU6000.hpp:168
void _set_sample_rate(unsigned desired_sample_rate_hz)
Definition: MPU6000.cpp:281
#define BITS_FS_2000DPS
Definition: icm20948.h:123
void perf_begin(perf_counter_t handle)
Begin a performance event.
#define ICM20689_REV_03
Definition: MPU6000.hpp:202
void Run() override
Definition: MPU6000.cpp:653
unsigned _call_interval
product code
Definition: MPU6000.hpp:337
uint8_t read_reg(unsigned reg, uint32_t speed=MPU6000_LOW_BUS_SPEED)
Read a register from the MPU6000.
Definition: MPU6000.cpp:539
__EXPORT hrt_abstime hrt_absolute_time(void)
Get absolute time in [us] (does not wrap).
virtual int read(unsigned address, void *data, unsigned count)
Read directly from the device.
Definition: Device.hpp:103
#define MPU_GYRO_DLPF_CFG_188HZ
Definition: MPU6000.hpp:137
#define BITS_FS_250DPS
Definition: icm20948.h:120
void _set_dlpf_filter(uint16_t frequency_hz)
Definition: MPU6000.cpp:305