Pages: [1]   Go Down
Author Topic: ADXL345 interrupt problems!  (Read 694 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 smiley
Logged

Poole, Dorset, UK
Offline Offline
Edison Member
*
Karma: 50
Posts: 2199
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Mark
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here comes some code:
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;
}



Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
/*

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
*/
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here comes the original polling code that works fine:

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 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;
}




Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Credit:
all code is based on Varesano.net, http://www.varesano.net/blog/fabio/exploring-advanced-features-adxl345-accelerometer-single-double-tap-activity-inactivity-f
Logged

Poole, Dorset, UK
Offline Offline
Edison Member
*
Karma: 50
Posts: 2199
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Mark
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

fuxen
Logged

Pages: [1]   Go Up
Jump to: