Firmware
MPU6000.hpp
1 /****************************************************************************
2  *
3  * Copyright (c) 2016 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 
58 #include <drivers/drv_hrt.h>
59 #include <lib/cdev/CDev.hpp>
60 #include <lib/drivers/accelerometer/PX4Accelerometer.hpp>
61 #include <lib/drivers/device/i2c.h>
62 #include <lib/drivers/device/spi.h>
63 #include <lib/drivers/gyroscope/PX4Gyroscope.hpp>
64 #include <lib/ecl/geo/geo.h>
65 #include <lib/perf/perf_counter.h>
66 #include <px4_config.h>
67 #include <px4_getopt.h>
68 #include <px4_time.h>
69 #include <px4_workqueue.h>
70 #include <systemlib/conversions.h>
71 #include <systemlib/px4_macros.h>
72 
73 /*
74  we set the timer interrupt to run a bit faster than the desired
75  sample rate and then throw away duplicates by comparing
76  accelerometer values. This time reduction is enough to cope with
77  worst case timing jitter due to other timers
78 
79  I2C bus is running at 100 kHz Transaction time is 2.163ms
80  I2C bus is running at 400 kHz (304 kHz actual) Transaction time
81  is 583 us
82 
83  */
84 
85 #pragma once
86 
87 #if defined(PX4_I2C_MPU6050_ADDR) || \
88  defined(PX4_I2C_MPU6000_ADDR) || \
89  defined(PX4_I2C_ICM_20608_G_ADDR)
90 # define USE_I2C
91 #endif
92 
93 enum MPU_DEVICE_TYPE {
94  MPU_DEVICE_TYPE_MPU6000 = 6000,
95  MPU_DEVICE_TYPE_ICM20602 = 20602,
96  MPU_DEVICE_TYPE_ICM20608 = 20608,
97  MPU_DEVICE_TYPE_ICM20689 = 20689
98 };
99 
100 #define DIR_READ 0x80
101 #define DIR_WRITE 0x00
102 
103 #define MPU_DEVICE_PATH "/dev/mpu6000"
104 #define MPU_DEVICE_PATH1 "/dev/mpu6000_1"
105 #define MPU_DEVICE_PATH_EXT "/dev/mpu6000_ext"
106 #define MPU_DEVICE_PATH_EXT1 "/dev/mpu6000_ext1"
107 #define MPU_DEVICE_PATH_EXT2 "/dev/mpu6000_ext2"
108 
109 
110 #define ICM20602_DEVICE_PATH "/dev/icm20602"
111 #define ICM20602_DEVICE_PATH1 "/dev/icm20602_1"
112 #define ICM20602_DEVICE_PATH_EXT "/dev/icm20602_ext"
113 #define ICM20602_DEVICE_PATH_EXT1 "/dev/icm20602_ext1"
114 
115 #define ICM20608_DEVICE_PATH "/dev/icm20608"
116 #define ICM20608_DEVICE_PATH1 "/dev/icm20608_1"
117 #define ICM20608_DEVICE_PATH_EXT "/dev/icm20608_ext"
118 #define ICM20608_DEVICE_PATH_EXT1 "/dev/icm20608_ext1"
119 
120 #define ICM20689_DEVICE_PATH "/dev/icm20689"
121 
122 // MPU 6000 registers
123 #define MPUREG_WHOAMI 0x75
124 #define MPUREG_SMPLRT_DIV 0x19
125 #define MPUREG_CONFIG 0x1A
126 #define MPUREG_GYRO_CONFIG 0x1B
127 #define MPUREG_ACCEL_CONFIG 0x1C
128 #define MPUREG_FIFO_EN 0x23
129 #define MPUREG_INT_PIN_CFG 0x37
130 #define MPUREG_INT_ENABLE 0x38
131 #define MPUREG_INT_STATUS 0x3A
132 #define MPUREG_ACCEL_XOUT_H 0x3B
133 #define MPUREG_ACCEL_XOUT_L 0x3C
134 #define MPUREG_ACCEL_YOUT_H 0x3D
135 #define MPUREG_ACCEL_YOUT_L 0x3E
136 #define MPUREG_ACCEL_ZOUT_H 0x3F
137 #define MPUREG_ACCEL_ZOUT_L 0x40
138 #define MPUREG_TEMP_OUT_H 0x41
139 #define MPUREG_TEMP_OUT_L 0x42
140 #define MPUREG_GYRO_XOUT_H 0x43
141 #define MPUREG_GYRO_XOUT_L 0x44
142 #define MPUREG_GYRO_YOUT_H 0x45
143 #define MPUREG_GYRO_YOUT_L 0x46
144 #define MPUREG_GYRO_ZOUT_H 0x47
145 #define MPUREG_GYRO_ZOUT_L 0x48
146 #define MPUREG_USER_CTRL 0x6A
147 #define MPUREG_PWR_MGMT_1 0x6B
148 #define MPUREG_PWR_MGMT_2 0x6C
149 #define MPUREG_FIFO_COUNTH 0x72
150 #define MPUREG_FIFO_COUNTL 0x73
151 #define MPUREG_FIFO_R_W 0x74
152 #define MPUREG_PRODUCT_ID 0x0C
153 #define MPUREG_TRIM1 0x0D
154 #define MPUREG_TRIM2 0x0E
155 #define MPUREG_TRIM3 0x0F
156 #define MPUREG_TRIM4 0x10
157 #define MPU_GYRO_DLPF_CFG_256HZ_NOLPF2 0x00 // delay: 0.98ms
158 #define MPU_GYRO_DLPF_CFG_188HZ 0x01 // delay: 1.9ms
159 #define MPU_GYRO_DLPF_CFG_98HZ 0x02 // delay: 2.8ms
160 #define MPU_GYRO_DLPF_CFG_42HZ 0x03 // delay: 4.8ms
161 #define MPU_GYRO_DLPF_CFG_20HZ 0x04 // delay: 8.3ms
162 #define MPU_GYRO_DLPF_CFG_10HZ 0x05 // delay: 13.4ms
163 #define MPU_GYRO_DLPF_CFG_5HZ 0x06 // delay: 18.6ms
164 #define MPU_GYRO_DLPF_CFG_2100HZ_NOLPF 0x07
165 #define MPU_DLPF_CFG_MASK 0x07
166 
167 // Configuration bits MPU 3000 and MPU 6000 (not revised)?
168 #define BIT_SLEEP 0x40
169 #define BIT_H_RESET 0x80
170 #define BITS_CLKSEL 0x07
171 #define MPU_CLK_SEL_PLLGYROX 0x01
172 #define MPU_CLK_SEL_PLLGYROZ 0x03
173 #define MPU_EXT_SYNC_GYROX 0x02
174 #define BITS_GYRO_ST_X 0x80
175 #define BITS_GYRO_ST_Y 0x40
176 #define BITS_GYRO_ST_Z 0x20
177 #define BITS_FS_250DPS 0x00
178 #define BITS_FS_500DPS 0x08
179 #define BITS_FS_1000DPS 0x10
180 #define BITS_FS_2000DPS 0x18
181 #define BITS_FS_MASK 0x18
182 #define BIT_INT_ANYRD_2CLEAR 0x10
183 #define BIT_RAW_RDY_EN 0x01
184 #define BIT_I2C_IF_DIS 0x10
185 #define BIT_INT_STATUS_DATA 0x01
186 
187 #define MPU_WHOAMI_6000 0x68
188 #define ICM_WHOAMI_20602 0x12
189 #define ICM_WHOAMI_20608 0xaf
190 #define ICM_WHOAMI_20689 0x98
191 
192 // ICM2608 specific registers
193 
194 #define ICMREG_ACCEL_CONFIG2 0x1D
195 #define ICM_ACC_DLPF_CFG_1046HZ_NOLPF 0x00
196 #define ICM_ACC_DLPF_CFG_218HZ 0x01
197 #define ICM_ACC_DLPF_CFG_99HZ 0x02
198 #define ICM_ACC_DLPF_CFG_44HZ 0x03
199 #define ICM_ACC_DLPF_CFG_21HZ 0x04
200 #define ICM_ACC_DLPF_CFG_10HZ 0x05
201 #define ICM_ACC_DLPF_CFG_5HZ 0x06
202 #define ICM_ACC_DLPF_CFG_420HZ 0x07
203 /* this is an undocumented register which
204  if set incorrectly results in getting a 2.7m/s/s offset
205  on the Y axis of the accelerometer
206 */
207 #define MPUREG_ICM_UNDOC1 0x11
208 #define MPUREG_ICM_UNDOC1_VALUE 0xc9
209 
210 // Product ID Description for ICM20602
211 // Read From device
212 
213 #define ICM20602_REV_01 1
214 #define ICM20602_REV_02 2
215 
216 // Product ID Description for ICM20608
217 
218 #define ICM20608_REV_FF 0xff // In the past, was thought to be not returning a value. But seem repeatable.
219 
220 // Product ID Description for ICM20689
221 
222 #define ICM20689_REV_FE 0xfe
223 #define ICM20689_REV_03 0x03
224 
225 // Product ID Description for MPU6000
226 // high 4 bits low 4 bits
227 // Product Name Product Revision
228 #define MPU6000ES_REV_C4 0x14
229 #define MPU6000ES_REV_C5 0x15
230 #define MPU6000ES_REV_D6 0x16
231 #define MPU6000ES_REV_D7 0x17
232 #define MPU6000ES_REV_D8 0x18
233 #define MPU6000_REV_C4 0x54
234 #define MPU6000_REV_C5 0x55
235 #define MPU6000_REV_D6 0x56
236 #define MPU6000_REV_D7 0x57
237 #define MPU6000_REV_D8 0x58
238 #define MPU6000_REV_D9 0x59
239 #define MPU6000_REV_D10 0x5A
240 #define MPU6050_REV_D8 0x28 // TODO:Need verification
241 
242 #define MPU6000_ACCEL_DEFAULT_RANGE_G 16
243 
244 #define MPU6000_GYRO_DEFAULT_RANGE_G 8
245 #define MPU6000_GYRO_DEFAULT_RATE 1000
246 
247 
248 #define MPU6000_DEFAULT_ONCHIP_FILTER_FREQ 98
249 
250 #pragma pack(push, 1)
251 
255 struct MPUReport {
256  uint8_t cmd;
257  uint8_t status;
258  uint8_t accel_x[2];
259  uint8_t accel_y[2];
260  uint8_t accel_z[2];
261  uint8_t temp[2];
262  uint8_t gyro_x[2];
263  uint8_t gyro_y[2];
264  uint8_t gyro_z[2];
265 };
266 #pragma pack(pop)
267 
268 #define MPU_MAX_READ_BUFFER_SIZE (sizeof(MPUReport) + 1)
269 #define MPU_MAX_WRITE_BUFFER_SIZE (2)
270 /*
271  The MPU6000 can only handle high bus speeds on the sensor and
272  interrupt status registers. All other registers have a maximum 1MHz
273  Communication with all registers of the device is performed using either
274  I2C at 400kHz or SPI at 1MHz. For applications requiring faster communications,
275  the sensor and interrupt registers may be read using SPI at 20MHz
276  */
277 #define MPU6000_LOW_BUS_SPEED 0
278 #define MPU6000_HIGH_BUS_SPEED 0x8000
279 # define MPU6000_IS_HIGH_SPEED(r) ((r) & MPU6000_HIGH_BUS_SPEED)
280 # define MPU6000_REG(r) ((r) &~MPU6000_HIGH_BUS_SPEED)
281 # define MPU6000_SET_SPEED(r, s) ((r)|(s))
282 # define MPU6000_HIGH_SPEED_OP(r) MPU6000_SET_SPEED((r), MPU6000_HIGH_BUS_SPEED)
283 # define MPU6000_LOW_SPEED_OP(r) MPU6000_REG((r))
284 
285 /* interface factories */
286 extern device::Device *MPU6000_SPI_interface(int bus, int device_type, bool external_bus);
287 extern device::Device *MPU6000_I2C_interface(int bus, int device_type, bool external_bus);
288 extern int MPU6000_probe(device::Device *dev, int device_type);
289 
290 typedef device::Device *(*MPU6000_constructor)(int, int, bool);
291 
292 
293 #define MPU6000_TIMER_REDUCTION 200
294 
295 enum MPU6000_BUS {
296  MPU6000_BUS_ALL = 0,
297  MPU6000_BUS_I2C_INTERNAL,
298  MPU6000_BUS_I2C_EXTERNAL,
299  MPU6000_BUS_SPI_INTERNAL1,
300  MPU6000_BUS_SPI_INTERNAL2,
301  MPU6000_BUS_SPI_EXTERNAL1,
302  MPU6000_BUS_SPI_EXTERNAL2
303 };
304 
305 class MPU6000 : public cdev::CDev
306 {
307 public:
308  MPU6000(device::Device *interface, const char *path, enum Rotation rotation, int device_type);
309 
310  virtual ~MPU6000();
311 
312  virtual int init();
313 
317  void print_info();
318 
319  void print_registers();
320 
326  int factory_self_test();
327 
328  // deliberately cause a sensor error
329  void test_error();
330 
334  void start();
335 
341  int reset();
342 
343 protected:
344  device::Device *_interface;
345 
346  virtual int probe();
347 
348 private:
349  int _device_type;
350  uint8_t _product{0};
352 #if defined(USE_I2C)
353  /*
354  * SPI bus based device use hrt
355  * I2C bus needs to use work queue
356  */
357  work_s _work{};
358 #endif
359  bool _use_hrt;
360 
361  struct hrt_call _call {};
362  unsigned _call_interval{1000};
363 
364  PX4Accelerometer _px4_accel;
365  PX4Gyroscope _px4_gyro;
366 
367  unsigned _sample_rate{1000};
368 
369  perf_counter_t _sample_perf;
370  perf_counter_t _measure_interval;
371  perf_counter_t _bad_transfers;
372  perf_counter_t _bad_registers;
373  perf_counter_t _reset_retries;
374  perf_counter_t _duplicates;
375 
376  uint8_t _register_wait{0};
377  uint64_t _reset_wait{0};
378 
379  // this is used to support runtime checking of key
380  // configuration registers to detect SPI bus errors and sensor
381  // reset
382  static constexpr int MPU6000_CHECKED_PRODUCT_ID_INDEX = 0;
383  static constexpr int MPU6000_NUM_CHECKED_REGISTERS = 10;
384 
385  static constexpr uint8_t _checked_registers[MPU6000_NUM_CHECKED_REGISTERS] {
386  MPUREG_PRODUCT_ID,
387  MPUREG_PWR_MGMT_1,
388  MPUREG_USER_CTRL,
389  MPUREG_SMPLRT_DIV,
390  MPUREG_CONFIG,
391  MPUREG_GYRO_CONFIG,
392  MPUREG_ACCEL_CONFIG,
393  MPUREG_INT_ENABLE,
394  MPUREG_INT_PIN_CFG,
395  MPUREG_ICM_UNDOC1
396  };
397 
398  uint8_t _checked_values[MPU6000_NUM_CHECKED_REGISTERS];
399  uint8_t _checked_next{0};
400 
401  // use this to avoid processing measurements when in factory
402  // self test
403  volatile bool _in_factory_test{false};
404 
405  // keep last accel reading for duplicate detection
406  uint16_t _last_accel[3] {};
407  bool _got_duplicate{false};
408 
412  void stop();
413 
417  bool is_icm_device() { return !is_mpu_device(); }
421  bool is_mpu_device() { return _device_type == MPU_DEVICE_TYPE_MPU6000; }
422 
423 
424 #if defined(USE_I2C)
425 
439  void cycle();
440 
447  static void cycle_trampoline(void *arg);
448 
449  void use_i2c(bool on_true) { _use_hrt = !on_true; }
450 
451 #endif
452 
453  bool is_i2c(void) { return !_use_hrt; }
454 
455 
465  static void measure_trampoline(void *arg);
466 
470  int measure();
471 
478  uint8_t read_reg(unsigned reg, uint32_t speed = MPU6000_LOW_BUS_SPEED);
479  uint16_t read_reg16(unsigned reg);
480 
481 
488  int write_reg(unsigned reg, uint8_t value);
489 
499  void modify_reg(unsigned reg, uint8_t clearbits, uint8_t setbits);
500 
507  void write_checked_reg(unsigned reg, uint8_t value);
508 
515  int set_accel_range(unsigned max_g);
516 
517  /*
518  set low pass filter frequency
519  */
520  void _set_dlpf_filter(uint16_t frequency_hz);
521  void _set_icm_acc_dlpf_filter(uint16_t frequency_hz);
522 
523  /*
524  set sample rate (approximate) - 1kHz to 5Hz
525  */
526  void _set_sample_rate(unsigned desired_sample_rate_hz);
527 
528  /*
529  check that key registers still have the right value
530  */
531  void check_registers(void);
532 
533  /* do not allow to copy this class due to pointer data members */
534  MPU6000(const MPU6000 &);
535  MPU6000 operator=(const MPU6000 &);
536 
537 };
Configuration flags used in code.
A set of useful macros for enhanced runtime and compile time error detection and warning suppression...
Definition: PX4Gyroscope.hpp:46
High-resolution timer with callouts and timekeeping.
Base class for devices connected via SPI.
void test_error()
trigger an error
Definition: fxas21002c.cpp:1377
Report conversation within the mpu, including command byte and interrupt status.
Definition: icm20948.h:333
Header common to all counters.
Definition: perf_counter.cpp:65
Definition: MPU6000.hpp:305
Definition of commonly used conversions.
void reset(enum BMP280_BUS busid)
Reset the driver.
Definition: bmp280.cpp:743
Rotation
Enum for board and external compass rotations.
Definition: rotation.h:51
Fundamental base class for all physical drivers (I2C, SPI).
Definition: Device.hpp:65
Abstract class for any character device.
Definition: CDev.hpp:58
Thread safe version of getopt.
Callout record.
Definition: drv_hrt.h:72
Definition: PX4Accelerometer.hpp:46
Performance measuring tools.