Go Down

Topic: ADXL345 interrupt problems! (Read 880 times) previous topic - next topic

fuxen

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 :)

holmes4

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

Mark

fuxen

Here comes some code:
Code: [Select]
#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;
}




fuxen

Code: [Select]
/*

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

fuxen

Here comes the original polling code that works fine:

Code: [Select]
#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;
}





fuxen

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

holmes4

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

Mark

fuxen

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

fuxen

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy