ADXL345 Arduino UNO Activity Inactivity interrupt

accelerometerarduinointerruptssensor

I have DATA_READY, Activity and Inactivity interrupts mapped from INT1 to INT0 on the arduino. DATA_READY works fine, the problem is Activity and Inactivity are always set to 0 in the INT_SOURCE register. I have set up the threshold for activity and inactivity and the time of inactivity. I would like the algorithm to run when DATA_READY and Activity interrupts are 1 and do nothing when Inactivity is 1 (activity is 0). When Activity is 0 the accelerometer should go automatically in sleep mode and wakes up if activity is detected.

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_ADXL345_U.h>
#include <avr/io.h>
#include <avr/power.h>


#define F_CPU 16000000UL 



int state=0; //0--active detecting; 1--sleeping
int state_count=0; //sleeping trigger between 2 states
double mag[40];
int i=0;
double acc_rate[39];
int hunt_sub=0;
int exit_marker=-10,trough_marker=-30,peak_marker=-10;
volatile int sensor_update=0, active_mode=0;//active_mode=0, inactive; 1--active;      sensor_update=0, no new data; 1--new data comes
byte buff[1] ;


volatile unsigned long time=0, time0=0,time_dis=0,time_array[40]={0};

//----------------------------------------------------------------------------------------------

//Read ADXL345 registers
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 (initiate again)
Wire.requestFrom(device, num);    // request 1 byte 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
}

//Write to ADXL345 registers
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
}



//----------------------------------------------------------------------------------------------

/////////////////////////////////////////////////////////////////////////////////////////////

//ISR function



void interrupt(void){

readFrom(0x53, 0x30, 1, buff); 

if(buff & 0b00010000){
  active_mode=1;//active state
}
if(buff & 0b00001000){ 
  active_mode=0;//inactivity state
}

if(buff & 0b10000000){
sensor_update=1;//DATA_READY each 10ms  
}

}




/* Assign a unique ID to this sensor at the same time */
Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345);





void setup(void) 
{
if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
Serial.begin(9600);
//Serial.println("Accelerometer Test"); Serial.println("");

pinMode(4, OUTPUT);// buzzer output pin
pinMode(2, INPUT);

/* 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_8_G);
accel.setDataRate(ADXL345_DATARATE_100_HZ);
// 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("");

//Create an interrupt that will trigger when a tap is detected.

writeTo(0x53, 0x2D, 59);//POWER_CTL  auto sleep, link, 1hz rate
writeTo(0x53, 0x2C, 10);//BW_RATE low power mode off rate 100Hz
writeTo(0x53, 0x2E, 0);// disable interrupt

attachInterrupt(0, interrupt, RISING);

writeTo(0x53, 0x2F, 0); //map to to INT1
writeTo(0x53, 0x2E, 152); //enable data_ready, activity, inactivity
writeTo(0x53, 0x25, 18); //THRESH_INACT  ((11/9.8)*1000)/62.5
writeTo(0x53, 0x26, 60); //TIME_INACT    one minute
writeTo(0x53, 0x24, 21); //THRESH_ACT    ((13/9.8)*1000)/62.5
writeTo(0x53, 0x27, 0); //ACT_INACT_CTL   dc coupled, use only magnitude.


}

void loop(void) 
{

readFrom(0x53, 0x30, 1, buff);
Serial.print("buff: "); Serial.print(buff); Serial.print("  ");

sensors_event_t event; 
do{ //clear DATA_READY
accel.getEvent(&event);
readFrom(0x53, 0x30, 1, buff);
}while(buff & 0b10000000);




if(sensor_update==1 && active_mode==1){
//When sensor_update is set to 1 in the ISR,the algorithm process the data from the accelerometer being updated every 10ms(100Hz)
//rest of algorithm is here
 sensor_update=0;//reset



}


}

Edit:

I have modified the program to check in the loop whether the different flags are set and only the DATA_READY is. Activity and Inactivity are never set.

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_ADXL345_U.h>
#include <avr/io.h>
#include <avr/power.h>


#define F_CPU 16000000UL 



int state=0; //0--active detecting; 1--sleeping
int state_count=0; //sleeping trigger between 2 states
double mag[40];
int i=0;
double acc_rate[39];
int hunt_sub=0;
int exit_marker=-10,trough_marker=-30,peak_marker=-10;
volatile int sensor_update=0, active_mode=0;//active_mode=0, inactive; 1--active;     sensor_update=0, no new data; 1--new data comes
byte buff[1] ;


volatile unsigned long time=0, time0=0,time_dis=0,time_array[40]={0};

//----------------------------------------------------------------------------------------------

//Read ADXL345 registers
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 (initiate again)
Wire.requestFrom(device, num);    // request 1 byte 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
}

//Write to ADXL345 registers
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
}



//----------------------------------------------------------------------------------------------

/////////////////////////////////////////////////////////////////////////////////////////////

//ISR function



void interrupt(void){


//    
//    if(buff & 0b00010000){
//      active_mode=1;//active state
//    }
//    if(buff & 0b00001000){ 
//      active_mode=0;//inactivity state
//    }
//    
//    if(buff & 0b10000000){
//    sensor_update=1;//DATA_READY each 10ms  
//    }

}




/* Assign a unique ID to this sensor at the same time */
Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345);





void setup(void) 
{
if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
Serial.begin(9600);
//Serial.println("Accelerometer Test"); Serial.println("");

pinMode(4, OUTPUT);// buzzer output pin
pinMode(2, INPUT);

/* 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_8_G);
accel.setDataRate(ADXL345_DATARATE_100_HZ);

//Create an interrupt that will trigger when a tap is detected.


  writeTo(0x53, 0x2D, 59);//POWER_CTL  auto sleep, link, 1hz rate
  writeTo(0x53, 0x2C, 10);//BW_RATE low power mode off rate 100Hz
  writeTo(0x53, 0x2E, 0);// disable interrupt

  attachInterrupt(0, interrupt, RISING);

  writeTo(0x53, 0x2F, 0); //map to to INT1
  writeTo(0x53, 0x2E, 152); //enable data_ready, activity, inactivity
  // writeTo(0x53, 0x25, 18); //THRESH_INACT  ((11/9.8)*1000)/62.5
  writeTo(0x53, 0x27, 119); //ACT_INACT_CTL   dc coupled, use only magnitude.
  writeTo(0x53, 0x25, 5); //THRESH_INACT  ((3.0625/9.8)*1000)/62.5
  writeTo(0x53, 0x26, 1); //TIME_INACT    one minute
  writeTo(0x53, 0x24, 21); //THRESH_ACT    ((12.8625/9.8)*1000)/62.5

  }

  void loop(void) 
  {

  if(digitalRead(2)) {

  readFrom(0x53, 0x30, 1, buff);

  //Serial.print("### ");

  //Serial.println(interruptSource, BIN);


  if(buff[0] & 0b10000000) {

  Serial.println("### DATA_READY");

  }


  if(buff[0] & 0b00001000) {

  Serial.println("### Inacitivity");

  }

  if(buff[0] & 0b00010000) {

  Serial.println("### activity");

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

}


delay(150);

}


sensors_event_t event; 
do{ //clear DATA_READY
accel.getEvent(&event);
readFrom(0x53, 0x30, 1, buff);
}while(buff & 0b10000000);




if(sensor_update==1 && active_mode==1){
//When sensor_update is set to 1 in the ISR,the algorithm process the data from the accelerometer being updated every 10ms(100Hz)
//rest of algorithm is here
 sensor_update=0;//reset



}


}

Best Answer

Edit2:
Try this to see if inactivity happens (activity still might not)

writeTo(0x53, 0x2F, 0); //map to INT1
writeTo(0x53, 0x25, 5); //THRESH_INACT ((3.0625/9.8)*1000)/62.5
writeTo(0x53, 0x26, 1); //TIME_INACT one second
writeTo(0x53, 0x24, 21); //THRESH_ACT ((12.8625/9.8)*1000)/62.5
writeTo(0x53, 0x27, 119); //ACT_INACT_CTL dc coupled, use only magnitude (all participating)
writeTo(0x53, 0x2E, 152); //enable data_ready, activity, inactivity (finish config then enable)

Also:

do{ //clear DATA_READY
accel.getEvent(&event);
Serial.Print(event); //repair statement as necessary to output readings to serial
readFrom(0x53, 0x30, 1, buff);
}while(buff & 0b10000000);

The ISR instantly consumes and clears all latched, non-data, interrupt sources.
This will never show you non-data interrupt sources because they've already been cleared:

readFrom(0x53, 0x30, 1, buff);
Serial.print("buff: "); Serial.print(buff); Serial.print("  ");

If Pin2 is still high after ISR, there is data, so the data flag is actually redundant.
Try something like this (not sure if you want to process all packets or just last):

sensors_event_t lastActiveEvent;
sensors_event_t event;
Serial.Print(active_mode);
while(DigitalRead(2) == HIGH))
{
  accel.getEvent(&event);
  if(active_mode == 1) lastActiveEvent = event;
}
if (lastActiveEvent) //process the last reading received before sleep
{
  //algorithm here
}