通过加速度计检测iPhone上任何地方的硬敲击

我正在尝试检测可能在iPhone上的任何地方,而不仅仅是iPhone屏幕上的水龙头。 这是一个链接 ,显示这是可能的。

基本上我想要做的就是发送一个提醒,如果用户在iPhone上点击3次,而电话是在他的口袋里。 我所取得的成就是我可以检测到3个水龙头,但是在这些情况下我也会收到错误警报。 1)如果用户走路,2)挥动手机3)跑步。 我需要检查用户是否已经打了3次iPhone。

这是我的代码。

- (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; } 

任何帮助将非常感激。

谢谢

您应该对加速计数据应用高通滤波器。 这会给你带来尖锐的信号 – 尖锐的水龙头。

我对“UIA加速度计高通滤波器”进行了快速search,并find了几个命中。 最简单的代码需要加速度计input的滚动平均值,然后从瞬时读数中减去该平均值以发现突变。 毫无疑问,更复杂的方法也是如此。

一旦你的代码能够识别尖锐的水龙头,你就需要制作能够检测到连续3个尖锐水龙头的代码。

正如另一个答案所build议的那样,所有这些都是从加速度计数据stream中筛选出来的。 类似脉冲的抽头将具有特征频谱图(频率组合),当来自适当滤波器的响应高于阈值时可以检测到该频谱图。

这是iPhone上非常常见的操作,我build议你看看这里的官方文档

我已链接的示例代码给你两个重要的东西:高通滤波器的官方示例代码和一个示例应用程序,将graphics加速度计数据。 你可以使用这个来看看你的水龙头,步骤和跳跃,以更好地理解为什么你的filter错误地回应。

此外,互联网是filterdevise文献的巨大来源 – 如果您需要制作高质量的filter,您可能需要查阅相关文献。 不过,我认为一个合适的二阶滤波器可能就足够了。

 @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 

重要的是,这个filter是方向不可知的,因为只有加速度的大小被过滤。 这对于响应看起来很正常至关重要。 否则,用户可能会觉得不得不从不同的angular度来寻找一个甜点。

另一方面,如果这个任务太困难了,我强烈build议捕获你的数据(例如在一个WAV文件中),并使用任何常见的信号分析程序来更好地了解它出错的地方。 见波特兰

这是我如何实现的。

 - (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration { if (pause) { return; } if (handModeOn == NO) { if(pocketFlag == NO) return; } // float accelZ = 0.0; // float accelX = 0.0; // float accelY = 0.0; rollingX = (acceleration.x * kFilteringFactor) + (rollingX * (1.0 - kFilteringFactor)); rollingY = (acceleration.y * kFilteringFactor) + (rollingY * (1.0 - kFilteringFactor)); rollingZ = (acceleration.z * kFilteringFactor) + (rollingZ * (1.0 - kFilteringFactor)); float accelX = acceleration.x - rollingX; float accelY = acceleration.y - rollingY; float accelZ = acceleration.z - rollingZ; 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) { [self.accArray addObject:[NSNumber numberWithFloat:-accelX]]; [self.accArray addObject:[NSNumber numberWithFloat:-accelY]]; [self.accArray addObject:[NSNumber numberWithFloat:-accelZ]]; } } 

试试这个代码:

 UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)]; longPress.minimumPressDuration = 2; //seconds //longPress.delegate = self; [myButton addGestureRecognizer:longPress];