ADXL345+Adafruit Datalogging Shield

I’m having issues getting acceleration data after one cycle of the loop. It seems to be that after the SDFile is written to that the accelerometer craps out. It gives me garbage data right after the good data is saved to the SD card.

Here’s the code:

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

//Assign the Chip Select signal to pin 10.
int ADXL_CS = 9;
int SD_CS = 10;

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

char BW_RATE = 0x2C;    // reading rate
char THRESH_FF = 0x28;  // ff threshold
char TIME_FF = 0x29;    // ff time

char INT_ENABLE = 0x2e;
char INT_MAP = 0x2f;
char INT_SOURCE = 0x30;  // source for interrupts
char FIFO_CTL = 0x38;  // FIFO control

char values[10];
int x,y,z;

double xg,yg,zg;

const int amt_read = 30;

double st_values[5][amt_read];

double g = 0.0039;  // +/- 16g

// sampling rate
#define S_R 1600

// delay in microseconds
#define D_MS (1000000)/(S_R)

long curr_time;

bool IN_FF = false;
char FF_AMT = 100;  // free fall sensativity @ 62.5mg/LSB

SdFat sd;
SdFile myFile;  // logger file

char filename[] = "LOGGER00.CSV";

void setup(){ 
  //Initiate an SPI communication instance.
  SPI.begin();

  //Create a serial connection to display the data on the terminal.
  Serial.begin(38400);
  
  // set the SD CS pin to output
  pinMode(SD_CS, OUTPUT);  
  
  //Set up the Chip Select pin to be an output from the Arduino.
  pinMode(ADXL_CS, OUTPUT);

  digitalWrite(ADXL_CS, HIGH);
  
  // initialize the sd card
  if (!sd.begin(SD_CS,SPI_FULL_SPEED) )    sd.initErrorHalt();
  else
    Serial.println("Done Initializing SD Card");
    
  //  create a new file that starts with logger00 and the next one will be logger01 if logger00 exists
  for (int i = 0; i < 100; i++) 
  {
    filename[6] = i/10 + '0';
    filename[7] = i%10 + '0';
    if (!sd.exists(filename)) 
    {
      // only open a new file if it doesn't exist
      if ( !myFile.open(filename, O_RDWR | O_CREAT | O_AT_END) )
        sd.errorHalt("opening the file for write failed");
      break;  // leave the loop!
    }
  }
  
  // set up the file header
  myFile.println("x-axis,y-axis,z-axis,millis,free-fall");
  
  //Configure the SPI connection for the ADXL345.
  SPI.setDataMode(SPI_MODE3);
  
  // before communication starts the CS pin must be set to high
  digitalWrite(ADXL_CS,HIGH);
  
  //Put the ADXL345 into +/- 16G range by writing the value 0x01 to the DATA_FORMAT register.
  //writeRegister(DATA_FORMAT, 0x0F);
  
  /// set the accelerometer into full resolution mode and +/- 16G mode
  writeRegister( DATA_FORMAT, 0x08 | 0x0F);

  // enable free fall interrupt
  writeRegister(INT_MAP, 0x00);  // pass the interrupt to the first interrupt pin
  writeRegister(INT_ENABLE,0x04);  // enable the free fall function

  writeRegister(THRESH_FF, FF_AMT);
  
  writeRegister(TIME_FF,1);
  
  writeRegister(FIFO_CTL,0x80);  // stream FIFO
  
  //Put the ADXL345 into Measurement Mode by writing 0x08 to the POWER_CTL register.
  writeRegister(POWER_CTL, 0x08);  //Measurement mode  
  writeRegister(BW_RATE,0x0F);  // change sampling rate
  
}

void loop(){
  
  for (int i = 0; i < amt_read; i++)
  {
    readRegister(DATAX0, 6, values);
  
    x = ((int)values[1]<<8)|(int)values[0];
    y = ((int)values[3]<<8)|(int)values[2];
    z = ((int)values[5]<<8)|(int)values[4];
    
    // save the data in gs
    xg = x*g;
    yg = y*g;
    zg = y*g;
    
    curr_time = millis();
    IN_FF = inFF();
    
    delayMicroseconds(D_MS);  // minimum delay for the accelerometer    
    
    // store the values into an array
    st_values[0][i] = xg;  // store x axis
    st_values[1][i] = yg;  // store y axis
    st_values[2][i] = zg;  // store z axis
    st_values[3][i] = curr_time;  // store the time
    st_values[4][i] = IN_FF;      // store FF    
  }
  
  // save all of the data
  for ( int i = 0; i < amt_read; i++)
  {
    Serial.print(st_values[0][i],4);
    Serial.print(',');
    Serial.print(st_values[1][i],4);
    Serial.print(',');
    Serial.print(st_values[2][i],4);      
    Serial.print(',');
    Serial.print(st_values[3][i],0);
    Serial.print(',');
    Serial.print(st_values[4][i],0);
    Serial.print('\n');
    
    myFile.print(st_values[0][i],4);
    myFile.print(',');
    myFile.print(st_values[1][i],4);
    myFile.print(',');
    myFile.print(st_values[2][i],4);
    myFile.print(',');
    myFile.print(st_values[3][i],0);
    myFile.print(',');
    myFile.print(st_values[4][i],0);
    myFile.print('\n');
  }

  //myFile.flush();
  
  Serial.println("--------------------------------------");
  
  //myFile.close();
  //delay(2);
  //myFile.open(filename, O_RDWR | O_CREAT | O_AT_END);
}

void writeRegister(char registerAddress, char value){  
  
  //Set Chip Select pin low to signal the beginning of an SPI packet.
  digitalWrite(ADXL_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(ADXL_CS, HIGH);
}

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(ADXL_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(ADXL_CS, HIGH);

}

bool inFF()
{
  char value[2];
  
  readRegister(INT_SOURCE,1,value);  // read the free fall interrupt
  
  if ( (value[0] & 0x04)==0x04 )
    return true;
  else
    return false;
}

Here's the output, the line is a marker to end one cycle:

à¥åDone Initializing SD Card 0.0000,-3.8064,-3.8064,57,1 0.1872,-3.9936,-3.9936,58,0 0.1248,-3.9936,-3.9936,59,1 0.1872,-3.9936,-3.9936,60,0 0.1872,-3.9936,-3.9936,60,0 0.2496,-3.8688,-3.8688,61,0 -0.1248,-3.9936,-3.9936,62,0 0.1872,-3.9936,-3.9936,62,0 0.1248,-3.9936,-3.9936,63,0 0.0000,-3.9312,-3.9312,64,1 0.0000,-3.8064,-3.8064,64,0 0.2496,-3.9936,-3.9936,65,0 0.0000,-3.8688,-3.8688,66,0 0.2496,-3.9936,-3.9936,67,0 0.3744,-3.8688,-3.8688,67,0 0.1248,-3.9312,-3.9312,68,1 0.0624,-3.9936,-3.9936,69,0 -0.4368,-3.9936,-3.9936,69,0 0.1248,-3.9936,-3.9936,70,0 0.2496,-3.9936,-3.9936,71,0 0.2496,-3.9312,-3.9312,71,0 0.1248,-3.9936,-3.9936,72,0 0.2496,-3.8688,-3.8688,73,1 0.1248,-3.9936,-3.9936,74,0 0.0624,-3.9312,-3.9312,74,0 0.1872,-3.9936,-3.9936,75,0 0.1248,-3.9936,-3.9936,76,0 0.2496,-3.8688,-3.8688,76,0 0.1872,-3.9312,-3.9312,77,0

0.1872,-3.9936,-3.9936,78,1

-0.3861,0.0000,0.0000,400,0 -0.3861,0.0000,0.0000,401,0 -0.3861,0.0000,0.0000,401,0 -0.3861,0.0000,0.0000,402,0 -0.3861,0.0000,0.0000,403,0 -0.3861,0.0000,0.0000,404,0 -0.3861,0.0000,0.0000,404,0 -0.3861,0.0000,0.0000,405,0 -0.3861,0.0000,0.0000,406,0 -0.3861,0.0000,0.0000,406,0 -0.3861,0.0000,0.0000,407,0 -0.3861,0.0000,0.0000,408,0 -0.3861,0.0000,0.0000,408,0 -0.3861,0.0000,0.0000,409,0 -0.3861,0.0000,0.0000,410,0 -0.3861,0.0000,0.0000,410,0 -0.3861,0.0000,0.0000,411,0 -0.3861,0.0000,0.0000,412,0 -0.3861,0.0000,0.0000,413,0 -0.3861,0.0000,0.0000,413,0 -0.3861,0.0000,0.0000,414,0 -0.3861,0.0000,0.0000,415,0 -0.3861,0.0000,0.0000,415,0 -0.3861,0.0000,0.0000,416,0 -0.3861,0.0000,0.0000,417,0 -0.3861,0.0000,0.0000,417,0 -0.3861,0.0000,0.0000,418,0 -0.3861,0.0000,0.0000,419,0 -0.3861,0.0000,0.0000,419,0 -0.3861,0.0000,0.0000,420,0

Anyone have any experience with the SDFat library? This program worked fine when I used the standard SD library but it was very slow. I modified the code earlier to use the PORT commands to change the digitalWrites, but that wasn’t significant.

I’m thinking the problem is that the SD card and the accelerometer are using the same pins. I solved that problem in the setup by setting the ADXL_CS to high before initializing the SD card and then initialized the ADXL345. I’m not sure if that will work in the loop because the SD card is still accessing the pins.

Is there anyway to stop the SD card from accessing those pins after it has written to the card? The SD library has a flush() function, but the SdFat library doesnt. How do I transfer control back to the accelerometer after the data is written?