Visualize IMU data sent over BLE on a computer

Dependencies:   PinDetect mbed

Fork of LSM9DS1_Library by jim hamblen

Files at this revision

API Documentation at this revision

Comitter:
cvmp94
Date:
Sun Mar 13 21:40:10 2016 +0000
Parent:
2:e8c2301f7523
Commit message:
initial commit

Changed in this revision

MadgwickUpdate.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
diff -r e8c2301f7523 -r fd549671e512 MadgwickUpdate.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MadgwickUpdate.h	Sun Mar 13 21:40:10 2016 +0000
@@ -0,0 +1,98 @@
+#include "mbed.h"
+#include "math.h"
+
+float deltat = 0.0f;
+int lastUpdate = 0, firstUpdate = 0, Now = 0;
+float q[4] = {1.0f, 0.0f, 0.0f, 0.0f};
+
+float PI = 3.14159265358979323846f;
+float GyroMeasError = PI * (60.0f / 180.0f);     // gyroscope measurement error in rads/s (start at 60 deg/s), then reduce after ~10 s to 3
+float beta = sqrt(3.0f / 4.0f) * GyroMeasError;  // compute beta
+float GyroMeasDrift = PI * (1.0f / 180.0f);      // gyroscope measurement drift in rad/s/s (start at 0.0 deg/s/s)
+float zeta = sqrt(3.0f / 4.0f) * GyroMeasDrift;
+
+void MadgwickQuaternionUpdate(float ax, float ay, float az, float gx, float gy, float gz) {
+    float q1 = q[0], q2 = q[1], q3 = q[2], q4 = q[3];         // short name local variable for readability
+    float norm;                                               // vector norm
+    float f1, f2, f3;                                         // objective funcyion elements
+    float J_11or24, J_12or23, J_13or22, J_14or21, J_32, J_33; // objective function Jacobian elements
+    float qDot1, qDot2, qDot3, qDot4;
+    float hatDot1, hatDot2, hatDot3, hatDot4;
+    float gerrx, gerry, gerrz, gbiasx, gbiasy, gbiasz;  // gyro bias error
+
+    // Auxiliary variables to avoid repeated arithmetic
+    float _halfq1 = 0.5f * q1;
+    float _halfq2 = 0.5f * q2;
+    float _halfq3 = 0.5f * q3;
+    float _halfq4 = 0.5f * q4;
+    float _2q1 = 2.0f * q1;
+    float _2q2 = 2.0f * q2;
+    float _2q3 = 2.0f * q3;
+    float _2q4 = 2.0f * q4;
+
+    // Normalise accelerometer measurement
+    norm = sqrt(ax * ax + ay * ay + az * az);
+    if (norm == 0.0f) return; // handle NaN
+    norm = 1.0f/norm;
+    ax *= norm;
+    ay *= norm;
+    az *= norm;
+    
+    // Compute the objective function and Jacobian
+    f1 = _2q2 * q4 - _2q1 * q3 - ax;
+    f2 = _2q1 * q2 + _2q3 * q4 - ay;
+    f3 = 1.0f - _2q2 * q2 - _2q3 * q3 - az;
+    J_11or24 = _2q3;
+    J_12or23 = _2q4;
+    J_13or22 = _2q1;
+    J_14or21 = _2q2;
+    J_32 = 2.0f * J_14or21;
+    J_33 = 2.0f * J_11or24;
+  
+    // Compute the gradient (matrix multiplication)
+    hatDot1 = J_14or21 * f2 - J_11or24 * f1;
+    hatDot2 = J_12or23 * f1 + J_13or22 * f2 - J_32 * f3;
+    hatDot3 = J_12or23 * f2 - J_33 *f3 - J_13or22 * f1;
+    hatDot4 = J_14or21 * f1 + J_11or24 * f2;
+    
+    // Normalize the gradient
+    norm = sqrt(hatDot1 * hatDot1 + hatDot2 * hatDot2 + hatDot3 * hatDot3 + hatDot4 * hatDot4);
+    hatDot1 /= norm;
+    hatDot2 /= norm;
+    hatDot3 /= norm;
+    hatDot4 /= norm;
+    
+    // Compute estimated gyroscope biases
+    gerrx = _2q1 * hatDot2 - _2q2 * hatDot1 - _2q3 * hatDot4 + _2q4 * hatDot3;
+    gerry = _2q1 * hatDot3 + _2q2 * hatDot4 - _2q3 * hatDot1 - _2q4 * hatDot2;
+    gerrz = _2q1 * hatDot4 - _2q2 * hatDot3 + _2q3 * hatDot2 - _2q4 * hatDot1;
+    
+    // Compute and remove gyroscope biases
+    gbiasx += gerrx * deltat * zeta;
+    gbiasy += gerry * deltat * zeta;
+    gbiasz += gerrz * deltat * zeta;
+//           gx -= gbiasx;
+//           gy -= gbiasy;
+//           gz -= gbiasz;
+    
+    // Compute the quaternion derivative
+    qDot1 = -_halfq2 * gx - _halfq3 * gy - _halfq4 * gz;
+    qDot2 =  _halfq1 * gx + _halfq3 * gz - _halfq4 * gy;
+    qDot3 =  _halfq1 * gy - _halfq2 * gz + _halfq4 * gx;
+    qDot4 =  _halfq1 * gz + _halfq2 * gy - _halfq3 * gx;
+
+    // Compute then integrate estimated quaternion derivative
+    q1 += (qDot1 -(beta * hatDot1)) * deltat;
+    q2 += (qDot2 -(beta * hatDot2)) * deltat;
+    q3 += (qDot3 -(beta * hatDot3)) * deltat;
+    q4 += (qDot4 -(beta * hatDot4)) * deltat;
+
+    // Normalize the quaternion
+    norm = sqrt(q1 * q1 + q2 * q2 + q3 * q3 + q4 * q4);    // normalise quaternion
+    norm = 1.0f/norm;
+    q[0] = q1 * norm;
+    q[1] = q2 * norm;
+    q[2] = q3 * norm;
+    q[3] = q4 * norm;
+    
+}
\ No newline at end of file
diff -r e8c2301f7523 -r fd549671e512 main.cpp
--- a/main.cpp	Wed Feb 03 18:24:29 2016 +0000
+++ b/main.cpp	Sun Mar 13 21:40:10 2016 +0000
@@ -1,29 +1,84 @@
 #include "LSM9DS1.h"
+#include "MadgwickUpdate.h"
 
-DigitalOut myled(LED1);
 Serial pc(USBTX, USBRX);
 
+Timer t;
+int lastPrint = 0;
+int printInterval = 500;
+
+RawSerial dev( p13, p14 );
+
+int calibrate = 1;
+
+void dev_recv()
+{
+    while(dev.readable()) {
+        if ( dev.getc() == 'r' ){
+                calibrate = 1;
+        }
+    }
+}
+
 int main() {
-    //LSM9DS1 lol(p9, p10, 0x6B, 0x1E);
-    LSM9DS1 lol(p9, p10, 0xD6, 0x3C);
+    
+    LSM9DS1 lol(p28, p27, 0xD6, 0x3C);
+    
+    t.start();
+
+    dev.baud(9600);
+    dev.attach(&dev_recv, Serial::RxIrq);
+
     lol.begin();
     if (!lol.begin()) {
         pc.printf("Failed to communicate with LSM9DS1.\n");
     }
-    lol.calibrate();
+
     while(1) {
-        lol.readTemp();
-        lol.readMag();
-        lol.readGyro();
+
+        if( calibrate ){
+            lol.calibrate();
+            firstUpdate = t.read_us();
+            lastUpdate = firstUpdate;
+            q[0] = 1.0f; q[1] = 0.0f; q[2] = 0.0f; q[3] = 0.0f; 
+            calibrate = 0;
+        }
         
-        //pc.printf("%d %d %d %d %d %d %d %d %d\n\r", lol.calcGyro(lol.gx), lol.calcGyro(lol.gy), lol.calcGyro(lol.gz), lol.ax, lol.ay, lol.az, lol.mx, lol.my, lol.mz);
-        //pc.printf("%d %d %d\n\r", lol.calcGyro(lol.gx), lol.calcGyro(lol.gy), lol.calcGyro(lol.gz));
-        pc.printf("gyro: %d %d %d\n\r", lol.gx, lol.gy, lol.gz);
-        pc.printf("accel: %d %d %d\n\r", lol.ax, lol.ay, lol.az);
-        pc.printf("mag: %d %d %d\n\n\r", lol.mx, lol.my, lol.mz);
-        myled = 1;
-        wait(2);
-        myled = 0;
-        wait(2);
+        if ( lol.accelAvailable() || lol.gyroAvailable() ) {
+         
+            lol.readAccel();
+            lol.readGyro();
+            
+            Now = t.read_us();
+            deltat = (float)((Now - lastUpdate)/1000000.0f);
+            lastUpdate = Now;
+            
+            float ax = lol.calcAccel(lol.ax);
+            float ay = lol.calcAccel(lol.ay);
+            float az = lol.calcAccel(lol.az);
+            
+            float gx = lol.calcGyro(lol.gx);
+            float gy = lol.calcGyro(lol.gy);
+            float gz = lol.calcGyro(lol.gz);
+            
+            
+            // switch x and y to convert to right handed coordinate system
+            MadgwickQuaternionUpdate( ay, ax, az, gy*PI/180.0f, gx*PI/180.0f, gz*PI/180.0f );
+            
+            int nowMs = t.read_ms();
+            if( nowMs - lastPrint > printInterval ){
+                lastPrint = nowMs;
+                pc.printf("gyro: %f %f %f\n\r", gx, gy, gz);
+                pc.printf("accel: %f %f %f\n\r", ax, ay, az);
+                pc.printf("quat: %f %f %f %f\n\r", q[0], q[1], q[2], q[3]);
+                char* str = (char*) &q;
+                int i = 0;
+                while (i < 16){
+                    dev.putc( str[i] );
+                    i += 1;   
+                }
+            }
+            
+        }
     }
 }