ADXL345 interrupt problems!

Hi!

I wonder if anyone has experience with interrupts to INT0 from ADXL345 breakout to an Arduino UNO R3. I built a program that works perfect with reading the interrupt from ADXL345 INT1 to arduino with polling the digital pin 2 with "digitalRead" on that pin so I know the hardware works and that an interrupt actually takes place from the ADXL345.

My problem begins when I do a "attachInterrupt" and its never seems to actually trigger. The idea is to make 50 interrups per second and let the arduino sleep between reads.

I would love to see a working example :slight_smile:

Post your code. It doesn't matter (that much) what the interrupt is from.

Mark

Here comes some code:

#define F_CPU 16000000
#define ARDUINO 100

#define DEVICE (0x1D)			// ADXL345 I2C device address
#define TO_READ (6)				// num of bytes we are going to read each time (two bytes for each axis)
#define pbIN 0					// Arduino pin which is connected to INT1 from the ADXL345
#define ledOut 8

#include "Arduino.h"

#include "Wire.h"
#include "Wire.cpp"

#include "twi.h"
#include "twi.c"

#include "binary_const.h"		// with this we can use something B8(01010101) that it will convert to 85 at compile time

#include <avr/power.h>
#include <avr/sleep.h>
								
#define R_DEVID  0
#define R_THRESH_TAP 29
#define R_OFSX 30
#define R_OFSY 31
#define R_OFSZ 32
#define R_DUR 33
#define R_LATENT 34
#define R_WINDOW 35
#define R_THRESH_ACT 36
#define R_THRESH_INACT 37
#define R_TIME_INACT 38
#define R_ACT_INACT_CTL 39
#define R_THRESH_FF 40
#define R_TIME_FF 41
#define R_TAP_AXES 42
#define R_ACT_TAP_STATUS 43
#define R_BW_RATE 44
#define R_POWER_CTL 45
#define R_INT_ENABLE 46
#define R_INT_MAP 47
#define R_INT_SOURCE 48
#define R_DATA_FORMAT 49
#define R_DATAX0 50
#define R_DATAX1 51
#define R_DATAY0 52
#define R_DATAY1 53
#define R_DATAZ0 54
#define R_DATAZ1 55
#define R_FIFO_CTL 56
#define R_FIFO_STATUS 57

byte buff[TO_READ];			//6 bytes buffer for saving data read from the device
char str[40];				//string buffer to transform data before sending it to the serial port
boolean inspected = 0;

volatile int state = 1;		// The input state toggle

// Declarations
void writeTo(int device, byte address, byte val);
void readFrom(int device, byte address, int num, byte buff[]);
byte readByte(int device, byte address);
void stateChange();

// Arduino compliance
void setup();
void loop();

void setup()
{
  Wire.begin();									// join i2c bus (address optional for master)
  Serial.begin(57600);							// start serial for output
  
  // ----------------------------------------------------------------------------
  
  // Low power - 45 uA, 50 Hz
  //writeTo(DEVICE, R_BW_RATE, B8(00011001));
  
  // Low power - 34 uA, 12.5 Hz
  writeTo(DEVICE, R_BW_RATE, B8(00010111));
  
  // interrupts setup; DATA_READY, Activity, Inactivity
  writeTo(DEVICE, R_INT_MAP, B8(01100111));				// send all interrupts to ADXL345's INT1 pin
  writeTo(DEVICE, R_INT_ENABLE, B8(10011000));			// enable DATA_READY, Activity, and Inactivity
  
  // inactivity configuration
  writeTo(DEVICE, R_TIME_INACT, 10);					// 1s / LSB
  writeTo(DEVICE, R_THRESH_INACT, 3);					// 62.5mg / LSB
  // also working good with high movements: R_TIME_INACT=5, R_THRESH_INACT=16, R_ACT_INACT_CTL=B8(00000111)
  // but unusable for a quite slow movements
  
  // activity configuration
  writeTo(DEVICE, R_THRESH_ACT, 8);						// 62.5mg / LSB
   
  // activity and inactivity control
  writeTo(DEVICE, R_ACT_INACT_CTL, B8(11111111));		// enable activity and inactivity detection on x,y,z using ac
  
  // Bypass mode, INT1 enabled (later INT2 maybe!!??)
  writeTo(DEVICE, R_FIFO_CTL, B8(00000000));
  
  // DATA_FORMAT, 16G, Full resolution
  writeTo(DEVICE, R_DATA_FORMAT, B8(00001011));
 
  // Enable measurement mode;    +++++ LAST STEP +++++
  // set the ADXL345 in measurement and sleep Mode: this will save power while while we will still be able to detect activity
  // set the Link bit to 1 so that the activity and inactivity functions aren't concurrent but alternatively activated
  // set the AUTO_SLEEP bit to 1 so that the device automatically goes to sleep when it detects inactivity
  writeTo(DEVICE, R_POWER_CTL, B8(00111100));
  
  // -----------------------------------------------------------------------------------

	pinMode(ledOut, OUTPUT);
	attachInterrupt(pbIN, stateChange, LOW);
}

void loop()
{
	Serial.print(state,DEC);
	delay(100);
		
	//sleepNow();
}


// Definitions

void stateChange()
{
	state = 0;
	digitalWrite(ledOut, HIGH); // Test if it triggers, if Serial might fool me!!
}

// ---------------- Functions ------------------
//Writes val to address register on device
void writeTo(int device, byte address, byte val) {
   Wire.beginTransmission(device);	// start transmission to device 
   Wire.write(address);				// send register address
   Wire.write(val);					// send value to write
   Wire.endTransmission();			// end transmission
}


//reads num bytes starting from address register on device in to buff array
void readFrom(int device, byte address, int num, byte buff[]) {
  Wire.beginTransmission(device);	// start transmission to device 
  Wire.write(address);				// sends address to read from
  Wire.endTransmission();			// end transmission
  
  Wire.beginTransmission(device);	// start transmission to device
  Wire.requestFrom(device, num);    // request 6 bytes from device
  
  int i = 0;
  while(Wire.available())			// device may send less than requested (abnormal)
  { 
    buff[i] = Wire.read();			// receive a byte
    i++;
  }
  Wire.endTransmission();			// end transmission
}


// read a single bite and returns the readed value
byte readByte(int device, byte address) {
  Wire.beginTransmission(device);	// start transmission to device 
  Wire.write(address);				// sends address to read from
  Wire.endTransmission();			// end transmission
  
  Wire.beginTransmission(device);	// start transmission to device
  Wire.requestFrom(device, 1);		// request 1 byte from device
  
  int readed = 0;
  
  if(Wire.available())
  { 
    readed = Wire.read();			// receive a byte
  }
  
  Wire.endTransmission();			// end transmission
  return readed;
}
/* 

binary_const.h file:

Binary constant generator macro
By Tom Torfs - donated to the public domain

From http://bytes.com/topic/c/answers/216333-binary-constant-macros
*/

/* All macro's evaluate to compile-time constants */

/* *** helper macros *** */

/* turn a numeric literal into a hex constant
(avoids problems with leading zeroes)
8-bit constants max value 0x11111111, always fits in unsigned long
*/
#define HEX__(n) 0x##n##LU

/* 8-bit conversion function */
#define B8__(x) ((x&0x0000000FLU)?1:0) \
+((x&0x000000F0LU)?2:0) \
+((x&0x00000F00LU)?4:0) \
+((x&0x0000F000LU)?8:0) \
+((x&0x000F0000LU)?16:0) \
+((x&0x00F00000LU)?32:0) \
+((x&0x0F000000LU)?64:0) \
+((x&0xF0000000LU)?128:0)

/* *** user macros *** */

/* for upto 8-bit binary constants */
#define B8(d) ((unsigned char)B8__(HEX__(d)))

/* for upto 16-bit binary constants, MSB first */
#define B16(dmsb,dlsb) (((unsigned short)B8(dmsb)<<8) \
+ B8(dlsb))

/* for upto 32-bit binary constants, MSB first */
#define B32(dmsb,db2,db3,dlsb) (((unsigned long)B8(dmsb)<<24) \
+ ((unsigned long)B8(db2)<<16) \
+ ((unsigned long)B8(db3)<<8) \
+ B8(dlsb))

/* Sample usage:
B8(01010101) = 85
B16(10101010,01010101) = 43605
B32(10000000,11111111,10101010,01010101) = 2164238933
*/

Here comes the original polling code that works fine:

#define F_CPU 16000000
#define ARDUINO 100

#define DEVICE (0x1D)			// ADXL345 I2C device address
#define TO_READ (6)				// num of bytes we are going to read each time (two bytes for each axis)
#define INTERRUPTPIN 2			// Arduino pin which is connected to INT1 from the ADXL345

#include "Arduino.h"

#include "Wire.h"
#include "Wire.cpp"

#include "twi.h"
#include "twi.c"

#include "binary_const.h"		// with this we can use something B8(01010101) that it will convert to 85 at compile time
								
#define R_DEVID  0
#define R_THRESH_TAP 29
#define R_OFSX 30
#define R_OFSY 31
#define R_OFSZ 32
#define R_DUR 33
#define R_LATENT 34
#define R_WINDOW 35
#define R_THRESH_ACT 36
#define R_THRESH_INACT 37
#define R_TIME_INACT 38
#define R_ACT_INACT_CTL 39
#define R_THRESH_FF 40
#define R_TIME_FF 41
#define R_TAP_AXES 42
#define R_ACT_TAP_STATUS 43
#define R_BW_RATE 44
#define R_POWER_CTL 45
#define R_INT_ENABLE 46
#define R_INT_MAP 47
#define R_INT_SOURCE 48
#define R_DATA_FORMAT 49
#define R_DATAX0 50
#define R_DATAX1 51
#define R_DATAY0 52
#define R_DATAY1 53
#define R_DATAZ0 54
#define R_DATAZ1 55
#define R_FIFO_CTL 56
#define R_FIFO_STATUS 57

byte buff[TO_READ];			//6 bytes buffer for saving data read from the device
char str[40];				//string buffer to transform data before sending it to the serial port
boolean inspected = 0;

// Declarations
void printTapAxes();
void writeTo(int device, byte address, byte val);
void readFrom(int device, byte address, int num, byte buff[]);
byte readByte(int device, byte address);

// Arduino compliance
void setup();
void loop();

void setup()
{
  Wire.begin();									// join i2c bus (address optional for master)
  Serial.begin(57600);							// start serial for output
  
  pinMode(INTERRUPTPIN, INPUT);   
  
  // --------------------------------------  CODE --------------------------------------
  
  // Low power - 45 uA, 50 Hz
  //writeTo(DEVICE, R_BW_RATE, B8(00011001));
  
  // Low power - 34 uA, 12.5 Hz
  writeTo(DEVICE, R_BW_RATE, B8(00010111));
  
  // interrupts setup; DATA_READY, Activity, Inactivity
  writeTo(DEVICE, R_INT_MAP, B8(01100111));				// send all interrupts to ADXL345's INT1 pin
  writeTo(DEVICE, R_INT_ENABLE, B8(10011000));			// enable DATA_READY, Activity, and Inactivity
  
  // inactivity configuration
  writeTo(DEVICE, R_TIME_INACT, 10);					// 1s / LSB
  writeTo(DEVICE, R_THRESH_INACT, 3);					// 62.5mg / LSB
  // also working good with high movements: R_TIME_INACT=5, R_THRESH_INACT=16, R_ACT_INACT_CTL=B8(00000111)
  // but unusable for a quite slow movements
  
  // activity configuration
  writeTo(DEVICE, R_THRESH_ACT, 8);						// 62.5mg / LSB
   
  // activity and inactivity control
  writeTo(DEVICE, R_ACT_INACT_CTL, B8(11111111));		// enable activity and inactivity detection on x,y,z using ac
  
  // Bypass mode, INT1 enabled (later INT2 maybe!!??)
  writeTo(DEVICE, R_FIFO_CTL, B8(00000000));
  
  // DATA_FORMAT, 16G, Full resolution
  writeTo(DEVICE, R_DATA_FORMAT, B8(00001011));
 
  // Enable measurement mode;    +++++ LAST STEP +++++
  // set the ADXL345 in measurement and sleep Mode: this will save power while while we will still be able to detect activity
  // set the Link bit to 1 so that the activity and inactivity functions aren't concurrent but alternatively activated
  // set the AUTO_SLEEP bit to 1 so that the device automatically goes to sleep when it detects inactivity
  writeTo(DEVICE, R_POWER_CTL, B8(00111100));
  
  // ----------------------------------------- END  ------------------------------------------

}

void loop()
{ 
  // we use a digitalRead instead of attachInterrupt so that we can use delay()
  if(digitalRead(INTERRUPTPIN)) {
	  
    int interruptSource = readByte(DEVICE, R_INT_SOURCE);
    Serial.print("### ");
    Serial.println(interruptSource, BIN);
    
    if(interruptSource & B8(00001000)) {
      Serial.println("### Inactivity");
	  Serial.println("### Taking a nap ...");
      // we don't need to put the device in sleep because we set the AUTO_SLEEP bit to 1 in R_POWER_CTL
      // set the LOW_POWER bit to 1 in R_BW_RATE: with this we get worst measurements but we save power
      //int bwRate = readByte(DEVICE, R_BW_RATE);
	  // +++++ INSPECT THIS BELOW +++++
      //writeTo(DEVICE, R_BW_RATE, bwRate | B8(00010000));
    }
	
    if(interruptSource & B8(00010000)) {
      Serial.println("### Activity");
      
      // get current power mode
      int powerCTL = readByte(DEVICE, R_POWER_CTL);
      // set the device back in measurement mode
      // as suggested on the data sheet, we put it in standby then in measurement mode
      // we do this using a bitwise and (&) so that we keep the current R_POWER_CTL configuration
	  // +++++ INSPECT THIS BELOW +++++
      //writeTo(DEVICE, R_POWER_CTL, powerCTL & B8(11110011));
      //delay(10);									// let's give it some time (not sure if this is needed)
	  // clear the sleep bit
      writeTo(DEVICE, R_POWER_CTL, powerCTL & B8(11111011));
      
      // set the LOW_POWER bit to 0 in R_BW_RATE: get back to full accuracy measurement (we will consume more power)
	  // +++++ INSPECT THIS BELOW +++++
      //int bwRate = readByte(DEVICE, R_BW_RATE);
      //writeTo(DEVICE, R_BW_RATE, bwRate & B8(01111));
    }
	
	//first axis-acceleration-data register on the ADXL345
	#define regAddress 0x32    
	int x, y, z;
  
	readFrom(DEVICE, regAddress, TO_READ, buff);		//read the acceleration data from the ADXL345
  
	//each axis reading comes in 10 bit resolution, IE 2 bytes.  Least Significant Byte first!!
	//thus we are converting both bytes in to one int
	x = (((int)buff[1]) << 8) | buff[0];   
	y = (((int)buff[3]) << 8) | buff[2];
	z = (((int)buff[5]) << 8) | buff[4];
  
	//we send the x y z values as a string to the serial port
	sprintf(str, "%d %d %d", x, y, z);  
	Serial.print(str);
	Serial.write("\n");									// New line
  
  }  
}



// Definitions

// ---------------- Functions ------------------
//Writes val to address register on device
void writeTo(int device, byte address, byte val) {
   Wire.beginTransmission(device);	// start transmission to device 
   Wire.write(address);				// send register address
   Wire.write(val);					// send value to write
   Wire.endTransmission();			// end transmission
}


//reads num bytes starting from address register on device in to buff array
void readFrom(int device, byte address, int num, byte buff[]) {
  Wire.beginTransmission(device);	// start transmission to device 
  Wire.write(address);				// sends address to read from
  Wire.endTransmission();			// end transmission
  
  Wire.beginTransmission(device);	// start transmission to device
  Wire.requestFrom(device, num);    // request 6 bytes from device
  
  int i = 0;
  while(Wire.available())			// device may send less than requested (abnormal)
  { 
    buff[i] = Wire.read();			// receive a byte
    i++;
  }
  Wire.endTransmission();			// end transmission
}


// read a single bite and returns the readed value
byte readByte(int device, byte address) {
  Wire.beginTransmission(device);	// start transmission to device 
  Wire.write(address);				// sends address to read from
  Wire.endTransmission();			// end transmission
  
  Wire.beginTransmission(device);	// start transmission to device
  Wire.requestFrom(device, 1);		// request 1 byte from device
  
  int readed = 0;
  
  if(Wire.available())
  { 
    readed = Wire.read();			// receive a byte
  }
  
  Wire.endTransmission();			// end transmission
  return readed;
}

Credit:
all code is based on Varesano.net, varesano.net -

From the reference INT0 in on pin 2 and INT1 on pin3. Have you changed this in both lots of code?

Mark

Yes, I use INT1 from ADXL345 to digital pin 2 (INT0 - atmega328)

fuxen