Unit testing and development for 9DOF sparkfun sensor stick

Dependencies:   ADXL345 HMC5883L ITG3200 mbed

Files at this revision

API Documentation at this revision

Comitter:
tylerjw
Date:
Mon Nov 05 18:35:42 2012 +0000
Parent:
2:d7e66940541d
Child:
4:8a77e21d08f1
Commit message:
Working adxl built in test and calibration test in adxl345unit;

Changed in this revision

ADXL345.lib Show annotated file Show diff for this revision Revisions of this file
adxl345unit.cpp Show annotated file Show diff for this revision Revisions of this file
adxl345unit.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
--- a/ADXL345.lib	Thu Nov 01 18:46:58 2012 +0000
+++ b/ADXL345.lib	Mon Nov 05 18:35:42 2012 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/tylerjw/code/ADXL345/#839128c6e20a
+http://mbed.org/users/tylerjw/code/ADXL345/#4cdd4315189f
--- 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
--- a/adxl345unit.h	Thu Nov 01 18:46:58 2012 +0000
+++ b/adxl345unit.h	Mon Nov 05 18:35:42 2012 +0000
@@ -40,7 +40,7 @@
         *
         * @param i2c buss to use for adxl345
         */
-        ADXL345UNIT(I2C &i2c);
+        ADXL345UNIT(I2C &i2c, Timer &t);
         
         /**
         * Initalize the device
@@ -48,16 +48,41 @@
         void init();
         
         /**
-        * Perform built in self test and print results to ADXL_BIT.csv
+        * Perform built in self test and print results to BIST.csv
+        * Raw data is printed to BIST_RAW.csv
+        *
+        * NOT YET TESTED
+        *
+        * @param store_raw true to store raw data
+        * @returns test result: true if passed, false if failed
+        */
+        bool builtInSelfTest(bool);
+        
+        /**
+        * Performs the offset callibration test and prints to OFF_CAL.csv
+        *
+        * NOT YET TESTED
         *
-        * @returns true if passed, false if failed
+        * TODO: implement into ADXL345 class.
+        *
+        * @param store_raw true to store raw data
         */
-        bool builtInSelfTest();
+        void offsetCalibration(bool);
+        
+        /**
+        * Tests the method of ADXL345 library
+        * 
+        * Results stored in method.txt
+        *
+        * @returns test result, true if passed, false if not
+        */
+        bool methodTest();
+        
     private:
         ADXL345 adxl345_;
         Serial pc_;
-        LocalFileSystem local_;
         DigitalOut open_file_;
+        Timer t_;
         
         /**
         * Averages an array of n length
@@ -65,7 +90,17 @@
         * @param the array
         * @param length
         */
-        int arr_avg(int*,int);
+        int16_t arr_avg(int16_t*,int16_t);
+        
+        /**
+        * Sample 100 times and average
+        *
+        * @param period of sample rate
+        * @param array to hold raw data, should be int16_t[100][3] (sample,axis)
+        * @param array to hold averages, should be 3 in length
+        * @param pointer to timer object (should already be started)
+        */
+        void sample100avg(float, int16_t[][3], int16_t*, Timer*);
 };
 
 #endif
\ No newline at end of file
--- a/main.cpp	Thu Nov 01 18:46:58 2012 +0000
+++ b/main.cpp	Mon Nov 05 18:35:42 2012 +0000
@@ -17,12 +17,54 @@
 #include "mbed.h"
 //#include "ITG3200.h"
 //#include "HMC5883L.h"
+#include "adxl345unit.h"
 
 I2C i2c_bus(p28, p27);
+ADXL345 accel(i2c_bus);
+Timer t;
+Serial pc(USBTX, USBRX);
+//ADXL345UNIT accel_test(i2c_bus, t);
 
 int main()
 {
+    t.start();
+    pc.baud(9600);
+    accel.calibrate(&t, true);
+    //accel_test.builtInSelfTest(true);
+    //accel_test.offsetCalibration(true);
+/*
+    int sample[3];
+    float elapsed_time;
+    float time_stamp[100];
+    int samples[100][3];
 
+    Timer t;
+    Serial pc(USBTX, USBRX);
+    pc.baud(9600);
+
+    accel.setDataRate(ADXL345_100HZ); // 100Hz data rate
+    accel.setDataFormatControl(ADXL345_16G | ADXL345_FULL_RES);
+    accel.setPowerControl(0x08); // start measurement
+
+    wait(0.001);
+
+    t.start();
+    accel.getOutput(sample);
+    elapsed_time = t.read();
+
+    pc.printf("Sample took %f seconds.\r\n", elapsed_time);
+    pc.printf("x: %d, y: %d, z: %d\r\n", sample[0],sample[1],sample[2]);
+
+    for(int i = 0; i < 100; i++) {
+        t.reset();
+        accel.getOutput(samples[i]);
+        time_stamp[i] = t.read();
+    }
+    for(int i = 0; i < 100; i++) {
+        pc.printf("Sample took %f seconds.\r\n", time_stamp[i]);
+        pc.printf("x: %d, y: %d, z: %d\r\n", samples[i][0],samples[i][1],samples[i][2]);
+    }
+    */
 }
 
 /*
@@ -31,7 +73,7 @@
     Serial pc(USBTX, USBRX);
 
     pc.baud(9600);
-    
+
     HMC5883L compass(i2c_bus);
 
     int data[3];