mbed MPU6050 - Using the Madgwick Orientation Filter library

I am currently trying to add a madgwick filter for MPU6050 in Mbed Studio OS6. I picked out a library to make implementation easier: MPU6050 - Library for MPU6050 motion sensor with Madgwick f… | Mbed

I’ve tried to follow the library as best I can but the Madgwick filter setup isn’t working as I had hoped. The time and temperature are showing correctly but the orientation values are listed as “0.00”:

TIME, PITCH, ROLL, YAW, TEMP

00:11:59:716, 0.00, 0.00, 0.00, 25.48

Now here is the loop, what am I missing in order to get values in my output?

// Loop
while(1)
{
    if (mpu6050.dataReady()) {
        mpu6050.accel(); // Read 2g acceleration data
        mpu6050.gyro(); // Read 250° gyroscope data
        //mpu6050.setGain(float beta, float zeta); // Do I need this?
        mpu6050.madgwickFilter(0.005f); // 5ms = 200Hz

        // Using existing functions defined in the .cpp and .h files
        float pitch = mpu6050.pitch();
        float roll = mpu6050.roll();
        float yaw = mpu6050.yaw();

        // Read temperature - this works
        float temperature = mpu6050.temp();
        // Read time - this works
        auto elapsed_time = t.elapsed_time();

        // Print values to serial console - Now includes Time
        snprintf(buffer, sizeof(buffer), 
             
             // Seperated by comma for data collection and visualiser
            "%02d:%02d:%02d:%03d, %.2f, %.2f, %.2f, %.2f\n",
            int (elapsed_time / 1h), int((elapsed_time % 1h) / 1min), int((elapsed_time % 1min) / 1s), int((elapsed_time % 1s) / 1ms),
            pitch, roll, yaw, temperature);
            
            // Raw values:
            //"[%02d:%02d:%02d,%03d] Accel: (X: %.2f, Y: %.2f, Z: %.2f) G | Gyro: (A: %.2f, B: %.2f, C: %.2f) °/s | Temperature: %.2f°C\n\r", 
            //int (elapsed_time / 1h), int(elapsed_time % 1h / 1min), int(elapsed_time % 1min / 1s), int(elapsed_time % 1s / 1ms),
            //ax, ay, az, gx, gy, gz, temperature);

        printf("%s", buffer);

        ThisThread::sleep_for(100ms); // Delay to read data
    }
}

Hello,

did you check/test the example for that library? - MPU6050_Hello - Example of using the MPU6050 library. | Mbed

BR, Jan

I tried to use that yes but it outputs the following and doesn’t change from:
“0, 0, 0”

I have a NUCLEO f303k8 and mpu6050 setup on a breadboard.
I managed to get the pitch and roll values using the following:

if (mpu6050.dataReady()) {
            mpu6050.accel(); // Read 2g acceleration data
            mpu6050.gyro(); // Read 250° gyroscope data

            // Displaying sensor values
            float ax = mpu6050.accelData[0];
            float ay = mpu6050.accelData[1];
            float az = mpu6050.accelData[2];

            float gx = mpu6050.gyroData[0];
            float gy = mpu6050.gyroData[1];
            float gz = mpu6050.gyroData[2];

            // Read temperature
            float temperature = mpu6050.temp();

            // Calculate Roll and Pitch - Found issue with Euler equation we now have Gimbal lock!
            float pitch = atan2(ay, sqrt(ax * ax + az * az)) * 180 / M_PI;
            float roll = atan2(-ax, sqrt(ay * ay + az * az)) * 180 / M_PI;

But I’m not really using the functions defined in the source file, I also tried to use the pitch and roll functions without the Madgwick filter defined but I have the same issue of it not even registering when moving the sensor still showing “0, 0, 0”

First:

In the header file is written

    // To compute yaw, pitch and roll after after aplying the madgwickFilter
    float yaw();
    float pitch();
    float roll();

These methods use an array what is filled in Madgwick filter method so it is not possible to use it without it.

Second:
The code above is probably not working because you use a constant value instead of a time between samples.

mpu6050.madgwickFilter(0.005f); // 5ms = 200Hz

The input parameter should be time between samples. That is what this one or Kalman filter usually needs. So check the example again and use it correctly.

BR, Jan

Okay I tried that and I think I have tried to follow what you ask me to do by adding a current time and a previous time and add a time but it is still not printing the pitch, yaw and roll values.
“00:06:25:861, 0.00, 0.00, 0.00, 24.57”

I’m unsure if elapsed_time() is the best way to find deltaT but this is what I did:

#include "mbed.h"
#include "MPU6050.h"
#include <cstdint>

MPU6050 mpu6050(0x68, AFS_2G, GFS_250DPS, PB_7, PB_6);

Timer t;
    
int main()
{

    t.start(); // Start Timer for output

    // Setup
    char buffer[128]; // Buffer for formatted strings

    //Read the WHO_AM_I register
    uint8_t whoami = mpu6050.getWhoAmI();
    snprintf(buffer, sizeof(buffer), "I am 0x%x\n\rI should be 0x68\n\r", whoami);
    printf("%s", buffer);

    if (!mpu6050.init()) {
        printf("MPU6050 initialisation failed\n\r");
        return 1; // Non-zero term for stderr
    }

    if (whoami == 0x68) 
    {
        printf("IMU MPU6050 connected...\n\r");
        ThisThread::sleep_for(1s);

        if (mpu6050.selfTestOK()) 
        {
            printf("Self test passed.\n\r");
            mpu6050.reset();
            mpu6050.calibrate();
            printf("MPU6050 calibrated and initialised.\n\r");
            ThisThread::sleep_for(1s);

            auto previousTime_us = t.elapsed_time().count(); // Store previous iteration time
            // Loop
            while(1)
            {
                auto currentTime_us = t.elapsed_time().count();
                if (mpu6050.dataReady()) {
                    mpu6050.accel(); // Read 2g acceleration data
                    mpu6050.gyro(); // Read 250° gyroscope data
                    
                    float temperature = mpu6050.temp(); // Read temperature
                    
                    float delta_Time = float((currentTime_us - previousTime_us) / 1000000.0f);

                    // if (currentTime_us - previousTime_us > 10000000.0f)
                    // {
                    //     mpu6050.setGain(0.04, 0.015);
                    // }

                    mpu6050.madgwickFilter(delta_Time);
                    float yaw = mpu6050.yaw();
                    float pitch = mpu6050.pitch();
                    float roll = mpu6050.roll();


                    int32_t total_seconds = currentTime_us / 1000000;
                    int8_t hours = total_seconds / 3600;
                    int8_t minutes = (total_seconds % 3600) / 60;
                    int8_t seconds = total_seconds % 60;
                    int16_t milliseconds = (currentTime_us % 1000000) / 1000;

                    // Print values to serial console - Now includes Time
                    snprintf(buffer, sizeof(buffer), 
                        
                        // Seperated by comma for CSV and C# visualiser
                        "%02d:%02d:%02d:%03d, %.2f, %.2f, %.2f, %.2f Delta: %f\n\r",
                        hours, minutes, seconds, milliseconds,
                        yaw, pitch, roll, temperature, delta_Time);

                    printf("%s", buffer);
                    previousTime_us = currentTime_us; // Update previous time for next iteration
                    ThisThread::sleep_for(100ms); // Delay to read data
                }
            }
        } else {
            printf("Device did not pass the self-test!\n\r");
            return 1; 
        } 
    } else {
        printf("Could not connect to the MPU6050: \n\r");
        printf("%x \n", whoami);     
    }   
}

I’ve added delta_Time as well:
00:00:50:494, 0.00, 0.00, 0.00, 24.87 Delta: 0.102000
00:00:50:596, 0.00, 0.00, 0.00, 24.89 Delta: 0.102000
00:00:50:698, 0.00, 0.00, 0.00, 24.87 Delta: 0.102000

P.S. I am using mbed_app.json file to define “printf” instead of using BufferedSerial

Sorry here is the new version, that should be the same as the MPU6050_Hello version of the code.

I’ve added two timers one for the output operational time and another for delta time. I then reset the time as per the MPU6050 hello after initialising the madgwick filter.

However, I am still getting the issue with no values appearing in the output for pitch, roll or yaw. I can print the raw values but cannot get values from the functions. I’m really lost here.

#include "mbed.h"
#include "MPU6050.h"
#include <cstdint>

MPU6050 mpu6050(0x68, AFS_2G, GFS_250DPS, PB_7, PB_6, NC);

Timer deltaTimer;
Timer totalTimer;


int main()
{
    totalTimer.start(); // Start Timer for operational time
    deltaTimer.start(); // For integration time

    // Setup
    char buffer[128]; // Buffer for formatted strings
    // float beta = 0;
    // float zeta = 0;

    //Read the WHO_AM_I register
    uint8_t whoami = mpu6050.getWhoAmI();
    snprintf(buffer, sizeof(buffer), "I am 0x%x\n\rI should be 0x68\n\r", whoami);
    printf("%s", buffer);

    if (!mpu6050.init()) {
        printf("MPU6050 initialisation failed\n\r");
        return 1; // Non-zero term for stderr
    }

    if (whoami == 0x68) 
    {
        printf("IMU MPU6050 connected...\n\r");
        ThisThread::sleep_for(1s);

        if (mpu6050.selfTestOK()) 
        {
            //mpu6050.setGain(beta, zeta);
            printf("Self test passed.\n\r");
            mpu6050.reset();
            
            mpu6050.calibrate();
            printf("MPU6050 calibrated and initialised.\n\r");
            ThisThread::sleep_for(1s);

            // Loop
            while(1)
            {
                
                if (mpu6050.dataReady()) {
                    
                    float* accelData = mpu6050.accel();
                    float* gyroData = mpu6050.gyro();
                    mpu6050.accel(); // Read 2g acceleration data
                    mpu6050.gyro(); // Read 250° gyroscope data
                    
                    float temperature = mpu6050.temp(); // Read temperature
                    
                    float delta_Time = float(deltaTimer.elapsed_time().count()) / 1000000.0f;

                    mpu6050.madgwickFilter(delta_Time); // Sensor fusion of accel and gyro
                    deltaTimer.reset(); // integration time immediately reset
                    float yaw = mpu6050.yaw(); // gyro based yaw
                    float pitch = mpu6050.pitch();
                    float roll = mpu6050.roll();

                    int64_t totalTime_us = totalTimer.elapsed_time().count();
                    int32_t total_seconds = totalTime_us / 1000000;
                    int8_t hours = total_seconds / 3600;
                    int8_t minutes = (total_seconds % 3600) / 60;
                    int8_t seconds = total_seconds % 60;
                    int16_t milliseconds = (totalTime_us % 1000000) / 1000;

                    // Print values to serial console - Now includes Time
                    snprintf(buffer, sizeof(buffer), 
                        
                        // Seperated by comma for CSV and C# visualiser
                        "%02d:%02d:%02d:%03d, %.2f, %.2f, %.2f, %.2f Delta: %f\n\r",
                        hours, minutes, seconds, milliseconds,
                        yaw, pitch, roll, temperature, delta_Time);

                        // Debug: Raw Accel & Gyro Data
                        // "[%02d:%02d:%02d,%03d] Accel: (X: %.2f, Y: %.2f, Z: %.2f) G | Gyro: (A: %.2f, B: %.2f, C: %.2f) °/s | Temperature: %.2f°C\n\r", 
                        // hours, minutes, seconds, milliseconds,
                        // accelData[0], accelData[1], accelData[2], gyroData[0], gyroData[1], gyroData[2], temperature);

                    printf("%s", buffer);
                    ThisThread::sleep_for(100ms); // Delay to read data
                }
            }
        } else {
            printf("Device did not pass the self-test!\n\r");
            return 1; 
        } 
    } else {
        printf("Could not connect to the MPU6050: \n\r");
        printf("%x \n", whoami);     
    }   
}

I tried to check if I have this device in my storage but suddenly not. I have just 6500 (9250) and I am not sure how far it is from this one.

Your code contains this line

    //Read the WHO_AM_I register
    uint8_t whoami = mpu6050.getWhoAmI();

But library what you mentioned about does not contain method getWhoAmI();. So I am little bit confused and I do not know what a library you use.

BR, Jan

Ah yes I added a line in the MPU6050.h to make a public reference to the WHO_AM_I_MPU6050 register, on Line 191 of MPU6050.h. Should be similar, 9250 has a magnetometer while the 6050 doesn’t:

uint8_t getWhoAmI() {
        return readReg(WHO_AM_I_MPU6050);               // Added this to library for public access to private func call
    }

I can agree same behavior. It seems like data are lost inside of method madgwickFilter.

BR, Jan