Ashley Mills
/
MMA8452_Test
A test program for the MMA8452 accelerometer
Embed:
(wiki syntax)
Show/hide line numbers
main.cpp
00001 #include "mbed.h" 00002 #include "MMA8452.h" 00003 00004 DigitalOut myled(LED1); 00005 00006 Serial pc(USBTX,USBRX); 00007 00008 #define LOG(...) pc.printf(__VA_ARGS__); pc.printf("\r\n"); 00009 #define LOGX(...) pc.printf(__VA_ARGS__); 00010 00011 void printByte(char b) { 00012 LOG("%d%d%d%d%d%d%d%d", 00013 (b&0x80)>>7, 00014 (b&0x40)>>6, 00015 (b&0x20)>>5, 00016 (b&0x10)>>4, 00017 (b&0x08)>>3, 00018 (b&0x04)>>2, 00019 (b&0x02)>>1, 00020 (b&0x01) 00021 ); 00022 } 00023 00024 enum SampleType { 00025 SAMPLE_RAW=0, 00026 SAMPLE_COUNT, 00027 SAMPLE_GRAVITY 00028 }; 00029 00030 void sampleTypeToString(SampleType t, char *dst) { 00031 switch(t) { 00032 case SAMPLE_RAW: 00033 sprintf(dst,"SAMPLE_RAW"); 00034 break; 00035 case SAMPLE_COUNT: 00036 sprintf(dst,"SAMPLE_COUNT"); 00037 break; 00038 case SAMPLE_GRAVITY: 00039 sprintf(dst,"SAMPLE_GRAVITY"); 00040 break; 00041 }; 00042 } 00043 00044 int testSampleTaking(MMA8452 *acc, int nsamples, SampleType sampleType) { 00045 int samples = 0; 00046 int bufLen = 6; 00047 00048 // buffers for multi and single raw sampling 00049 char bufferMulti[6]; 00050 char bufferSingle[6]; 00051 memset(&bufferMulti,0x00,bufLen); 00052 memset(&bufferSingle,0x00,bufLen); 00053 00054 // variables for multi and single count sampling 00055 int xCountM = 0, yCountM = 0, zCountM = 0; 00056 int xCountS = 0, yCountS = 0, zCountS = 0; 00057 00058 // variables for multi and single gravity sampling 00059 double xGravityM = 0, yGravityM = 0, zGravityM = 0; 00060 double xGravityS = 0, yGravityS = 0, zGravityS = 0; 00061 00062 // keep track of errors 00063 int error = 0; 00064 // mismatches between multi and single read calls are inevitable 00065 // since the MMA8452 has an internal sampling mechanism which is 00066 // not synchronous to this test routine. At low internal sampling 00067 // rates, these mismatches should be rare, so keep track to 00068 // check that this is sane 00069 int mismatchCount = 0; 00070 00071 // take samples 00072 while(samples<nsamples) { 00073 // wait for device to be ready 00074 if(!acc->isXYZReady()) { 00075 wait(0.01); 00076 continue; 00077 } 00078 00079 switch(sampleType) { 00080 case SAMPLE_RAW: 00081 // read raw data via multi and single calls 00082 memset(&bufferMulti,0x00,bufLen); 00083 memset(&bufferSingle,0x00,bufLen); 00084 error = 0; 00085 error += acc->readXYZRaw((char*)&bufferMulti); 00086 error += acc->readXRaw((char*)&bufferSingle[0]); 00087 error += acc->readYRaw((char*)&bufferSingle[2]); 00088 error += acc->readZRaw((char*)&bufferSingle[4]); 00089 if(error) { 00090 LOG("Error reading raw accelerometer data. Fail."); 00091 return false; 00092 } 00093 // compare multi and single samples for equivalence 00094 // note that this is bound to fail for high data rates 00095 if(acc->getBitDepth()==MMA8452::BIT_DEPTH_12) { 00096 if(memcmp(bufferMulti,bufferSingle,bufLen)) { 00097 LOG("Multi and single sampling mismatch"); 00098 LOG("Multi: %x %x %x %x %x %x", 00099 bufferMulti[0],bufferMulti[1], 00100 bufferMulti[2],bufferMulti[3], 00101 bufferMulti[4],bufferMulti[5] 00102 ); 00103 LOG("Single: %x %x %x %x %x %x", 00104 bufferSingle[0],bufferSingle[1], 00105 bufferSingle[2],bufferSingle[3], 00106 bufferSingle[4],bufferSingle[5] 00107 ); 00108 mismatchCount++; 00109 } 00110 LOG("12bit raw sample %d/%d: %x %x %x %x %x %x", 00111 samples,nsamples, 00112 bufferMulti[0],bufferMulti[1], 00113 bufferMulti[2],bufferMulti[3], 00114 bufferMulti[4],bufferMulti[5] 00115 ); 00116 } else { 00117 if(bufferMulti[0]!=bufferSingle[0]|| 00118 bufferMulti[1]!=bufferSingle[2]|| 00119 bufferMulti[2]!=bufferSingle[4]) { 00120 LOG("Multi and single sampling mismatch"); 00121 mismatchCount++; 00122 } 00123 LOG("8 bit raw sample %d/%d: %x %x %x", 00124 samples,nsamples, 00125 bufferMulti[0],bufferMulti[1],bufferMulti[2] 00126 ); 00127 } 00128 break; 00129 case SAMPLE_COUNT: 00130 error = 0; 00131 error += acc->readXYZCounts(&xCountM,&yCountM,&zCountM); 00132 error += acc->readXCount(&xCountS); 00133 error += acc->readYCount(&yCountS); 00134 error += acc->readZCount(&zCountS); 00135 if(error) { 00136 LOG("Error reading signed counts. Fail."); 00137 break; 00138 } 00139 // check for equivlance (note this fails sometimes but this is expected) 00140 if(xCountS!=xCountM || yCountS!=yCountM || zCountS!=zCountM) { 00141 LOG("Multi and single sampling mismatch"); 00142 mismatchCount++; 00143 } 00144 LOG("Count sample %d/%d: %d %d %d",samples,nsamples,xCountM,yCountM,zCountM); 00145 break; 00146 case SAMPLE_GRAVITY: 00147 error = 0; 00148 error += acc->readXYZGravity(&xGravityM,&yGravityM,&zGravityM); 00149 error += acc->readXGravity(&xGravityS); 00150 error += acc->readYGravity(&yGravityS); 00151 error += acc->readZGravity(&zGravityS); 00152 if(error) { 00153 LOG("Error reading gravities. Fail."); 00154 break; 00155 } 00156 if(xGravityS!=xGravityM || yGravityS!=yGravityM || zGravityS!=zGravityM) { 00157 LOG("Multi and single sampling mismatch"); 00158 mismatchCount++; 00159 } 00160 LOG("Gravity sample %d/%d: %lf %lf %lf",samples,nsamples,xGravityM,yGravityM,zGravityM); 00161 break; 00162 } 00163 samples++; 00164 } 00165 LOG("Mismatches between single and multi-byte reads %d/%d (mismatches are to be expected)",mismatchCount,nsamples); 00166 return true; 00167 } 00168 00169 int sampleMMA8452Raw(MMA8452 *acc, int nsamples) { 00170 int samples = 0; 00171 int bufLen = 6; 00172 char buffer[6]; 00173 memset(&buffer,0x00,bufLen); 00174 while(samples<nsamples) { 00175 if(!acc->isXYZReady()) { 00176 wait(0.01); 00177 continue; 00178 } 00179 memset(&buffer,0x00,bufLen); 00180 acc->readXYZRaw(buffer); 00181 LOGX("Sample %d of %d: ",samples,nsamples); 00182 for(int i=0; i<bufLen; i++) { 00183 LOGX("%.2x ",buffer[i]); 00184 } 00185 LOG(" "); 00186 samples++; 00187 } 00188 return true; 00189 } 00190 00191 int sampleMMA8452Counts(MMA8452 *acc, int nsamples) { 00192 int samples = 0; 00193 int bufLen = 6; 00194 char buffer[6]; 00195 int x = 0, y = 0, z = 0; 00196 memset(&buffer,0x00,bufLen); 00197 while(samples<nsamples) { 00198 if(!acc->isXYZReady()) { 00199 wait(0.01); 00200 continue; 00201 } 00202 memset(&buffer,0x00,bufLen); 00203 if(acc->readXYZCounts(&x,&y,&z)) { 00204 LOG("Error reading sample"); 00205 break; 00206 } 00207 LOG("Sample %d of %d: %d, %d, %d",samples,nsamples,x,y,z); 00208 samples++; 00209 } 00210 return true; 00211 } 00212 00213 int sampleMMA8452Gravities(MMA8452 *acc, int nsamples) { 00214 int samples = 0; 00215 int bufLen = 6; 00216 char buffer[6]; 00217 double x = 0, y = 0, z = 0; 00218 memset(&buffer,0x00,bufLen); 00219 while(samples<nsamples) { 00220 if(!acc->isXYZReady()) { 00221 wait(0.01); 00222 continue; 00223 } 00224 memset(&buffer,0x00,bufLen); 00225 if(acc->readXYZGravity(&x,&y,&z)) { 00226 LOG("Error reading sample"); 00227 break; 00228 } 00229 LOG("Sample %d of %d: %lf, %lf, %lf",samples,nsamples,x,y,z); 00230 samples++; 00231 } 00232 return true; 00233 } 00234 00235 void bitDepthToString(MMA8452::BitDepth d, char *dst) { 00236 switch(d) { 00237 case MMA8452::BIT_DEPTH_12: 00238 sprintf(dst,"BIT_DEPTH_12"); 00239 break; 00240 case MMA8452::BIT_DEPTH_8: 00241 sprintf(dst,"BIT_DEPTH_8"); 00242 break; 00243 } 00244 } 00245 00246 void dynamicRangeToString(MMA8452::DynamicRange r, char *dst) { 00247 switch(r) { 00248 case MMA8452::DYNAMIC_RANGE_2G: 00249 sprintf(dst,"DYNAMIC_RANGE_2G"); 00250 break; 00251 case MMA8452::DYNAMIC_RANGE_4G: 00252 sprintf(dst,"DYNAMIC_RANGE_4G"); 00253 break; 00254 case MMA8452::DYNAMIC_RANGE_8G: 00255 sprintf(dst,"DYNAMIC_RANGE_8G"); 00256 break; 00257 } 00258 } 00259 00260 void dataRateToString(MMA8452::DataRateHz r, char *dst) { 00261 switch(r) { 00262 case MMA8452::RATE_800: 00263 sprintf(dst,"RATE_800"); 00264 break; 00265 case MMA8452::RATE_400: 00266 sprintf(dst,"RATE_400"); 00267 break; 00268 case MMA8452::RATE_200: 00269 sprintf(dst,"RATE_200"); 00270 break; 00271 case MMA8452::RATE_100: 00272 sprintf(dst,"RATE_100"); 00273 break; 00274 case MMA8452::RATE_50: 00275 sprintf(dst,"RATE_50"); 00276 break; 00277 case MMA8452::RATE_12_5: 00278 sprintf(dst,"RATE_12_5"); 00279 break; 00280 case MMA8452::RATE_6_25: 00281 sprintf(dst,"RATE_6_25"); 00282 break; 00283 case MMA8452::RATE_1_563: 00284 sprintf(dst,"RATE_1_563"); 00285 break; 00286 } 00287 } 00288 00289 int test() { 00290 MMA8452 acc(p28, p27, 40000); 00291 00292 acc.debugRegister(MMA8452_CTRL_REG_1); 00293 00294 LOG("Entering standby"); 00295 if(acc.standby()) { 00296 LOG("Error putting MMA8452 in standby"); 00297 return false; 00298 } 00299 00300 acc.debugRegister(MMA8452_CTRL_REG_1); 00301 00302 LOG("Activating MMA8452"); 00303 if(acc.activate()) { 00304 LOG("Error activating MMA8452"); 00305 return false; 00306 } 00307 00308 char devID = 0; 00309 if(acc.getDeviceID(&devID)) { 00310 LOG("Error getting device ID"); 00311 return false; 00312 } 00313 LOG("DeviceID: 0x%x",devID); 00314 if(devID!=0x2a) { 00315 LOG("Error, fetched device ID: 0x%x does not match expected 0x2a",devID); 00316 return false; 00317 } else { 00318 LOG("Device ID OK"); 00319 } 00320 00321 // test setting dynamic range 00322 MMA8452::DynamicRange setRange = MMA8452::DYNAMIC_RANGE_UNKNOWN; 00323 MMA8452::DynamicRange readRange = MMA8452::DYNAMIC_RANGE_UNKNOWN; 00324 for(int i=0; i<=(int)MMA8452::DYNAMIC_RANGE_8G; i++) { 00325 setRange = (MMA8452::DynamicRange)i; 00326 if(acc.setDynamicRange(setRange)) { 00327 LOG("Error setting dynamic range. Failing."); 00328 return false; 00329 } 00330 readRange = acc.getDynamicRange(); 00331 if(readRange!=setRange) { 00332 LOG("Read dynamic range: 0x%x does not match set: 0x%x",readRange,setRange); 00333 return false; 00334 } 00335 LOG("Success on dynamic range %d",i); 00336 } 00337 00338 // test setting data rate 00339 for(int i=0; i<=(int)MMA8452::RATE_1_563; i++) { 00340 if(acc.setDataRate((MMA8452::DataRateHz)i)) { 00341 LOG("Error setting data rate. Failing."); 00342 return false; 00343 } 00344 if(acc.getDataRate()!=(MMA8452::DataRateHz)i) { 00345 LOG("Read data rate: 0x%x does not match set: 0x%x",acc.getDataRate(),(MMA8452::DataRateHz)i); 00346 return false; 00347 } 00348 LOG("Success on data rate %d",i); 00349 } 00350 00351 char depthString[32], rangeString[32], rateString[32], sampleTypeString[32]; 00352 // draw some samples at each bit depth, rate, and dynamic range 00353 for(int depth=0; depth<=(int)MMA8452::BIT_DEPTH_8; depth++) { 00354 bitDepthToString((MMA8452::BitDepth)depth,(char*)&depthString); 00355 LOG("Setting bit depth to %s",depthString); 00356 if(acc.setBitDepth((MMA8452::BitDepth)depth)) { 00357 LOG("Error setting bit depth to %s. Fail.",depthString); 00358 return false; 00359 } 00360 for(int range=0; range<=(int)MMA8452::DYNAMIC_RANGE_8G; range++) { 00361 dynamicRangeToString((MMA8452::DynamicRange)range,(char*)&rangeString); 00362 LOG("Setting dynamic range to %s",rangeString); 00363 if(acc.setDynamicRange((MMA8452::DynamicRange)range)) { 00364 LOG("Error setting dynamic range to %s. Fail.",rangeString); 00365 return false; 00366 } 00367 for(int rate=0; rate<=(int)MMA8452::RATE_1_563; rate++) { 00368 dataRateToString((MMA8452::DataRateHz)rate,(char*)&rateString); 00369 LOG("Setting data rate to %s",rateString); 00370 if(acc.setDataRate((MMA8452::DataRateHz)rate)) { 00371 LOG("Error setting data rate to %s",rateString); 00372 return false; 00373 } 00374 // take samples 00375 for(int sampleType=0; sampleType<=(int)SAMPLE_GRAVITY; sampleType++) { 00376 sampleTypeToString((SampleType)sampleType,sampleTypeString); 00377 LOG("Setting sample type to %s",sampleTypeString); 00378 if(testSampleTaking(&acc, 10, (SampleType)sampleType)!=true) { 00379 LOG("Sample taking failed for %s, %s, %s, %s",sampleTypeString,depthString,rangeString,rateString); 00380 return false; 00381 } 00382 } 00383 } 00384 } 00385 } 00386 00387 LOG("Samping gravities for interactive examination"); 00388 if(acc.setBitDepth(MMA8452::BIT_DEPTH_8)) { 00389 LOG("Error setting bit depth. Fail."); 00390 return false; 00391 } 00392 if(acc.setDynamicRange(MMA8452::DYNAMIC_RANGE_4G)) { 00393 LOG("Error setting dynamic range. Fail."); 00394 return false; 00395 } 00396 if(acc.setDataRate(MMA8452::RATE_100)) { 00397 LOG("Error setting data rate. Fail"); 00398 return false; 00399 } 00400 if(sampleMMA8452Gravities(&acc,1000)!=true) { 00401 LOG("Sampling gravities failed"); 00402 return false; 00403 } 00404 00405 return true; 00406 } 00407 00408 void loop() { 00409 while(1) { 00410 wait(1); 00411 } 00412 } 00413 00414 void u16d(uint16_t n) { 00415 int shift = 16; 00416 uint16_t mask = 0x8000; 00417 while(--shift>=0) { 00418 LOGX("%d",(n&mask)>>shift); 00419 mask >>= 1; 00420 } 00421 LOG(" "); 00422 } 00423 00424 int eightBitToSigned(char *buf) { 00425 return (int8_t)*buf; 00426 } 00427 00428 int twelveBitToSigned(char *buf) { 00429 //LOG("Doing twos complement conversion for 0x%x 0x%x",buf[0],buf[1]); 00430 00431 // cheat by using the int16_t internal type 00432 // all we need to do is convert to little-endian format and shift right 00433 int16_t x = 0; 00434 ((char*)&x)[1] = buf[0]; 00435 ((char*)&x)[0] = buf[1]; 00436 // note this only works because the below is an arithmetic right shift 00437 return x>>4; 00438 00439 // for reference, here is the full conversion, in case you port this somewhere where the above won't work 00440 /* 00441 uint16_t number = 0x0000; 00442 //u16d(number); 00443 int negative = false; 00444 00445 // bit depth 12, is spread over two bytes 00446 // put it into a uint16_t for easy manipulation 00447 number |= (buf[0]<<8); 00448 number |= buf[1]; 00449 00450 // if this is a negative number take the twos complement 00451 if(number&0x8000) { 00452 negative = true; 00453 // flip all bits (doesn't matter about lower 4 bits) 00454 number ^= 0xFFFF; 00455 00456 // add 1 (but do so in a way that deals with overflow and respects our current leftwise shift) 00457 number += 0x0010; 00458 } 00459 00460 // shifting down the result by 4 bits gives us the absolute number 00461 number >>= 4; 00462 00463 int result = number; 00464 if(negative) { 00465 result *= -1; 00466 } 00467 return result; 00468 */ 00469 } 00470 00471 int twosCompTest() { 00472 // 12 bits of number gives 2048 steps 00473 int16_t i = -2047; 00474 while(1) { 00475 //LOG("number: %d",i); 00476 //u16d(number); 00477 uint16_t shiftedNumber = i<<4; 00478 //LOG("shifted:"); 00479 //u16d(shiftedNumber); 00480 // ARM is little endian whereas 12 bit 2's comp rep is big endian 00481 uint16_t flippedNumber = 0x0000; 00482 //LOG("switching bytes"); 00483 //u16d(flippedNumber); 00484 ((char*)&flippedNumber)[0] = ((char*)&shiftedNumber)[1]; 00485 00486 //u16d(flippedNumber); 00487 ((char*)&flippedNumber)[1] = ((char*)&shiftedNumber)[0]; 00488 00489 //u16d(flippedNumber); 00490 int value = twelveBitToSigned((char*)&flippedNumber); 00491 //LOG("%d converts to %d",i,value); 00492 if(i!=value) { 00493 return false; 00494 } 00495 if(i==2047) { 00496 break; 00497 } 00498 i++; 00499 } 00500 00501 int8_t n = -127; 00502 while(1) { 00503 int value = eightBitToSigned((char*)&n); 00504 //LOG("%d converts to %d",n,value); 00505 if(n!=value) { 00506 return false; 00507 } 00508 if(n==127) { 00509 break; 00510 } 00511 n++; 00512 } 00513 00514 return true; 00515 } 00516 00517 int main() { 00518 pc.baud(115200); 00519 LOG("Begin"); 00520 LOG("Executing twos complement test"); 00521 if(!twosCompTest()) { 00522 LOG("Twos complement test failed"); 00523 loop(); 00524 } 00525 LOG("Twos complement test passed"); 00526 00527 LOG("Executing MMA8452 tests"); 00528 if(!test()) { 00529 LOG("MMA8452 test failed."); 00530 loop(); 00531 } 00532 LOG("MMA8452 test passed"); 00533 LOG("All tests passed"); 00534 loop(); 00535 }
Generated on Fri Jul 22 2022 21:38:47 by 1.7.2