Cannot get interrupt working with ADXL345 *SOLVED*

Hi guys

I am trying to get my atmega328p (bare bones arduino) to wake from sleep using an interrupt generated from the ADXL345. I can read all the values from the chip over the I2C bus, but cannot get it to generate an interrupt out of “INT1”.

Chip datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ADXL345.pdf

Library: https://github.com/Seeed-Studio/Accelerometer_ADXL345

Can anyone see what I am doing wrong?

My code is as follows

// **** INCLUDES *****
#include "LowPower.h"
#include <avr/wdt.h>
#include "Wire.h"
#include <ADXL345.h>

const int manualwakeuppin = 3;

ADXL345 adxl; //variable adxl is an instance of the ADXL345 library



void wakeUp()
{
  // Just a handler for the pin interrupt.
}

void setup()
{
  wdt_enable(WDTO_8S);
  setupIO();

  Wire.begin();
  Serial.begin(9600);delay(1000);
  Serial.println("BEGIN CODE OR LOCKED UP"); delay(1000);

   setupaccelerometer();

}



void loop()
{
  
    
  wdt_reset();
  wdt_disable();
  
  Serial.println("GOING TO SLEEP"); delay(1000);
  attachInterrupt(digitalPinToInterrupt(manualwakeuppin), wakeUp, CHANGE);
   
  LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
  wdt_enable(WDTO_8S);
  detachInterrupt(digitalPinToInterrupt(manualwakeuppin));
 
//interrupt test
  if (digitalRead(manualwakeuppin) == HIGH) {
     Serial.print("Accelerometer wake up at "); delay(1000);
       }


wdt_reset();

 printacceldata();


}

//accelerometer functions

void printacceldata(){
  //Boring accelerometer stuff 
 
  int x,y,z;  
  adxl.readXYZ(&x, &y, &z); //read the accelerometer values and store them in variables  x,y,z
  // Output x,y,z values 
  Serial.print("values of X , Y , Z: ");
  Serial.print(x);
  Serial.print(" , ");
  Serial.print(y);
  Serial.print(" , ");
  Serial.println(z);
  
  double xyz[3];
  double ax,ay,az;
  adxl.getAcceleration(xyz);
  ax = xyz[0];
  ay = xyz[1];
  az = xyz[2];
  Serial.print("X=");
  Serial.print(ax);
    Serial.println(" g");
  Serial.print("Y=");
  Serial.print(ay);
    Serial.println(" g");
  Serial.print("Z=");
  Serial.print(az);
    Serial.println(" g");
  Serial.println("**********************");
  delay(500);
 
}



void setupaccelerometer() {
  
 adxl.powerOn();

  //set activity/ inactivity thresholds (0-255)
  adxl.setActivityThreshold(75); //62.5mg per increment
  adxl.setInactivityThreshold(75); //62.5mg per increment
  adxl.setTimeInactivity(10); // how many seconds of no activity is inactive?
 
  //look of activity movement on this axes - 1 == on; 0 == off 
  adxl.setActivityX(1);
  adxl.setActivityY(1);
  adxl.setActivityZ(1);
 
  //look of inactivity movement on this axes - 1 == on; 0 == off
  adxl.setInactivityX(1);
  adxl.setInactivityY(1);
  adxl.setInactivityZ(1);
 
  //look of tap movement on this axes - 1 == on; 0 == off
  adxl.setTapDetectionOnX(1);
  adxl.setTapDetectionOnY(1);
  adxl.setTapDetectionOnZ(1);
 
  //set values for what is a tap, and what is a double tap (0-255)
  adxl.setTapThreshold(50); //62.5mg per increment
  adxl.setTapDuration(15); //625us per increment
  adxl.setDoubleTapLatency(80); //1.25ms per increment
  adxl.setDoubleTapWindow(200); //1.25ms per increment
 
  //set values for what is considered freefall (0-255)
  adxl.setFreeFallThreshold(7); //(5 - 9) recommended - 62.5mg per increment
  adxl.setFreeFallDuration(45); //(20 - 70) recommended - 5ms per increment
 
  //setting all interrupts to take place on int pin 1
  //I had issues with int pin 2, was unable to reset it
  adxl.setInterruptMapping( ADXL345_INT_SINGLE_TAP_BIT,   ADXL345_INT1_PIN );
  adxl.setInterruptMapping( ADXL345_INT_DOUBLE_TAP_BIT,   ADXL345_INT1_PIN );
  adxl.setInterruptMapping( ADXL345_INT_FREE_FALL_BIT,    ADXL345_INT1_PIN );
  adxl.setInterruptMapping( ADXL345_INT_ACTIVITY_BIT,     ADXL345_INT1_PIN );
  adxl.setInterruptMapping( ADXL345_INT_INACTIVITY_BIT,   ADXL345_INT1_PIN );
 
  //register interrupt actions - 1 == on; 0 == off  
  adxl.setInterrupt( ADXL345_INT_SINGLE_TAP_BIT, 1);
  adxl.setInterrupt( ADXL345_INT_DOUBLE_TAP_BIT, 1);
  adxl.setInterrupt( ADXL345_INT_FREE_FALL_BIT,  1);
  adxl.setInterrupt( ADXL345_INT_ACTIVITY_BIT,   1);
  adxl.setInterrupt( ADXL345_INT_INACTIVITY_BIT, 1);



}


void setupIO(){
   pinMode(manualwakeuppin, INPUT);
   pinMode(2, INPUT_PULLUP);

  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  pinMode(6, INPUT_PULLUP);
  pinMode(7, INPUT_PULLUP);
  pinMode(8, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);
  pinMode(13, INPUT_PULLUP);
  pinMode(A1, INPUT_PULLUP);
  pinMode(A2, INPUT_PULLUP);
  pinMode(A3, INPUT_PULLUP);
  pinMode(A4, INPUT_PULLUP);
  pinMode(A5, INPUT_PULLUP);
}

How are you powering the accelerometer? Are you certain that you are not powering it off when you go to sleep?

Thanks for the response

The accelerometer is powered directly from a battery. Not via the atmega328p.

Do you have the grounds connected? Post a wiring diagram (not Fritzing).

Can you read data from the accelerometer if you don't keep falling asleep?

Feel free to tell us as much as possible about what you have tried, as far as debugging the issue.

if I manually interrupt D3 by connecting it to VCC, the chip wakes up and reads the accelerometer values over the I2C bus just fine.

The grounds are all connected together.

The only difference is between this connection and when I want it to interrupt from the ADXL345 (instead of doing it manually via VCC) is I connect INT1 directly to D3.

The grounds are all connected together.

I can draw a diagram but you'll have to give me 5 minutes :slight_smile:

Excuse my crappy drawing, but here it is: Imgur: The magic of the Internet

As mentioned in the previous post, when I connect D3 from the atmega328p to VCC, it interrupts fine and reads the accelerometer values via SDA/SCL.

Just can't get it to interrupt via INT1.

I've even tried a simple while loop to check the status of D3:

int buttonState = digitalRead(manualwakeuppin);

if (buttonState == HIGH) {     
Serial.println ("1");
 } 
 else {
Serial.println ("0");
 }

It never returns a 1. So that interrupt is not being generated from the ADXL345 for some reason :\

Solved it - a bit of a poor solder connection and you need to clear the INT1 register after the interrupt has triggered from the ADXL345. In this library you can use adxl.getInterruptSource();