Problemas con Tapp en ADXL345

Buenas a todos. Estoy haciendo un programa para detectar los tapp con en adxl345, ya ha realizado toda la parte de correccion de medida y demás pero me falta detectar un tapp simple o doble y no veo donde estoy fallando. ¿Alguna idea?

Es configuración spi sin libreria. aqui os dejo el codigo encuestion:

#include <SPI.h>

int CS2 = 10;
// ***Configuracion del control y formato***//
char POWER_CTL = 0x2D;  //Power Control Register
char DATA_FORMAT = 0x31;
char DATAX0 = 0x32; //X-Axis Data 0
char DATAX1 = 0x33; //X-Axis Data 1
char DATAY0 = 0x34; //Y-Axis Data 0
char DATAY1 = 0x35; //Y-Axis Data 1
char DATAZ0 = 0x36; //Z-Axis Data 0 
char DATAZ1 = 0x37; //Z-Axis Data 1

//**configuracion de los tapp***//
        char INT_SOURCE=0x30; //INT_SOURCE
        char INT_ENABLE = 0x2E;  //configuracion  DEL TAP
        char INT_MAP = 0x2F;  //configuracion DEL TAP;
        char TAP_AXES = 0x2A; //configuracion DEL TAP
        char DURATION = 0x21;  //configuracion DEL TAP
        char LATENT = 0x22;  //configuracion DEL TAP
        char WINDOW = 0x23;  //configuracion DEL TAP
char tapps[10];
//byte buff;

byte values1[10];
int x2, y2, z2;
float Xg,Yg,Zg;
float Xg_offset,Yg_offset,Zg_offset;
float Xg_gain,Yg_gain,Zg_gain;
float accX,accY,accZ;

#define TO_READ (6)        
byte buff[TO_READ] ;      
int regAddress = 0x32;      


int tapType=0;

 
 
 void setup()
 {
   SPI.begin();
   SPI.setDataMode(SPI_MODE3);
   Serial.begin(9600);
    pinMode(CS2, OUTPUT);
    digitalWrite(CS2, HIGH);

writeRegister(DATA_FORMAT, 0x01, CS2);  //lo configuro +-4g
writeRegister(POWER_CTL, 0x08, CS2);    //se activa la medicion continua

//Configuracion de los tapp

//Activo los Single y Double Taps.
  writeRegister(INT_ENABLE, 0xE0,CS2 ); //1110 0000
  //Envio el tap y doble tap interuupts  al pin 1 de INT1
  writeRegister(INT_MAP, 0x9F, CS2); //1001 1111
  //busco los tap solamente en el eje x
  writeRegister(TAP_AXES, 0x01, CS2); //0000 0001  pag 26.

  //defino la duracion del tap que tiene que ser leida.
  writeRegister(DURATION, 0x10, CS2); //0000 1010 pag 25
  
  //100ms defino la latencia que puedes espera para el segundo tapp.
  writeRegister(LATENT, 0x50, CS2); //en decimal 80
  writeRegister(WINDOW, 0xFF, CS2); //calcula el tiempo durante la segunda latencia


   delay(50);
  }

  void loop()
  {
    readRegister(DATAX0, 6, values1, CS2);
    x2 = ((int)values1[1] << 8) | (int)values1[0];
    y2 = ((int)values1[3] << 8) | (int)values1[2];
    z2 = ((int)values1[5] << 8) | (int)values1[4];
 /*   Serial.print(x2 * 1);
    Serial.print(',');
    Serial.print(y2 * 1);
    Serial.print(',');
    Serial.println(z2 * 1);

   delay(2000);
*/
//convierto los valores a valores G
Xg=((float)x2)*(4.0/1024.0);Yg=((float)y2)*(4.0/1024.0); Zg=(float)z2*(4.0/1024.0); 

//  offsetAxis = 0.5 * (Acel+1g + Accel-1g)
//  gainAxis = 0.5 * ((Acel+1g - Accel-1g)/1g)
// Calculo el offset y la ganancia para calcular los nuevos valores finales del acelerometro

/** Los siguientes valores son calculadaod mediante medicion directa de Xg, Yg, Zg **************/
/*                    // OFFSET values                         */

Xg_offset=-0.03; Yg_offset=-0.005; Zg_offset=-0.04;
Xg_gain=0.53;    Yg_gain=0.545;    Zg_gain=0.48;

//Calculo los resultados finales
accX = (Xg - Xg_offset)/Xg_gain; accY = (Yg - Yg_offset)/Yg_gain; accZ = (Zg - Zg_offset)/Zg_gain;
 
/*//muestro los nuevos valores con la correcion por programa
//Imprime los resultado..
Serial.println("Valores convertidos a fuerza G");
 Serial.print("Xg="); Serial.println(Xg);
 Serial.print("Yg="); Serial.println(Yg);
 Serial.print("Zg="); Serial.println(Zg);
 Serial.println(); 
 delay(2000);
*/
//muestro los nuevos valores con la correcion por programa
//Imprime los resultado..
//Serial.println("Valores Corregidos");
 Serial.print("accX="); Serial.print(accX);Serial.print("   ");
 Serial.print("accY="); Serial.print(accY);Serial.print("   ");
 Serial.print("accZ="); Serial.print(accZ);Serial.print("   ");
 Serial.println(tapType);
 Serial.println(); 
 delay(500);



if(tapType > 0)
  {
    if(tapType == 1){
      Serial.println("SINGLE");
    }
    else{
      Serial.println("DOUBLE");
    }
    detachInterrupt(0);
    delay(500);}

    attachInterrupt(0, tap, RISING);
   
}

 void writeRegister(char registerAddress, char value, int CS)
 {
   digitalWrite(CS, LOW);
   SPI.transfer(registerAddress);
   SPI.transfer(value);
   digitalWrite(CS, HIGH);
   }

   void readRegister(char registerAddress, int numBytes, byte *  values, int CS)
  {
   char address = 0x80 | registerAddress;
    if (numBytes > 1)address = address | 0x40;

   digitalWrite(CS, LOW);
   SPI.transfer(address);
    for (int i = 0; i < numBytes; i++)
   {
     values[i] = SPI.transfer(0x00);
    }
     digitalWrite(CS, HIGH);
   }

void tap(void){
  //borrar la variable de interrupciones ADXL345
  readRegister(INT_SOURCE, 1, values1,  CS2); 
  if(values1[0] & (1<<5))tapType=2;
  else tapType=1;;
}

me falta detectar un tapp simple o doble

Qué es un tapp simple o doble?

el dectectar cuando realiza como un golpero, el mando de la wii por ejemplo, si haces como si lanzaras una caña de pescar eso seria un tapp.

Puedes por favor contextualizar tu consulta.
Esto que significa?

//**configuracion de los tapp***//
        char INT_SOURCE=0x30; //INT_SOURCE
        char INT_ENABLE = 0x2E;  //configuracion  DEL TAP
        char INT_MAP = 0x2F;  //configuracion DEL TAP;
        char TAP_AXES = 0x2A; //configuracion DEL TAP
        char DURATION = 0x21;  //configuracion DEL TAP
        char LATENT = 0x22;  //configuracion DEL TAP
        char WINDOW = 0x23;  //configuracion DEL TAP

Donde miro un esquema para entender de que hablas y poder darte un consejo?

Perdon, en esta parte no acabe de completar los datos, todo esto sale del data sheet del adxl345. Explico lo que es cada cosa,
Aquí defino lo que son las direcciones de los registros.

//**configuracion de los tapp***//
        char INT_SOURCE=0x30;    //Source of interrupts 
        char INT_ENABLE = 0x2E;   //Interrupt enable control 
        char INT_MAP = 0x2F;       //Interrupt mapping control 
        char TAP_AXES = 0x2A;     //Axis control for single tap/double tap 
        char DURATION = 0x21;     //Tap duration 
        char LATENT = 0x22;        //Tap latency 
        char WINDOW = 0x23;      //Tap window

y a cada uno de estos valores le he asignado el dato:

//Activo los Single y Double Taps.
  writeRegister(INT_ENABLE, 0xE0,CS2 ); //1110 0000
  //Envio el tap y doble tap interuupts  al pin 1 de INT1
  writeRegister(INT_MAP, 0x9F, CS2); //1001 1111
  //busco los tap solamente en el eje x
  writeRegister(TAP_AXES, 0x01, CS2); //0000 0001  pag 26.
  //defino la duracion del tap que tiene que ser leida.
  writeRegister(DURATION, 0x10, CS2); //0000 1010 pag 25
  //100ms defino la latencia que puedes espera para el segundo tapp.
  writeRegister(LATENT, 0x50, CS2); //en decimal 80
  writeRegister(WINDOW, 0xFF, CS2); //calcula el tiempo durante la segunda latencia

Espero que ahora se entienda mejor mi problema.

Tengo definido todo pero no consigo que funcione.

Y porque no usas una librería en lugar de reinventar la rueda y te concentras en tu problema solamente?

Con la librería no te go problemas. Pero quiero hacerlo sin ella ya que es cuestión formativa. Por eso no puedo usar librería.

A ver si comprendo la idea.
No quieres usar librería pero.... no sabes si tu código de lectura del sensor funciona bien.
Porque no estableces una prueba física con valores medibles en las que tu código y la librería arrojen valores similares?
Luego de realizado esto, sigue con tu problema tapp!!
Si tienes un acelerómetro, porque no realizas un frenado controlado o sometes al sensor mas arduino a una fuerza centífuga que sea de determinada aceleración. Cuando tengas coincidencia de lecturas pasas a tu 2do problema.
Yo haría eso.

Hola compañero, gracias por el interes y tiempo (Eso es lo primero).

Voy a tratar de explicame mejor, se que mi codigo funciona bien (almenos lo referente a la lectura de fuerza G) lo que no funciona tan bien es lo de los tapp, tengo una variable que pongo a 0 si no tiene
a 1 si es simple y a 2 si es doble.

Pero no funciona bien. he montado el circuito. muevo la placa, veo el puerto serie y veo los datos.

Pero la parte del tapp es la que no va y no veo el error en el codigo. No se si es de algun ajuste que no estoy haciendo bien o esque no lo he programado bien.

Creo que ahora lo he puesto algo mas claro. os añado una imagen.

En la imagen puede ver como en el eje x, que es donde busco tapp llenago incluso a marchar -2,44 no consigo que ponga que se ha producido un tapp.
Saludos y nuevamente gracias.

Captura imagen

La imagen no la veo porque no esta insertada como dicen las normas.
Lee como se insertan las imagenes y edita tu post. Usa tu propio adjunto para hacerlo. No uses (mi consejo) un repositorio de imágenes.

Modificada y añadida como un enlace.

Saludos y espero que ahora se puede ver bien.

Ahora subo la imagen


Acá esta la imagen, con tus capturas.
Se adjunta aca y se captura el enlace de la imagen, se edita y ya esta.
Bueno no digas nada, es mi rollo como moderador, tu ya lo hiciste, yo en 6 meses veré que este hilo no tiene tu enlace. Se porque lo digo.

Tu lo que quieres es detectar el momento en que el pez muerde el anzuelo.
Los valores que leo son

 Ax Ay AZ
-1,05 0,26 1,13
-0,76 0,07 0,46
-1,74 0,51 0,82
-1,79 0,40 2,57
-0,92 -0,18 0,04
-1,97 -0,71 3,92
-2,44 -0,69 2,36
-0,38 -0,06 4,08
-1,37 -0,92 3,95

veo que Az tiene grandes cambios asi que tal como lo tienes ubicado para ser tu eje para comparar.

Definitivamente es algo que tengo que acabar de ajustar en el codigo, cuando logre que funcione correctamente pondre aqui algo. siempre y cuando lo logre.

ahora ya responde algo mas.

Solo busco tapp en el eje z, pero eso no quiere decir que solo mire los valores en todos los ejes.

Porque no pones un umbral de detección?
Dices cuando Az es > que tanto tengo el momento buscado y ya, eso no puede fallar.
Ejemplo. Si no malintepreto los datos, son valores tomados en intervalos de 500mseg.
Vemos la columna Az solamente
Az con At = 500mseg
Pos Az DeltaAz

  1. 1,13 0
  2. 0,46 -0.67
  3. 0,82 0.36
    4. 2,57 1.75
  4. 0,04 -2.35
    6. 3,92 3.88
  5. 2,36 -1.56
    8. 4,08 1.72
  6. 3,95 -0.13

yo veo momentos en que el DeltaAz crece por encima de digamos 1.5 y muestre al menos 3 picos con uno muy notorio en la posición 6 respecto de la 5.
Esos deberian ser tus momentos o me equivoco?

Saludos nuevamente, eso seria una opcion, pero el sistema lo tiene que hacer autromaticamente no tomando yo los valores y operando con ellos.

De momento lo tengo que dejar parado, cuando pueda retomare el tema y si lo soluciono pondre la solucion.

Saludos.

No entendiste mi sugerencia
Umbral de detección 1.70 por ejemplo

Tomas un valor ahora, y otro cada 500 mseg, la diferencia te dará un Delta o diferencia.
Si esta diferencia es mayor que ese umbral, estas en tu situación buscada.
Simple
Supongamos algunas variables definidas como globales como

unsigned long start;

// debajo de esto
float accX,accY,accZ;
// agregas esto
float accZAnt;
float deltaZ;


.... en el loop
if (millis() > start) { // cambia cada 500 mseg
   deltaZ = accZ-accZAnt;
   if (deltaZ > UMBRAL) {
      // situacion buscada, tomas la acción pertinente
   }
   accZAnt = accZ; preparo para el proximo caso.
}

Deberías ahora garantizar que las lecturas se toman cada 500 mseg