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:
Thu Nov 01 18:46:58 2012 +0000
Parent:
1:dc730a26cdc2
Child:
3:5e21a352e236
Commit message:
ADXL345 unit test initial commit, built in self test (not tested)

Changed in this revision

ADXL345.lib Show annotated file Show diff for this revision Revisions of this file
HMC5883L.lib Show annotated file Show diff for this revision Revisions of this file
ITG3200.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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ADXL345.lib	Thu Nov 01 18:46:58 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/tylerjw/code/ADXL345/#839128c6e20a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HMC5883L.lib	Thu Nov 01 18:46:58 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/tylerjw/code/HMC5883L/#8eb755577f83
--- a/ITG3200.lib	Tue Oct 30 23:47:14 2012 +0000
+++ b/ITG3200.lib	Thu Nov 01 18:46:58 2012 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/tylerjw/code/ITG3200/#33a9ed8e8988
+http://mbed.org/users/tylerjw/code/ITG3200/#9a354f34d8e3
--- /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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/adxl345unit.h	Thu Nov 01 18:46:58 2012 +0000
@@ -0,0 +1,71 @@
+/*
+ * @file adxl345unit.h
+ * @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: 
+ */
+
+#ifndef ADXL345UNIT_H
+#define ADXL345UNIT_H
+
+#include "mbed.h"
+#include "ADXL345.h"
+
+class ADXL345UNIT {
+    public:
+        /**
+        * Constructor
+        * runs init()
+        *
+        * @param i2c buss to use for adxl345
+        */
+        ADXL345UNIT(I2C &i2c);
+        
+        /**
+        * Initalize the device
+        */
+        void init();
+        
+        /**
+        * Perform built in self test and print results to ADXL_BIT.csv
+        *
+        * @returns true if passed, false if failed
+        */
+        bool builtInSelfTest();
+    private:
+        ADXL345 adxl345_;
+        Serial pc_;
+        LocalFileSystem local_;
+        DigitalOut open_file_;
+        
+        /**
+        * Averages an array of n length
+        *
+        * @param the array
+        * @param length
+        */
+        int arr_avg(int*,int);
+};
+
+#endif
\ No newline at end of file
--- a/main.cpp	Tue Oct 30 23:47:14 2012 +0000
+++ b/main.cpp	Thu Nov 01 18:46:58 2012 +0000
@@ -1,5 +1,5 @@
 /**
- 10 second 9-dof data log
+ 9-dof unit testing
 
  The purpose of this program is to demonstrate and calibrate the three
  sensors on teh 9-doft board.
@@ -10,147 +10,39 @@
  See: http://mbed.org/users/gltest26/code/ITG3200/wiki/Thermal-Drift
 
  The second versoin of this will test the HMC5883L 3 axis magnometer
+
+ The thrid version tests the ADXL345 library.
 */
 
 #include "mbed.h"
 //#include "ITG3200.h"
-
-// configuration register a
-#define AVG1_SAMPLES    0x00
-#define AVG2_SAMPLES    0x20
-#define AVG4_SAMPLES    0x80
-#define AVG8_SAMPLES    0xC0
-
-#define OUTPUT_RATE_0_75    0x00
-#define OUTPUT_RATE_1_5     0x04
-#define OUTPUT_RATE_3       0x08
-#define OUTPUT_RATE_7_5     0x0C
-#define OUTPUT_RATE_15      0x10
-#define OUTPUT_RATE_30      0x14
-#define OUTPUT_RATE_75      0x18
-
-#define NORMAL_MEASUREMENT  0x00
-#define POSITIVE_BIAS       0x01
-#define NEGATIVE_BIAS       0x02
-
-// mode register
-#define CONTINUOUS_MODE     0x00
-#define SINGLE_MODE         0x01
-#define IDLE_MODE           0x02
-
-// status register 
-#define LOCK        0x02
-#define READY       0x01
-
-char addr = 0x3D;
-
-I2C i2c_(p28, p27); // sda, scl
-
-void setConfigurationA(char,char,char);
-char getConfigurationA();
-void setConfigurationB(char);
-char getConfigurationB();
-void setMode(char);
-char getMode();
-void getXYZ(int*);
-char getStatus();
-
-void setConfigurationA(char averaged_samples = AVG1_SAMPLES, char output_rate = OUTPUT_RATE_15, char measurement_mode = NORMAL_MEASUREMENT)
-{
-    char cmd[2];
-    cmd[0] = 0x00; // register a address
-    cmd[1] = averaged_samples | output_rate | measurement_mode;
-    
-    i2c_.write(addr, cmd, 2);
-}
+//#include "HMC5883L.h"
 
-char getConfigurationA()
-{
-    char cmd[2];
-    cmd[0] = 0x00; // register a address
-    i2c_.write(addr, cmd, 1, true);
-    i2c_.read(addr, &cmd[1], 1, false);
-    return cmd[1];
-}
-
-void setConfigurationB(char gain = 0x20) // default value 0x20
-{
-    char cmd[2];
-    cmd[0] = 0x01;
-    cmd[1] = gain;
-    
-    i2c_.write(addr, cmd, 2);
-}
-
-char getConfigurationB()
-{
-    char cmd[2];
-    cmd[0] = 0x01; // register b address
-    i2c_.write(addr, cmd, 1, true);
-    i2c_.read(addr, &cmd[1], 1, false);
-    return cmd[1];
-}
-
-void setMode(char mode = SINGLE_MODE)
-{
-    char cmd[2];
-    cmd[0] = 0x02; // mode register address
-    cmd[1] = mode;
-    i2c_.write(addr,cmd,2);
-}
-
-char getMode()
-{
-    char cmd[2];
-    cmd[0] = 0x02; // mode register address
-    i2c_.write(addr, cmd, 1, true);
-    i2c_.read(addr, &cmd[1], 1, false);
-    return cmd[1];
-}
-
-void getXYZ(int output[3])
-{
-    char cmd[2];
-    char data[6];
-    cmd[0] = 0x03; // starting point for reading
-    i2c_.write(addr, cmd, 1, true); // set the pointer to the start of x
-    i2c_.read(addr, data, 6, false);
-    
-    for(int i = 0; i < 3; i++) // fill the output variables
-        output[i] = (data[i*2] << 8) + data[i*2+1];
-}
-
-char getStatus()
-{
-    char cmd[2];
-    cmd[0] = 0x09; // status register address
-    i2c_.write(addr, cmd, 1, true);
-    i2c_.read(addr, &cmd[1], 1, false);
-    return cmd[1];
-}
+I2C i2c_bus(p28, p27);
 
 int main()
 {
+
+}
+
+/*
+void hmc5883l_test()
+{
     Serial pc(USBTX, USBRX);
-    
+
     pc.baud(9600);
     
+    HMC5883L compass(i2c_bus);
+
     int data[3];
-    
-    // configure
-    setConfigurationA(AVG8_SAMPLES); // 8 sample average, 15Hz, normal mode
-    setConfigurationB(); // default (0x20)
-    setMode(CONTINUOUS_MODE); // continuous sample mode
-    wait(0.006); // 6 milisecond pause to allow registers to fill up
-    
-    while(1)
-    {
-        getXYZ(data);
-        pc.printf("x: 0x%4x, y: 0x%4x, z: 0x%4x\r\n", data[0], data[1], data[2]);
+
+    while(1) {
+        compass.getXYZ(data);
+        pc.printf("x: %4d, y: %4d, z: %4d\r\n", data[0], data[1], data[2]);
         wait(0.067);
     }
 }
-
+*/
 /*
 void itg3200_test()
 {