A test program for the MMA8452 accelerometer

Dependencies:   MMA8452 mbed

The test program runs a bunch of tests for the MMA8452 accelerometer.

What is below is not the test program, but an example to whet your appetite about the library.

#include "mbed.h"
#include "MMA8452.h"

int main() {
   Serial pc(USBTX,USBRX);
   pc.baud(115200);
   double x = 0, y = 0, z = 0;

   MMA8452 acc(p28, p27, 40000);
   acc.setBitDepth(MMA8452::BIT_DEPTH_12);
   acc.setDynamicRange(MMA8452::DYNAMIC_RANGE_4G);
   acc.setDataRate(MMA8452::RATE_100);
   
   while(1) {
      if(!acc.isXYZReady()) {
         wait(0.01);
         continue;
      }
      acc.readXYZGravity(&x,&y,&z);
      pc.printf("Gravities: %lf %lf %lf\r\n",x,y,z);
   }
}

An easy way to test that this actually works is to run the loop above and hold the MMA8452 parallel to the ground along the respective axis (and upsidedown in each axis). You will see 1G on the respective axis and 0G on the others.

Revision:
1:e9981919b524
Parent:
0:0c17274c3b7c
Child:
2:0630128bdb32
--- a/main.cpp	Tue Mar 04 17:51:27 2014 +0000
+++ b/main.cpp	Wed Mar 05 15:04:45 2014 +0000
@@ -21,7 +21,7 @@
    );
 }
 
-void sampleMMA8452(MMA8452 *acc, int nsamples) {
+void sampleMMA8452Raw(MMA8452 *acc, int nsamples) {
    int samples = 0;
    int bufLen = 6;
    char buffer[6];
@@ -32,7 +32,7 @@
          continue;
       }
       memset(&buffer,0x00,bufLen);
-      acc->readRawXYZ(buffer);
+      acc->readXYZRaw(buffer);
       LOGX("Sample %d of %d: ",samples,nsamples);
       for(int i=0; i<bufLen; i++) {
          LOGX("%.2x ",buffer[i]);
@@ -42,6 +42,48 @@
    }
 }
 
+void sampleMMA8452Counts(MMA8452 *acc, int nsamples) {
+   int samples = 0;
+   int bufLen = 6;
+   char buffer[6];
+   int x = 0, y = 0, z = 0;
+   memset(&buffer,0x00,bufLen);
+   while(samples<nsamples) {
+      if(!acc->isXYZReady()) {
+         wait(0.01);
+         continue;
+      }
+      memset(&buffer,0x00,bufLen);
+      if(acc->readXYZCounts(&x,&y,&z)) {
+         LOG("Error reading sample");
+         break;
+      }
+      LOG("Sample %d of %d: %d, %d, %d",samples,nsamples,x,y,z);
+      samples++;
+   }
+}
+
+void sampleMMA8452Gravities(MMA8452 *acc, int nsamples) {
+   int samples = 0;
+   int bufLen = 6;
+   char buffer[6];
+   double x = 0, y = 0, z = 0;
+   memset(&buffer,0x00,bufLen);
+   while(samples<nsamples) {
+      if(!acc->isXYZReady()) {
+         wait(0.01);
+         continue;
+      }
+      memset(&buffer,0x00,bufLen);
+      if(acc->readXYZGravity(&x,&y,&z)) {
+         LOG("Error reading sample");
+         break;
+      }
+      LOG("Sample %d of %d: %lf, %lf, %lf",samples,nsamples,x,y,z);
+      samples++;
+   }
+}
+
 int test() {
     MMA8452 acc(p28, p27, 40000);
     
@@ -61,6 +103,19 @@
        return false;
     }
     
+    char devID = 0;
+    if(acc.getDeviceID(&devID)) {
+       LOG("Error getting device ID");
+       return false;
+    }
+    LOG("DeviceID: 0x%x",devID);
+    if(devID!=0x2a) {
+       LOG("Error, fetched device ID: 0x%x does not match expected 0x2a",devID);
+       return false;
+    } else {
+       LOG("Device ID OK");
+    }
+    
     // test setting dynamic range
     MMA8452::DynamicRange setRange = MMA8452::DYNAMIC_RANGE_UNKNOWN;
     MMA8452::DynamicRange readRange = MMA8452::DYNAMIC_RANGE_UNKNOWN;
@@ -94,13 +149,20 @@
     // set bit depth to 8 and read some values
     LOG("Sampling at BIT_DEPTH_8");
     acc.setBitDepth(MMA8452::BIT_DEPTH_8);
-    sampleMMA8452(&acc,10);
+    sampleMMA8452Raw(&acc,10);
     
     // set bit depth to 12 and read some values
     LOG("Sampling at BIT_DEPTH_12");
     acc.setDataRate(MMA8452::RATE_100);
     acc.setBitDepth(MMA8452::BIT_DEPTH_12);
-    sampleMMA8452(&acc,10);
+    sampleMMA8452Raw(&acc,10);
+   
+    LOG("Sampling counts");
+    acc.setDynamicRange(MMA8452::DYNAMIC_RANGE_2G);
+    sampleMMA8452Counts(&acc,100);
+
+    LOG("Samping gravities");
+    sampleMMA8452Gravities(&acc,100);
 
     return true;
 }
@@ -111,9 +173,120 @@
    }
 }
 
+void u16d(uint16_t n) {
+   int shift = 16;
+   uint16_t mask = 0x8000;
+   while(--shift>=0) {
+      LOGX("%d",(n&mask)>>shift);
+      mask >>= 1;
+   }
+   LOG(" ");
+}
+
+int eightBitToSigned(char *buf) {
+   return (int8_t)*buf;
+}
+
+int twelveBitToSigned(char *buf) {
+   //LOG("Doing twos complement conversion for 0x%x 0x%x",buf[0],buf[1]);
+   
+   // cheat by using the int16_t internal type
+   // all we need to do is convert to little-endian format and shift right
+   int16_t x = 0;
+   ((char*)&x)[1] = buf[0];
+   ((char*)&x)[0] = buf[1];
+   // note this only works because the below is an arithmetic right shift
+   return x>>4; 
+
+   // for reference, here is the full conversion, in case you port this somewhere where the above won't work
+   /*
+   uint16_t number = 0x0000;
+   //u16d(number);
+   int negative = false;
+   
+   // bit depth 12, is spread over two bytes
+   // put it into a uint16_t for easy manipulation
+   number |= (buf[0]<<8);
+   number |= buf[1];
+
+   // if this is a negative number take the twos complement
+   if(number&0x8000) {
+       negative = true;
+       // flip all bits (doesn't matter about lower 4 bits)
+       number ^= 0xFFFF;
+
+       // add 1 (but do so in a way that deals with overflow and respects our current leftwise shift)
+       number += 0x0010;
+   }
+   
+   // shifting down the result by 4 bits gives us the absolute number
+   number >>= 4;
+
+   int result = number;
+   if(negative) {
+      result *= -1;
+   }
+   return result;
+   */
+}
+
+int twosCompTest() {
+    u16d((int16_t)5);
+    u16d((int16_t)-5);
+    // 12 bits of number gives 2048 steps
+    int16_t i = -2047;
+    while(1) {
+       //LOG("number: %d",i);
+       //u16d(number);
+       uint16_t shiftedNumber = i<<4;
+       //LOG("shifted:");
+       //u16d(shiftedNumber);
+       // ARM is little endian whereas 12 bit 2's comp rep is big endian
+       uint16_t flippedNumber = 0x0000;
+       //LOG("switching bytes");
+       //u16d(flippedNumber);
+       ((char*)&flippedNumber)[0] = ((char*)&shiftedNumber)[1];
+       
+       //u16d(flippedNumber);
+       ((char*)&flippedNumber)[1] = ((char*)&shiftedNumber)[0]; 
+       
+       //u16d(flippedNumber);
+       int value = twelveBitToSigned((char*)&flippedNumber);
+       //LOG("%d converts to %d",i,value);
+       if(i!=value) {
+          return false;
+       }
+       if(i==2047) {
+          break;
+       }
+       i++;
+    }
+    
+    int8_t n = -127;
+    while(1) {
+       int value = eightBitToSigned((char*)&n);
+       //LOG("%d converts to %d",n,value);
+       if(n!=value) {
+          return false;
+       }
+       if(n==127) {
+          break;
+       }
+       n++;
+    }
+ 
+    return true;
+}
+
 int main() {
     pc.baud(115200);
     LOG("Begin");
+    if(!twosCompTest()) {
+       LOG("twos comp test failed");
+       loop();
+    }
+    LOG("twos comp test passed");
+    //loop();
     for(int i=0; i<20; i++) {
        LOG(" ");
     }