Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Diff: MPU9250.h
- Revision:
- 3:e7be5e23013d
- Parent:
- 2:4e59a37182df
--- a/MPU9250.h Tue Aug 05 01:37:23 2014 +0000
+++ b/MPU9250.h Mon Jul 25 05:54:41 2022 +0000
@@ -1,12 +1,12 @@
+//------------------------------------------------------------------------------
+// Attitude measurement using IMU(MPU-9250)
+//------------------------------------------------------------------------------
#ifndef MPU9250_H
#define MPU9250_H
#include "mbed.h"
#include "math.h"
-
-// See also MPU-9250 Register Map and Descriptions, Revision 4.0, RM-MPU-9250A-00, Rev. 1.4, 9/9/2013 for registers not listed in
-// above document; the MPU9250 and MPU9150 are virtually identical but the latter has a different register map
-//
+
//Magnetometer Registers
#define AK8963_ADDRESS 0x0C<<1
#define WHO_AM_I_AK8963 0x00 // should return 0x48
@@ -30,7 +30,8 @@
#define SELF_TEST_Y_GYRO 0x01
#define SELF_TEST_Z_GYRO 0x02
-/*#define X_FINE_GAIN 0x03 // [7:0] fine gain
+/*
+#define X_FINE_GAIN 0x03 // [7:0] fine gain
#define Y_FINE_GAIN 0x04
#define Z_FINE_GAIN 0x05
#define XA_OFFSET_H 0x06 // User-defined trim values for accelerometer
@@ -38,7 +39,8 @@
#define YA_OFFSET_H 0x08
#define YA_OFFSET_L_TC 0x09
#define ZA_OFFSET_H 0x0A
-#define ZA_OFFSET_L_TC 0x0B */
+#define ZA_OFFSET_L_TC 0x0B
+*/
#define SELF_TEST_X_ACCEL 0x0D
#define SELF_TEST_Y_ACCEL 0x0E
@@ -153,7 +155,6 @@
#define ZA_OFFSET_H 0x7D
#define ZA_OFFSET_L 0x7E
-// Using the MSENSR-9250 breakout board, ADO is set to 0
// Seven-bit device address is 110100 for ADO = 0 and 110101 for ADO = 1
//mbed uses the eight-bit device address, so shift seven-bit addresses left by one!
#define ADO 0
@@ -190,25 +191,27 @@
float aRes, gRes, mRes; // scale resolutions per LSB for the sensors
//Set up I2C, (SDA,SCL)
-I2C i2c(I2C_SDA, I2C_SCL);
+I2C i2c(p9, p10);
-DigitalOut myled(LED1);
-
// Pin definitions
-int intPin = 12; // These can be changed, 2 and 3 are the Arduinos ext int pins
-
int16_t accelCount[3]; // Stores the 16-bit signed accelerometer sensor output
int16_t gyroCount[3]; // Stores the 16-bit signed gyro sensor output
int16_t magCount[3]; // Stores the 16-bit signed magnetometer sensor output
float magCalibration[3] = {0, 0, 0}, magbias[3] = {0, 0, 0}; // Factory mag calibration and mag bias
float gyroBias[3] = {0, 0, 0}, accelBias[3] = {0, 0, 0}; // Bias corrections for gyro and accelerometer
-float ax, ay, az, gx, gy, gz, mx, my, mz; // variables to hold latest sensor data values
+float ax, ay, az, gx, gy, gz, mx, my, mz; // variables to hold latest sensor data values
+float th_ax, th_ay, th_az;
+float th_ax_LPF, th_ay_LPF, th_az_LPF;
+float pre_th_ax, pre_th_ay, pre_th_az;
+float th_gx, th_gy, th_gz;
+float pre_gx, pre_gy, pre_gz;
+float th_x, th_y, th_z, th_x_d, th_y_d, th_z_d;
int16_t tempCount; // Stores the real internal chip temperature in degrees Celsius
float temperature;
float SelfTest[6];
-int delt_t = 0; // used to control display output rate
-int count = 0; // used to control display output rate
+float delt_t = 0.0f; // used to display output rate
+float sum_dt = 0.0f; //
// parameters for 6 DoF sensor fusion calculations
float PI = 3.14159265358979323846f;
@@ -221,7 +224,7 @@
float pitch, yaw, roll;
float deltat = 0.0f; // integration interval for both filter schemes
-int lastUpdate = 0, firstUpdate = 0, Now = 0; // used to calculate integration interval // used to calculate integration interval
+float lastUpdate = 0.0f, firstUpdate = 0.0f, Now = 0.0f; // used to calculate integration interval // used to calculate integration interval
float q[4] = {1.0f, 0.0f, 0.0f, 0.0f}; // vector to hold quaternion
float eInt[3] = {0.0f, 0.0f, 0.0f}; // vector to hold integral error for Mahony method
@@ -263,7 +266,6 @@
dest[ii] = data[ii];
}
}
-
void getMres() {
switch (Mscale)
@@ -279,7 +281,6 @@
}
}
-
void getGres() {
switch (Gscale)
{
@@ -301,7 +302,6 @@
}
}
-
void getAres() {
switch (Ascale)
{
@@ -348,11 +348,12 @@
if(readByte(AK8963_ADDRESS, AK8963_ST1) & 0x01) { // wait for magnetometer data ready bit to be set
readBytes(AK8963_ADDRESS, AK8963_XOUT_L, 7, &rawData[0]); // Read the six raw data and ST2 registers sequentially into data array
uint8_t c = rawData[6]; // End data read by reading ST2 register
- if(!(c & 0x08)) { // Check if magnetic sensor overflow set, if not then report data
+ if(!(c & 0x08))
+ { // Check if magnetic sensor overflow set, if not then report data
destination[0] = (int16_t)(((int16_t)rawData[1] << 8) | rawData[0]); // Turn the MSB and LSB into a signed 16-bit value
destination[1] = (int16_t)(((int16_t)rawData[3] << 8) | rawData[2]) ; // Data stored as little Endian
destination[2] = (int16_t)(((int16_t)rawData[5] << 8) | rawData[4]) ;
- }
+ }
}
}
@@ -364,11 +365,12 @@
}
-void resetMPU9250() {
+void resetMPU9250()
+{
// reset device
writeByte(MPU9250_ADDRESS, PWR_MGMT_1, 0x80); // Write a one to bit 7 reset bit; toggle reset device
wait(0.1);
- }
+}
void initAK8963(float * destination)
{
@@ -428,7 +430,7 @@
// It is possible to get a 4 kHz sample rate from the accelerometer by choosing 1 for
// accel_fchoice_b bit [3]; in this case the bandwidth is 1.13 kHz
c = readByte(MPU9250_ADDRESS, ACCEL_CONFIG2);
- writeByte(MPU9250_ADDRESS, ACCEL_CONFIG2, c & ~0x0F); // Clear accel_fchoice_b (bit 3) and A_DLPFG (bits [2:0])
+ writeByte(MPU9250_ADDRESS, ACCEL_CONFIG2, c & ~0x0F); // Clear accel_fchoice_b (bit 3) and A_DLPFG (bits [2:0])
writeByte(MPU9250_ADDRESS, ACCEL_CONFIG2, c | 0x03); // Set accelerometer rate to 1 kHz and bandwidth to 41 Hz
// The accelerometer, gyro, and thermometer are set to 1 kHz sample rates,
@@ -488,7 +490,8 @@
fifo_count = ((uint16_t)data[0] << 8) | data[1];
packet_count = fifo_count/12;// How many sets of full gyro and accelerometer data for averaging
- for (ii = 0; ii < packet_count; ii++) {
+ for (ii = 0; ii < packet_count; ii++)
+ {
int16_t accel_temp[3] = {0, 0, 0}, gyro_temp[3] = {0, 0, 0};
readBytes(MPU9250_ADDRESS, FIFO_R_W, 12, &data[0]); // read data for averaging
accel_temp[0] = (int16_t) (((int16_t)data[0] << 8) | data[1] ) ; // Form signed 16-bit integer for each sample in FIFO
@@ -503,9 +506,9 @@
accel_bias[2] += (int32_t) accel_temp[2];
gyro_bias[0] += (int32_t) gyro_temp[0];
gyro_bias[1] += (int32_t) gyro_temp[1];
- gyro_bias[2] += (int32_t) gyro_temp[2];
-
-}
+ gyro_bias[2] += (int32_t) gyro_temp[2];
+ }
+
accel_bias[0] /= (int32_t) packet_count; // Normalize sums to get average count biases
accel_bias[1] /= (int32_t) packet_count;
accel_bias[2] /= (int32_t) packet_count;
@@ -513,16 +516,16 @@
gyro_bias[1] /= (int32_t) packet_count;
gyro_bias[2] /= (int32_t) packet_count;
- if(accel_bias[2] > 0L) {accel_bias[2] -= (int32_t) accelsensitivity;} // Remove gravity from the z-axis accelerometer bias calculation
- else {accel_bias[2] += (int32_t) accelsensitivity;}
+ if(accel_bias[2] > 0L) {accel_bias[2] -= (int32_t) accelsensitivity;} // Remove gravity from the z-axis accelerometer bias calculation
+ else {accel_bias[2] += (int32_t) accelsensitivity;}
-// Construct the gyro biases for push to the hardware gyro bias registers, which are reset to zero upon device startup
- data[0] = (-gyro_bias[0]/4 >> 8) & 0xFF; // Divide by 4 to get 32.9 LSB per deg/s to conform to expected bias input format
- data[1] = (-gyro_bias[0]/4) & 0xFF; // Biases are additive, so change sign on calculated average gyro biases
- data[2] = (-gyro_bias[1]/4 >> 8) & 0xFF;
- data[3] = (-gyro_bias[1]/4) & 0xFF;
- data[4] = (-gyro_bias[2]/4 >> 8) & 0xFF;
- data[5] = (-gyro_bias[2]/4) & 0xFF;
+ // Construct the gyro biases for push to the hardware gyro bias registers, which are reset to zero upon device startup
+ data[0] = (-gyro_bias[0]/4 >> 8) & 0xFF; // Divide by 4 to get 32.9 LSB per deg/s to conform to expected bias input format
+ data[1] = (-gyro_bias[0]/4) & 0xFF; // Biases are additive, so change sign on calculated average gyro biases
+ data[2] = (-gyro_bias[1]/4 >> 8) & 0xFF;
+ data[3] = (-gyro_bias[1]/4) & 0xFF;
+ data[4] = (-gyro_bias[2]/4 >> 8) & 0xFF;
+ data[5] = (-gyro_bias[2]/4) & 0xFF;
/// Push gyro biases to hardware registers
/* writeByte(MPU9250_ADDRESS, XG_OFFSET_H, data[0]);
@@ -532,9 +535,9 @@
writeByte(MPU9250_ADDRESS, ZG_OFFSET_H, data[4]);
writeByte(MPU9250_ADDRESS, ZG_OFFSET_L, data[5]);
*/
- dest1[0] = (float) gyro_bias[0]/(float) gyrosensitivity; // construct gyro bias in deg/s for later manual subtraction
- dest1[1] = (float) gyro_bias[1]/(float) gyrosensitivity;
- dest1[2] = (float) gyro_bias[2]/(float) gyrosensitivity;
+ dest1[0] = (float) gyro_bias[0]/(float) gyrosensitivity; // construct gyro bias in deg/s for later manual subtraction
+ dest1[1] = (float) gyro_bias[1]/(float) gyrosensitivity;
+ dest1[2] = (float) gyro_bias[2]/(float) gyrosensitivity;
// Construct the accelerometer biases for push to the hardware accelerometer bias registers. These registers contain
// factory trim values which must be added to the calculated accelerometer biases; on boot up these registers will hold
@@ -542,35 +545,35 @@
// compensation calculations. Accelerometer bias registers expect bias input as 2048 LSB per g, so that
// the accelerometer biases calculated above must be divided by 8.
- int32_t accel_bias_reg[3] = {0, 0, 0}; // A place to hold the factory accelerometer trim biases
- readBytes(MPU9250_ADDRESS, XA_OFFSET_H, 2, &data[0]); // Read factory accelerometer trim values
- accel_bias_reg[0] = (int16_t) ((int16_t)data[0] << 8) | data[1];
- readBytes(MPU9250_ADDRESS, YA_OFFSET_H, 2, &data[0]);
- accel_bias_reg[1] = (int16_t) ((int16_t)data[0] << 8) | data[1];
- readBytes(MPU9250_ADDRESS, ZA_OFFSET_H, 2, &data[0]);
- accel_bias_reg[2] = (int16_t) ((int16_t)data[0] << 8) | data[1];
+ int32_t accel_bias_reg[3] = {0, 0, 0}; // A place to hold the factory accelerometer trim biases
+ readBytes(MPU9250_ADDRESS, XA_OFFSET_H, 2, &data[0]); // Read factory accelerometer trim values
+ accel_bias_reg[0] = (int16_t) ((int16_t)data[0] << 8) | data[1];
+ readBytes(MPU9250_ADDRESS, YA_OFFSET_H, 2, &data[0]);
+ accel_bias_reg[1] = (int16_t) ((int16_t)data[0] << 8) | data[1];
+ readBytes(MPU9250_ADDRESS, ZA_OFFSET_H, 2, &data[0]);
+ accel_bias_reg[2] = (int16_t) ((int16_t)data[0] << 8) | data[1];
- uint32_t mask = 1uL; // Define mask for temperature compensation bit 0 of lower byte of accelerometer bias registers
- uint8_t mask_bit[3] = {0, 0, 0}; // Define array to hold mask bit for each accelerometer bias axis
+ uint32_t mask = 1uL; // Define mask for temperature compensation bit 0 of lower byte of accelerometer bias registers
+ uint8_t mask_bit[3] = {0, 0, 0}; // Define array to hold mask bit for each accelerometer bias axis
- for(ii = 0; ii < 3; ii++) {
- if(accel_bias_reg[ii] & mask) mask_bit[ii] = 0x01; // If temperature compensation bit is set, record that fact in mask_bit
- }
+ for(ii = 0; ii < 3; ii++) {
+ if(accel_bias_reg[ii] & mask) mask_bit[ii] = 0x01; // If temperature compensation bit is set, record that fact in mask_bit
+ }
- // Construct total accelerometer bias, including calculated average accelerometer bias from above
- accel_bias_reg[0] -= (accel_bias[0]/8); // Subtract calculated averaged accelerometer bias scaled to 2048 LSB/g (16 g full scale)
- accel_bias_reg[1] -= (accel_bias[1]/8);
- accel_bias_reg[2] -= (accel_bias[2]/8);
+ // Construct total accelerometer bias, including calculated average accelerometer bias from above
+ accel_bias_reg[0] -= (accel_bias[0]/8); // Subtract calculated averaged accelerometer bias scaled to 2048 LSB/g (16 g full scale)
+ accel_bias_reg[1] -= (accel_bias[1]/8);
+ accel_bias_reg[2] -= (accel_bias[2]/8);
- data[0] = (accel_bias_reg[0] >> 8) & 0xFF;
- data[1] = (accel_bias_reg[0]) & 0xFF;
- data[1] = data[1] | mask_bit[0]; // preserve temperature compensation bit when writing back to accelerometer bias registers
- data[2] = (accel_bias_reg[1] >> 8) & 0xFF;
- data[3] = (accel_bias_reg[1]) & 0xFF;
- data[3] = data[3] | mask_bit[1]; // preserve temperature compensation bit when writing back to accelerometer bias registers
- data[4] = (accel_bias_reg[2] >> 8) & 0xFF;
- data[5] = (accel_bias_reg[2]) & 0xFF;
- data[5] = data[5] | mask_bit[2]; // preserve temperature compensation bit when writing back to accelerometer bias registers
+ data[0] = (accel_bias_reg[0] >> 8) & 0xFF;
+ data[1] = (accel_bias_reg[0]) & 0xFF;
+ data[1] = data[1] | mask_bit[0]; // preserve temperature compensation bit when writing back to accelerometer bias registers
+ data[2] = (accel_bias_reg[1] >> 8) & 0xFF;
+ data[3] = (accel_bias_reg[1]) & 0xFF;
+ data[3] = data[3] | mask_bit[1]; // preserve temperature compensation bit when writing back to accelerometer bias registers
+ data[4] = (accel_bias_reg[2] >> 8) & 0xFF;
+ data[5] = (accel_bias_reg[2]) & 0xFF;
+ data[5] = data[5] | mask_bit[2]; // preserve temperature compensation bit when writing back to accelerometer bias registers
// Apparently this is not working for the acceleration biases in the MPU-9250
// Are we handling the temperature correction bit properly?
@@ -617,7 +620,9 @@
gAvg[2] += (int16_t)(((int16_t)rawData[4] << 8) | rawData[5]) ;
}
- for (int ii =0; ii < 3; ii++) { // Get average of 200 values and store as average current readings
+ for (int ii =0; ii < 3; ii++)
+ {
+ // Get average of 200 values and store as average current readings
aAvg[ii] /= 200;
gAvg[ii] /= 200;
}
@@ -625,22 +630,25 @@
// Configure the accelerometer for self-test
writeByte(MPU9250_ADDRESS, ACCEL_CONFIG, 0xE0); // Enable self test on all three axes and set accelerometer range to +/- 2 g
writeByte(MPU9250_ADDRESS, GYRO_CONFIG, 0xE0); // Enable self test on all three axes and set gyro range to +/- 250 degrees/s
- delay(25); // Delay a while to let the device stabilize
+ //delay(25); // Delay a while to let the device stabilize
- for( int ii = 0; ii < 200; ii++) { // get average self-test values of gyro and acclerometer
-
+ for( int ii = 0; ii < 200; ii++)
+ {
+ // get average self-test values of gyro and acclerometer
readBytes(MPU9250_ADDRESS, ACCEL_XOUT_H, 6, &rawData[0]); // Read the six raw data registers into data array
aSTAvg[0] += (int16_t)(((int16_t)rawData[0] << 8) | rawData[1]) ; // Turn the MSB and LSB into a signed 16-bit value
aSTAvg[1] += (int16_t)(((int16_t)rawData[2] << 8) | rawData[3]) ;
aSTAvg[2] += (int16_t)(((int16_t)rawData[4] << 8) | rawData[5]) ;
- readBytes(MPU9250_ADDRESS, GYRO_XOUT_H, 6, &rawData[0]); // Read the six raw data registers sequentially into data array
+ readBytes(MPU9250_ADDRESS, GYRO_XOUT_H, 6, &rawData[0]); // Read the six raw data registers sequentially into data array
gSTAvg[0] += (int16_t)(((int16_t)rawData[0] << 8) | rawData[1]) ; // Turn the MSB and LSB into a signed 16-bit value
gSTAvg[1] += (int16_t)(((int16_t)rawData[2] << 8) | rawData[3]) ;
gSTAvg[2] += (int16_t)(((int16_t)rawData[4] << 8) | rawData[5]) ;
}
- for (int ii =0; ii < 3; ii++) { // Get average of 200 values and store as average self-test readings
+ for (int ii =0; ii < 3; ii++)
+ {
+ // Get average of 200 values and store as average self-test readings
aSTAvg[ii] /= 200;
gSTAvg[ii] /= 200;
}
@@ -648,7 +656,7 @@
// Configure the gyro and accelerometer for normal operation
writeByte(MPU9250_ADDRESS, ACCEL_CONFIG, 0x00);
writeByte(MPU9250_ADDRESS, GYRO_CONFIG, 0x00);
- delay(25); // Delay a while to let the device stabilize
+ //delay(25); // Delay a while to let the device stabilize
// Retrieve accelerometer and gyro factory Self-Test Code from USR_Reg
selfTest[0] = readByte(MPU9250_ADDRESS, SELF_TEST_X_ACCEL); // X-axis accel self-test results
@@ -668,7 +676,8 @@
// Report results as a ratio of (STR - FT)/FT; the change from Factory Trim of the Self-Test Response
// To get percent, must multiply by 100
- for (int i = 0; i < 3; i++) {
+ for (int i = 0; i < 3; i++)
+ {
destination[i] = 100.0*((float)(aSTAvg[i] - aAvg[i]))/factoryTrim[i]; // Report percent differences
destination[i+3] = 100.0*((float)(gSTAvg[i] - gAvg[i]))/factoryTrim[i+3]; // Report percent differences
}