This library communicates with InvenSense MPU-9250 and MPU-9255 Inertial Measurement Units (IMUs).
The InvenSense MPU-9250 is a System in Package (SiP) that combines two chips: the MPU-6500 three-axis gyroscope and three-axis accelerometer; and the AK8963 three-axis magnetometer. The MPU-9250 supports I2C, up to 400 kHz, and SPI communication, up to 1 MHz for register setup and 20 MHz for data reading. The following selectable full scale sensor ranges are available:
Gyroscope Full Scale Range | Accelerometer Full Scale Range | Magnetometer Full Scale Range |
---|---|---|
+/- 250 deg/s | +/- 2g | +/- 4800 uT |
+/- 500 deg/s | +/- 4g | |
+/- 1000 deg/s | +/- 8g | |
+/- 2000 deg/s | +/- 16g |
The MPU-9250 samples the gyros, accelerometers, and magnetometers with 16 bit analog to digital converters. It also features programmable digital filters, a precision clock, an embedded temperature sensor, and programmable interrupts.
CMake is used to build this library, which is exported as a library target called mpu9250. The header is added as:
#include "mpu9250/mpu9250.h"
The library can be also be compiled stand-alone using the CMake idiom of creating a build directory and then, from within that directory issuing:
cmake .. -DMCU=MK66FX1M0
make
This will build the library and example executables called i2c_example and spi_example. The example executable source files are located at examples/i2c.cc and examples/spi.cc. Notice that the cmake command includes a define specifying the microcontroller the code is being compiled for. This is required to correctly configure the code, CPU frequency, and compile/linker options. The available MCUs are:
- MK20DX128
- MK20DX256
- MK64FX512
- MK66FX1M0
- MKL26Z64
- IMXRT1062_T40
- IMXRT1062_T41
These are known to work with the same packages used in Teensy products. Also switching packages is known to work well, as long as it's only a package change.
The i2c_example and spi_example targets create executables for communicating with the sensor using I2C or SPI communication, respectively. Each target also has a _hex for creating the hex file to upload to the microcontroller.
This library is within the namespace sensors.
Mpu9250(i2c_t3 *bus, uint8_t addr) Creates a Mpu9250 object. This constructor is used for the I2C communication interface. A pointer to the I2C bus object is passed along with the I2C address of the sensor. The address will be 0x68 if the AD0 pin is grounded and 0x69 if the AD0 pin is pulled high.
sensors::Mpu9250 mpu9250(&Wire, 0x68);
Mpu9250(SPIClass *bus, uint8_t cs) Creates a Mpu9250 object. This constructor is used for the SPI communication interface. A pointer to the SPI bus object is passed along with the chip select pin of the sensor. Any pin capable of digital I/O can be used as a chip select pin.
sensors::Mpu9250 mpu9250(&SPI, 2);
bool Begin() Initializes communication with the sensor and configures the default sensor ranges, sampling rates, and low pass filter settings. The default accelerometer range is +/- 16g and the default gyro range is +/- 2,000 deg/s. The default sampling rate is 1000 Hz and the low-pass filter is set to a cutoff frequency of 184 Hz. True is returned if communication is able to be established with the sensor and configuration completes successfully, otherwise, false is returned.
bool status = mpu9250.Begin();
if (!status) {
// ERROR
}
bool EnableDrdyInt() Enables the data ready interrupt. A 50 us interrupt will be triggered on the MPU-9250 INT pin when IMU data is ready. This interrupt is active high. This method returns true if the interrupt is successfully enabled, otherwise, false is returned.
bool status = mpu9250.EnableDrdyInt();
if (!status) {
// ERROR
}
bool DisableDrdyInt() Disables the data ready interrupt. This method returns true if the interrupt is successfully disabled, otherwise, false is returned.
bool status = mpu9250.DisableDrdyInt();
if (!status) {
// ERROR
}
void ApplyRotation(const Eigen::Matrix3f &c) Applies a rotation matrix to the sensor measurements. The default value for c is the identity matrix and the default sensor reference frame is shown below:
Outputs are defined as:
Xu = c * Xb
Where Xu is the output, c is the rotation matrix, and Xb are the measurements in the sensor reference frame.
/*
* c = 0 1 0
* 1 0 0
* 0 0 1
*/
Eigen::Matrix3f c = Eigen::Matrix3f::Zero();
c(0, 1) = 1.0f;
c(1, 0) = 1.0f;
c(2, 2) = 1.0f;
mpu9250.ApplyRotation(c);
Eigen::Matrix3f rotation() Returns the current rotation matrix.
Eigen::Matrix3f c = mpu9250.rotation();
bool ConfigAccelRange(const AccelRange range) Sets the accelerometer full scale range. Options are:
Range | Enum Value |
---|---|
+/- 2g | ACCEL_RANGE_2G |
+/- 4g | ACCEL_RANGE_4G |
+/- 8g | ACCEL_RANGE_8G |
+/- 16g | ACCEL_RANGE_16G |
True is returned on succesfully setting the accelerometer range, otherwise, false is returned. The default range is +/-16g.
bool status = mpu9250.ConfigAccelRange(Mpu9250::ACCEL_RANGE_4G);
if (!status) {
// ERROR
}
AccelRange accel_range() Returns the current accelerometer range.
AccelRange range = mpu9250.accel_range();
bool ConfigGyroRange(const GyroRange range) Sets the gyro full scale range. Options are:
Range | Enum Value |
---|---|
+/- 250 deg/s | GYRO_RANGE_250DPS |
+/- 500 deg/s | GYRO_RANGE_500DPS |
+/- 1000 deg/s | GYRO_RANGE_1000DPS |
+/- 2000 deg/s | GYRO_RANGE_2000DPS |
True is returned on succesfully setting the gyro range, otherwise, false is returned. The default range is +/-2000 deg/s.
bool status = mpu9250.ConfigGyroRange(Mpu9250::GYRO_RANGE_1000DPS);
if (!status) {
// ERROR
}
GyroRange gyro_range() Returns the current gyro range.
GyroRange range = mpu9250.gyro_range();
bool ConfigSrd(const uint8_t srd) Sets the sensor sample rate divider. The MPU-9250 samples the accelerometer and gyro at a rate, in Hz, defined by:
A srd setting of 0 means the MPU-9250 samples the accelerometer and gyro at 1000 Hz. A srd setting of 4 would set the sampling at 200 Hz. The IMU data ready interrupt is tied to the rate defined by the sample rate divider. The magnetometer is sampled at 100 Hz for sample rate divider values corresponding to 100 Hz or greater. Otherwise, the magnetometer is sampled at 8 Hz.
True is returned on succesfully setting the sample rate divider, otherwise, false is returned. The default sample rate divider value is 0, resulting in a 1000 Hz sample rate.
/* Set sample rate divider for 50 Hz */
bool status = mpu9250.sample_rate_divider(19);
if (!status) {
// ERROR
}
uint8_t srd() Returns the current sample rate divider value.
uint8_t srd = mpu9250.srd();
bool ConfigDlpf(const DlpfBandwidth dlpf) Sets the cutoff frequency of the digital low pass filter for the accelerometer, gyro, and temperature sensor. Available bandwidths are:
DLPF Bandwidth | Enum Value |
---|---|
184 Hz | DLPF_BANDWIDTH_184HZ |
92 Hz | DLPF_BANDWIDTH_92HZ |
41 Hz | DLPF_BANDWIDTH_41HZ |
20 Hz | DLPF_BANDWIDTH_20HZ |
10 Hz | DLPF_BANDWIDTH_10HZ |
5 Hz | DLPF_BANDWIDTH_5HZ |
True is returned on succesfully setting the digital low pass filters, otherwise, false is returned. The default bandwidth is 184 Hz.
bool status = mpu9250.ConfigDlpf(Mpu9250::DLPF_BANDWIDTH_20HZ);
if (!status) {
// ERROR
}
DlpfBandwidth dlpf() Returns the current digital low pass filter bandwidth setting.
DlpfBandwidth dlpf = mpu9250.dlpf();
void DrdyCallback(uint8_t int_pin, void (*function)()) Assigns a callback function to be called on the MPU-9250 data ready interrupt. Input parameters are the microcontroller pin number connected to the MPU-9250 interrupt pin and the function name.
void imu_isr() {
/* Read the IMU data */
if (mpu9250.Read()) {
}
}
void main() {
/* Setup callback for data ready interrupt */
mpu9250.DrdyCallback(MPU9250_I2C_INT, imu_isr);
}
bool Read() Reads data from the MPU-9250 and stores the data in the Mpu9250 object. Returns true if data is successfully read, otherwise, returns false.
/* Read the IMU data */
if (mpu9250.Read()) {
}
float accel_x_mps2() Returns the x accelerometer data from the Mpu9250 object in units of m/s/s. Similar methods exist for the y and z axis data.
/* Read the IMU data */
if (mpu9250.Read()) {
float ax = mpu9250.accel_x_mps2();
float ay = mpu9250.accel_y_mps2();
float az = mpu9250.accel_z_mps2();
}
Eigen::Vector3f accel_mps2() Returns the accelerometer data from the Mpu9250 objects as a 3-dimensional vector in units of m/s/s.
/* Read the IMU data */
if (mpu9250.Read()) {
Eigen::Vector3f accel = mpu9250.accel_mps2();
}
float gyro_x_radps() Returns the x gyro data from the Mpu9250 object in units of rad/s. Similar methods exist for the y and z axis data.
/* Read the IMU data */
if (mpu9250.Read()) {
float gx = mpu9250.gyro_x_radps();
float gy = mpu9250.gyro_y_radps();
float gz = mpu9250.gyro_z_radps();
}
Eigen::Vector3f gyro_radps() Returns the gyro data from the Mpu9250 objects as a 3-dimensional vector in units of rad/s.
/* Read the IMU data */
if (mpu9250.Read()) {
Eigen::Vector3f gyro = mpu9250.gyro_radps();
}
float mag_x_ut() Returns the x magnetometer data from the Mpu9250 object in units of uT. Similar methods exist for the y and z axis data.
/* Read the IMU data */
if (mpu9250.Read()) {
float hx = mpu9250.mag_x_ut();
float hy = mpu9250.mag_y_ut();
float hz = mpu9250.mag_z_ut();
}
Eigen::Vector3f mag_ut() Returns the magnetometer data from the Mpu9250 objects as a 3-dimensional vector in units of uT.
/* Read the IMU data */
if (mpu9250.Read()) {
Eigen::Vector3f mag = mpu9250.mag_ut();
}
float die_temperature_c() Returns the die temperature of the sensor in units of C.
/* Read the IMU data */
if (mpu9250.Read()) {
float temp = mpu9250.die_temperature_c();
}