How to know if Android device is Flat on table

3.3k views Asked by At

I'm using accelometer sensor to detect whether my device is flat on a table or not. The weird thing is even when I put my phone flat or rotate it on it's side the value is always between 90 and 100! This shouldn't be correct! am I missing something? Here is my code:

   float[] values = event.values;
    // Movement
    float x = values[0];
    float y = values[1];
    float z = values[2];
    float norm_Of_g =(float) Math.sqrt(x * x + y * y + z * z);

    // Normalize the accelerometer vector
    x = (x / norm_Of_g);
    y = (y / norm_Of_g);
    z = (z / norm_Of_g);
    int inclination = (int) Math.round(Math.toDegrees(Math.acos(y)));
    Log.i("tag","incline is:"+inclination);

    if (inclination < 25 || inclination > 155)
    {
        // device is flat
        Toast.makeText(this,"device flat - beep!",Toast.LENGTH_SHORT);
    }

Edit: I'm using this code : How to measure the tilt of the phone in XY plane using accelerometer in Android

2

There are 2 answers

0
Svj0hn On BEST ANSWER

You're using the y-axis instead of the z-axis as used in the answer you linked.

The value of acos will be near-zero when the argument is near one (or near 180 degrees when near negative one), as seen in this picture:

Arccos(x)

As such, your inclination will be near zero (or 180) degrees only when the y axis is normalized to about one or negative one, eg when it is parallel to gravity, (thus, the device is "standing up").

If there's no other error, simply switching from:

int inclination = (int) Math.round(Math.toDegrees(Math.acos(y)));

to

int inclination = (int) Math.round(Math.toDegrees(Math.acos(z)));

should do it.

2
dangVarmit On

I used the code on this page Motion Sensors

public void onSensorChanged(SensorEvent event){
  // In this example, alpha is calculated as t / (t + dT),
  // where t is the low-pass filter's time-constant and
  // dT is the event delivery rate.

  final float alpha = 0.8;

  // Isolate the force of gravity with the low-pass filter.
  gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0];
  gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1];
  gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2];

  // Remove the gravity contribution with the high-pass filter.
  linear_acceleration[0] = event.values[0] - gravity[0];
  linear_acceleration[1] = event.values[1] - gravity[1];
  linear_acceleration[2] = event.values[2] - gravity[2];
}

The intention of this is to factor out the force of gravity (over repeated measurements) in the accelerometer values, leaving just the acceleration component in each direction.

The force of gravity is measured along each axis, so once you know which axis represents the device lying flat, you can just check if the majority of the force of gravity lays in just that axis. That would mean the device is laying flat on the table.

You can also look at the linear acceleration to make sure the device isn't moving.