ADXL345 Reliable (Double)Tap Detection - SOLVED

Hi everyone!

Lately I've been experimenting with the ADXL345 accelerometer from Analog Devices. I'm using Jeff Rowberg's i2cdevlib library for the 345 i2cdevlib/Arduino/ADXL345 at master · jrowberg/i2cdevlib · GitHub.

I'm trying to use the 345 for tap and double-tap detection, but I've noticed that the results are very inconsistent. I can usually detect a singular tap, although when I try continuously tapping (once every 5-10 seconds), I notice it will miss taps occasionally. Double-taps are a complete gamble. Sometimes, it will register nothing. Other times, it registers two single-taps. Yet, other times, I'll get a single-tap followed by a double-tap.

What I'm curious about is if anyone else has had this issue and was able to get a consistent detection/differentiation between tap events. I have tried adjusting tap thresholds, latency, etc. I can post code if need be.

Thanks for any input!

Problem Solved!

For anyone else who is using this library and having similar problems, I had to make a tweak in order to achieve what I was after. If I'm not overlooking something, it would seem that the problem I was having was related to reading the interrupt source registers. The datasheet wasn't crystal clear on this point, but it would seem that reading any bit from the interrupt source register will clear all the source bits, but just the one you read. So in my case, what was happening was when I checked the single-tap interrupt source bit, it cleared the double-tap interrupt source bit as well.

My solution to this was to add a library function which returns the entire byte of data from the interrupt source register. I placed the following at line 1366 of ADXL345.cpp

/** Get ENTIRE INTERRUPT SOURCE REGISTER
 * @return Interrupt source register
 * @see ADXL345_RA_INT_SOURCE
 */
uint8_t ADXL345::getIntSource() {
    I2Cdev::readByte(devAddr, ADXL345_RA_INT_SOURCE, buffer);
    return buffer[0];
}

Add the appropriate prototype defs to the .h file. Then, call this function to return all 8 bits of the interrupt register at once. No more accidental clearing!

I then used this operation to differentiate between single and double taps, where accel is an ADXL345 instance, and tapType is a boolean where true = double-tap and false = single-tap

if(accel.getIntSource() & (1<<5))tapType=1;
    else tapType=0;

I hope this can help someone. Please let me know if you have questions in the future!