Accelerometer 101

What follows is the 30,000 foot introduction to working with the accelerometer on the iPhone.

There is one instance of the UIAccelerometer object that is shared throughout your application. To start receiving input from the accelerometer, set the update interval for the frequency of updates and set the delegate to receive the callbacks. If often looks like this:

// Start receiving callbacks, every 40 milliseconds
[[UIAccelerometer sharedAccelerometer] setUpdateInterval:1/25];
 
// Set the delegate to this object
[[UIAccelerometer sharedAccelerometer] setDelegate: self];


To get this to work as expected the class that is referenced by self must implement the UIAccelerometerDelegate, so your class definition might look as follows:

@interface ShootWeaponViewController : UIViewController <UIAccelerometerDelegate>
{
  ...
  UIAccelerationValue accelerationArray[3];
  ...
}

The code above creates an array with three entries, each of the type UIAccelerationValue (a floating point number) to hold the accelerometer info for each of the three axis (x, y and z), more on this in a moment.

The accelerometer will deliver data to the delegate method accelerometer:didAccelerate:. The values returned are between -1.0 and 1.0. The figure below shows the reference of x,y and z as it relates to the device.

A common filter that is applied to the incoming data is one that weeds out the effect of gravity on the device, often times referred to as a high-pass filter. Once the data has been filtered, we can begin to look for the specific movements of the device:

// High-pass filter constant
#define HIGHPASS_FILTER 0.1
 
// Axis
#define X_DIR  0
#define Y_DIR  1
#define Z_DIR  2
 
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration 
{
  // High pass filter
  accelerationArray[X_DIR] = acceleration.x - ((acceleration.x * HIGHPASS_FILTER) + (accelerationArray[X_DIR] * (1.0 - HIGHPASS_FILTER)));
  accelerationArray[Y_DIR] = acceleration.y - ((acceleration.y * HIGHPASS_FILTER) + (accelerationArray[Y_DIR] * (1.0 - HIGHPASS_FILTER)));
  accelerationArray[Z_DIR] = acceleration.z - ((acceleration.z * HIGHPASS_FILTER) + (accelerationArray[Z_DIR] * (1.0 - HIGHPASS_FILTER)));
 
  // Was the device moved away or toward you...
  if (z - accelerationArray[Z_DIR] > 0.5 || z - accelerationArray[Z_DIR] < -0.5)
  {
    ...
  }
  // Was the device moved up or down
  else if (y - accelerationArray[Y_DIR] > 0.5 || y - accelerationArray[Y_DIR] < -0.5)
  {
    ...
  }
  // Was the device moved left or right
  else if (x - accelerationArray[X_DIR] > 0.5 || X - accelerationArray[X_DIR] < -0.5)
  {
    ...
  }
}

You’ll find that tinkering with the values shown above (0.5 and -0.5) will allow you to adjust how much force in movement is required to detect the events you are after.

Stop Receiving Data:
To stop receiving data from the accelerometer, set the delegate method to nil, which will notify the device it can turn off the accelerometer hardware.

[[UIAccelerometer sharedAccelerometer] setDelegate:nil];
  1. Right, it’s important to not forget to set tne Deletate to nil at the end because if you release the view/viewcontroller which has the delegated method you will have a crash due to the fact that the accelerometer will try to send datas to that , now invalid, method.

  2. newby question-
    doesn’t 1/25 equal 0? shouldn’t you be using floats?

  3. bh,

    it would be more clear to write 1.0/25.0, and a good practice, however, the conversion to a double will be done for you.

  4. I am developing an app, in which i need to detect device motion for doing different-2 task.

    Could you please help any one how we got it using acceleration values?

    Example:- Suppose we move Device like a (Frisbee Throw)? How we can get this motion occur in Device.

    i am using (UIAccelerometerDelegate). my problem is how we distinguished between different-2 device motion.

    For example we have moved device like a frisbee, and we get x, y, z data in acceleration.

    How we calibrate these data for identifying motion?

    One idea take some sample motion data in x, y, z as a standard for particular motion and compare it.

    But every time we got different data and it’s not possible to how to compare these data?

    Please help me….

  5. hi John Muchow

    this is awesome

    before i not delegate to nil my app will crashing and while i assign nil to delegate it work fine thanks buddy. great post keep it up…….

  6. Hey, great stuff!

    Is it good practice to set the delegate back and forth between nil and self repeatedly if you’re starting and stopping accelerometer data collection, or should you turn it on once and then turn it off when the view disappears etc.?

    • I would guess it’s common practice to set to self and nil as needed. Anyone else have recommendations?

  7. Hello All ,

    I just wanted to know that the value of parameter x,y,z which that is using for subtracting filtered value.

    I mean in code..

    if (z – accelerationArray[Z_DIR] > 0.5 || z – accelerationArray[Z_DIR] < -0.5)
    {

    }

    what is value of z.
    same for x and y.

    Thank you in advance

Comments are closed.