Program takes accelerometer and gyroscope data from the MPU6050 registers and calibrates them for better results. Then uses this data is to obtain pitch and roll angles and writes these angles to the terminal which mbed is connected to.

Dependencies:   MPU6050 ledControl2 mbed

main.cpp

Committer:
BaserK
Date:
2015-07-13
Revision:
3:88737ad5c803
Parent:
2:497faa1563ea
Child:
4:33fef1998fc8

File content as of revision 3:88737ad5c803:

/*   MPU6050 example with I2C interface on LPC1768 
*
*    @author: Baser Kandehir 
*    @date: July 9, 2015
*    @license: Use this code however you'd like
*   
*    @description of the program: 
*    
*    First of all most of the credit goes to Kris Winer for his useful MPU6050 code.
*    I rewrite the code in my way using class prototypes and my comments. This program
*    can be a starter point for more advanced projects including quadcopters, balancing
*    robots etc. Program takes accelerometer and gyroscope data from the MPU6050 registers
*    and calibrates them for better results. And writes accel and gyro x,y,z data to the
*    terminal. I will use this code later on for sensor fusion with a compass to get pitch,
*    roll and yaw angles. After that I am planning to use some filtering algorithms like
*    Kalman Filter and Complementary filter. I will keep updating the code as I write them.
*   
*    @connections:
*-------------------------------------------------------------- 
*    |LPC1768|        |Peripherals|
*    Pin 9 ---------> SDA of MPU6050
*    Pin 10 --------> SCL of MPU6050
*    Pin 13 --------> (TX) RX pin of the FTDI or Bluetooth etc.
*    Pin 14 --------> (RX) TX pin of the FTDI or Bluetooth etc.
*    GND -----------> GND of any peripheral
*    VOUT (3.3 V) --> VCC of MPU6050
*---------------------------------------------------------------
*   Note: For any mistakes or comments, please contact me.
*/

#include "mbed.h"
#include "MPU6050.h"
#include "ledControl.h"

/* */

/* Defined in the MPU6050.cpp file  */
// I2C i2c(p9,p10);         // setup i2c (SDA,SCL)  

Serial ftdi(p13,p14);    // default baud rate: 9600
MPU6050 mpu6050;         // class: MPU6050, object: mpu6050 
Ticker toggler1;
Ticker filter;           

void toggle_led1();
void toggle_led2();
void complementaryFilter(float* pitch, float* roll);
void compFilter();

float pitchAngle = 0;
float rollAngle = 0;

int main() 
{
    ftdi.baud(9600);                            // baud rate: 9600
    i2c.frequency(400000);                      // fast i2c: 400 kHz
    mpu6050.whoAmI();                           // Communication test: WHO_AM_I register reading 
    wait(1);
    mpu6050.calibrate(accelBias,gyroBias);      // Calibrate MPU6050 and load biases into bias registers
    ftdi.printf("Calibration is completed. \r\n");
    wait(0.5);
    mpu6050.init();                             // Initialize the sensor
    wait(1);
    ftdi.printf("MPU6050 is initialized for operation.. \r\n\r\n");
    wait_ms(500);
    
    while(1) 
    {
//        /* Get actual acc value */
//        mpu6050.readAccelData(accelData);
//        mpu6050.getAres();
//        ax = accelData[0]*aRes - accelBias[0];
//        ay = accelData[1]*aRes - accelBias[1];
//        az = accelData[2]*aRes - accelBias[2]; 
//        
//        /* Get actual gyro value */
//        mpu6050.readGyroData(gyroData);
//        mpu6050.getGres();     
//        gx = gyroData[0]*gRes;  // - gyroBias[0];      // Results are better without extracting gyroBias[i]
//        gy = gyroData[1]*gRes;  // - gyroBias[1]; 
//        gz = gyroData[2]*gRes;  // - gyroBias[2]; 
//        
//        ftdi.printf(" _____________________________________________________________  \r\n");
//        ftdi.printf("| Accelerometer(g) | ax=%.3f | ay=%.3f | az=%.3f                \r\n",ax,ay,az);
//        ftdi.printf("| Gyroscope(deg/s) | gx=%.3f | gy=%.3f | gz=%.3f                \r\n",gx,gy,gz);
//        ftdi.printf("|_____________________________________________________________  \r\n\r\n");
//        
//        wait(2.5);
                
        filter.attach(&compFilter, 0.005);    // Call the complementaryFilter func. every 5 ms (200 Hz sampling period)
        
        ftdi.printf(" _______________\r\n");
        ftdi.printf("| Pitch: %.3f   \r\n",pitchAngle);
        ftdi.printf("| Roll:  %.3f   \r\n",rollAngle);
        ftdi.printf("|_______________\r\n\r\n");
        
        wait(1);
    }
}

void toggle_led1() {ledToggle(1);}
void toggle_led2() {ledToggle(2);}

/* This function is created to avoid address error that caused from Ticker.attach func */ 
void compFilter() {complementaryFilter(&pitchAngle, &rollAngle);}

void complementaryFilter(float* pitch, float* roll)
{
    /* Get actual acc value */
    mpu6050.readAccelData(accelData);
    mpu6050.getAres();
    ax = accelData[0]*aRes - accelBias[0];
    ay = accelData[1]*aRes - accelBias[1];
    az = accelData[2]*aRes - accelBias[2]; 

    /* Get actual gyro value */
    mpu6050.readGyroData(gyroData);
    mpu6050.getGres();     
    gx = gyroData[0]*gRes;  // - gyroBias[0];      // Results are better without extracting gyroBias[i]
    gy = gyroData[1]*gRes;  // - gyroBias[1]; 
    gz = gyroData[2]*gRes;  // - gyroBias[2]; 

    float pitchAcc, rollAcc;

    /* Integrate the gyro data(deg/s) over time to get angle */
    *pitch += gx * dt;  // Angle around the X-axis
    *roll -=  gy * dt;  // Angle around the Y-axis
    
    /* Turning around the X-axis results in a vector on the Y-axis
    whereas turning around the Y-axis results in a vector on the X-axis. */
    pitchAcc = atan2f((float)accelData[1], (float)accelData[2])*180/PI;
    rollAcc  = atan2f((float)accelData[0], (float)accelData[2])*180/PI;
    
    /* Apply Complementary Filter */
    *pitch = *pitch * 0.98 + pitchAcc * 0.02;
    *roll  = *roll  * 0.98 + rollAcc  * 0.02;   
}