I have a DFRobots MPU6050 module wired to SCL/SDA/Pin 2 on a Mega 2560 board, using Jeff Rowberg's I2CDev/MPU6050_6Axis_MotionApps libraries. I have 2.2K pullups on the MPU6050 module, tied to +5V, as shown in the following photo.
I used a modified version of the code from Jeff's example to retrieve heading values from the MPU6050, as shown below
bool GetIMUHeadingDeg() //08/28/18 chg to bool return
{
//Purpose: Encapsulate everything needed to acquire a yaw value
//Inputs:
// global_yawval = float variable defined at global scope
// fifocount = uint8_t variable defined at global scope
// packetsize = uint8_t variable defined at global scope
// mpuIntStatus = uint8_t variable defined at global scope
// whilecount = long variable defined at global scope
// resetcount = int variable defined at global scope
//Outputs:
// global_yawval filled with latest yaw value from sensor
// true = success, false = failure
//Notes:
// 08/13/18 now returns global_yawval to calling routine
// 08/28/18 chg return to bool so can return success/failure
// if programming failed, don't try to do anything
//if (!dmpReady) return;
//if (!dmpReady) false;
bool result = false; //added 01/16/19 to supress warnings
// wait for MPU interrupt or extra packet(s) available
while (!mpuInterrupt && fifoCount < DMPpacketSize)
{
whilecount++;
delay(10);
delay(10);
if (mpuInterrupt)
{
fifoCount = mpu.getFIFOCount();
mySerial.printf("%ld\t%d\n", whilecount, fifoCount);
whilecount = 0;
break;
}
}
// reset interrupt flag and get INT_STATUS byte
mpuIntStatus = mpu.getIntStatus();
mpuInterrupt = false;
// get current FIFO count
fifoCount = mpu.getFIFOCount();
// check for overflow (this should never happen unless our code is too inefficient)
if ((mpuIntStatus & 0x10) || fifoCount == 1024)//0x10 is mask for MPU6050_INTERRUPT_FIFO_OFLOW_BIT
{
// reset so we can continue cleanly
mpu.resetFIFO();
Serial.println(F("FIFO overflow!"));
result = false; //added 01/16/19 to supress warnings
// otherwise, check for DMP data ready interrupt (this should happen frequently)
}
else if (mpuIntStatus & 0x02)//0x02 is mask for MPU6050_INTERRUPT_DMP_INT_BIT
{
// wait for correct available data length, should be a VERY short wait
while (fifoCount < DMPpacketSize)
{
fifoCount = mpu.getFIFOCount();
//mySerial.printf("fifo count = %d\n", fifoCount);
}
//07/08/18 added to watch for non-modulo FIFO counts
if (fifoCount == 0 || fifoCount % DMPpacketSize != 0)
{
mpu.resetFIFO();
FIFO_resetcount++;
}
else
{
//07/07/18 modified to read all outstanding packets
// read a packet from FIFO
while (fifoCount >= DMPpacketSize)
{
//mySerial.printf("fifo count = %d\n", fifoCount);
mpu.getFIFOBytes(fifoBuffer, DMPpacketSize);
fifoCount -= DMPpacketSize;
}
// display Euler angles in degrees
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
global_yawval = ypr[0] * 180 / M_PI;
result = true; //added 01/16/19 to supress warnings
}
////DEBUG!!
// mySerial.printf("yawdeg = %4.2f\n", global_yawval);
// mySerial.printf("time = %ld\tyawdeg = %6.2f\n", millis(), global_yawval);
////DEBUG!!
}
return result; //added 01/16/19 to surpress warnings
}
I have noticed occasional bad data points in the computed Heading values retrieved from the MPU6050, as shown in the attached plot. Any ideas what I can do about this? Is bad value detection/removal an expected issue when dealing with IMU products like the MPU6050?
As an experiment, I excluded all points for which the rotation rate was unrealistically high, resulting in the 'Adj Hdg' line (gray line) in the plot below. This (mostly) works, except for one instance where there were two bad values in a row.
Frank