The accelerometer outputs data correctly before the function setupRAM is called. After setupRAM is called the accelerometer outputs data as if the accelerometer was not correctly initialized. In other words, I can get the accelerometer to read correctly when setupRAM call is commented out.
//Add the SPI library so we can communicate with the ADXL345 sensor + SD Card + File time stamp
#include <SPI.h>
#include <SdFat.h>
#include <SdFatUtil.h>
#include <M23LCV1024.h>
#include <RamDisk.h>
#include <RTClib.h>
#include <Wire.h>
// Multiple SRAM chips so use CS pin list.
uint8_t csPins[] = {9, 8};
const uint8_t CHIP_COUNT = 2;
M23LCV1024 ram;
const uint8_t SD_CS_PIN = SS;
SdFat sd;
SdBaseFile sdFile;
RamVolume vol;
RamFile ramFile;
char buf[40];
/* ADXL Connections
SCL => pin 13
SDA => pin 11
SDO => pin 12
CS => pin 5
*/
const int AccCS=5; // Assign ADXL to pin 5
const int inputPin = 2; // input pin for the on/off switch. The other side of switch goes to gnd
int count;
static boolean firstFlag = false; // Flag to correct first read interval error
char FILENAME[15];
int fileNum = 0; // part of file name
// some of the registers available on the ADXL345.
char BW_RATE = 0x2C; //Bandwidth Register
char POWER_CTL = 0x2D; //Power Control Register
char DATA_FORMAT = 0x31; // g range setting
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 data[50]; // x,y,z data to be stored into SD Card
char values[10]; //This buffer will hold values read from the ADXL345 registers.
int x,y,z; //These variables will be used to hold the x,y and z axis accelerometer values.
RTC_DS1307 RTC; // define the Real Time Clock object
//------------------------------------------------------------------------------
void setup(){
Serial.begin(115200);
SPI.begin(); //Initiate an SPI communication instance.
SPI.setDataMode(SPI_MODE3); //Configure the SPI connection for the ADXL345.
pinMode(AccCS, OUTPUT); //Set up the Chip Select pin to be an output from the Arduino.
digitalWrite(AccCS, HIGH); //Set Chip Select pin to high.
writeRegister(DATA_FORMAT, 0x01); //Put the ADXL345 into +/- 4G range by writing the value 0x01 to the DATA_FORMAT register.
writeRegister(POWER_CTL, 0x08); //Put the ADXL345 into Measure Mode by writing 0x08 to the POWER_CTL register.
writeRegister(BW_RATE, 0x0D); //Set bandwidth to: E= 800 Hz, D=400, C=200, B=100, A=50
pinMode(inputPin, INPUT); // Switch input
digitalWrite(inputPin, HIGH); // turn on internal pull-up for on/off switch
setupRAM();
}
//----------------------------------------------------------------------------
void loop(){
int val = digitalRead(inputPin); // read on/off switch
if (val == LOW) // if switch is LOW, take measurements
{
readAcc();
}
else
{
if (firstFlag == true)
{
saveToSD(); // save ram to SD
fileNum++; //`increase file name by 1
setupRAM(); // get ready for the next measurement & format ram
}
count = 0; // count number of measurements
firstFlag = false; // reset first count interval flag
}
}
//-------------------------------------------------------------------------------
void setupRAM(){
ram.begin(csPins, CHIP_COUNT);
if (!sd.begin(SD_CS_PIN)) sd.errorHalt();
if (!vol.format(&ram)) {
Serial.println(F("format fail"));
return;
}
if (!vol.init(&ram)) {
Serial.println(F("init fail"));
return;
}
Wire.begin(); // add time stamp
if (!RTC.begin()) {
Serial.println("RTC failed");
while(1);
}
SdFile::dateTimeCallback(dateTime); // set date time callback function
sprintf(FILENAME, "run_%d.CSV", fileNum);
vol.remove(FILENAME); //format
if (!ramFile.open(FILENAME, O_CREAT | O_RDWR)) {
Serial.println(F("open fail"));
return;
}
Serial.println(F("Ready to write ramFile"));
}
//-------------------------------------------------------------------
void saveToSD()
{
// like closing and opening file (need to update dir for ls).
ramFile.sync();
ramFile.rewind();
// vol.ls(&Serial, LS_DATE | LS_SIZE);
if (!sdFile.open(FILENAME, O_CREAT | O_RDWR | O_TRUNC)) {
Serial.println(F("sdFile.open failed"));
return;
}
Serial.println(F("Copying ramFile to sdFile"));
int n;
while ((n = ramFile.read(buf, sizeof(buf))) > 0) {
if (sdFile.write(buf, n) != n) {
Serial.println(F("sdFile.write failed"));
return;
}
}
ramFile.close();
sdFile.close();
sd.ls(&Serial, LS_DATE | LS_SIZE);
Serial.println(F("Done"));
}
//------------------------------------------------------------------------------
void readAcc()
{
static const unsigned long READ_INTERVAL = 5; // duration between Accelerometer reads in ms
static unsigned long lastReadTime = millis(); // define for first loop
static unsigned long MeasurementTime; // determine time to do one measurement
// static unsigned long MeasurementError;
if(millis() - lastReadTime >= READ_INTERVAL)
{
lastReadTime = millis();
SPI.setDataMode(SPI_MODE3); //Configure the SPI connection for the ADXL345.
//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];
if (firstFlag)
{
//Print the results to the terminal.
sprintf(data, "%d,%d,%d,%d",count,x,y,z);
Serial.println(data);
ramFile.println(data);
count++;
MeasurementTime = millis() - lastReadTime;
}
else
{
firstFlag = true; // flag OK to get measurements
}
}
}
//----------------------------------------------------------------
//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.
// Serial.println(registerAddress);
// Serial.println(value);
digitalWrite(AccCS, 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(AccCS, 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(AccCS, 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);
}
digitalWrite(AccCS, HIGH); //Set the Chips Select pin high to end the SPI packet.
}
//--------------------------------------------------------------------------------
// call back for file timestamps
void dateTime(uint16_t* date, uint16_t* time) {
DateTime now = RTC.now();
// return date using FAT_DATE macro to format fields
*date = FAT_DATE(now.year(), now.month(), now.day());
// return time using FAT_TIME macro to format fields
*time = FAT_TIME(now.hour(), now.minute(), now.second());
}
Thanks,
Gerry