read acceleration and angler ratio from mpu6050 and estimate pitch and roll angle

Dependencies:   mbed

Revision:
3:40559ebef0f1
Parent:
2:4a6b46653abf
--- a/main.cpp	Mon Apr 20 14:54:55 2015 +0000
+++ b/main.cpp	Wed May 13 04:02:27 2015 +0000
@@ -4,20 +4,23 @@
 #include "ErrorLogger.h"
 #include "Matrix.h"
 #include "Vector.h"
+#include "MPU6050.h"
+#include "HMC5883L.h"
 /********** private define **********/
 /********** private macro **********/
 /********** private typedef **********/
-/********** public variables **********/
-/********** public functions **********/
 /********** private variables **********/
+const static float dt = 0.01f;
 
 DigitalOut myled(LED1);                 // デバッグ用LEDのためのデジタル出力
 Serial pc(SERIAL_TX, SERIAL_RX);        // PC通信用シリアルポート
 I2C i2c(D14, D15);                  // mpu6050用I2Cオブジェクト
 Ticker INS_ticker;                      // 割り込み用タイマー
+MPU6050 mpu6050(&i2c);
+HMC5883L hmc5883l(&i2c);
 
-const int mpu6050_addr = 0xd0;          // mpu6050アドレス
-const int hmc5883l_addr = 0x3C;         // hmc5883lアドレス
+//const int mpu6050_addr = 0xd0;          // mpu6050アドレス
+//const int hmc5883l_addr = 0x3C;         // hmc5883lアドレス
 volatile int ret = 0;                   // I2C関数の返り値保存用
 uint8_t cmd[2] = {};                    // I2C送信データ
 uint8_t data[14] = {};                  // I2C受信データ
@@ -27,7 +30,11 @@
 //int16_t mag[3] = {};                    // 地磁気
 Vector acc(3);
 Vector gyro(3);
+Vector mag(3);
 Vector g(3);
+Vector n(3);
+Vector v_acc(3);
+Vector v(3);
 float theta[2] = {};                    // ロール、ピッチ角
 
 char text[256];                         // デバッグ用文字列
@@ -41,23 +48,52 @@
 int main() {
     
     i2c.frequency(400000);                      // mpu6050との通信は400kHz
+    mpu6050.init();
+    hmc5883l.init();
     
     // 0x6bレジスタに0x00を書き込んでmpu6050のスリープモードを解除
-    cmd[0] = 0x6b;
+    /*cmd[0] = 0x6b;
     cmd[1] = 0x00;
     ret = i2c.write(mpu6050_addr, (char*)cmd, 2);
-    pc.printf("ret = %d ", ret);
+    pc.printf("ret = %d ", ret);*/
+    
+    // 地磁気センサの初期値を取得
+    hmc5883l.read();
+    mag.SetComp(1, (float)hmc5883l.data.value[0]);
+    mag.SetComp(2, (float)hmc5883l.data.value[1]);
+    mag.SetComp(3, (float)hmc5883l.data.value[2]);
+    
+    mag = mag.Normalize();
+    
+    v.SetComp(1, 0.0f);
+    v.SetComp(2, 0.0f);
+    v.SetComp(3, 0.0f);
+    
+    g.SetComp(1, 0.0f);
+    g.SetComp(2, 0.0f);
+    g.SetComp(3, 1.0f);
     
     // センサー値の取得・計算は割り込み関数内で行う。
     // 割り込み周期は10ms(10000μs)
-    INS_ticker.attach_us(&INS_IntFunc, 10000);    
+    INS_ticker.attach_us(&INS_IntFunc, 1000000 * dt);    
     
     while(1) {
        // メインループではひたすらLEDチカチカ
        myled = 1; // LED is ON
-       wait(0.2); // 200 ms
+       wait(0.05); // 50 ms
+       
+            pc.printf("%.3f\t", g.GetComp(1));
+            pc.printf("%.3f\t", g.GetComp(2));
+            pc.printf("%.3f\t", g.GetComp(3));
+            pc.printf("%.3f\t", n.GetComp(1));
+            pc.printf("%.3f\t", n.GetComp(2));
+            pc.printf("%.3f\t", n.GetComp(3));
+            pc.printf("%.3f\t", v.GetComp(1));
+            pc.printf("%.3f\t", v.GetComp(2));
+            pc.printf("%.3f\r\n", v.GetComp(3));
+            
        myled = 0; // LED is OFF
-       wait(1.0); // 1 sec
+       wait(0.05); // 1 sec
            
     }
 }
@@ -65,7 +101,7 @@
 void INS_IntFunc() {
         
         // 0x3bレジスタからデータの読み取りを行う
-        cmd[0] = 0x3b;
+        /*cmd[0] = 0x3b;
         ret = i2c.write(mpu6050_addr, (char*)cmd, 1, true);
         i2c.read(mpu6050_addr | 0x01, (char*)data, 14, false);
         
@@ -80,23 +116,65 @@
             int16_t gyro_temp = 0;
             gyro_temp = ((int16_t)data[i*2])<<8 | ((int16_t)data[i*2+1]);
             gyro.SetComp(i-3, (float)gyro_temp * GYRO_LSB_TO_DEG * DEG_TO_RAD);
+        }*/
+        
+        mpu6050.read();
+        hmc5883l.read();
+        
+        for(int i=0; i<3; i++) {
+            acc.SetComp(i+1, (float)mpu6050.data.value.acc[i] * ACC_LSB_TO_G);
+            gyro.SetComp(i+1, (float)mpu6050.data.value.gyro[i] * GYRO_LSB_TO_DEG * DEG_TO_RAD);
+            mag.SetComp(i+1, (float)hmc5883l.data.value[i]);
         }
         
+        //acc = acc.Normalize();      // 欲しいのは方向のみなので単位ベクトル化
+        //mag = mag.Normalize();      // 欲しいのは方向のみなので単位ベクトル化
+        
+        /*pc.printf("%.4f\t", acc.GetComp(1));
+        pc.printf("%.4f\t", acc.GetComp(2));
+        pc.printf("%.4f\t", acc.GetComp(3));
+        pc.printf("%.4f\t", gyro.GetComp(1));
+        pc.printf("%.4f\t", gyro.GetComp(2));
+        pc.printf("%.4f\t", gyro.GetComp(3));
+        pc.printf("%.4f\t", mag.GetComp(1));
+        pc.printf("%.4f\t", mag.GetComp(2));
+        pc.printf("%.4f\r\n", mag.GetComp(3));
+        */
         // 重力ベクトルを推定
         {
-            acc = acc.GetUnit();            // 欲しいのは方向のみなので、単位ベクトル化
-            Vector delta = Cross(gyro, g);  // Δg = ω × g
+            Vector delta_g = Cross(gyro, g);  // Δg = ω × g
+            Vector delta_n = Cross(gyro, n);  // Δf = ω × f
+            
             
             // 相補フィルタを使ってみる
-            g = 0.9f * (g + 0.01f * delta) + 0.1f * acc;
-            g = g.GetUnit();
+            //g = g + delta * dt;
+            g = 0.9f * (g + delta_g * dt) + 0.1f * acc.Normalize();
+            g = g.Normalize();
+            n = 0.9f * (n + delta_n * dt) + 0.1f * mag.Normalize();
+            n = n.Normalize();
+            
+            v_acc = G_TO_MPSS * (acc - (acc * g) * g);
+            
+            v += v_acc * dt;
             
             // 推定結果をPCに送信
-            pc.printf("%.4f\t", g.GetComp(1));
-            pc.printf("%.4f\t", g.GetComp(2));
-            pc.printf("%.4f\r\n", g.GetComp(3));
+            /*pc.printf("%.3f\t", g.GetComp(1));
+            pc.printf("%.3f\t", g.GetComp(2));
+            pc.printf("%.3f\t", g.GetComp(3));
+            pc.printf("%.3f\t", n.GetComp(1));
+            pc.printf("%.3f\t", n.GetComp(2));
+            pc.printf("%.3f\t", n.GetComp(3));
+            pc.printf("%.3f\t", v.GetComp(1));
+            pc.printf("%.3f\t", v.GetComp(2));
+            pc.printf("%.3f\r\n", v.GetComp(3));*/
             
-        }       
+            
+            
+            //pc.printf("%f\t", (float)mpu6050.data.value.gyro[0] * GYRO_LSB_TO_DEG);
+            //pc.printf("%f\t", (float)mpu6050.data.value.gyro[1] * GYRO_LSB_TO_DEG);
+            //pc.printf("%f\r\n", (float)mpu6050.data.value.gyro[2] * GYRO_LSB_TO_DEG);
+            
+        }
         
         /*
         // 各センサー値からセンサーの姿勢・角速度を計算