Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect hard taps anywhere on iPhone through accelerometer

Tags:

I am trying to detect the taps which could be anywhere on iPhone not just iPhone screen. Here is a link which shows that it is possible.

Basically what i want to do is send an alert if user taps 3 times on iPhone while the Phone is in his pocket. What i have achieved is that i can detect the 3 taps but i also get the false alerts as well in these cases. 1) if user walking, 2) waving his phone 3) running. I need to just check if user has hit his iPhone 3 times.

Here is my code.

- (void)accelerometer:(UIAccelerometer *)accelerometer
        didAccelerate:(UIAcceleration *)acceleration
{
    if (handModeOn == NO)
    {
        if(pocketFlag == NO)
            return;
    }

    float accelZ = 0.0;
    float accelX = 0.0;
    float accelY = 0.0;

    accelX = (acceleration.x * kFilteringFactor) + (accelX * (1.0 - kFilteringFactor));
    accelY = (acceleration.y * kFilteringFactor) + (accelY * (1.0 - kFilteringFactor));
    accelZ = (acceleration.z * kFilteringFactor) + (accelZ * (1.0 - kFilteringFactor));

        self.z.text = [NSString stringWithFormat:@"%0.1f", -accelZ];

        if((-accelZ >= [senstivity floatValue] && timerFlag) || (-accelZ <= -[senstivity floatValue] && timerFlag)|| (-accelX >= [senstivity floatValue] && timerFlag) || (-accelX <= -[senstivity floatValue] && timerFlag) || (-accelY >= [senstivity floatValue] && timerFlag) || (-accelY <= -[senstivity floatValue] && timerFlag))
        {
            timerFlag = false;
            addValueFlag = true;
            timer = [NSTimer scheduledTimerWithTimeInterval:1.5 target:self selector:@selector(timerTick:) userInfo:nil repeats:YES];
        }

        if(addValueFlag)
        {
            if (self.xSwitch.on)
            {
                NSLog(@"X sWitch is on");
                [self.accArray addObject:[NSNumber numberWithFloat:-accelX]];
            }
            if (self.ySwitch.on)
            {
                NSLog(@"Y Switch is on");
                [self.accArray addObject:[NSNumber numberWithFloat:-accelY]];
            }
            if (self.zSwitch.on)
            {
                NSLog(@"Z Switch is on");
                [self.accArray addObject:[NSNumber numberWithFloat:-accelZ]];
            }

        }
    //}
}

- (void)timerTick:(NSTimer *)timer1
{
    [timer1 invalidate];
    addValueFlag = false;
    int count = 0;

    for(int i = 0; i < self.accArray.count; i++)
    {
        if(([[self.accArray objectAtIndex:i] floatValue] >= [senstivity floatValue]) || ([[self.accArray objectAtIndex:i] floatValue] <= -[senstivity floatValue]))
        {
            count++;
            [self playAlarm:@"beep-1" FileType:@"mp3"];
        }

        if(count >= 3)
        {
            [self playAlarm:@"06_Alarm___Auto___Rapid_Beeping_1" FileType:@"caf"];
            [self showAlert];
            timerFlag = true;
            [self.accArray removeAllObjects];
            return;
        }
    }
    [self.accArray removeAllObjects];
    timerFlag = true;
}

Any help will be really appreciated.

Thanks

like image 693
sajjoo Avatar asked Nov 23 '13 00:11

sajjoo


People also ask

How does iPhone detect back Tap?

This way, you can configure different shortcuts for double-tapping and triple-tapping your iPhone's back. The functionality uses the iPhone's accelerometer and gyroscope to detect when you tap and how often you tapped on the back.

How do I test my iPhone accelerometer?

Open the Phone app and tap Keypad, then type *#0*#. A diagnostic screen pops up with buttons for a variety of tests. Tap Red, Green, or Blue to test those pixel colors. Tap Receiver to check the audio, Vibration to try the vibrating feature, or Sensor to test the accelerometer and other sensors.

Is there an accelerometer in iPhone?

The Accelerometer in iOSThe iPhone is equipped with accurate accelerometer and gyroscope hardware. It can measure the altitude, rotation rate, and acceleration of your iPhone with high accuracy. Steve Jobs demonstrated the capabilities of these two sensors during the introduction of iPhone 4.


2 Answers

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.

like image 112
Duncan C Avatar answered Nov 01 '22 22:11

Duncan C


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

like image 33
user3125280 Avatar answered Nov 01 '22 22:11

user3125280