Unit testing and development for 9DOF sparkfun sensor stick

Dependencies:   ADXL345 HMC5883L ITG3200 mbed

Revision:
3:5e21a352e236
Parent:
2:d7e66940541d
Child:
4:8a77e21d08f1
--- a/adxl345unit.cpp	Thu Nov 01 18:46:58 2012 +0000
+++ b/adxl345unit.cpp	Mon Nov 05 18:35:42 2012 +0000
@@ -28,7 +28,7 @@
 
 #include "adxl345unit.h"
 
-ADXL345UNIT::ADXL345UNIT(I2C &i2c) : adxl345_(i2c), pc_(USBTX, USBRX), local_("local"), open_file_(LED1)
+ADXL345UNIT::ADXL345UNIT(I2C &i2c, Timer &t) : adxl345_(i2c), pc_(USBTX, USBRX), open_file_(LED1), t_(t)
 {
     pc_.baud(9600);
     open_file_ = 0;
@@ -40,85 +40,73 @@
     // place initilazaition code here
 }
 
-bool ADXL345UNIT::builtInSelfTest()
+bool ADXL345UNIT::builtInSelfTest(bool store_raw)
 {
+    LocalFileSystem local("local");
+    FILE *fp; // file pointer
+
     bool test_pass[4] = {true,true,true,true};
     bool full_test = true;
 
-    int st_off[3][100]; // {x,y,z}, self test off
-    int st_off_avg[3];  // self test off average
-    int st_on[3][100];  // {x,y,z}, self test off
-    int st_on_avg[3];   // self test on average
-    int delta[3];       // st_on - st_off
+    int16_t st_off[100][3]; // {x,y,z}, self test off
+    int16_t st_off_avg[3];  // self test off average
+    int16_t st_on[100][3];  // {x,y,z}, self test off
+    int16_t st_on_avg[3];   // self test on average
+    int16_t delta[3];       // st_on - st_off
 
     const char axisK[3] = {'X','Y','Z'};
-    const int resolutionsK[4] = {16,8,4,2};
+    const int16_t resolutionsK[4] = {16,8,4,2};
     const char data_formatK[4] = {ADXL345_16G, ADXL345_8G, ADXL345_4G, (ADXL345_2G | ADXL345_FULL_RES)};
-    const int delta_minK[4][3] = {{6,-67,10},{12,-135,19},{25,-270,38},{50,-540,75}}; // {{16g},{8g},{4g},{2g}} from datasheet
-    const int delta_maxK[4][3] = {{67,-6,110},{135,-12,219},{270,-25,438},{540,-50,875}};
+    const int16_t delta_minK[4][3] = {{6,-67,10},{12,-135,19},{25,-270,38},{50,-540,75}}; // {{16g},{8g},{4g},{2g}} from datasheet
+    const int16_t delta_maxK[4][3] = {{67,-6,110},{135,-12,219},{270,-25,438},{540,-50,875}};
 
-    Timer t; // for timming sample readings
-    float start_time, elapsed_time;
-    float period = 0.001; // period of sample rate
+    float period = 0.01; // period of sample rate
+
+    adxl345_.setDataRate(ADXL345_100HZ); // 100Hz data rate
+    adxl345_.setPowerMode(0); // high power
 
     for(int res = 0; res < 4; res++) {
         //print starting message
         pc_.printf("ADXL345: Starting Built In Self Test (%dg resolution)... \n\r", resolutionsK[res]);
+
         //wait 1.1ms
-        wait(0.0011);
+        wait(0.0111);
+
+        pc_.puts("Calibrating... ");
         //initial command sequence
-        adxl345_.setDataFormatControl(data_formatK[res]); // 16g, 13bit mode
-        adxl345_.setDataRate(ADXL345_100HZ); // 100Hz data rate
-        adxl345_.setPowerMode(0); // high power
+        adxl345_.setDataFormatControl(data_formatK[res]);
         adxl345_.setPowerControl(0x08); // start measurement
-        adxl345_.setInterruptEnableControl(0x80); // enable data_ready interupt (not needed?)
-        //wait 1.1ms
-        wait(0.0011);
+        //adxl345_.setInterruptEnableControl(0x80); // enable data_ready interupt (not needed?)
+        pc_.puts("Done!\r\n");
+
+        //wait 11.1ms
+        wait(0.0111);
+
+        pc_.puts("Sampling: ");
         //take 100 data points and average (100Hz)
-        for(int sample = 0; sample < 100; sample++) {
-            start_time = t.read();
-
-            adxl345_.getOutput(st_off[sample]);
+        sample100avg(period, st_off, st_off_avg, &t_);
 
-            elapsed_time = t.read() - start_time;
-            if(elapsed_time > period) {
-                pc_.puts("Error: elapsed_time > period\n\r");
-                return false;
-            }
-            wait(period - elapsed_time);
-        }
-        for(int axis = 0; axis < 3; axis++)
-            st_off_avg[axis] = arr_avg(st_off[axis], 100); // average
-            
         //activate self test
         adxl345_.setDataFormatControl(data_formatK[res] | ADXL345_SELF_TEST); // self test enabled
-        //wait 1.1ms
-        wait(0.0011);
-        //take 100 data points and average (100Hz)
-        for(int sample = 0; sample < 100; sample++) {
-            start_time = t.read();
-
-            adxl345_.getOutput(st_on[sample]);
 
-            elapsed_time = t.read() - start_time;
-            if(elapsed_time > period) {
-                pc_.puts("Error: elapsed_time > period\n\r");
-                return false;
-            }
-            wait(period - elapsed_time);
-        }
-        for(int axis = 0; axis < 3; axis++)
-            st_on_avg[axis] = arr_avg(st_on[axis], 100); // average
+        //wait 11.1ms
+        wait(0.0111);
+        
+        //take 100 data points and average (100Hz)
+        sample100avg(period, st_on, st_on_avg, &t_);
+        pc_.puts("Done!\r\n");
+
         //inactivate self test
         adxl345_.setDataFormatControl(data_formatK[res]); // self test off
+
         //calculate self test delta(change) and compare to limits in data sheet
         //open file
         open_file_ = 1;
-        FILE *fp = fopen("/local/ADXL_BIT.csv", "a"); // open append, or create
-        fprintf(fp, "ADXL345 Built In Self-Test at %dg resolution.\r\nAxis,Min,Max,Actual,Pass\r\n", resolutionsK[res]);
+        fp = fopen("/local/BIST.csv", "a"); // open append, or create
+        fprintf(fp, "ADXL345 Built In Self-Test\n\rResolution,%d,g\r\n\r\nAxis,Min,Max,Actual,Pass\r\n", resolutionsK[res]);
         for(int axis = 0; axis < 3; axis++) {
             delta[axis] = st_on_avg[axis] - st_off_avg[axis];
-            bool test = (delta[axis] > delta_minK[res][axis] && delta[axis] < delta_maxK[res][axis]);
+            bool test = (delta[axis] >= delta_minK[res][axis] && delta[axis] <= delta_maxK[res][axis]);
             if(test == false)
                 test_pass[res] = full_test = false;
             fprintf(fp, "%c,%4d,%4d,%4d,%s\r\n", axisK[axis],delta_minK[res][axis],delta_maxK[res][axis],delta[axis],(test)?"pass":"fail");
@@ -127,16 +115,113 @@
         // close file
         fclose(fp);
         open_file_ = 0;
-        pc_.printf("%s\r\n", (test_pass[res])?"pass":"fail");
+        pc_.printf("Test Result: %s\r\n", (test_pass[res])?"pass":"fail");
+
+        pc_.puts("Dumping raw data to BIT_RAW.csv... ");
+        open_file_ = 1;
+
+        if(store_raw) {
+            //dump raw data to ADXL_RAW.csv
+            fp = fopen("/local/BIST_RAW.csv", "a"); // open append, or create
+            fprintf(fp, "ADXL345 Built In Self-Test Raw Data\n\rResolution,%d,g\r\nSample,X st_off,X st_on,Y st_off,Y st_on,Z st_off, Z st_off\r\n", resolutionsK[res]);
+            for(int sample = 0; sample < 100; sample++)
+                fprintf(fp, "%3d,%4d,%4d,%4d,%4d,%4d,%4d\r\n", (sample+1),st_on[sample][0],st_off[sample][0],st_on[sample][1],st_off[sample][1],st_on[sample][2],st_off[sample][2]);
+            fputs("\r\n",fp);
+            fclose(fp);
+            open_file_ = 0;
+        }
+
+        pc_.puts("Done!\r\n");
     }
+
     //return result
     return full_test;
 }
 
-int ADXL345UNIT::arr_avg(int* arr,int length)
+void ADXL345UNIT::offsetCalibration(bool store_raw)
+{
+    int16_t data[100][3]; // {x,y,z}, data
+    int16_t data_avg[3];
+    int16_t calibration_offset[3];
+
+    LocalFileSystem local("local");
+
+    float period = 0.01; // period of sample rate
+
+    // place sensor in x = 0g, y = 0g, z = 1g orientation
+    pc_.puts("Offset Calibration: Sensor should be in x=0g,y=0g,z=1g orientation\r\n");
+
+    // wait 11.1ms
+    wait(0.0111);
+
+    // initalize command sequence
+    adxl345_.setDataFormatControl((ADXL345_16G | ADXL345_FULL_RES));
+    adxl345_.setDataRate(ADXL345_100HZ); // 100Hz data rate
+    adxl345_.setPowerMode(0); // high power
+    adxl345_.setPowerControl(0x08); // start measurement
+
+    // wait 1.1ms
+    wait(0.0111);
+
+    //take 100 data points and average (100Hz)
+    sample100avg(period, data, data_avg, &t_);
+
+    // calculate calibration value
+    calibration_offset[0] = -1 * (data_avg[0] / 4); // x
+    calibration_offset[1] = -1 * (data_avg[1] / 4); // y
+    calibration_offset[2] = -1 * ((data_avg[2] - 256) / 4); // z
+
+    // display and store values
+    pc_.printf("X offset: %d\r\n", calibration_offset[0]);
+    pc_.printf("Y offset: %d\r\n", calibration_offset[1]);
+    pc_.printf("Z offset: %d\r\n", calibration_offset[2]);
+
+    open_file_ = 1;
+    FILE *fp = fopen("/local/OFF_CAL.csv", "w"); // write
+    fprintf(fp, "ADXL345 Calibration offsets\r\nx,%d\r\ny,%d\r\nz,%d\r\n\r\n", calibration_offset[0], calibration_offset[1], calibration_offset[2]);
+    if(store_raw) {
+        fputs("Raw Data:\r\nX,Y,Z\r\n", fp);
+        for(int sample = 0; sample < 100; sample++)
+            fprintf(fp, "%d,%d,%d\r\n",data[sample][0],data[sample][1],data[sample][2]);
+    }
+    fclose(fp);
+    open_file_ = 0;
+}
+
+bool ADXL345UNIT::methodTest()
+{
+    // constructors and size of obj tests
+    // destructor test
+    // get device id [0xE5]
+    // set power mode > get bw rate
+    //
+}
+
+int16_t ADXL345UNIT::arr_avg(int16_t* arr,int16_t length)
 {
     double average;
     for(int i = 0; i < length; i++)
         average += static_cast<double>(arr[i]) / static_cast<double>(length);
-    return static_cast<int>(average);
+    return static_cast<int16_t>(average);
+}
+
+void ADXL345UNIT::sample100avg(float period, int16_t buffer[][3], int16_t *avg, Timer* t)
+{
+    double start_time;
+    
+    for(int sample = 0; sample < 100; sample++) {
+        start_time = t->read();
+
+        adxl345_.getOutput(buffer[sample]);
+
+        wait(period - (start_time - t->read()));
+    }
+
+    for(int axis = 0; axis < 3; axis++) {
+        double average = 0.0;
+        for(int sample = 0; sample < 100; sample++)
+            average += buffer[sample][axis];
+        average /= 100.0;
+        avg[axis] = static_cast<int16_t>(average);
+    }
 }
\ No newline at end of file