MPU6050 arduino port by Szymon Gaertig (http://mbed.org/users/garfieldsg/code/MPU6050/) 1 memory overflow error corrected.

Dependents:   MbedFreeIMU gurvanAHRS

Fork of MPU6050 by Simon Garfieldsg

Files at this revision

API Documentation at this revision

Comitter:
pommzorz
Date:
Sat Jun 22 11:23:45 2013 +0000
Parent:
5:bdb6ad020352
Commit message:
Commit;

Changed in this revision

GurvIMU.cpp Show annotated file Show diff for this revision Revisions of this file
GurvIMU.h Show annotated file Show diff for this revision Revisions of this file
MPU6050.cpp Show annotated file Show diff for this revision Revisions of this file
MPU6050.h Show annotated file Show diff for this revision Revisions of this file
diff -r bdb6ad020352 -r 40ac13ef7290 GurvIMU.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GurvIMU.cpp	Sat Jun 22 11:23:45 2013 +0000
@@ -0,0 +1,187 @@
+#include "GurvIMU.h"
+#include "MPU6050.h"
+#include "mbed.h"
+
+#define  M_PI 3.1415926535897932384626433832795
+
+#define twoKpDef    (2.0f * 2.0f)   // 2 * proportional gain
+#define twoKiDef    (2.0f * 0.5f)   // 2 * integral gain
+
+
+GurvIMU::GurvIMU()
+{
+    //MPU
+    mpu = MPU6050(0x69); //0x69 = MPU6050 I2C ADDRESS
+
+    // Variable definitions
+    q0 = 1.0f, q1 = 0.0f, q2 = 0.0f, q3 = 0.0f;  // quaternion of sensor frame relative to auxiliary frame
+    twoKp = twoKpDef;                                            // 2 * proportional gain (Kp)
+    twoKi = twoKiDef;                                            // 2 * integral gain (Ki)
+    integralFBx = 0.0f,  integralFBy = 0.0f, integralFBz = 0.0f; // integral error terms scaled by Ki
+    cycle_nb = 0;
+    timer_us.start();    
+}
+
+//Function definitions
+
+void GurvIMU::getValues(float * values)
+{
+    int16_t accgyroval[6];
+    mpu.getMotion6(&accgyroval[0], &accgyroval[1], &accgyroval[2], &accgyroval[3], &accgyroval[4], &accgyroval[5]);
+    for(int i = 0; i<3; i++) values[i] = (float) accgyroval[i];
+    for(int i = 3; i<6; i++) values[i] = (accgyroval[i]-offset[i]) * (M_PI / 180) / 16.4f;
+}
+
+void GurvIMU::getVerticalAcceleration(float av)
+{
+    float values[6];
+    float q[4]; // quaternion
+    float g_x, g_y, g_z; // estimated gravity direction
+    getQ(q);
+  
+    g_x = 2 * (q[1]*q[3] - q[0]*q[2]);
+    g_y = 2 * (q[0]*q[1] + q[2]*q[3]);
+    g_z = q[0]*q[0] - q[1]*q[1] - q[2]*q[2] + q[3]*q[3];   
+    
+    getValues(values);
+    av = g_x*values[0]+g_y*values[1]+g_z*values[2]-offset[2];
+}
+     
+
+void GurvIMU::getOffset(void)
+{
+    int sample_nb = 50;
+    float values[6];
+    for(int i=0; i<6 ; i++) offset[i] = 0;
+    for(int i=0; i<sample_nb; i++) {
+        getValues(values);
+        for(int j=0; j<6; j++) offset[j]+=values[j];        
+    }     
+    for(int j=0; j<6; j++) offset[j]/=sample_nb;
+}
+
+
+void GurvIMU::AHRS_update(float gx, float gy, float gz, float ax, float ay, float az)
+{
+    float recipNorm;
+    float halfvx, halfvy, halfvz;
+    float halfex, halfey, halfez;
+    float qa, qb, qc;
+    
+    dt_us=timer_us.read_us();
+    sample_freq = 1.0 / ((dt_us) / 1000000.0);
+    timer_us.reset();
+    
+    // Compute feedback only if accelerometer measurement valid (avoids NaN in accelerometer normalisation)
+    if(!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) {
+
+        // Normalise accelerometer measurement
+        recipNorm = invSqrt(ax * ax + ay * ay + az * az);
+        ax *= recipNorm;
+        ay *= recipNorm;
+        az *= recipNorm;        
+
+        // Estimated direction of gravity
+        halfvx = q1 * q3 - q0 * q2;
+        halfvy = q0 * q1 + q2 * q3;
+        halfvz = q0 * q0 - 0.5f + q3 * q3;
+    
+        // Error is sum of cross product between estimated and measured direction of gravity
+        halfex = (ay * halfvz - az * halfvy);
+        halfey = (az * halfvx - ax * halfvz);
+        halfez = (ax * halfvy - ay * halfvx);
+
+        // Compute and apply integral feedback if enabled
+        if(twoKi > 0.0f) {
+            integralFBx += twoKi * halfex * (1.0f / sample_freq);    // integral error scaled by Ki
+            integralFBy += twoKi * halfey * (1.0f / sample_freq);
+            integralFBz += twoKi * halfez * (1.0f / sample_freq);
+            gx += integralFBx;  // apply integral feedback
+            gy += integralFBy;
+            gz += integralFBz;
+        }
+        else {
+            integralFBx = 0.0f; // prevent integral windup
+            integralFBy = 0.0f;
+            integralFBz = 0.0f;
+        }
+
+        // Apply proportional feedback
+        gx += twoKp * halfex;
+        gy += twoKp * halfey;
+        gz += twoKp * halfez;
+    }
+    
+    // Integrate rate of change of quaternion
+    gx *= (0.5f * (1.0f / sample_freq));     // pre-multiply common factors
+    gy *= (0.5f * (1.0f / sample_freq));
+    gz *= (0.5f * (1.0f / sample_freq));
+    qa = q0;
+    qb = q1;
+    qc = q2;
+    q0 += (-qb * gx - qc * gy - q3 * gz);
+    q1 += (qa * gx + qc * gz - q3 * gy);
+    q2 += (qa * gy - qb * gz + q3 * gx);
+    q3 += (qa * gz + qb * gy - qc * gx); 
+    
+    // Normalise quaternion
+    recipNorm = invSqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);
+    q0 *= recipNorm;
+    q1 *= recipNorm;
+    q2 *= recipNorm;
+    q3 *= recipNorm;
+}
+
+void GurvIMU::getQ(float * q) {
+  float val[6];
+  getValues(val);
+  //while(cycle_nb < 1000){
+    AHRS_update(val[3], val[4], val[5], val[0], val[1], val[2]);
+  //cycle_nb++;}
+
+  q[0] = q0;
+  q[1] = q1;
+  q[2] = q2;
+  q[3] = q3;
+  
+}
+
+void GurvIMU::getYawPitchRollRad(float * ypr) {
+  float q[4]; // quaternion
+  float g_x, g_y, g_z; // estimated gravity direction
+  getQ(q);
+  
+  g_x = 2 * (q[1]*q[3] - q[0]*q[2]);
+  g_y = 2 * (q[0]*q[1] + q[2]*q[3]);
+  g_z = q[0]*q[0] - q[1]*q[1] - q[2]*q[2] + q[3]*q[3];
+  
+  ypr[0] = atan2(2 * q[1] * q[2] - 2 * q[0] * q[3], 2 * q[0]*q[0] + 2 * q[1] * q[1] - 1);
+  ypr[1] = atan(g_x * invSqrt(g_y*g_y + g_z*g_z));
+  ypr[2] = atan(g_y * invSqrt(g_x*g_x + g_z*g_z));
+}
+
+void GurvIMU::init()
+{
+    mpu.initialize();
+    mpu.setI2CMasterModeEnabled(0);
+    mpu.setI2CBypassEnabled(1);
+    mpu.setFullScaleGyroRange(MPU6050_GYRO_FS_2000);
+    getOffset();
+    wait(0.005);
+}
+
+
+float invSqrt(float number)
+{
+    volatile long i;
+    volatile float x, y;
+    volatile const float f = 1.5F;
+
+    x = number * 0.5F;
+    y = number;
+    i = * ( long * ) &y;
+    i = 0x5f375a86 - ( i >> 1 );
+    y = * ( float * ) &i;
+    y = y * ( f - ( x * y * y ) );
+    return y;
+}
\ No newline at end of file
diff -r bdb6ad020352 -r 40ac13ef7290 GurvIMU.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GurvIMU.h	Sat Jun 22 11:23:45 2013 +0000
@@ -0,0 +1,40 @@
+#ifndef _GURVIMU_H_
+#define _GURVIMU_H_
+
+#include "mbed.h"
+#include "MPU6050.h"
+
+class GurvIMU {
+    private:
+        //Variables
+        MPU6050 mpu;
+        float twoKp;            // 2 * proportional gain (Kp)
+        float twoKi;            // 2 * integral gain (Ki)
+        float integralFBx, integralFBy, integralFBz; // integral error terms scaled by Ki
+        float q0, q1, q2, q3;   // quaternion of sensor frame relative to auxiliary frame
+        float ax, ay, az, gx, gy, gz;
+        float sample_freq;
+        float offset[6];
+        Timer timer_us;
+        float dt_us;
+        float cycle_nb;
+        
+        
+        //Functions
+        void getOffset();
+        void getValues(float * values);
+        void AHRS_update(float gx, float gy, float gz, float ax, float ay, float az);
+        void getQ(float * q);
+
+    public:
+        GurvIMU();
+        void init();
+        void getYawPitchRollRad(float * ypr);
+        void getVerticalAcceleration(float * av);
+        
+};
+
+//Fast Inverse Square Root
+float invSqrt(float number);
+
+#endif /* _GURVIMU_H_ */
\ No newline at end of file
diff -r bdb6ad020352 -r 40ac13ef7290 MPU6050.cpp
--- a/MPU6050.cpp	Wed Feb 20 18:29:30 2013 +0000
+++ b/MPU6050.cpp	Sat Jun 22 11:23:45 2013 +0000
@@ -80,8 +80,6 @@
 
     debugSerial.baud(921600); //uses max serial speed
 #ifdef useDebugSerial
-
-    debugSerial.baud(921600);
     debugSerial.printf("MPU6050::initialize start\n");
 #endif
     setClockSource(MPU6050_CLOCK_PLL_XGYRO);
@@ -172,6 +170,7 @@
     i2Cdev.writeByte(devAddr, MPU6050_RA_SMPLRT_DIV, rate);
 }
 
+
 // CONFIG register
 
 /** Get external FSYNC configuration.
diff -r bdb6ad020352 -r 40ac13ef7290 MPU6050.h
--- a/MPU6050.h	Wed Feb 20 18:29:30 2013 +0000
+++ b/MPU6050.h	Sat Jun 22 11:23:45 2013 +0000
@@ -420,6 +420,7 @@
         // SMPLRT_DIV register
         uint8_t getRate();
         void setRate(uint8_t rate);
+        
 
         // CONFIG register
         uint8_t getExternalFrameSync();