Pages: [1]   Go Down
Author Topic: ADXL 345 no reading with SPI  (Read 336 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I've done a search in regards to this problem and it appears a number of people have/had this problem with no resolution.  The ADXL345 runs fine with I2C.  However I want more speed, hence going with SPI. 

My connections and code are shown here:
https://www.sparkfun.com/tutorials/240

Code:
//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.
  SPI.begin();
  //Configure the SPI connection for the ADXL345.
  SPI.setDataMode(SPI_MODE3);
  //Create a serial connection to display the data on the terminal.
  Serial.begin(9600);
 
  //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] & 0xFF;
  //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(100);
}

//This function will write a value to a register on the ADXL345.
//Parameters:
//  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.
  SPI.transfer(registerAddress);
  //Transfer the desired register value over SPI.
  SPI.transfer(value);
  //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.
//Parameters:
//  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.
  SPI.transfer(address);
  //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);
}

My output is always 0,0,0.

I have shortened the SDO, SDA and SCL wires to 1 inch with no improvement. 

I connected an old analog scope to the communication lines.  CS and SCL remain high.  SDO and SDA remain low.  I don't see any switching.  It doesn't look like I'm getting through to the ADXL.

Any insights & help is appreciated.
Gerry

Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 122
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I can not find a problem.
The example is for the Arduino Uno. If you have an other board, it might not work. Are you perhaps using an Arduino Leonardo or Mega ?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm using the Uno.
Logged

Offline Offline
Newbie
*
Karma: 1
Posts: 37
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo!
Sparkfun Codes works well.
On an Uno , you will need a (4) Levelshifter..the Breakouts are 3,6 V max

mfg Martin
Logged

Offline Offline
Edison Member
*
Karma: 27
Posts: 2033
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The instructions for chip select are very confusing.  Chip-select = pin 10 is for when you want the arduino to be the spi slave device controlled by something else.    which you usually don't want,   when interfacing with sensors.   Try using a different pin for the chip select signal to the sensor device.
Logged

Norfolk UK
Offline Offline
Edison Member
*
Karma: 52
Posts: 2203
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The instructions for chip select are very confusing.  Chip-select = pin 10 is for when you want the arduino to be the spi slave device controlled by something else.    which you usually don't want,   when interfacing with sensors.   Try using a different pin for the chip select signal to the sensor device.
Pin 10 is the hardware SS pin. It need to be set to output for the UNO SPI hardware to be master (no matter what pin you use for SS) and if it's set to input and your using the hardware SPI then it will make the UNO a slave device.
Logged

Handle every stressful situation like a dog. If you can't eat it or hump it. Piss on it and walk away.

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for the reply's.  I don't understand it.  There may be thousands of these accelerometers working with the Uno.  Many are connected as shown in the Spark Fun link.  Yet the absolute maximum input voltage of the ADXL345 is 3.9V.  The Uno data outputs are I believe 5V.  A voltage level shifter was suggested; I tend to agree.  I think the ADXL may be saved because the Uno outputs are current limited.   The I2C configuration was working OK.  That's also operating off of 5V with no level shifter, right?

It's also strange that Uno pin 13 is chosen for the clock signal (SCL).  The Uno LED is loading the clock signal.  That can't be good for signal integrity. 

I was a bit careless yesterday fooling around with the accelerometer.  I lifted the power input and to my surprise, the on-board ADXL red LED remained on.  Do the ADXL data inputs have clamping diodes to Vcc?  That's probably the reason 5V data inputs won't destroy the chip.   Is there a schematic for the ADXL345 circuit board?  In any event, I probably overstressed the unit when I connected 5V to Vs.  It may have been defective before that event.  More accelerometers are on order.

What's a common voltage level shift circuit used for this application?

Gerry
Logged

Offline Offline
Newbie
*
Karma: 1
Posts: 37
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello!
4-channel Bi-directional Logic Level Converter.. 5V High 3,3 Low
A small Breakout with 4 MosFets on it ...from $2 to $4  at your local Store.
Maybe the 345 lives, do also on mine ,5V to Int1...rerouting and it works again.
Have Luck!

mfg Martin
 
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

OK.  Level converters are on order.  I could very well have a signal integrity problem.  They should clear up the signal at least. 

I'm surprised the 345 is still operational in I2C mode.  I got a little burn blister on my finger when touching the IC yesterday with 5V on it.  i though for sure it was dead. 

The troubleshooting goes on.

Gerry

Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Any Update on this Gary?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I received a different brand of ADXL345 modules.  The first module didn't work in SPI mode.  This module is identified as having pin headers on two sides of the module.  The newer module has just one pin header row.  It works in SPI mode without a voltage level converter. 

Even though it "works", there's still a problem.  5V is being fed to the ADXL345 SPI inputs.  The ADXL wants 3.3V.  The excess voltage feeds through the SPI clamping diodes to Vcc. This raises Vcc to 3.9V.  Seems like the chip can take it.  I believe now the accelerometer scaling is screwed up.  Scaling is based on Vcc = 3.3V.  Accelerometer data is 18% low.

All is well after adding the suggested voltage converter.

Gerry
Logged

Pages: [1]   Go Up
Jump to: