Unit testing and development for 9DOF sparkfun sensor stick

Dependencies:   ADXL345 HMC5883L ITG3200 mbed

Revision:
2:d7e66940541d
Child:
3:5e21a352e236
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/adxl345unit.cpp	Thu Nov 01 18:46:58 2012 +0000
@@ -0,0 +1,142 @@
+/*
+ * @file adxl345unit.cpp
+ * @author Tyler Weaver
+ *
+ * @section LICENSE
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * @section DESCRIPTION
+ *
+ * Unit test for the ADXL345 library.
+ *
+ * Reference:
+ */
+
+#include "adxl345unit.h"
+
+ADXL345UNIT::ADXL345UNIT(I2C &i2c) : adxl345_(i2c), pc_(USBTX, USBRX), local_("local"), open_file_(LED1)
+{
+    pc_.baud(9600);
+    open_file_ = 0;
+    init();
+}
+
+void ADXL345UNIT::init()
+{
+    // place initilazaition code here
+}
+
+bool ADXL345UNIT::builtInSelfTest()
+{
+    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
+
+    const char axisK[3] = {'X','Y','Z'};
+    const int 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}};
+
+    Timer t; // for timming sample readings
+    float start_time, elapsed_time;
+    float period = 0.001; // period of sample rate
+
+    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);
+        //initial command sequence
+        adxl345_.setDataFormatControl(data_formatK[res]); // 16g, 13bit mode
+        adxl345_.setDataRate(ADXL345_100HZ); // 100Hz data rate
+        adxl345_.setPowerMode(0); // high power
+        adxl345_.setPowerControl(0x08); // start measurement
+        adxl345_.setInterruptEnableControl(0x80); // enable data_ready interupt (not needed?)
+        //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_off[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_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
+        //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]);
+        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]);
+            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");
+        }
+        fprintf(fp, "Test Result: %s\r\n\r\n", (test_pass[res])?"pass":"fail");
+        // close file
+        fclose(fp);
+        open_file_ = 0;
+        pc_.printf("%s\r\n", (test_pass[res])?"pass":"fail");
+    }
+    //return result
+    return full_test;
+}
+
+int ADXL345UNIT::arr_avg(int* arr,int 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);
+}
\ No newline at end of file