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
Revision 6:40ac13ef7290, committed 2013-06-22
- Comitter:
- pommzorz
- Date:
- Sat Jun 22 11:23:45 2013 +0000
- Parent:
- 5:bdb6ad020352
- Commit message:
- Commit;
Changed in this revision
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();