Interrupción de inactividad de actividad UNO de Arduino UNO Arduino

0

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



}


}
    
pregunta user49395

1 respuesta

1

Edit2:
Intente esto para ver si ocurre inactividad (la actividad aún podría no)

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)

También:

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

El ISR consume y borra instantáneamente todas las fuentes de interrupción bloqueadas, sin datos.
Esto nunca le mostrará las fuentes de interrupción que no son datos porque ya se han borrado:

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

Si Pin2 sigue siendo alto después de ISR, hay datos, por lo que el indicador de datos es realmente redundante.
Intente algo como esto (no estoy seguro si desea procesar todos los paquetes o simplemente el último):

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
}
    
respondido por el Jon

Lea otras preguntas en las etiquetas