/************************************************************************************
Stefan Dzisiewski-Smith, March 2012
Basic accelerometer value reading code for the Sparkfun ADXL345 Eval Board
Based on the code at http://www.sparkfun.com/tutorials/240 but modified for use
with shiftOut() instead of hardware SPI, due to the pin mapping on the eval board
I'm not responsible for anything this code does to ANYTHING you own - use it
at your own risk.
************************************************************************************/
// ADXL345 register addresses
const char ID = 0x00;
const char THRESH_TAP = 0x1D;
const char OFSX = 0x1E;
const char OFSY = 0x1F;
const char OFSZ = 0x20;
const char DUR = 0x21;
const char Latent = 0x22;
const char Window = 0x23;
const char THRESH_ACT = 0x24;
const char THRESH_INACT = 0x25;
const char TIME_INACT = 0x26;
const char ACT_INACT_CTL = 0x27;
const char THRESH_FF = 0x28;
const char TIME_FF = 0x29;
const char TAP_AXES = 0x2A;
const char BW_RATE = 0x2C;
const char POWER_CTL = 0x2D; //Power Control Register
const char INT_ENABLE = 0x2E;
const char INT_MAP = 0x2F;
const char DATA_FORMAT = 0x31;
const char DATAX0 = 0x32; //X-Axis Data 0
const char DATAX1 = 0x33; //X-Axis Data 1
const char DATAY0 = 0x34; //Y-Axis Data 0
const char DATAY1 = 0x35; //Y-Axis Data 1
const char DATAZ0 = 0x36; //Z-Axis Data 0
const char DATAZ1 = 0x37; //Z-Axis Data 1
const char FIFO_CTL = 0x28;
unsigned char values[10];
int x, y, z;
// pins from the eval board schematic
// we're in 4-wire mode
#define CS 14
#define SCK 15
#define DI 17
#define DO 16
// LED pins - defined, although I do nothing with them in this code
#define RED 7
#define YELLOW 5
#define GREEN 6
void setup() {
initAccelerometer();
Serial.begin(9600);
Serial.println("");
}
void loop() {
//Reading 6 bytes of data starting at register DATAX0 will retrieve the x,y and z acceleration values from the ADXL345.
//The results of the read operation will get stored to the values[] buffer.
rAxxReg(DATAX0, 6, (char*)values);
//The ADXL345 gives 10-bit acceleration values, but they are stored as bytes (8-bits). To get the full value, two bytes must be combined for each axis.
//The X value is stored in values[0] and values[1].
x = ((int)values[1]<<8)|(int)values[0];
//The Y value is stored in values[2] and values[3].
y = ((int)values[3]<<8)|(int)values[2];
//The Z value is stored in values[4] and values[5].
z = ((int)values[5]<<8)|(int)values[4];
//Print the results to the terminal.
Serial.print(x, DEC);
Serial.print(',');
Serial.print(y, DEC);
Serial.print(',');
Serial.println(z, DEC);
delay(10);
}
void wAxxReg(char address, unsigned char value){
digitalWrite(CS, LOW);
// we're rising edge clocked (see the ADXL345 datasheet) so we have to set SCK low before
// calling shiftOut
digitalWrite(SCK, LOW);
shiftOut(DO, SCK, MSBFIRST, address);
shiftOut(DO, SCK, MSBFIRST, (char)value);
// reset SCK to its idle HIGH value
digitalWrite(SCK, HIGH);
digitalWrite(CS, HIGH);
}
void rAxxReg(char address, int numBytes, char * values){
// since we're performing a read operation, the most significant bit of the register address should be set
char scratchAddress = 0x80 | address;
// if we're doing a multi-byte read, bit 6 needs to be set as well
if(numBytes > 1)scratchAddress |= 0x40;
digitalWrite(CS, LOW);
// we're rising edge clocked (see the ADXL345 datasheet) so we have to set SCK low before
// calling shiftOut
digitalWrite(SCK, LOW);
shiftOut(DO, SCK, MSBFIRST, scratchAddress);
for(int i=0; i<numBytes; i++){
values[i] = shiftIn(DI, SCK, MSBFIRST);
}
// reset SCK to its idle HIGH value
digitalWrite(SCK, HIGH);
digitalWrite(CS, HIGH);
}
void initAccelerometer(){
// setup ADXL345 pins
pinMode(CS, OUTPUT);
pinMode(SCK, OUTPUT);
pinMode(DI, INPUT);
pinMode(DO, OUTPUT);
digitalWrite(CS, HIGH);
digitalWrite(SCK, HIGH);
// Put the ADXL345 into +/- 4G range by writing the value 0x01 to the DATA_FORMAT register.
wAxxReg(DATA_FORMAT, 0x01);
// Put the ADXL345 into Measurement Mode by writing 0x08 to the POWER_CTL register.
wAxxReg(POWER_CTL, 0x08);
// Initialise the rest of the registers to their correct reboot values
// This isn't strictly necessary, but I managed to somehow end up with an offset on my
// x-axis after an arduino crash one time - better safe than sorry
wAxxReg(THRESH_TAP, 0x00);
wAxxReg(OFSX, 0x00);
wAxxReg(OFSY, 0x00);
wAxxReg(OFSZ, 0x00);
wAxxReg(DUR, 0x00);
wAxxReg(Latent, 0x00);
wAxxReg(Window, 0x00);
wAxxReg(THRESH_ACT, 0x00);
wAxxReg(THRESH_INACT, 0x00);
wAxxReg(TIME_INACT, 0x00);
wAxxReg(ACT_INACT_CTL, 0x00);
wAxxReg(THRESH_FF, 0x00);
wAxxReg(TIME_FF, 0x00);
wAxxReg(TAP_AXES, 0x00);
wAxxReg(BW_RATE, 0x0A); // note that this register DOESN'T get set to 0x00
wAxxReg(INT_ENABLE, 0x00);
wAxxReg(INT_MAP, 0x00);
wAxxReg(FIFO_CTL, 0x00);
}