Go Down

Topic: Acelerómetro ADXL345: Detectar caida libre (Read 330 times) previous topic - next topic

luisvc91

Hola,

Estoy liado con un miniproyecto que necesito acabar. El proyecto tiene varias funciones, pero una de ellas es usar un acelerómetro ADXL345.
El ADXL345 se usa para detectar caida libre y el volcado de un objeto. En primer problema que tengo es con la caida libre...
He encontrado dos librerias que tienen ya implementadas los metodos y demas:
-ADXL345: https://github.com/jarzebski/Arduino-ADXL345
Code: [Select]
/*
    ADXL345 Triple Axis Accelerometer. Free Fall Detection
    Read more: http://www.jarzebski.pl/arduino/czujniki-i-sensory/3-osiowy-akcelerometr-adxl345.html
    GIT: https://github.com/jarzebski/Arduino-ADXL345
    Web: http://www.jarzebski.pl
    (c) 2014 by Korneliusz Jarzebski
*/

#include <Wire.h>
#include <ADXL345.h>

ADXL345 accelerometer;

void setup(void)
{
  Serial.begin(9600);

  // Initialize ADXL345
  Serial.println("Initialize L3G4200D");

  if (!accelerometer.begin())
  {
    Serial.println("Could not find a valid ADXL345 sensor, check wiring!");
    delay(500);
  }

  // Values for Free Fall detection
  accelerometer.setFreeFallThreshold(0.35); // Recommended 0.3 -0.6 g
  accelerometer.setFreeFallDuration(0.1);  // Recommended 0.1 s

  // Select INT 1 for get activities
  accelerometer.useInterrupt(ADXL345_INT1);

  // Check settings
  checkSetup();
}

void checkSetup()
{
  Serial.print("Free Fall Threshold = "); Serial.println(accelerometer.getFreeFallThreshold());
  Serial.print("Free Fall Duration = "); Serial.println(accelerometer.getFreeFallDuration());
}

void loop(void)
{
  delay(50);

  // Read values for activities
  Vector norm = accelerometer.readNormalize();

  // Read activities
  Activites activ = accelerometer.readActivites();

  if (activ.isFreeFall)
  {
    Serial.println("Free Fall Detected!");
  }
}

-SparkFun_ADXL345: https://github.com/sparkfun/SparkFun_ADXL345_Arduino_Library
Code: [Select]
/*  *********************************************
 *  SparkFun_ADXL345_Example
 *  Triple Axis Accelerometer Breakout - ADXL345
 *  Hook Up Guide Example
 * 
 *  Utilizing Sparkfun's ADXL345 Library
 *  Bildr ADXL345 source file modified to support
 *  both I2C and SPI Communication
 * 
 *  E.Robert @ SparkFun Electronics
 *  Created: Jul 13, 2016
 *  Updated: Sep 06, 2016
 * 
 *  Development Environment Specifics:
 *  Arduino 1.6.11
 * 
 *  Hardware Specifications:
 *  SparkFun ADXL345
 *  Arduino Uno
 *  *********************************************/

#include <SparkFun_ADXL345.h>         // SparkFun ADXL345 Library

/*********** COMMUNICATION SELECTION ***********/
/*    Comment Out The One You Are Not Using    */
//ADXL345 adxl = ADXL345(10);           // USE FOR SPI COMMUNICATION, ADXL345(CS_PIN);
ADXL345 adxl = ADXL345();             // USE FOR I2C COMMUNICATION

/****************** INTERRUPT ******************/
/*      Uncomment If Attaching Interrupt       */
//int interruptPin = 2;                 // Setup pin 2 to be the interrupt pin (for most Arduino Boards)


/******************** SETUP ********************/
/*          Configure ADXL345 Settings         */
void setup(){
 
  Serial.begin(9600);                 // Start the serial terminal
  Serial.println("SparkFun ADXL345 Accelerometer Hook Up Guide Example");
  Serial.println();
 
  adxl.powerOn();                     // Power on the ADXL345

  adxl.setRangeSetting(16);           // Give the range settings
                                      // Accepted values are 2g, 4g, 8g or 16g
                                      // Higher Values = Wider Measurement Range
                                      // Lower Values = Greater Sensitivity

  adxl.setSpiBit(0);                  // Configure the device to be in 4 wire SPI mode when set to '0' or 3 wire SPI mode when set to 1
                                      // Default: Set to 1
                                      // SPI pins on the ATMega328: 11, 12 and 13 as reference in SPI Library
   
  adxl.setActivityXYZ(1, 0, 0);       // Set to activate movement detection in the axes "adxl.setActivityXYZ(X, Y, Z);" (1 == ON, 0 == OFF)
  adxl.setActivityThreshold(75);      // 62.5mg per increment   // Set activity   // Inactivity thresholds (0-255)
 
  adxl.setInactivityXYZ(1, 0, 0);     // Set to detect inactivity in all the axes "adxl.setInactivityXYZ(X, Y, Z);" (1 == ON, 0 == OFF)
  adxl.setInactivityThreshold(75);    // 62.5mg per increment   // Set inactivity // Inactivity thresholds (0-255)
  adxl.setTimeInactivity(10);         // How many seconds of no activity is inactive?

  adxl.setTapDetectionOnXYZ(0, 0, 1); // Detect taps in the directions turned ON "adxl.setTapDetectionOnX(X, Y, Z);" (1 == ON, 0 == OFF)
 
  // Set values for what is considered a TAP and what is a DOUBLE TAP (0-255)
  adxl.setTapThreshold(50);           // 62.5 mg per increment
  adxl.setTapDuration(15);            // 625 μs per increment
  adxl.setDoubleTapLatency(80);       // 1.25 ms per increment
  adxl.setDoubleTapWindow(200);       // 1.25 ms per increment
 
  // Set values for what is considered FREE FALL (0-255)
  adxl.setFreeFallThreshold(7);       // (5 - 9) recommended - 62.5mg per increment
  adxl.setFreeFallDuration(30);       // (20 - 70) recommended - 5ms per increment
 
  // Setting all interupts to take place on INT1 pin
  //adxl.setImportantInterruptMapping(1, 1, 1, 1, 1);     // Sets "adxl.setEveryInterruptMapping(single tap, double tap, free fall, activity, inactivity);"
                                                        // Accepts only 1 or 2 values for pins INT1 and INT2. This chooses the pin on the ADXL345 to use for Interrupts.
                                                        // This library may have a problem using INT2 pin. Default to INT1 pin.
 
  // Turn on Interrupts for each mode (1 == ON, 0 == OFF)
  adxl.InactivityINT(1);
  adxl.ActivityINT(1);
  adxl.FreeFallINT(1);
  adxl.doubleTapINT(1);
  adxl.singleTapINT(1);
 
//attachInterrupt(digitalPinToInterrupt(interruptPin), ADXL_ISR, RISING);   // Attach Interrupt

}

/****************** MAIN CODE ******************/
/*     Accelerometer Readings and Interrupt    */
void loop(){
 
  // Accelerometer Readings
  int x,y,z;   
  adxl.readAccel(&x, &y, &z);         // Read the accelerometer values and store them in variables declared above x,y,z

  // Output Results to Serial
  /* UNCOMMENT TO VIEW X Y Z ACCELEROMETER VALUES */ 
  //Serial.print(x);
  //Serial.print(", ");
  //Serial.print(y);
  //Serial.print(", ");
  //Serial.println(z);
 
  ADXL_ISR();
  // You may also choose to avoid using interrupts and simply run the functions within ADXL_ISR();
  //  and place it within the loop instead. 
  // This may come in handy when it doesn't matter when the action occurs.

}

/********************* ISR *********************/
/* Look for Interrupts and Triggered Action    */
void ADXL_ISR() {
 
  // getInterruptSource clears all triggered actions after returning value
  // Do not call again until you need to recheck for triggered actions
  byte interrupts = adxl.getInterruptSource();
 
  // Free Fall Detection
  if(adxl.triggered(interrupts, ADXL345_FREE_FALL)){
    Serial.println("*** FREE FALL ***");
    //add code here to do when free fall is sensed
  }
 
  // Inactivity
  if(adxl.triggered(interrupts, ADXL345_INACTIVITY)){
    Serial.println("*** INACTIVITY ***");
     //add code here to do when inactivity is sensed
  }
 
  // Activity
  if(adxl.triggered(interrupts, ADXL345_ACTIVITY)){
    Serial.println("*** ACTIVITY ***");
     //add code here to do when activity is sensed
  }
 
  // Double Tap Detection
  if(adxl.triggered(interrupts, ADXL345_DOUBLE_TAP)){
    Serial.println("*** DOUBLE TAP ***");
     //add code here to do when a 2X tap is sensed
  }
 
  // Tap Detection
  if(adxl.triggered(interrupts, ADXL345_SINGLE_TAP)){
    Serial.println("*** TAP ***");
     //add code here to do when a tap is sensed
  }
}

Ambas librerias tienen métodos que devuelven una variable que indica si se ha producido caida libre o no... pero por más que muevo el sensor o lo tiro nunca se activa esa variable...
Los valores de aceleracion, actividad, inactividad, taps... funcionan bien, pero el free fall no...
Estoy un poco desesperado porque he repasado varias veces la conexión del ADXL345 y el codigo y no doy con lo que pasa... Utilizo I2C y a priori la comunicación es buena pues la lectura bruta de la aceleración la obtengo

Un saludo

surbyte

En el primer ejemplo me llama la atención que no funcione.
Sería bueno que indiques que valores arroja

checkSetup()

Porque ahi se pueden ver los umbrales y tiempo seleccionados.

En el ejemplo de SparkFun veo comentada la linea que habilita la interrupcion y luego la interrupcion es llamada en cada ciclo del loop, porque ?

Un error que veo en esa rutina es usar Serial.print.
En una rutina de interrupción no se pueden usar Serial.print.

Habilita flags y si se cumplen los flags, entonces los muestras en el loop.




luisvc91

Hola @surbyte

Para el primer ejemplo (libreria ADXL345). La funcion checkSetup para
Code: [Select]
  // Values for Free Fall detection
  accelerometer.setFreeFallThreshold(0.35); // Recommended 0.3 -0.6 g
  accelerometer.setFreeFallDuration(0.1);  // Recommended 0.1 s

me devuelve
Initialize L3G4200D
Free Fall Threshold = 0.31
Free Fall Duration = 0.10
No coincide con lo que se declara.... igualmente deberia detectar la caida libre con esos valores, no?


Respecto al segundo ejemplo, a cual de las lineas comentadas te refieres?
Code: [Select]
//int interruptPin = 2;                 // Setup pin 2 to be the interrupt pin (for most Arduino Boards)

o
Code: [Select]
  //adxl.setImportantInterruptMapping(1, 1, 1, 1, 1);     // Sets "adxl.setEveryInterruptMapping(single tap, double tap, free fall, activity, inactivity);"
                                                        // Accepts only 1 or 2 values for pins INT1 and INT2. This chooses the pin on the ADXL345 to use for Interrupts.
                                                        // This library may have a problem using INT2 pin. Default to INT1 pin.
 

o
Code: [Select]
//attachInterrupt(digitalPinToInterrupt(interruptPin), ADXL_ISR, RISING);   // Attach Interrupt

Porque comprobando esta habilitada la interrupcion para el freefall:   adxl.FreeFallINT(1);
Por otro lado, te pregunto... Las interrupciones INT1 e INT2 están relaccionadas con los pines INT1 e INT2... envían una interrupcion cambio de nivel) si se produce el evento (por ejemplo freefall)?
Sino puedo usar Serial.print en la interrupcion, que puedo hacer? activar una variable general y leerla en el loop, no?

surbyte

pin 2 es INT0
pin 3 es INT1

no existe INT2 en un UNO.

Quote
Sino puedo usar Serial.print en la interrupcion, que puedo hacer? activar una variable general y leerla en el loop, no?
Activas no una variable general, sino una volatile que es la que se comparte con las interrupciones.
Usa un flag tipo bool

bool flag;

luisvc91

Perdon, me equivoque.

Es que tengo un poco de lio con las interrupciones.
Para usar
Code: [Select]
  if(adxl.triggered(interrupts, ADXL345_FREE_FALL)){
Necesito conectar el IN2 e IN1 que hay en el sensor ADXL345 a algun pin de arduino? físicamente me refiero a algun puerto de arduino

Go Up