Problem with adxl345 3-axis accelerometer! Need help!

I connect adxl345 breakout to Arduino Uno via I2C and SPI mode respectively. But the output data makes me confused. When the adxl345 is placed on the flat, x, y, z axis data should be approximate to 0 , 0 , 256. In datasheet, 256 represent 1g. But actually, the output data I got is quite different from it. I tried another same board and several examples, the output is almost same as before. Any help is appreciated.

I2C mode:
CS ->3V3
SDA ->A4
SCL → A5
VCC ->3V3

And when I tilt the board, Z axis data barely changes via I2C.

#include <Wire.h> 
#define DEVICE (0x53)    //ADXL345 device address 
#define TO_READ (6)        //num of bytes we are going to read each time (two bytes for each axis) 
byte buff[TO_READ] ;    //6 bytes buffer for saving data read from the device 
char str[512];                      //string buffer to transform data before sending it to the serial port 
void setup() 
  Wire.begin();        // join i2c bus (address optional for master) 
  Serial.begin(9600);  // start serial for output 
  //Turning on the ADXL345 
  writeTo(DEVICE, 0x2D, 0);       
  writeTo(DEVICE, 0x2D, 16); 
  writeTo(DEVICE, 0x2D, 8); 
void loop() 
  int regAddress = 0x32;    //first axis-acceleration-data register on the ADXL345 
  int x, y, z; 
  readFrom(DEVICE, regAddress, TO_READ, buff); //read the acceleration data from the ADXL345 
  //each axis reading comes in 10 bit resolution, ie 2 bytes.  Least Significat Byte first!! 
  //thus we are converting both bytes in to one int 
  x = (((int)buff[1]) << 8) | buff[0];    
  y = (((int)buff[3])<< 8) | buff[2]; 
  z = (((int)buff[5]) << 8) | buff[4]; 
  //we send the x y z values as a string to the serial port 
  sprintf(str, "%d %d %d", x, y, z);   
  Serial.print(10, BYTE); 
  //It appears that delay is needed in order not to clog the port 
//---------------- Functions 
//Writes val to address register on device 
void writeTo(int device, byte address, byte val) { 
  Wire.beginTransmission(device); //start transmission to device  
  Wire.send(address);        // send register address 
  Wire.send(val);        // send value to write 
  Wire.endTransmission(); //end transmission 
//reads num bytes starting from address register on device in to buff array 
void readFrom(int device, byte address, int num, byte buff[]) { 
  Wire.beginTransmission(device); //start transmission to device  
  Wire.send(address);        //sends address to read from 
  Wire.endTransmission(); //end transmission 
    Wire.beginTransmission(device); //start transmission to device 
  Wire.requestFrom(device, num);    // request 6 bytes from device 
  int i = 0; 
  while(Wire.available())    //device may send less than requested (abnormal) 
    buff[i] = Wire.receive(); // receive a byte 
  Wire.endTransmission(); //end transmission 

SPI mode:
CS ->D10
SDA ->D11
SDO ->D12
SCL ->D13
VCC ->3V3

//Add the SPI library so we can communicate with the ADXL345 sensor
#include <SPI.h>

//Assign the Chip Select signal to pin 10.
int CS=10;

//This is a list of some of the registers available on the ADXL345.
//To learn more about these and the rest of the registers on the ADXL345, read the datasheet!
char POWER_CTL = 0x2D;	//Power Control Register
char DATA_FORMAT = 0x31;
char DATAX0 = 0x32;	//X-Axis Data 0
char DATAX1 = 0x33;	//X-Axis Data 1
char DATAY0 = 0x34;	//Y-Axis Data 0
char DATAY1 = 0x35;	//Y-Axis Data 1
char DATAZ0 = 0x36;	//Z-Axis Data 0
char DATAZ1 = 0x37;	//Z-Axis Data 1

//This buffer will hold values read from the ADXL345 registers.
char values[10];
//These variables will be used to hold the x,y and z axis accelerometer values.
int x,y,z;

void setup(){ 
  //Initiate an SPI communication instance.
  //Configure the SPI connection for the ADXL345.
  //Create a serial connection to display the data on the terminal.
  //Set up the Chip Select pin to be an output from the Arduino.
  pinMode(CS, OUTPUT);
  //Before communication starts, the Chip Select pin needs to be set high.
  digitalWrite(CS, HIGH);
  //Put the ADXL345 into +/- 4G range by writing the value 0x01 to the DATA_FORMAT register.
  writeRegister(DATA_FORMAT, 0x01);
  //Put the ADXL345 into Measurement Mode by writing 0x08 to the POWER_CTL register.
  writeRegister(POWER_CTL, 0x08);  //Measurement mode  

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.
  readRegister(DATAX0, 6, 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(y, DEC);
  Serial.println(z, DEC);      

//This function will write a value to a register on the ADXL345.
//  char registerAddress - The register to write a value to
//  char value - The value to be written to the specified register.
void writeRegister(char registerAddress, char value){
  //Set Chip Select pin low to signal the beginning of an SPI packet.
  digitalWrite(CS, LOW);
  //Transfer the register address over SPI.
  //Transfer the desired register value over SPI.
  //Set the Chip Select pin high to signal the end of an SPI packet.
  digitalWrite(CS, HIGH);

//This function will read a certain number of registers starting from a specified address and store their values in a buffer.
//  char registerAddress - The register addresse to start the read sequence from.
//  int numBytes - The number of registers that should be read.
//  char * values - A pointer to a buffer where the results of the operation should be stored.
void readRegister(char registerAddress, int numBytes, char * values){
  //Since we're performing a read operation, the most significant bit of the register address should be set.
  char address = 0x80 | registerAddress;
  //If we're doing a multi-byte read, bit 6 needs to be set as well.
  if(numBytes > 1)address = address | 0x40;
  //Set the Chip select pin low to start an SPI packet.
  digitalWrite(CS, LOW);
  //Transfer the starting register address that needs to be read.
  //Continue to read registers until we've read the number specified, storing the results to the input buffer.
  for(int i=0; i<numBytes; i++){
    values[i] = SPI.transfer(0x00);
  //Set the Chips Select pin high to end the SPI packet.
  digitalWrite(CS, HIGH);

I used a logic level converter for the said accelerometer. You don't want the 5V to damage it.

Thanks for your advice, but does it have any influences with the output data?

If you supply voltage beyond the max accepted voltage to the device, you are not guaranteed to get anything that makes sense. I would try to use it the right way, then if it doesn't work, maybe it is broken. I've only used it with 3.3V signals and found no problem.

Hello, I am experiencing the same problem. I have 9DOF board from, it has 3 axis accelerometer, gyroscope, magnetometer and some atmel microcontroller. All of these chips are connected through I2C. For some reason, the ADXL345 returns always value 511 for Z-axis. Y axis shows relatively big offset (it returns values between -512..170), and X axis is working fine (range -337..340)

By mistake I connected 5V source to the board, is there any chance that this is the reason for incorrect reading from ADXL345?

As a workaround I calculate Z acceleration with Phytagorean equation (square root of sum of squares for all three axes sould return value corresponding to 1g), but this doesn't provide very nice results.

Here is a screenshot fom my appication:

Gabriel (

You have to do 2 things: 1.Set the offset registers in the ADXL345 2.Make another offset in the Arduino sketch.

Here is some help for you. By looking here at the offset section you'll know how to do the second offset (in the Arduino):

And here is a snap of what you should get(the first 3 lines represent the accelerometer):

After this, is time for some filtering...

Best regards, RobertEagle

Hello Robert,

I owe you a beer! Thank you for your fast response, the application note helped me to fix my problem. The arduino code I am using (Razor_AHRS) initializes the accelerometer for range +-2g. By switching to +-16 g mode (writing 0x0B instead of 0x08 to register 0x31), I was able to get unclipped reading from Z axis. For some reason it only returns positive numbers even when I set the calibration register to largest negative number (0x80), the x, y axes nicely show positive or negative numbers depending on the orientation of device. But it's ok, I will find average value of Z axis acceleration and then subtract this value from raw value from device.

I have just finished my first IMU project based on Razor AHRS project
instead of using weird development platform as “Processing”, calibration,
visualization and all mathematical algorithms are implemented in javascript.

you can find it here:

You're welcome, gabonator!

Try to rotate the physical accelerometer at 180 degrees and see if the Z axis gives you negatives.

HI guys
I am Karthick,I am working with ADXL345 accelerometer.
When I was reading the X,Y,Z axis using I2C ,I faced a problem.
I can able to read only the raw data of DATAX1(0X33),DATAY1(0X35),DATAZ1(0X37) of the 3 axis.
Remaining DATAX0(0X32),DATAY0(0X33),DATAZ0(0X36) I cant read.
Please help me with this problem.

Can anyone explain the meaning of these commands ?
x = (((int)buff[1]) << 8) | buff[0];
y = (((int)buff[3])<< 8) | buff[2];
z = (((int)buff[5]) << 8) | buff[4];

how do you know the adxl345 is broken