Hello everyone!
I am attempting to construct a data-logger using an Arduino pro mini 5v, an ADXL345 accelerometer by Adafruit, along with an SD card breakout board using the SPI communication.
I have searched countless forums which leads me down tunnels getting me more confused than when I began so I figure I should post my problems here and get a direct answer to my own situation.
Through example codes, I have constructed my own code to read data from the ADXL345 and write it to the SD card on the SD breakout board. For the most part, I understand most of my code. I am not sure I need the 'interupt' features for my project but I left them in the code for the time being. It has compiled fine but when opening the serial monitor I generally receive all zeroes as output data. Occasionally, it prints out 13.9776000976-0.9983999252-0.9983999252
-0.9983999252-0.9983999252-0.9983999252 repeating. I have double checked my wiring and have both the ADXL345 and SD Breakout Board running over SPI together. When I move the accelerometer around, no numbers change on the output screen. I have the pro mini attached via Sparkfun's FTDI basic board to upload code.
//#SPI Communication
#include <SPI.h> //SPI communication library
#include <SD.h> //SD library
//Assign Chip Select
int CS = 8; // For ADXL345
const int CS_SD = 10; // For SD Breakout
// ADXL345 Registerr Addresses
#define DEVID 0x00 //Device ID Register
#define THRESH_TAP 0x1D //Tap Threshold
#define OFSX 0x1E //X-axis offset
#define OFSY 0x1F //Y-axis offset
#define OFSZ 0x20 //Z-axis offset
#define DURATION 0x21 //Tap Duration
#define LATENT 0x22 //Tap latency
#define WINDOW 0x23 //Tap window
#define THRESH_ACT 0x24 //Activity Threshold
#define THRESH_INACT 0x25 //Inactivity Threshold
#define TIME_INACT 0x26 //Inactivity Time
#define ACT_INACT_CTL 0x27 //Axis enable control for activity and inactivity detection
#define THRESH_FF 0x28 //free-fall threshold
#define TIME_FF 0x29 //Free-Fall Time
#define TAP_AXES 0x2A //Axis control for tap/double tap
#define ACT_TAP_STATUS 0x2B //Source of tap/double tap
#define BW_RATE 0x2C //Data rate and power mode control
#define POWER_CTL 0x2D //Power Control Register
#define INT_ENABLE 0x2E //Interrupt Enable Control
#define INT_MAP 0x2F //Interrupt Mapping Control
#define INT_SOURCE 0x30 //Source of interrupts
#define DATA_FORMAT 0x31 //Data format control
#define DATAX0 0x32 //X-Axis Data 0
#define DATAX1 0x33 //X-Axis Data 1
#define DATAY0 0x34 //Y-Axis Data 0
#define DATAY1 0x35 //Y-Axis Data 1
#define DATAZ0 0x36 //Z-Axis Data 0
#define DATAZ1 0x37 //Z-Axis Data 1
#define FIFO_CTL 0x38 //FIFO control
#define FIFO_STATUS 0x39 //FIFO status
//Buffer will hold values read from registers.
char values[10];
char output[20];
// x,y,x axis accelerometer values
int x, y, z;
double xg, yg, zg;
char tapType = 0;
char inactivityEvent = 0;
void setup()
{ //Initiate SPI communication instance.
SPI.begin();
//Configure SPI connection for ADXL345
SPI.setDataMode(SPI_MODE3);
//Create a serial connectino to display data
Serial.begin(9600);
//Set up Chip Select pin to be an output from Arduino.
pinMode(CS, OUTPUT);
//Before communication starts, CS needs to be set high
digitalWrite(CS, HIGH);
// Create interrupt that will trigger when a tap is detected
attachInterrupt( 0, tap, RISING);
//Put ADXL345 into +/- 4g range by writing the value 0x01 to the DATA_FORMAT register.
writeRegister(DATA_FORMAT, 0x01);
//Suggested to properly program accelerometer
writeRegister(INT_ENABLE, 0x00);
// Set a threshold of 3g
writeRegister(THRESH_INACT, 0x0F);
// Raise INACT event immeidately (otherwise it would be in 1 second...)
writeRegister(TIME_INACT, 0);
// Consider all axes AND compare THRESH_INACT from 0 acceleration (otherwise it would be differential)
writeRegister(ACT_INACT_CTL, 0x07);
// Send all interrrupts to INT 1 (PIN 2)
writeRegister(INT_MAP, 0);
// Enable interrupts for INACTIVITY only.
writeRegister(INT_ENABLE, 0x08);
//Put the ADXL345 into Measurement Mode by writing 0x08 to the POWER_CTL register.
writeRegister(POWER_CTL, 0x08); //Measurement mode
readRegister(INT_SOURCE, 1, values); //Clear the interrupts from the INT_SOURCE register.
//Initialize SD card
Serial.print(F("Initializing SD Card!"));
if (!SD.begin(CS_SD))
{
Serial.println(F("Card is Fail... "));
while (1);
Serial.println(F("Card is Ready... "));
}
}
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];
//Convert the accelerometer value to G's.
//With 10 bits measuring over a +/-4g range we can find how to convert by using the equation:
// Gs = Measurement Value * (G-range/(2^10)) or Gs = Measurement Value * (8/1024)
xg = x * 0.0078;
yg = y * 0.0078;
zg = z * 0.0078;
Serial.print(xg, DEC);
Serial.print(yg, DEC);
Serial.print(zg, DEC);
Serial.println();
if (inactivityEvent == 1) {
Serial.println("inactivity event");
inactivityEvent = 0;
}
//detachInterrupt(0);
delay(1000);
//attachInterrupt(0,tap,RISING);
}
//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);
}
void tap(void) {
//Clear the interrupts on the ADXL345
if (values[0] & (1 << 3)) {
inactivityEvent = 1;
} else {
inactivityEvent = 0;
}
readRegister(INT_SOURCE, 1, values);
}
///SD ///
void printData() {
//Initialize date and time strings
//Uncomment if needed
String time, date;
//// or 'long' x,y,z?
/////////////String xg,yg,zg??????
//placeholder variables for reading the accelerometer
//or "initialize variables"
// Below correct?? added 'g'
int xg = 0;
int yg = 0;
int zg = 0;
//Writing to a file //
File dataFile = SD.open("Test_1.csv", FILE_WRITE);
if (dataFile) //if there is a file....//
{
dataFile.print(date);
dataFile.print(F(","));
dataFile.print(time);
dataFile.print(F(","));
dataFile.print(x);
dataFile.print(F(","));
dataFile.print(y);
dataFile.print(F(","));
dataFile.println(z);
dataFile.close();
Serial.print(date);
Serial.print(F(","));
Serial.print(time);
Serial.print(F(","));
Serial.print(x);
Serial.print(F(","));
Serial.print(y);
Serial.print(F(","));
Serial.println(z);
}
else
{ Serial.println(F("Couldn't open Test_1 file."));
}
delay(1000);
}
Any help is greatly appreciated!! Apologies I am fairly new to the Arduino world and programming so the answer may be simpler than I think! Thank you.