Skip to main content
Bumped by Community user
Bumped by Community user
Bumped by Community user
Bumped by Community user
Bumped by Community user
Bumped by Community user
Bumped by Community user
Bumped by Community user
Bumped by Community user
Fixed syntax highlighting.
Source Link
VE7JRO
  • 2.5k
  • 19
  • 26
  • 29
bool GetIMUHeadingDeg() //08/28/18 chg to bool return 
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
//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
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
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
added 335 characters in body
Source Link
starship15
  • 772
  • 4
  • 11

enter image description here

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.

enter image description here TIA,

enter image description here TIA,

enter image description here

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.

enter image description here TIA,

Source Link
starship15
  • 772
  • 4
  • 11

MPU6050/DMP Intermittent bad data output?

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.

enter image description here

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?

enter image description here TIA,

Frank