![](/media/cache/profiles/dfdfab9941ac833a0c364aa2e608185e.50x50_q85.jpg)
A test program for the MMA8452 accelerometer
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.
main.cpp
- Committer:
- ashleymills
- Date:
- 2014-03-05
- Revision:
- 2:0630128bdb32
- Parent:
- 1:e9981919b524
- Child:
- 3:2a8e59a590db
File content as of revision 2:0630128bdb32:
#include "mbed.h" #include "MMA8452.h" DigitalOut myled(LED1); Serial pc(USBTX,USBRX); #define LOG(...) pc.printf(__VA_ARGS__); pc.printf("\r\n"); #define LOGX(...) pc.printf(__VA_ARGS__); void printByte(char b) { LOG("%d%d%d%d%d%d%d%d", (b&0x80)>>7, (b&0x40)>>6, (b&0x20)>>5, (b&0x10)>>4, (b&0x08)>>3, (b&0x04)>>2, (b&0x02)>>1, (b&0x01) ); } void sampleMMA8452Raw(MMA8452 *acc, int nsamples) { int samples = 0; int bufLen = 6; char buffer[6]; memset(&buffer,0x00,bufLen); while(samples<nsamples) { if(!acc->isXYZReady()) { wait(0.01); continue; } memset(&buffer,0x00,bufLen); acc->readXYZRaw(buffer); LOGX("Sample %d of %d: ",samples,nsamples); for(int i=0; i<bufLen; i++) { LOGX("%.2x ",buffer[i]); } LOG(" "); samples++; } } 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); acc.debugRegister(MMA8452_CTRL_REG_1); LOG("Entering standby"); if(acc.standby()) { LOG("Error putting MMA8452 in standby"); return false; } acc.debugRegister(MMA8452_CTRL_REG_1); LOG("Activating MMA8452"); if(acc.activate()) { LOG("Error activating MMA8452"); 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; for(int i=0; i<=(int)MMA8452::DYNAMIC_RANGE_8G; i++) { setRange = (MMA8452::DynamicRange)i; if(acc.setDynamicRange(setRange)) { LOG("Error setting dynamic range. Failing."); return false; } readRange = acc.getDynamicRange(); if(readRange!=setRange) { LOG("Read dynamic range: 0x%x does not match set: 0x%x",readRange,setRange); return false; } LOG("Success on dynamic range %d",i); } // test setting data rate for(int i=0; i<=(int)MMA8452::RATE_1_563; i++) { if(acc.setDataRate((MMA8452::DataRateHz)i)) { LOG("Error setting data rate. Failing."); return false; } if(acc.getDataRate()!=(MMA8452::DataRateHz)i) { LOG("Read data rate: 0x%x does not match set: 0x%x",acc.getDataRate(),(MMA8452::DataRateHz)i); return false; } LOG("Success on data rate %d",i); } // set bit depth to 8 and read some values LOG("Sampling at BIT_DEPTH_8"); acc.setBitDepth(MMA8452::BIT_DEPTH_8); 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); sampleMMA8452Raw(&acc,10); LOG("Sampling counts"); acc.setDynamicRange(MMA8452::DYNAMIC_RANGE_2G); sampleMMA8452Counts(&acc,100); LOG("Samping gravities"); acc.setBitDepth(MMA8452::BIT_DEPTH_8); acc.setDynamicRange(MMA8452::DYNAMIC_RANGE_4G); sampleMMA8452Gravities(&acc,2000); return true; } void loop() { while(1) { wait(1); } } 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(" "); } if(!test()) { LOG("FAIL."); loop(); } LOG("Tests passed"); loop(); }