Detect hard taps anywhere on iPhone through accelerometer

You should apply a high pass filter to the accelerometer data. That will give you just the spikes in the signal - sharp taps.

I did a quick search on "UIAccelerometer high pass filter" and found several hits. The simplest code takes a rolling average of the accelerometer input, then subtracts that average from the instantaneous reading to find sudden changes. There are no doubt more sophisticated methods as well.

Once you have code that recognizes sharp taps, you'll need to craft code that detects 3 sharp taps in a row.


This is, as suggested by another answer, all to do with filtering the taps from the stream of accelerometer data. The impulse-like tap's will have a characteristic spectrogram (combination of frequencies) that can be detected when the response from a proper filter is higher than a threshold.

This is a very common operation on iPhone, I would suggest you look at official documentation such as here

The sample code I have linked to gives you two important things: official example code for high-pass filter AND a sample app that will graph the accelerometer data. This you can use to visual your taps, steps and jumps, to better understand why your filter responds falsely.

Furthermore, the internet is a huge source of literature on filter design - if you need to make a very high quality filter, you may need to consult the literature. I think however that a suitable second order filter would likely be sufficient.

@implementation HighpassFilter

- (id)initWithSampleRate:(double)rate cutoffFrequency:(double)freq
{
    self = [super init];

    if (self != nil)
    {
        double dt = 1.0 / rate;
        double RC = 1.0 / freq;
        filterConstant = RC / (dt + RC);
    }

    return self;    
}

- (void)addAcceleration:(UIAcceleration *)accel
{
    double alpha = filterConstant;   

    if (adaptive)
    {
        double d = Clamp(fabs(Norm(x, y, z) - Norm(accel.x, accel.y, accel.z)) / kAccelerometerMinStep - 1.0, 0.0, 1.0);
        alpha = d * filterConstant / kAccelerometerNoiseAttenuation + (1.0 - d) * filterConstant;
    }

    x = alpha * (x + accel.x - lastX);
    y = alpha * (y + accel.y - lastY);
    z = alpha * (z + accel.z - lastZ);

    lastX = accel.x;
    lastY = accel.y;
    lastZ = accel.z;
}

- (NSString *)name
{
    return adaptive ? @"Adaptive Highpass Filter" : @"Highpass Filter";
}

@end

Importantly this filter is direction agnostic, since only the magnitude of the acceleration is filtered. This is crucial to make the response seem normal. Otherwise users may feel like the have to tap from different angles to find a sweetspot.

On another note, if this task is proving too difficult and fiddly, I strongly suggest capturing your data ( in a WAV file for example) and using one of any common signal anaylsing program to get a better idea of where it is going wrong. See Baudline