Tengo las interrupciones DATA_READY, Activity e Inactivity mapeadas de INT1 a INT0 en el arduino. DATA_READY funciona bien, el problema es que la actividad y la inactividad siempre se establecen en 0 en el registro INT_SOURCE. He configurado el umbral de actividad e inactividad y el tiempo de inactividad. Me gustaría que el algoritmo se ejecute cuando DATA_READY y las interrupciones de actividad sean 1 y no haga nada cuando la inactividad es 1 (la actividad es 0). Cuando la Actividad es 0, el acelerómetro debería pasar automáticamente al modo de suspensión y se reactiva si se detecta actividad.
#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
}
}
Editar:
He modificado el programa para verificar en el bucle si las diferentes banderas están establecidas y solo lo está el DATA_READY. La actividad y la inactividad nunca se establecen.
#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
}
}