Interrupción de datos UNO de Arduino ADXL345

2

Me gustaría que los valores del sensor se actualicen cada 10 ms (100 Hz) y luego ejecuten el algoritmo y repitan el mismo proceso. Sin embargo, después de cronometrar el algoritmo está tomando solo 2 ms, creo que la interrupción data_ready no está funcionando como se esperaba. La conexión física del hardware es desde la INT1 de ADXL345 al pin2 de la UNO.

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

#define F_CPU 16000000UL 

volatile int sensor_update=0;
//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){
  sensor_update=1;
  }
void buzz(int targetPin, long frequency, long length) {
  long delayValue = 1000000/frequency/2; // calculate the delay value between transitions
  //// 1 second's worth of microseconds, divided by the frequency, then split in half since
  //// there are two phases to each cycle
  long numCycles = frequency * length/ 1000; // calculate the number of cycles for proper timing
  //// multiply frequency, which is really cycles per second, by the number of seconds to 
  //// get the total number of cycles to produce
  for (long i=0; i < numCycles; i++){ // for the calculated length of time...
    digitalWrite(targetPin,HIGH); // write the buzzer pin high to push out the diaphram
    delayMicroseconds(delayValue); // wait for the calculated delay value
    digitalWrite(targetPin,LOW); // write the buzzer pin low to pull back the diaphram
    delayMicroseconds(delayValue); // wait againf or the calculated delay value
  }
}

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

  /* 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_16_G);
  accel.setDataRate(ADXL345_DATARATE_100_HZ);
  // displaySetRange(ADXL345_RANGE_8_G);
  // displaySetRange(ADXL345_RANGE_4_G);
  // displaySetRange(ADXL345_RANGE_2_G);

  //Create an interrupt that will trigger when a tap is detected.
  attachInterrupt(0, interrupt, RISING);

  writeTo(0x1D, 0x2E, 0);
  writeTo(0x1D, 0x2F, 0);
  writeTo(0x1D, 0x2E, 128);
  writeTo(0x1D, 0x2F, 127);
}

void loop(void) 
{


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

  }
}

Actualización:

#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;
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){
sensor_update=1;
//  time0 = time;
//   time= millis();
//        time_dis=time-time0;
//        if(i<40){
//          time_array[i]=time_dis;
//    }
 //readFrom(0x53, 0x30, 1, buff); //clear interrupt
}





/* 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_16_G);
accel.setDataRate(ADXL345_DATARATE_1_56_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(0x1D, 0x2E, 0);// disable interrupt

attachInterrupt(0, interrupt, RISING);
writeTo(0x53, 0x2F, 0); //map data_ready to INT1
writeTo(0x53, 0x2E, 128); //enable data_ready




}

void loop(void) 
{


sensors_event_t event; 
readFrom(0x53, 0x30, 1, buff); //read the acceleration data from the ADXL345   (device,register to read from,number of bytes,array to store in)  
while(buff[0] & 0b10000000){
accel.getEvent(&event);
} 

 Serial.print("buff: "); Serial.print(buff[0], BIN); Serial.print("  ");
 delay(10);

 mag_calculation (event.acceleration.x, event.acceleration.y, event.acceleration.z);
 detachInterrupt(0);


 if(sensor_update==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
 attachInterrupt(0, interrupt, RISING);


 }


 }    
    
pregunta user49395

1 respuesta

3

Eliminar esta línea del bucle:

/* Get a new sensor event */ 
  interrupt();

No es necesario llamar a la rutina de interrupción. Las interrupciones funcionan al interrumpir el flujo principal del programa siempre que se cumpla una condición de interrupción, luego ejecutando la rutina de servicio de interrupción (en su caso interrupt() ) y luego volver a donde sea que se encuentre. programa dejado de lado.

attachInterrupt(0, interrupt, RISING); es una función que habilita una interrupción, en este caso el flanco ascendente en INT0, y le dice a qué función debe saltar ( interrupt ) cuando se cumple la condición de interrupción.

De la forma en que lo tienes ahora, está configurando sensor_update=1; tan rápido como el bucle puede hacer un bucle.

De los comentarios:

void loop(void) 
{
    sensors_event_t event; 

Lo siguiente se repetirá para siempre si la bandera se establece como buff [0] no se actualiza:

    readFrom(0x53, 0x30, 1, buff);
    while(buff[0] & 0b10000000){
        accel.getEvent(&event);
    } 

En su lugar, lea los datos y luego marque la bandera utilizando un bucle do :

    do {
        accel.getEvent(&event);
        readFrom(0x53, 0x30, 1, buff);
    } while(buff[0] & 0b10000000);

El resto del código:

    Serial.print("buff: "); Serial.print(buff[0], BIN); Serial.print("  ");

    delay(10);
    mag_calculation (event.acceleration.x, 
                     event.acceleration.y, 
                     event.acceleration.z);

Eliminar la interrupción de desconexión, no es necesario. La MCU borrará su indicador de interrupción cuando el código entre en el ISR. Al separarse aquí, la interrupción se desactiva, y si sensor_update era 0, entonces no se volvería a habilitar con su siguiente código.

    detachInterrupt(0);

    if(sensor_update==1 ) {
        sensor_update=0;//reset

Asimismo, elimine la interrupción de adjuntar.

        attachInterrupt(0, interrupt, RISING);
    }
} 
    
respondido por el geometrikal

Lea otras preguntas en las etiquetas