Republished Library, to be refined for use with the SparkFun 9DOF in HARP project.
Fork of ADXL345 by
Diff: ADXL345.cpp
- Revision:
- 11:c0fe48a352ca
- Parent:
- 10:d81793e01ec4
--- a/ADXL345.cpp Tue Nov 06 17:36:40 2012 +0000 +++ b/ADXL345.cpp Wed Jan 16 11:10:19 2013 +0000 @@ -1,25 +1,9 @@ /** - * @file ADXL345.cpp - * @author Tyler Weaver - * @author Peter Swanson - * A personal note from me: Jesus Christ has changed my life so much it blows my mind. I say this because - * today, religion is thought of as something that you do or believe and has about as - * little impact on a person as their political stance. But for me, God gives me daily - * strength and has filled my life with the satisfaction that I could never find in any - * of the other things that I once looked for it in. - * If your interested, heres verse that changed my life: - * Rom 8:1-3: "Therefore, there is now no condemnation for those who are in Christ Jesus, - * because through Christ Jesus, the law of the Spirit who gives life has set - * me free from the law of sin (which brings...) and death. For what the law - * was powerless to do in that it was weakened by the flesh, God did by sending - * His own Son in the likeness of sinful flesh to be a sin offering. And so He - * condemned sin in the flesh in order that the righteous requirements of the - * (God's) law might be fully met in us, who live not according to the flesh - * but according to the Spirit." + * @author Aaron Berk + * + * @section LICENSE * - * A special thanks to Ewout van Bekkum for all his patient help in developing this library! - * - * @section LICENSE + * Copyright (c) 2010 ARM Limited * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -41,166 +25,54 @@ * * @section DESCRIPTION * - * ADXL345, triple axis, I2C interface, accelerometer. + * ADXL345, triple axis, digital interface, accelerometer. * * Datasheet: * * http://www.analog.com/static/imported-files/data_sheets/ADXL345.pdf - */ - -/* + */ + +/** * Includes */ #include "ADXL345.h" -//#include "mbed.h" - -ADXL345::ADXL345(PinName sda, PinName scl) : i2c_(*(new I2C(sda, scl))) -{ - myI2c = &i2c_; - init(); -} - -ADXL345::~ADXL345() -{ - delete myI2c; -} - -void ADXL345::init() -{ - setDataRate(ADXL345_25HZ); - setPowerMode(0); // high power - setDataFormatControl(ADXL345_FULL_RES | ADXL345_2G); // full resolution, right justified, 2g range - setFifoControl(0x00); // bypass mode - setPowerControl(0x08); // start measurements - - int8_t calibration_offset[3] = {-5,-4,2}; // calibration offset values - for(char axis = 0x00; axis < 0x03; axis++) - setOffset(axis,calibration_offset[axis]); -} - -char ADXL345::SingleByteRead(char address) -{ - char tx = address; - char output; - i2c_.write( ADXL345_WRITE , &tx, 1); //tell it what you want to read - i2c_.read( ADXL345_READ , &output, 1); //tell it where to store the data - return output; -} - - -/* -***info on the i2c_.write*** -address 8-bit I2C slave address [ addr | 0 ] -data Pointer to the byte-array data to send -length Number of bytes to send -repeated Repeated start, true - do not send stop at end -returns 0 on success (ack), or non-0 on failure (nack) -*/ - -int ADXL345::SingleByteWrite(char address, char data) -{ - int ack = 0; - char tx[2]; - tx[0] = address; - tx[1] = data; - return ack | i2c_.write( ADXL345_WRITE , tx, 2); -} - +ADXL345::ADXL345(PinName mosi, + PinName miso, + PinName sck, + PinName cs) : spi_(mosi, miso, sck), nCS_(cs) { -void ADXL345::multiByteRead(char address, char* output, int size) -{ - i2c_.write( ADXL345_WRITE, &address, 1); //tell it where to read from - i2c_.read( ADXL345_READ , output, size); //tell it where to store the data read -} - - -int ADXL345::multiByteWrite(char address, char* ptr_data, int size) -{ - int ack; - - ack = i2c_.write( ADXL345_WRITE, &address, 1); //tell it where to write to - return ack | i2c_.write( ADXL345_READ, ptr_data, size); //tell it what data to write -} - - -void ADXL345::getXYZ(int16_t* readings) -{ - char buffer[6]; - multiByteRead(ADXL345_DATAX0_REG, buffer, 6); - - readings[0] = wordExtend(&buffer[0]); - readings[1] = wordExtend(&buffer[2]); - readings[2] = wordExtend(&buffer[4]); -} + //1.5MHz, allowing us to use the fastest data rates without problems with the FIFO (must be less than 1.6MHz) + spi_.frequency(1500000); + spi_.format(8,3); + + nCS_ = 1; -char ADXL345::getDeviceID() -{ - return SingleByteRead(ADXL345_DEVID_REG); -} -// -int ADXL345::setPowerMode(char mode) -{ - //Get the current register contents, so we don't clobber the rate value. - char registerContents = (mode << 4) | SingleByteRead(ADXL345_BW_RATE_REG); - - return SingleByteWrite(ADXL345_BW_RATE_REG, registerContents); -} - -char ADXL345::getBwRateReg() -{ - return SingleByteRead(ADXL345_BW_RATE_REG); -} - -int ADXL345::setBwRateReg(char reg) -{ - return SingleByteWrite(ADXL345_BW_RATE_REG, reg); -} - -char ADXL345::getPowerControl() -{ - return SingleByteRead(ADXL345_POWER_CTL_REG); -} - -int ADXL345::setPowerControl(char settings) -{ - return SingleByteWrite(ADXL345_POWER_CTL_REG, settings); + wait_us(500); } -char ADXL345::getDataFormatControl(void) -{ - return SingleByteRead(ADXL345_DATA_FORMAT_REG); -} +int ADXL345::getDevId(void) { -int ADXL345::setDataFormatControl(char settings) -{ - return SingleByteWrite(ADXL345_DATA_FORMAT_REG, settings); + return oneByteRead(ADXL345_DEVID_REG); + } -int ADXL345::setDataFormatControl(char settings, char mask, char *prev) -{ - char old = SingleByteRead(ADXL345_DATA_FORMAT_REG); - if(prev) - *prev = old; - return SingleByteWrite(ADXL345_DATA_FORMAT_REG, (old | (settings & mask)) & (settings | ~mask)); +int ADXL345::getTapThreshold(void) { + + return oneByteRead(ADXL345_THRESH_TAP_REG); + } -int ADXL345::setDataRate(char rate) -{ - //Get the current register contents, so we don't clobber the power bit. - char registerContents = SingleByteRead(ADXL345_BW_RATE_REG); +void ADXL345::setTapThreshold(int threshold) { - registerContents &= 0x10; - registerContents |= rate; + oneByteWrite(ADXL345_THRESH_TAP_REG, threshold); - return SingleByteWrite(ADXL345_BW_RATE_REG, registerContents); } +int ADXL345::getOffset(int axis) { -char ADXL345::getOffset(char axis) -{ - char address = 0; + int address = 0; if (axis == ADXL345_X) { address = ADXL345_OFSX_REG; @@ -210,12 +82,13 @@ address = ADXL345_OFSZ_REG; } - return SingleByteRead(address); + return oneByteRead(address); + } -int ADXL345::setOffset(char axis, char offset) -{ - char address = 0; +void ADXL345::setOffset(int axis, char offset) { + + int address = 0; if (axis == ADXL345_X) { address = ADXL345_OFSX_REG; @@ -225,308 +98,338 @@ address = ADXL345_OFSZ_REG; } - return SingleByteWrite(address, offset); + return oneByteWrite(address, offset); + +} + +int ADXL345::getTapDuration(void) { + + return oneByteRead(ADXL345_DUR_REG)*625; + +} + +void ADXL345::setTapDuration(int duration_us) { + + int tapDuration = duration_us / 625; + + oneByteWrite(ADXL345_DUR_REG, tapDuration); + +} + +float ADXL345::getTapLatency(void) { + + return oneByteRead(ADXL345_LATENT_REG)*1.25; + +} + +void ADXL345::setTapLatency(int latency_ms) { + + int tapLatency = latency_ms / 1.25; + + oneByteWrite(ADXL345_LATENT_REG, tapLatency); + +} + +float ADXL345::getWindowTime(void) { + + return oneByteRead(ADXL345_WINDOW_REG)*1.25; + +} + +void ADXL345::setWindowTime(int window_ms) { + + int windowTime = window_ms / 1.25; + + oneByteWrite(ADXL345_WINDOW_REG, windowTime); + +} + +int ADXL345::getActivityThreshold(void) { + + return oneByteRead(ADXL345_THRESH_ACT_REG); + +} + +void ADXL345::setActivityThreshold(int threshold) { + + oneByteWrite(ADXL345_THRESH_ACT_REG, threshold); + +} + +int ADXL345::getInactivityThreshold(void) { + + return oneByteRead(ADXL345_THRESH_INACT_REG); + +} + +void ADXL345::setInactivityThreshold(int threshold) { + + return oneByteWrite(ADXL345_THRESH_INACT_REG, threshold); + +} + +int ADXL345::getTimeInactivity(void) { + + return oneByteRead(ADXL345_TIME_INACT_REG); + +} + +void ADXL345::setTimeInactivity(int timeInactivity) { + + oneByteWrite(ADXL345_TIME_INACT_REG, timeInactivity); + +} + +int ADXL345::getActivityInactivityControl(void) { + + return oneByteRead(ADXL345_ACT_INACT_CTL_REG); + +} + +void ADXL345::setActivityInactivityControl(int settings) { + + oneByteWrite(ADXL345_ACT_INACT_CTL_REG, settings); + +} + +int ADXL345::getFreefallThreshold(void) { + + return oneByteRead(ADXL345_THRESH_FF_REG); + +} + +void ADXL345::setFreefallThreshold(int threshold) { + + oneByteWrite(ADXL345_THRESH_FF_REG, threshold); + +} + +int ADXL345::getFreefallTime(void) { + + return oneByteRead(ADXL345_TIME_FF_REG)*5; + +} + +void ADXL345::setFreefallTime(int freefallTime_ms) { + + int freefallTime = freefallTime_ms / 5; + + oneByteWrite(ADXL345_TIME_FF_REG, freefallTime); + +} + +int ADXL345::getTapAxisControl(void) { + + return oneByteRead(ADXL345_TAP_AXES_REG); + +} + +void ADXL345::setTapAxisControl(int settings) { + + oneByteWrite(ADXL345_TAP_AXES_REG, settings); + +} + +int ADXL345::getTapSource(void) { + + return oneByteRead(ADXL345_ACT_TAP_STATUS_REG); + +} + +void ADXL345::setPowerMode(char mode) { + + //Get the current register contents, so we don't clobber the rate value. + char registerContents = oneByteRead(ADXL345_BW_RATE_REG); + + registerContents = (mode << 4) | registerContents; + + oneByteWrite(ADXL345_BW_RATE_REG, registerContents); + +} + +int ADXL345::getPowerControl(void) { + + return oneByteRead(ADXL345_POWER_CTL_REG); + +} + +void ADXL345::setPowerControl(int settings) { + + oneByteWrite(ADXL345_POWER_CTL_REG, settings); + +} + +int ADXL345::getInterruptEnableControl(void) { + + return oneByteRead(ADXL345_INT_ENABLE_REG); + +} + +void ADXL345::setInterruptEnableControl(int settings) { + + oneByteWrite(ADXL345_INT_ENABLE_REG, settings); + +} + +int ADXL345::getInterruptMappingControl(void) { + + return oneByteRead(ADXL345_INT_MAP_REG); + +} + +void ADXL345::setInterruptMappingControl(int settings) { + + oneByteWrite(ADXL345_INT_MAP_REG, settings); + +} + +int ADXL345::getInterruptSource(void){ + + return oneByteRead(ADXL345_INT_SOURCE_REG); + +} + +int ADXL345::getDataFormatControl(void){ + + return oneByteRead(ADXL345_DATA_FORMAT_REG); + +} + +void ADXL345::setDataFormatControl(int settings){ + + oneByteWrite(ADXL345_DATA_FORMAT_REG, settings); + +} + +void ADXL345::setDataRate(int rate) { + + //Get the current register contents, so we don't clobber the power bit. + char registerContents = oneByteRead(ADXL345_BW_RATE_REG); + + registerContents &= 0x10; + registerContents |= rate; + + oneByteWrite(ADXL345_BW_RATE_REG, registerContents); + +} + +int ADXL345::getAx(){ + + char buffer[2]; + + multiByteRead(ADXL345_DATAX0_REG, buffer, 2); + + return ((int)buffer[1] << 8 | (int)buffer[0]); } -char ADXL345::getFifoControl(void) -{ - return SingleByteRead(ADXL345_FIFO_CTL); -} - -int ADXL345::setFifoControl(char settings) -{ - return SingleByteWrite(ADXL345_FIFO_STATUS, settings); -} +int ADXL345::getAy(){ -char ADXL345::getFifoStatus(void) -{ - return SingleByteRead(ADXL345_FIFO_STATUS); -} - -char ADXL345::getTapThreshold(void) -{ - return SingleByteRead(ADXL345_THRESH_TAP_REG); -} - -int ADXL345::setTapThreshold(char threshold) -{ - return SingleByteWrite(ADXL345_THRESH_TAP_REG, threshold); -} - -float ADXL345::getTapDuration(void) -{ - return (float)SingleByteRead(ADXL345_DUR_REG)*625; + char buffer[2]; + + multiByteRead(ADXL345_DATAY0_REG, buffer, 2); + + return ((int)buffer[1] << 8 | (int)buffer[0]); } -int ADXL345::setTapDuration(short int duration_us) -{ - short int tapDuration = duration_us / 625; - char tapChar[2]; - tapChar[0] = (tapDuration & 0x00FF); - tapChar[1] = (tapDuration >> 8) & 0x00FF; - return multiByteWrite(ADXL345_DUR_REG, tapChar, 2); -} - -float ADXL345::getTapLatency(void) -{ - return (float)SingleByteRead(ADXL345_LATENT_REG)*1.25; -} +int ADXL345::getAz(){ -int ADXL345::setTapLatency(short int latency_ms) -{ - latency_ms = latency_ms / 1.25; - char latChar[2]; - latChar[0] = (latency_ms & 0x00FF); - latChar[1] = (latency_ms << 8) & 0xFF00; - return multiByteWrite(ADXL345_LATENT_REG, latChar, 2); -} - -float ADXL345::getWindowTime(void) -{ - return (float)SingleByteRead(ADXL345_WINDOW_REG)*1.25; -} - -int ADXL345::setWindowTime(short int window_ms) -{ - window_ms = window_ms / 1.25; - char windowChar[2]; - windowChar[0] = (window_ms & 0x00FF); - windowChar[1] = ((window_ms << 8) & 0xFF00); - return multiByteWrite(ADXL345_WINDOW_REG, windowChar, 2); -} - -char ADXL345::getActivityThreshold(void) -{ - return SingleByteRead(ADXL345_THRESH_ACT_REG); + char buffer[2]; + + multiByteRead(ADXL345_DATAZ0_REG, buffer, 2); + + return ((int)buffer[1] << 8 | (int)buffer[0]); } -int ADXL345::setActivityThreshold(char threshold) -{ - return SingleByteWrite(ADXL345_THRESH_ACT_REG, threshold); -} + -char ADXL345::getInactivityThreshold(void) -{ - return SingleByteRead(ADXL345_THRESH_INACT_REG); -} - -//int FUNCTION(short int * ptr_Output) -//short int FUNCTION () - -int ADXL345::setInactivityThreshold(char threshold) -{ - return SingleByteWrite(ADXL345_THRESH_INACT_REG, threshold); -} +void ADXL345::getOutput(int* readings){ -char ADXL345::getTimeInactivity(void) -{ - return SingleByteRead(ADXL345_TIME_INACT_REG); -} + char buffer[6]; + + multiByteRead(ADXL345_DATAX0_REG, buffer, 6); + + readings[0] = (int)buffer[1] << 8 | (int)buffer[0]; + readings[1] = (int)buffer[3] << 8 | (int)buffer[2]; + readings[2] = (int)buffer[5] << 8 | (int)buffer[4]; -int ADXL345::setTimeInactivity(char timeInactivity) -{ - return SingleByteWrite(ADXL345_TIME_INACT_REG, timeInactivity); -} - -char ADXL345::getActivityInactivityControl(void) -{ - return SingleByteRead(ADXL345_ACT_INACT_CTL_REG); -} - -int ADXL345::setActivityInactivityControl(char settings) -{ - return SingleByteWrite(ADXL345_ACT_INACT_CTL_REG, settings); } -char ADXL345::getFreefallThreshold(void) -{ - return SingleByteRead(ADXL345_THRESH_FF_REG); -} +int ADXL345::getFifoControl(void){ -int ADXL345::setFreefallThreshold(char threshold) -{ - return SingleByteWrite(ADXL345_THRESH_FF_REG, threshold); -} + return oneByteRead(ADXL345_FIFO_CTL); -char ADXL345::getFreefallTime(void) -{ - return SingleByteRead(ADXL345_TIME_FF_REG)*5; } -int ADXL345::setFreefallTime(short int freefallTime_ms) -{ - freefallTime_ms = freefallTime_ms / 5; - char fallChar[2]; - fallChar[0] = (freefallTime_ms & 0x00FF); - fallChar[1] = (freefallTime_ms << 8) & 0xFF00; +void ADXL345::setFifoControl(int settings){ - return multiByteWrite(ADXL345_TIME_FF_REG, fallChar, 2); + oneByteWrite(ADXL345_FIFO_CTL, settings); + } -char ADXL345::getTapAxisControl(void) -{ - return SingleByteRead(ADXL345_TAP_AXES_REG); -} +int ADXL345::getFifoStatus(void){ -int ADXL345::setTapAxisControl(char settings) -{ - return SingleByteWrite(ADXL345_TAP_AXES_REG, settings); -} + return oneByteRead(ADXL345_FIFO_STATUS); -char ADXL345::getTapSource(void) -{ - return SingleByteRead(ADXL345_ACT_TAP_STATUS_REG); } -char ADXL345::getInterruptEnableControl(void) -{ - return SingleByteRead(ADXL345_INT_ENABLE_REG); -} +int ADXL345::oneByteRead(int address) { + + int tx = (ADXL345_SPI_READ | (address & 0x3F)); + int rx = 0; -int ADXL345::setInterruptEnableControl(char settings) -{ - return SingleByteWrite(ADXL345_INT_ENABLE_REG, settings); -} + nCS_ = 0; + //Send address to read from. + spi_.write(tx); + //Read back contents of address. + rx = spi_.write(0x00); + nCS_ = 1; -char ADXL345::getInterruptMappingControl(void) -{ - return SingleByteRead(ADXL345_INT_MAP_REG); -} + return rx; -int ADXL345::setInterruptMappingControl(char settings) -{ - return SingleByteWrite(ADXL345_INT_MAP_REG, settings); } -char ADXL345::getInterruptSource(void) -{ - return SingleByteRead(ADXL345_INT_SOURCE_REG); -} +void ADXL345::oneByteWrite(int address, char data) { -void ADXL345::sample100avg(float period, int16_t buffer[][3], int16_t *avg, Timer* t) -{ - double start_time; - - for(int sample = 0; sample < 100; sample++) { - start_time = t->read(); + int tx = (ADXL345_SPI_WRITE | (address & 0x3F)); - getXYZ(buffer[sample]); - - wait(period - (start_time - t->read())); - } + nCS_ = 0; + //Send address to write to. + spi_.write(tx); + //Send data to be written. + spi_.write(data); + nCS_ = 1; - for(int axis = 0; axis < 3; axis++) { - double average = 0.0; - for(int sample = 0; sample < 100; sample++) - average += buffer[sample][axis]; - average /= 100.0; - avg[axis] = static_cast<int16_t>(average); - } } -void ADXL345::calibrate(Timer* t, bool store_output, Serial *pc) -{ - int16_t data[100][3]; // {x,y,z}, data - int16_t data_avg[3]; - int8_t calibration_offset[3]; - - float period = 0.01; // period of sample rate - - // wait 11.1ms - wait(0.0111); +void ADXL345::multiByteRead(int startAddress, char* buffer, int size) { - pc->puts("Reading old register states... "); - // read current register states - char bw_rate = getBwRateReg(); - char power_control = getPowerControl(); - char data_format = getDataFormatControl(); - - pc->puts("Done!\r\nSetting new register states... "); - // initalize command sequence - setDataFormatControl((ADXL345_16G | ADXL345_FULL_RES)); - setBwRateReg(ADXL345_100HZ); // 100Hz data rate - setPowerControl(0x08); // start measurement + int tx = (ADXL345_SPI_READ | ADXL345_MULTI_BYTE | (startAddress & 0x3F)); - // wait 1.1ms - wait(0.0111); - pc->puts("Done!\r\nSampling... "); - //take 100 data points and average (100Hz) - sample100avg(period, data, data_avg, t); - pc->puts("Done!\r\nCalculating offset values... "); - // calculate calibration value - calibration_offset[0] = -1 * (data_avg[0] / 4); // x - calibration_offset[1] = -1 * (data_avg[1] / 4); // y - calibration_offset[2] = -1 * ((data_avg[2] - 256) / 4); // z + nCS_ = 0; + //Send address to start reading from. + spi_.write(tx); - if(store_output) { - pc->puts("Done!\r\nStoring output to file... "); - LocalFileSystem local("local"); - FILE *fp = fopen("/local/OFF_CAL.csv", "w"); // write - fprintf(fp, "ADXL345 Calibration offsets\r\nx,%d\r\ny,%d\r\nz,%d\r\n\r\n", calibration_offset[0], calibration_offset[1], calibration_offset[2]); - - fputs("Raw Data:\r\nX,Y,Z\r\n", fp); - for(int sample = 0; sample < 100; sample++) - fprintf(fp, "%d,%d,%d\r\n",data[sample][0],data[sample][1],data[sample][2]); - fclose(fp); + for (int i = 0; i < size; i++) { + buffer[i] = spi_.write(0x00); } - pc->puts("Done!\r\nSetting the offset registers... "); - // update offset registers - for(char axis = 0x00; axis < 0x03; axis++) - setOffset(axis,calibration_offset[axis]); - pc->puts("Done!\r\nReturning registers to original state... "); - // return control registers to original state - setDataFormatControl(data_format); - setBwRateReg(bw_rate); - setPowerControl(power_control); - pc->puts("Done!\r\n"); + + nCS_ = 1; + } -void ADXL345::calibrate(Timer* t, bool store_output) -{ - int16_t data[100][3]; // {x,y,z}, data - int16_t data_avg[3]; - int8_t calibration_offset[3]; +void ADXL345::multiByteWrite(int startAddress, char* buffer, int size) { - float period = 0.01; // period of sample rate + int tx = (ADXL345_SPI_WRITE | ADXL345_MULTI_BYTE | (startAddress & 0x3F)); - // wait 11.1ms - wait(0.0111); - - // read current register states - char bw_rate = getBwRateReg(); - char power_control = getPowerControl(); - char data_format = getDataFormatControl(); - - // initalize command sequence - setDataFormatControl((ADXL345_16G | ADXL345_FULL_RES)); - setBwRateReg(ADXL345_100HZ); // 100Hz data rate - setPowerControl(0x08); // start measurement + nCS_ = 0; + //Send address to start reading from. + spi_.write(tx); - // wait 1.1ms - wait(0.0111); - //take 100 data points and average (100Hz) - sample100avg(period, data, data_avg, t); - // calculate calibration value - calibration_offset[0] = -1 * (data_avg[0] / 4); // x - calibration_offset[1] = -1 * (data_avg[1] / 4); // y - calibration_offset[2] = -1 * ((data_avg[2] - 256) / 4); // z - - if(store_output) { - LocalFileSystem local("local"); - FILE *fp = fopen("/local/OFF_CAL.csv", "w"); // write - fprintf(fp, "ADXL345 Calibration offsets\r\nx,%d\r\ny,%d\r\nz,%d\r\n\r\n", calibration_offset[0], calibration_offset[1], calibration_offset[2]); + for (int i = 0; i < size; i++) { + buffer[i] = spi_.write(0x00); + } - fputs("Raw Data:\r\nX,Y,Z\r\n", fp); - for(int sample = 0; sample < 100; sample++) - fprintf(fp, "%d,%d,%d\r\n",data[sample][0],data[sample][1],data[sample][2]); - fclose(fp); - } - // update offset registers - for(char axis = 0x00; axis < 0x03; axis++) - setOffset(axis,calibration_offset[axis]); - // return control registers to original state - setDataFormatControl(data_format); - setBwRateReg(bw_rate); - setPowerControl(power_control); + nCS_ = 1; + } \ No newline at end of file