How to determine the direction of shake iPhone

I am using an accelerometer to scroll through several subspecies in UIScrollVIEW. I want the view (portrait orientation) to scroll to the right when the user clicks the iPhone to the right and scrolls to the left when the device moves to the left.

I thought I could do this by noting positive or negative values ​​of the acceleration x, but I see that the values ​​are usually a mixture of positive and negative values. I set the floor to 1.5 g to eliminate movement without jitter, and I look at the x values ​​for 0.5 seconds.

I am sure that there is a trigonometric method for determining the general direction of a click and that you should measure values ​​over the duration of the click. I am also sure that someone already understood this.

Any ideas there?

thanks

+4
source share
2 answers

I developed a solution that gives me better feedback than the proposed solution (left and right shake only). The way I did it here is quite sensitive (recognizes a slight jitter), but the sensitivity can be adapted by changing tresholdFirstMove and tresholdBackMove (increase for lower sensitivity)

In Swift: (in your viewController and add "import CoreMotion")

var startedLeftTilt = false var startedRightTilt = false var dateLastShake = NSDate(timeIntervalSinceNow: -2) var dateStartedTilt = NSDate(timeIntervalSinceNow: -2) var motionManager = CMMotionManager() let tresholdFirstMove = 3.0 let tresholdBackMove = 0.5 override func viewDidLoad() { // your code motionManager.gyroUpdateInterval = 0.01 } override func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) motionManager.startGyroUpdatesToQueue(NSOperationQueue.currentQueue(), withHandler: { (gyroData, error) -> Void in self.handleGyroData(gyroData.rotationRate) }) } private func handleGyroData(rotation: CMRotationRate) { if fabs(rotation.z) > tresholdFirstMove && fabs(dateLastShake.timeIntervalSinceNow) > 0.3 { if !startedRightTilt && !startedLeftTilt { dateStartedTilt = NSDate() if (rotation.z > 0) { startedLeftTilt = true startedRightTilt = false } else { startedRightTilt = true startedLeftTilt = false } } } if fabs(dateStartedTilt.timeIntervalSinceNow) >= 0.3 { startedRightTilt = false startedLeftTilt = false } else { if (fabs(rotation.z) > tresholdBackMove) { if startedLeftTilt && rotation.z < 0 { dateLastShake = NSDate() startedRightTilt = false startedLeftTilt = false println("\\\n Shaked left\n/") } else if startedRightTilt && rotation.z > 0 { dateLastShake = NSDate() startedRightTilt = false startedLeftTilt = false println("\\\n Shaked right\n/") } } } } 
+6
source

OK, I developed a solution. When I detect a shaking movement (acceleration greater than 1.5 on the x axis), I start the timer and set BOOL to true. While BOOL is true, I am adding acceleration values. When the timer expires, I stop adding acceleration values ​​and determine the direction of shaking by the sign of full acceleration.

 - (void)accelerometer:(UIAccelerometer *)acel didAccelerate:(UIAcceleration *)aceler { if (fabsf(aceler.x) > 1.5) { shake = YES; NSTimeInterval myInterval = .75; [NSTimer scheduledTimerWithTimeInterval:myInterval target:self selector:@selector(endShake) userInfo:nil repeats:NO]; return; } if(shake) { totalG += aceler.x; } } - (void) endShake { shake = NO; int direction; if (totalG isLessThan 0) direction = 1; if(totalG isGreaterThan 0) direction = -1; [self changePageByShake:direction]; totalG = 0; } 

Note: I was unable to get <and> characters for proper formatting in the code block above, so I replaced isLessThan and isGreaterThan for characters.

+5
source

Source: https://habr.com/ru/post/1286477/


All Articles