Offset calibration program for an SPI ADXL345. Tested with mbed LPC1768.

Dependencies:   ADXL345 mbed

Fork of Accelerometer_ADXL345 by Thomas Emil

This is a program for offset calibration of ADXL345, it will also compute a fine offset correction number which cannot be corrected on ADXL345 itself. The IMU will need to be re-oriented 6x2 times for the calibration first 6 times for the coarse calibration, during which offsets on the ADXL will be calibrated and the next 6 will compute the fine offsets...

Files at this revision

API Documentation at this revision

Comitter:
akashvibhute
Date:
Mon Nov 03 06:57:18 2014 +0000
Parent:
0:6b905abf1374
Commit message:
First commit, working program

Changed in this revision

TextLCD.lib 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 6b905abf1374 -r a1d998b362e9 TextLCD.lib
--- a/TextLCD.lib	Mon Mar 31 19:09:14 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://mbed.org/users/wim/code/TextLCD/#e0da005a777f
diff -r 6b905abf1374 -r a1d998b362e9 main.cpp
--- a/main.cpp	Mon Mar 31 19:09:14 2014 +0000
+++ b/main.cpp	Mon Nov 03 06:57:18 2014 +0000
@@ -1,24 +1,38 @@
 #include "mbed.h"
 #include "ADXL345.h"
-#include "TextLCD.h"
 
 ADXL345 accelerometer(p5, p6, p7, p8); // (SDA, SDO, SCL, CS);
 Serial pc(USBTX, USBRX); //For raw data
-TextLCD lcd(p15, p16, p17, p18, p19, p20, TextLCD::LCD16x2); // rs, e, d4-d7
+
+int readings[3] = {0, 0, 0};
+float mag_lsb;
+
+float x,y,z,mag_g;
+float acc_readings[6][3];
+float calc_offsets[3];
+const float g=9.80665;
+const float g_mm=g*1000;
+const float acc_res_mg=3.9063; //acc resolution mg/LSB
 
-float x,y,z;
+int8_t offset2_8bit_int[3]={0,0,0};
+char offset2_8bit_char[3];
+
+float mg_offsets[3]={0.0,0.0,0.0}; //fine offsets in mg's which cannot be corrected by adxl
+
+void acc_read();
+void display_acc();
+void acc_store_offsets();   
+int sign(float input); 
+void display_fine_acc();
 
 
 int main()
 {
-
-    int readings[3] = {0, 0, 0};
-
-    lcd.cls();
-    lcd.printf("Starting ADXL345 test...\n");
-    lcd.printf("Device ID is: 0x%02x\n", accelerometer.getDevId());
-        pc.printf("Starting ADXL345 test...\n");
-        pc.printf("Device ID is: 0x%02x\n", accelerometer.getDevId());
+    pc.baud(921600); //set baud rate for USB serial to 921600bps
+    
+    pc.printf("Starting ADXL345 test...\n");
+    pc.printf("Device ID is: 0x%02x\n", accelerometer.getDevId());
+        
 
     //Go into standby mode to configure the device.
     accelerometer.setPowerControl(0x00);
@@ -29,28 +43,298 @@
     //3.2kHz data rate.
     accelerometer.setDataRate(ADXL345_3200HZ);
 
+    pc.printf("Axes offsets: ");
+    pc.printf("X: %d \t",accelerometer.getOffset(0x00));
+    pc.printf("Y: %d \t",accelerometer.getOffset(0x01));
+    pc.printf("Z: %d \n",accelerometer.getOffset(0x02));
+
     //Measurement mode.
     accelerometer.setPowerControl(0x08);
-
-    while (1) {
+    
+    pc.printf("Current IMU reading: \n");
+    acc_read();
+    display_acc();
+    
+    pc.printf("\nTo Calculate new offsets IMU needs to be re-oriented 12 times,\n Send 'R' when ready...\n\n");
+    while(pc.getc() != 'R') {}
+    
+    pc.printf("Resetting current offsets... \n");
+    acc_store_offsets();
+    
+    {
+        pc.printf("Okay, ready for first coarse reading set,\n Put IMU with +Z pointing up, then press 'R' when ready \n");
+        while(pc.getc() != 'R') {}
+        wait(0.1);
+        for(int n=0; n<10; n++)
+        {
+        wait(0.1); 
+        acc_read();
+        acc_readings[4][0]+=x;
+        acc_readings[4][1]+=y;
+        acc_readings[4][2]+=z;
+        }  
+        //display_acc();
+        pc.printf("\n");
+    
+        pc.printf("Put IMU with -Z pointing up, then press 'R' when ready \n");
+        while(pc.getc() != 'R') {}
+        wait(0.1); 
+        for(int n=0; n<10; n++)
+        {
+        wait(0.1);
+        acc_read();
+        acc_readings[5][0]+=x;
+        acc_readings[5][1]+=y;
+        acc_readings[5][2]+=z;
+        }
+        //display_acc();
+        pc.printf("\n");
+    
+        
+        pc.printf("Put IMU with +Y pointing up, then press 'R' when ready \n");
+        while(pc.getc() != 'R') {}
+        wait(0.1); 
+        for(int n=0; n<10; n++)
+        {
+        wait(0.1);
+        acc_read();
+        acc_readings[2][0]+=x;
+        acc_readings[2][1]+=y;
+        acc_readings[2][2]+=z;
+        }
+        //display_acc();
+        pc.printf("\n");
+        
+        pc.printf("Put IMU with -Y pointing up, then press 'R' when ready \n");
+        while(pc.getc() != 'R') {}
+        wait(0.1); 
+        for(int n=0; n<10; n++)
+        {
+        wait(0.1);
+        acc_read();
+        acc_readings[3][0]+=x;
+        acc_readings[3][1]+=y;
+        acc_readings[3][2]+=z;
+        }
+        //display_acc();
+        pc.printf("\n");
+        
+        pc.printf("Put IMU with +X pointing up, then press 'R' when ready \n");
+        while(pc.getc() != 'R') {}
+        wait(0.1); 
+        for(int n=0; n<10; n++)
+        {
+        wait(0.1);
+        acc_read();
+        acc_readings[0][0]+=x;
+        acc_readings[0][1]+=y;
+        acc_readings[0][2]+=z;
+        }
+        //display_acc();
+        pc.printf("\n");
+        
+        pc.printf("Put IMU with -X pointing up, then press 'R' when ready \n");
+        while(pc.getc() != 'R') {}
+        wait(0.1); 
+        for(int n=0; n<10; n++)
+        {
+        wait(0.1);
+        acc_read();
+        acc_readings[1][0]+=x;
+        acc_readings[1][1]+=y;
+        acc_readings[1][2]+=z;
+        }
+        //display_acc();
+        pc.printf("\n");
+    }
+    
+     calc_offsets[0] = (acc_readings[0][0] - acc_readings[1][0])/(10*2*acc_res_mg) - 256;
+     calc_offsets[1] = (acc_readings[2][1] - acc_readings[3][1])/(10*2*acc_res_mg) - 256;
+     calc_offsets[2] = (acc_readings[4][2] - acc_readings[5][2])/(10*2*acc_res_mg) - 256;
+     
+    calc_offsets[0] = calc_offsets[0]/4; //convert to 8 bit scale 15.6 mg/LSB
+    calc_offsets[1] = calc_offsets[1]/4; //convert to 8 bit scale 15.6 mg/LSB
+    calc_offsets[2] = calc_offsets[2]/4; //convert to 8 bit scale 15.6 mg/LSB
+    
+    pc.printf("Coarse calibration complete, offsets in 8bit scale (15.6mg/LSB) are: \t");
+    pc.printf("X: %.1f, Y: %.1f, Z: %.1f", calc_offsets[0], calc_offsets[1], calc_offsets[2]);
 
-        wait(0.1); //Intaval
-
-        accelerometer.getOutput(readings);
 
-        x=(int16_t)readings[0];
-        x=x*4e-3;
-        y=(int16_t)readings[1];
-        y=y*4e-3;
-        z=(int16_t)readings[2];
-        z=z*4e-3;
+    pc.printf("\n Apply offsets to ADXL345? Press Y to continue... \n");
+    while(pc.getc() != 'Y') {}
+    acc_store_offsets();    
+    pc.printf("\n Done! ADXL 345 is now calibrated!!!\n\n New offsets are: \n");
+        pc.printf("X: %d \t",accelerometer.getOffset(0x00));
+        pc.printf("Y: %d \t",accelerometer.getOffset(0x01));
+        pc.printf("Z: %d \n",accelerometer.getOffset(0x02));
+    pc.printf("\n");
+    wait(1);
+    
+    
+    {
+        float mg_offsets_x[2]={0,0};
+        float mg_offsets_y[2]={0,0};
+        float mg_offsets_z[2]={0,0};
+        
+        pc.printf("Ready for fine reading set,\n Put IMU with +Z pointing up, then press 'R' when ready \n");
+        while(pc.getc() != 'R') {}
+        wait(0.1);
+        for(int n=0; n<10; n++)
+        {
+        wait(0.1); 
+        acc_read();
+        mg_offsets_z[0]+=z;
+        }
+        pc.printf("\n");
+        
+        pc.printf("Put IMU with -Z pointing up, then press 'R' when ready \n");
+        while(pc.getc() != 'R') {}
+        wait(0.1); 
+        for(int n=0; n<10; n++)
+        {
+        wait(0.1); 
+        acc_read();
+        mg_offsets_z[1]+=z;
+        }
+        pc.printf("\n");
+        
+        pc.printf("Put IMU with +Y pointing up, then press 'R' when ready \n");
+        while(pc.getc() != 'R') {}
+        wait(0.1); 
+        for(int n=0; n<10; n++)
+        {
+        wait(0.1); 
+        acc_read();
+        mg_offsets_y[0]+=y;
+        }
+        pc.printf("\n");
+        
+        pc.printf("Put IMU with -Y pointing up, then press 'R' when ready \n");
+        while(pc.getc() != 'R') {}
+        wait(0.1); 
+        for(int n=0; n<10; n++)
+        {
+        wait(0.1); 
+        acc_read();
+        mg_offsets_y[1]+=y;
+        }
+        pc.printf("\n");
+        
+        pc.printf("Put IMU with +X pointing up, then press 'R' when ready \n");
+        while(pc.getc() != 'R') {}
+        wait(0.1); 
+        for(int n=0; n<10; n++)
+        {
+        wait(0.1); 
+        acc_read();
+        mg_offsets_x[0]+=x;
+        }
+        pc.printf("\n");
+        
+        pc.printf("Put IMU with -X pointing up, then press 'R' when ready \n");
+        while(pc.getc() != 'R') {}
+        wait(0.1); 
+        for(int n=0; n<10; n++)
+        {
+        wait(0.1); 
+        acc_read();
+        mg_offsets_x[1]+=x;
+        }
+        pc.printf("\n");
+        
+        mg_offsets[0] = ((mg_offsets_x[0]/10 - 1000) + (1000 + mg_offsets_x[1]/10))/2;
+        mg_offsets[1] = ((mg_offsets_y[0]/10 - 1000) + (1000 + mg_offsets_y[1]/10))/2;
+        mg_offsets[2] = ((mg_offsets_z[0]/10 - 1000) + (1000 + mg_offsets_z[1]/10))/2;
+            
+        pc.printf("Fine calibration complete, offsets in mg are: \t");
+            pc.printf("X: %f \t",mg_offsets[0]);
+            pc.printf("Y: %f \t",mg_offsets[1]);
+            pc.printf("Z: %f \n",mg_offsets[2]);
+    }
+    
+    wait(5);
+    
+    while(1)
+    {
+        wait(0.25);
+        pc.printf("\nCurrent IMU reading:\n");
+        acc_read();
+        display_fine_acc();
+    }
+}
 
-        //13-bit, sign extended values.
-        lcd.cls();
-        lcd.printf("%.1f, %.1f, %.1f\n", x,y,z); //Convertet to G
-        lcd.printf(" X    Y    Z  ");
-            pc.printf("%i, %i, %i\n\r", (int16_t)readings[0], (int16_t)readings[1], (int16_t)readings[2]); //Raw data
+void acc_read()
+{
+    accelerometer.getOutput(readings);
+
+    x=(int16_t)readings[0] * acc_res_mg;
+    y=(int16_t)readings[1] * acc_res_mg;
+    z=(int16_t)readings[2] * acc_res_mg;
+        
+    mag_g = sqrt(pow(x,2)+pow(y,2)+pow(z,2));
+    mag_lsb = mag_g/acc_res_mg;
+}
+
+void display_acc()
+{
+    pc.printf("Raw: %i, %i, %i : %.1f\n", (int16_t)readings[0], (int16_t)readings[1], (int16_t)readings[2], mag_lsb); //Raw data
+    pc.printf("mG's: %.3f, %.3f, %.3f : %.4f\n", x, y, z, mag_g); //In G's data
+}
+
+void display_fine_acc()
+{
+    x -= mg_offsets[0];
+    y -= mg_offsets[1];
+    z -= mg_offsets[2];
+    
+    readings[0] -= (int16_t) (mg_offsets[0]/acc_res_mg);
+    readings[1] -= (int16_t) (mg_offsets[1]/acc_res_mg);
+    readings[2] -= (int16_t) (mg_offsets[2]/acc_res_mg);
+    
+    mag_g = sqrt(pow(x,2)+pow(y,2)+pow(z,2));
+    mag_lsb = mag_g/acc_res_mg;
+    
+    pc.printf("Raw: %i, %i, %i : %.1f\n", (int16_t)readings[0], (int16_t)readings[1], (int16_t)readings[2], mag_lsb); //Raw data
+    pc.printf("mG's: %.3f, %.3f, %.3f : %.4f\n", x, y, z, mag_g); //In G's data
+    pc.printf("Fine offset in mG's: %.3f, %.3f, %.3f\n", mg_offsets[0], mg_offsets[1], mg_offsets[2]); //In G's data
+}
 
+void acc_store_offsets()
+{
+    for(int v=0; v<=2; v++)
+    {
+        offset2_8bit_int[v] = (int8_t) calc_offsets[v];
+        if(abs(calc_offsets[v] - offset2_8bit_int[v]) >= 0.5)
+            offset2_8bit_int[v] += (int8_t) sign(calc_offsets[v]);
+        
+        offset2_8bit_int[v] = ~offset2_8bit_int[v];
+        offset2_8bit_int[v] += 1;
+        
+        offset2_8bit_char[v] = offset2_8bit_int[v];
     }
+    
+        //Go into standby mode to configure the device.
+        accelerometer.setPowerControl(0x00);
+    
+        accelerometer.setOffset(0x00, offset2_8bit_char[0]);
+        wait(0.1); //wait a bit
+        
+        accelerometer.setOffset(0x01, offset2_8bit_char[1]);
+        wait(0.1); //wait a bit
+        
+        accelerometer.setOffset(0x02, offset2_8bit_char[2]);
+        wait(0.1); //wait a bit
+        
+        //Measurement mode.
+        accelerometer.setPowerControl(0x08);
+}
 
-}
\ No newline at end of file
+int sign(float input)
+{
+    if (input<0)
+        return -1;
+    else if(input>0)
+        return 1;
+    else
+        return 0;
+}