ADXL345 gives wiring error in SPI mode

Hello everyone,
I get the following output from serial monitor when trying to use the ADXL345 with Arduino Uno in SPI mode (I2C mode works fine):

“CA
Ooops, no ADXL345 detected … Check your wiring!”

See photo for wiring. I have tried it with another breakout board, and that produces the same results. Interestingly this tutorial says the breakout should work in SPI mode, but it’s only illustrated for I2C. Overview | ADXL345 Digital Accelerometer | Adafruit Learning System

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_ADXL345_U.h>    
/* Assign a unique ID to this sensor at the same time */
Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(13,12,11,9);
//Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified();

//Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(clock,miso,mosi,cs,sensorID);
void displaySensorDetails(void)
{
  sensor_t sensor;
  accel.getSensor(&sensor);
  Serial.println("------------------------------------");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value); Serial.println(" m/s^2");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println(" m/s^2");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println(" m/s^2"); 
  Serial.println("------------------------------------");
  Serial.println("");
  delay(500);
}

void displayDataRate(void)
{
  Serial.print  ("Data Rate:    ");

  switch(accel.getDataRate())
  {
    case ADXL345_DATARATE_3200_HZ:
      Serial.print  ("3200 ");
      break;
    case ADXL345_DATARATE_1600_HZ:
      Serial.print  ("1600 ");
      break;
    case ADXL345_DATARATE_800_HZ:
      Serial.print  ("800 ");
      break;
    case ADXL345_DATARATE_400_HZ:
      Serial.print  ("400 ");
      break;
    case ADXL345_DATARATE_200_HZ:
      Serial.print  ("200 ");
      break;
    case ADXL345_DATARATE_100_HZ:
      Serial.print  ("100 ");
      break;
    case ADXL345_DATARATE_50_HZ:
      Serial.print  ("50 ");
      break;
    case ADXL345_DATARATE_25_HZ:
      Serial.print  ("25 ");
      break;
    case ADXL345_DATARATE_12_5_HZ:
      Serial.print  ("12.5 ");
      break;
    case ADXL345_DATARATE_6_25HZ:
      Serial.print  ("6.25 ");
      break;
    case ADXL345_DATARATE_3_13_HZ:
      Serial.print  ("3.13 ");
      break;
    case ADXL345_DATARATE_1_56_HZ:
      Serial.print  ("1.56 ");
      break;
    case ADXL345_DATARATE_0_78_HZ:
      Serial.print  ("0.78 ");
      break;
    case ADXL345_DATARATE_0_39_HZ:
      Serial.print  ("0.39 ");
      break;
    case ADXL345_DATARATE_0_20_HZ:
      Serial.print  ("0.20 ");
      break;
    case ADXL345_DATARATE_0_10_HZ:
      Serial.print  ("0.10 ");
      break;
    default:
      Serial.print  ("???? ");
      break;
  } 
  Serial.println(" Hz"); 
}

void displayRange(void)
{
  Serial.print  ("Range:         +/- ");

  switch(accel.getRange())
  {
    case ADXL345_RANGE_16_G:
      Serial.print  ("16 ");
      break;
    case ADXL345_RANGE_8_G:
      Serial.print  ("8 ");
      break;
    case ADXL345_RANGE_4_G:
      Serial.print  ("4 ");
      break;
    case ADXL345_RANGE_2_G:
      Serial.print  ("2 ");
      break;
    default:
      Serial.print  ("?? ");
      break;
  } 
  Serial.println(" g"); 
}

void setup(void)
{
#ifndef ESP8266
  while (!Serial); // for Leonardo/Micro/Zero
#endif
  Serial.begin(9600);
  Serial.println("Accelerometer Test"); Serial.println("");
  pinMode(9,OUTPUT);
  /* Initialise the sensor */
  if(!accel.begin())
  {
    /* There was a problem detecting the ADXL345 ... check your connections */
    Serial.println("Ooops, no ADXL345 detected ... Check your wiring!");
    while(1);
  }

  /* Set the range to whatever is appropriate for your project */
  accel.setRange(ADXL345_RANGE_16_G);
  // displaySetRange(ADXL345_RANGE_8_G);
  // displaySetRange(ADXL345_RANGE_4_G);
  // displaySetRange(ADXL345_RANGE_2_G);

  /* Display some basic information on this sensor */
  displaySensorDetails();

  /* Display additional settings (outside the scope of sensor_t) */
  displayDataRate();
  displayRange();
  Serial.println("");
}

void loop(void)
{
  /* Get a new sensor event */
  sensors_event_t event;
  accel.getEvent(&event);

  /* Display the results (acceleration is measured in m/s^2) */
  Serial.print("X: "); Serial.print(event.acceleration.x); Serial.print("  ");
  Serial.print("Y: "); Serial.print(event.acceleration.y); Serial.print("  ");
  Serial.print("Z: "); Serial.print(event.acceleration.z); Serial.print("  ");Serial.println("m/s^2 ");
//  delay(500);
}

Doc1.pdf (262 KB)

Does it work okay if you change the CS pin from 9 to 10 in the code/wiring?
IIRC pin 10 is the SPI hardware CS pin and need to be set to output to ensure the SPI hardware is working in master mode.

Hi Riva,
Thanks for the reply. Changing to pin 10 in hardware & code doesn't change anything.

EDIT: I've also tried using different wires, checked whether the wires are still functional (with a multimeter) etc.

daanvV:
Thanks for the reply. Changing to pin 10 in hardware & code doesn't change anything.

EDIT: I've also tried using different wires, checked whether the wires are still functional (with a multimeter) etc.

Grrrr, github is returning a lot of unicorns this afternoon.

After looking at the Adafruit library I see it uses soft SPI so my comment about needing pin 10 set to output does not matter.
Maybe they have never tested the module using SPI so try another library. Here there appears to be a few options. I would start with the Sparkfun library first as it appears to use hardware SPI.

Great thanks, will have a look at this tomorrow!

Riva:
I would start with the Sparkfun library first as it appears to use hardware SPI.

Done that now, and this is the output I receive for the x, y and z axes (never changes).

-13365, -13365, -13365
-13365, -13365, -13365
-13365, -13365, -13365
-13365, -13365, -13365

Code:

/*  ********************************************* 
 *  SparkFun_ADXL345_Example
 *  Triple Axis Accelerometer Breakout - ADXL345 
 *  Hook Up Guide Example 
 *  
 *  Utilizing Sparkfun's ADXL345 Library
 *  Bildr ADXL345 source file modified to support 
 *  both I2C and SPI Communication
 *  
 *  E.Robert @ SparkFun Electronics
 *  Created: Jul 13, 2016
 *  Updated: Sep 06, 2016
 *  
 *  Development Environment Specifics:
 *  Arduino 1.6.11
 *  
 *  Hardware Specifications:
 *  SparkFun ADXL345
 *  Arduino Uno
 *  *********************************************/

#include <SparkFun_ADXL345.h>         // SparkFun ADXL345 Library

/*********** COMMUNICATION SELECTION ***********/
/*    Comment Out The One You Are Not Using    */
ADXL345 adxl = ADXL345(10);           // USE FOR SPI COMMUNICATION, ADXL345(CS_PIN);
//ADXL345 adxl = ADXL345();             // USE FOR I2C COMMUNICATION

/****************** INTERRUPT ******************/
/*      Uncomment If Attaching Interrupt       */
//int interruptPin = 2;                 // Setup pin 2 to be the interrupt pin (for most Arduino Boards)


/******************** SETUP ********************/
/*          Configure ADXL345 Settings         */
void setup(){
  
  Serial.begin(9600);                 // Start the serial terminal
  Serial.println("SparkFun ADXL345 Accelerometer Hook Up Guide Example");
  Serial.println();
  
  adxl.powerOn();                     // Power on the ADXL345

  adxl.setRangeSetting(16);           // Give the range settings
                                      // Accepted values are 2g, 4g, 8g or 16g
                                      // Higher Values = Wider Measurement Range
                                      // Lower Values = Greater Sensitivity

  adxl.setSpiBit(0);                  // Configure the device to be in 4 wire SPI mode when set to '0' or 3 wire SPI mode when set to 1
                                      // Default: Set to 1
                                      // SPI pins on the ATMega328: 11, 12 and 13 as reference in SPI Library 
   
//  Set SPI mode to that matching ADXL345 (I guess this would be in here by default? ) 

  adxl.setActivityXYZ(1, 0, 0);       // Set to activate movement detection in the axes "adxl.setActivityXYZ(X, Y, Z);" (1 == ON, 0 == OFF)
  adxl.setActivityThreshold(75);      // 62.5mg per increment   // Set activity   // Inactivity thresholds (0-255)
 
  adxl.setInactivityXYZ(1, 0, 0);     // Set to detect inactivity in all the axes "adxl.setInactivityXYZ(X, Y, Z);" (1 == ON, 0 == OFF)
  adxl.setInactivityThreshold(75);    // 62.5mg per increment   // Set inactivity // Inactivity thresholds (0-255)
  adxl.setTimeInactivity(10);         // How many seconds of no activity is inactive?

  adxl.setTapDetectionOnXYZ(0, 0, 1); // Detect taps in the directions turned ON "adxl.setTapDetectionOnX(X, Y, Z);" (1 == ON, 0 == OFF)
 
  // Set values for what is considered a TAP and what is a DOUBLE TAP (0-255)
  adxl.setTapThreshold(50);           // 62.5 mg per increment
  adxl.setTapDuration(15);            // 625 μs per increment
  adxl.setDoubleTapLatency(80);       // 1.25 ms per increment
  adxl.setDoubleTapWindow(200);       // 1.25 ms per increment
 
  // Set values for what is considered FREE FALL (0-255)
  adxl.setFreeFallThreshold(7);       // (5 - 9) recommended - 62.5mg per increment
  adxl.setFreeFallDuration(30);       // (20 - 70) recommended - 5ms per increment
 
  // Setting all interupts to take place on INT1 pin
  //adxl.setImportantInterruptMapping(1, 1, 1, 1, 1);     // Sets "adxl.setEveryInterruptMapping(single tap, double tap, free fall, activity, inactivity);" 
                                                        // Accepts only 1 or 2 values for pins INT1 and INT2. This chooses the pin on the ADXL345 to use for Interrupts.
                                                        // This library may have a problem using INT2 pin. Default to INT1 pin.
  
  // Turn on Interrupts for each mode (1 == ON, 0 == OFF)
  adxl.InactivityINT(1);
  adxl.ActivityINT(1);
  adxl.FreeFallINT(1);
  adxl.doubleTapINT(1);
  adxl.singleTapINT(1);
  
//attachInterrupt(digitalPinToInterrupt(interruptPin), ADXL_ISR, RISING);   // Attach Interrupt

}

/****************** MAIN CODE ******************/
/*     Accelerometer Readings and Interrupt    */
void loop(){
  
  // Accelerometer Readings
  int x,y,z;   
  adxl.readAccel(&x, &y, &z);         // Read the accelerometer values and store them in variables declared above x,y,z

  // Output Results to Serial
  /* UNCOMMENT TO VIEW X Y Z ACCELEROMETER VALUES */  
  Serial.print(x);
  Serial.print(", ");
  Serial.print(y);
  Serial.print(", ");
  Serial.println(z); 
  
//  ADXL_ISR();
  // You may also choose to avoid using interrupts and simply run the functions within ADXL_ISR(); 
  //  and place it within the loop instead.  
  // This may come in handy when it doesn't matter when the action occurs. 

}

/********************* ISR *********************/
/* Look for Interrupts and Triggered Action    */
void ADXL_ISR() {
  
  // getInterruptSource clears all triggered actions after returning value
  // Do not call again until you need to recheck for triggered actions
  byte interrupts = adxl.getInterruptSource();
  
  // Free Fall Detection
  if(adxl.triggered(interrupts, ADXL345_FREE_FALL)){
    Serial.println("*** FREE FALL ***");
    //add code here to do when free fall is sensed
  } 
  
  // Inactivity
  if(adxl.triggered(interrupts, ADXL345_INACTIVITY)){
    Serial.println("*** INACTIVITY ***");
     //add code here to do when inactivity is sensed
  }
  
  // Activity
  if(adxl.triggered(interrupts, ADXL345_ACTIVITY)){
    Serial.println("*** ACTIVITY ***"); 
     //add code here to do when activity is sensed
  }
  
  // Double Tap Detection
  if(adxl.triggered(interrupts, ADXL345_DOUBLE_TAP)){
    Serial.println("*** DOUBLE TAP ***");
     //add code here to do when a 2X tap is sensed
  }
  
  // Tap Detection
  if(adxl.triggered(interrupts, ADXL345_SINGLE_TAP)){
    Serial.println("*** TAP ***");
     //add code here to do when a tap is sensed
  } 
}

Ok, finally it works now using the sparkfun library (also using pin 9). :grinning: :grinning: :grinning: I added a couple of delay(500) statements in the setup, which seems to have done the trick. See code below.

Would anyone know why this is necessary? Why are these delay statements so important, and why aren’t they included in the sparkfun library?

N.B. If tried adding the same delays to the Adafruit example script, with no results.

/*  ********************************************* 
 *  SparkFun_ADXL345_Example
 *  Triple Axis Accelerometer Breakout - ADXL345 
 *  Hook Up Guide Example 
 *  
 *  Utilizing Sparkfun's ADXL345 Library
 *  Bildr ADXL345 source file modified to support 
 *  both I2C and SPI Communication
 *  
 *  E.Robert @ SparkFun Electronics
 *  Created: Jul 13, 2016
 *  Updated: Sep 06, 2016
 *  
 *  Development Environment Specifics:
 *  Arduino 1.6.11
 *  
 *  Hardware Specifications:
 *  SparkFun ADXL345
 *  Arduino Uno
 *  *********************************************/

#include <SparkFun_ADXL345.h>         // SparkFun ADXL345 Library

/*********** COMMUNICATION SELECTION ***********/
/*    Comment Out The One You Are Not Using    */
ADXL345 adxl = ADXL345(9);           // USE FOR SPI COMMUNICATION, ADXL345(CS_PIN);
//ADXL345 adxl = ADXL345();             // USE FOR I2C COMMUNICATION

/****************** INTERRUPT ******************/
/*      Uncomment If Attaching Interrupt       */
//int interruptPin = 2;                 // Setup pin 2 to be the interrupt pin (for most Arduino Boards)


/******************** SETUP ********************/
/*          Configure ADXL345 Settings         */
void setup(){
  
  Serial.begin(9600);                 // Start the serial terminal
  Serial.println("SparkFun ADXL345 Accelerometer Hook Up Guide Example");
  Serial.println();
  
  adxl.powerOn();                     // Power on the ADXL345
  delay(500); 
  adxl.setRangeSetting(16);           // Give the range settings
                                      // Accepted values are 2g, 4g, 8g or 16g
                                      // Higher Values = Wider Measurement Range
                                      // Lower Values = Greater Sensitivity
  delay(500); 
  adxl.setSpiBit(0);                  // Configure the device to be in 4 wire SPI mode when set to '0' or 3 wire SPI mode when set to 1
                                      // Default: Set to 1
                                      // SPI pins on the ATMega328: 11, 12 and 13 as reference in SPI Library 
  delay(500); 
//  Set SPI mode to that matching ADXL345 (I guess this would be in here by default? ) 

  adxl.setActivityXYZ(1, 0, 0);       // Set to activate movement detection in the axes "adxl.setActivityXYZ(X, Y, Z);" (1 == ON, 0 == OFF)
  adxl.setActivityThreshold(75);      // 62.5mg per increment   // Set activity   // Inactivity thresholds (0-255)
 
  adxl.setInactivityXYZ(1, 0, 0);     // Set to detect inactivity in all the axes "adxl.setInactivityXYZ(X, Y, Z);" (1 == ON, 0 == OFF)
  adxl.setInactivityThreshold(75);    // 62.5mg per increment   // Set inactivity // Inactivity thresholds (0-255)
  adxl.setTimeInactivity(10);         // How many seconds of no activity is inactive?

  adxl.setTapDetectionOnXYZ(0, 0, 1); // Detect taps in the directions turned ON "adxl.setTapDetectionOnX(X, Y, Z);" (1 == ON, 0 == OFF)
 
  // Set values for what is considered a TAP and what is a DOUBLE TAP (0-255)
  adxl.setTapThreshold(50);           // 62.5 mg per increment
  adxl.setTapDuration(15);            // 625 μs per increment
  adxl.setDoubleTapLatency(80);       // 1.25 ms per increment
  adxl.setDoubleTapWindow(200);       // 1.25 ms per increment
 
  // Set values for what is considered FREE FALL (0-255)
  adxl.setFreeFallThreshold(7);       // (5 - 9) recommended - 62.5mg per increment
  adxl.setFreeFallDuration(30);       // (20 - 70) recommended - 5ms per increment
 
  // Setting all interupts to take place on INT1 pin
  //adxl.setImportantInterruptMapping(1, 1, 1, 1, 1);     // Sets "adxl.setEveryInterruptMapping(single tap, double tap, free fall, activity, inactivity);" 
                                                        // Accepts only 1 or 2 values for pins INT1 and INT2. This chooses the pin on the ADXL345 to use for Interrupts.
                                                        // This library may have a problem using INT2 pin. Default to INT1 pin.
  
  // Turn on Interrupts for each mode (1 == ON, 0 == OFF)
  adxl.InactivityINT(1);
  adxl.ActivityINT(1);
  adxl.FreeFallINT(1);
  adxl.doubleTapINT(1);
  adxl.singleTapINT(1);
  
//attachInterrupt(digitalPinToInterrupt(interruptPin), ADXL_ISR, RISING);   // Attach Interrupt

}

/****************** MAIN CODE ******************/
/*     Accelerometer Readings and Interrupt    */
void loop(){
  
  // Accelerometer Readings
  int x,y,z;   
  adxl.readAccel(&x, &y, &z);         // Read the accelerometer values and store them in variables declared above x,y,z

  // Output Results to Serial
  /* UNCOMMENT TO VIEW X Y Z ACCELEROMETER VALUES */  
  Serial.print(x);
  Serial.print(", ");
  Serial.print(y);
  Serial.print(", ");
  Serial.println(z); 
  
//  ADXL_ISR();
  // You may also choose to avoid using interrupts and simply run the functions within ADXL_ISR(); 
  //  and place it within the loop instead.  
  // This may come in handy when it doesn't matter when the action occurs. 

}

/********************* ISR *********************/
/* Look for Interrupts and Triggered Action    */
void ADXL_ISR() {
  
  // getInterruptSource clears all triggered actions after returning value
  // Do not call again until you need to recheck for triggered actions
  byte interrupts = adxl.getInterruptSource();
  
  // Free Fall Detection
  if(adxl.triggered(interrupts, ADXL345_FREE_FALL)){
    Serial.println("*** FREE FALL ***");
    //add code here to do when free fall is sensed
  } 
  
  // Inactivity
  if(adxl.triggered(interrupts, ADXL345_INACTIVITY)){
    Serial.println("*** INACTIVITY ***");
     //add code here to do when inactivity is sensed
  }
  
  // Activity
  if(adxl.triggered(interrupts, ADXL345_ACTIVITY)){
    Serial.println("*** ACTIVITY ***"); 
     //add code here to do when activity is sensed
  }
  
  // Double Tap Detection
  if(adxl.triggered(interrupts, ADXL345_DOUBLE_TAP)){
    Serial.println("*** DOUBLE TAP ***");
     //add code here to do when a 2X tap is sensed
  }
  
  // Tap Detection
  if(adxl.triggered(interrupts, ADXL345_SINGLE_TAP)){
    Serial.println("*** TAP ***");
     //add code here to do when a tap is sensed
  } 
}

I could understand a delay after adxl.powerOn(); but unsure why you would need the other delays. Does the Sparkfun example use delays?

Riva:
Does the Sparkfun example use delays?

No it had none, I added them in there. And the error doesn’t seem reproduceable in the sense that when I take all the delays back out, the output it still good (giving values I expect, i.e. somewhere around 9.81 m/s^2).

Another thing that has popped up. I now connect two accelerometers (SPI) and both measure along the same (z) axis. Every now and then one of the accelerometers has a value which is extremely high (adxl_1 in the code), around 4091, whereas it should be around 4. See attachment.
So I don’t know whether this is something to do with bad wire connections, or with something else. I moved the wires around a bit (put them in and out of them contacts) and inserted an extra delay after adxl_1.setActivity and then the problem was gone. Again, this doesn’t seem reproducible though because when I remove the delay, the problem remains gone.

Could it be that with SPI, switching rapidly between different devices and writing to their registers, sometimes it goes too fast and numbers end up in the wrong place? Or do you think this might be a wire issue?
I posted the same question on the adafruit forum, and a moderator there said it might be due to speed and tripping over constraints. I do wonder how to make this more robust though, because generating a random near-infinite number every so often is not exactly what I had in mind when making precise measurements.

EDIT: To test whether it might be something to do with the wires, I moved them around and shook them up a bit whilst measuring. I moved the wire pins around in the headers very fast, but this doesn’t produce the big numbers on the serial monitor that I was seeing earlier. So I don’t think it’s anything to do with the wires.

// ***************** SETUP ADXL 345 ****************************
  adxl_1.powerOn();                     // Power on the ADXL345
  delay(100);
  adxl_1.setRangeSetting(16);           // Give the range settings
  delay(100);
  adxl_1.setSpiBit(0);                  // Select '0'for 4 wire SPI, default is '1' for 3 wire SPI
  delay(100);
  adxl_1.setRate(dataRate);                  
  delay(100);
  adxl_1.setActivityXYZ(0, 0, 1);       // Set to activate movement detection in the axes "adxl.setActivityXYZ(X, Y, Z);" (1 == ON, 0 == OFF)  
  delay(100);
// 
  adxl_2.powerOn();                     // Power on the ADXL345
  delay(100);
  adxl_2.setRangeSetting(16);           // Give the range settings
  delay(100);
  adxl_2.setSpiBit(0);  
  delay(100);
  adxl_2.setRate(dataRate);                  
  delay(100);
  adxl_2.setActivityXYZ(0, 0, 1);       // Set to activate movement detection in the axes "adxl.setActivityXYZ(X, Y, Z);" (1 == ON, 0 == OFF)

Random Huge number.pdf (28.1 KB)

Do you get the random readings when using I2C instead of SPI?
Maybe the SPI is not as mature/well tested as I2C or breadboard is creating random error (some of the cheap stuff is more trouble than its worth)

My sensors have stopped working again. >:(
I had put the project aside for a while, and haven't changed anything, and now when I try it again only one accelerometer gives a sensible output and the other one gives a value of -8191.96 (m/s^2).
I haven't tried with I2C yet, because you need a multiplexer for two or more of the same devices. However using a single accelerometer (either one) with either SPI or I2C works fine.
The moment I have two accelerometers connected via SPI, only one of them will output sensible values and the other one outputs garbage.

EDIT: I've also tried shortening the wires because I read that that could cause problems, but I've had no luck so far.

Just a though but are you using a separate CS pins for each ADXL345 and defining two of them in your sketches. If you have connected both to a single CS pin then you will get clashes.

Hi Riva, yes I have seperate CS pins, and using the Sparkfun ADXL library the CS pins are passed into the initialisation.
See attachment, and latest code below. My current code gives as output:
0, -13365, 589.62
0, -13365, 620.35
-1, -13365, 618.81
-1, -13365, 588.24
-1, -13365, 588.24
0, -13365, 588.24

The first column being “good” values that correspond to motion, the second column being “bad” constant values.

#include <SparkFun_ADXL345.h>                // SparkFun ADXL345 Library
#include <pins_arduino.h>

#define DEBUG_ENABLED           // COMMENT THIS IF DEBUGGING IS NOT NEEDED

#define LED_BUILTIN               13
#define VBATPIN                   A9
#define ADXL345_MG2G_MULTIPLIER   (0.004)      // 4mg per lsb
#define SENSORS_GRAVITY_STANDARD  (9.80665F)


ADXL345 adxl_1 = ADXL345(9);

ADXL345 adxl_2 = ADXL345(8);

/// INTERRUPT
/*      Uncomment If Attaching Interrupt       */
int     interruptPin  =   1;      // Setup pin X to be the interrupt pin


int     dataRate      =   400;

unsigned long   loopT =   1 / ((unsigned long)dataRate) * 1000 * 1000; // = 1/500*1000*1000; // The duration for one loop, expressed in microseconds


// ADXL # 1
double   ab_accX_1;
double   ab_accY_1;
double   ab_accZ_1;
double   accX_1;
double   accY_1;
double   accZ_1;

// Offset due to gravity/sensor
double gXoffset_1;
double gYoffset_1;
double gZoffset_1;

// ADXL # 2
double   ab_accX_2;
double   ab_accY_2;
double   ab_accZ_2;
double   accX_2;
double   accY_2;
double   accZ_2;

// Offset due to gravity/sensor
double gXoffset_2;
double gYoffset_2;
double gZoffset_2;

unsigned long dt;
unsigned long t1;
unsigned long tNow;
double        dtS;




void DEBUG_TRACE(String str)
{
#ifdef DEBUG_ENABLED
  Serial.println(String(str));
#endif
}


void setup()
{

  delay(2000);
  Serial.begin(115200);
  delay(2000); 


  // ***************** SETUP ADXL 345 ****************************
  adxl_1.powerOn();                     // Power on the ADXL345
  delay(500);
  adxl_1.setRangeSetting(16);           // Give the range settings
  delay(500);
  adxl_1.setSpiBit(0);                  // Select '0'for 4 wire SPI, default is '1' for 3 wire SPI
  delay(500);
  adxl_1.setRate(dataRate);
  delay(500);
  adxl_1.setActivityXYZ(0, 0, 1);       // Set to activate movement detection in the axes "adxl.setActivityXYZ(X, Y, Z);" (1 == ON, 0 == OFF)
  delay(500);
  //
  adxl_2.powerOn();                     // Power on the ADXL345
  delay(500);
  adxl_2.setRangeSetting(16);           // Give the range settings
  delay(500);
  adxl_2.setSpiBit(0);
  delay(500);
  adxl_2.setRate(dataRate);
  delay(500);
  adxl_2.setActivityXYZ(0, 0, 1);       // Set to activate movement detection in the axes "adxl.setActivityXYZ(X, Y, Z);" (1 == ON, 0 == OFF)
  delay(500);
  double offXsum_1 = 0;
  double offYsum_1 = 0;
  double offZsum_1 = 0;

  double offXsum_2 = 0;
  double offYsum_2 = 0;
  double offZsum_2 = 0;

  int j = 0;

  unsigned long calMil = millis();



  //  Serial.println("************START*****************");
  // 10 seconds worth of measurements for calibration
  while (millis() -  calMil < 1000) // should be 10 000 (10 seconds)
  {
    // Accelerometer Readings
    j = j + 1;
    int x_1, y_1, z_1;
    int x_2, y_2, z_2;
    adxl_1.readAccel(&x_1, &y_1, &z_1);
    adxl_2.readAccel(&x_2, &y_2, &z_2);

    accX_1 = 0.3065 * x_1;
    accY_1 = 0.3065 * y_1;
    accZ_1 = 0.3065 * z_1;

    accX_2 = 0.3065 * x_2;
    accY_2 = 0.3065 * y_2;
    accZ_2 = 0.3065 * z_2;

    offXsum_1 += accX_1;
    offYsum_1 += accY_1;
    offZsum_1 += accZ_1;

    offXsum_2 += accX_2;
    offYsum_2 += accY_2;
    offZsum_2 += accZ_2;
//    String dataString = String(accY_1) + String(", ") + String(accY_2);
//    Serial.println(dataString);
  }

  gXoffset_1 = (double) offXsum_1 / j;
  gYoffset_1 = (double) offYsum_1 / j;
  gZoffset_1 = (double) offZsum_1 / j;

  gXoffset_2 = (double) offXsum_2 / j;
  gYoffset_2 = (double) offYsum_2 / j;
  gZoffset_2 = (double) offZsum_2 / j;


}

void loop()
{

  //  Serial.print(", "); Serial.println(ab_accZ_2);
  // *************************** ADXL345 ********************************

  int x_1, y_1, z_1;
  int x_2, y_2, z_2;
  //  Serial.println(z_1);
  adxl_1.readAccel(&x_1, &y_1, &z_1);         // Read the accelerometer values and store them in variables declared above x,y,z
  adxl_2.readAccel(&x_2, &y_2, &z_2);

  accY_1 = 0.3065 * double(y_1);
  accY_2 = 0.3065 * double(y_2);

 
  ab_accY_1 = abs(abs(accY_1) - abs(gYoffset_1));
  ab_accY_2 = abs(abs(accY_2) - abs(gYoffset_2));

  accY_1    = accY_1 - abs(gYoffset_1);
  accY_2    = accY_2 - abs(gYoffset_2);
  

  
  while (micros() - t1  < loopT) {
    // Wait to ensure rate of loop is 400/500/800 Hz
  }
  tNow      =     micros();
  dt        =     tNow - t1;          // Time step in micro seconds
  t1        =     tNow;
  dtS       =     (double) dt / 1000000;  // Time step in seconds

  
//  String dataString = String(accY_1) + String(", ") + String(accY_2) + String(", ") + String((double) 1 / dtS);
  String dataString = String(y_1) + String(", ") + String(y_2) + String(", ") + String((double) 1 / dtS);
  DEBUG_TRACE(dataString);

}

Wiring.pdf (159 KB)