Search code examples
androidaccelerometer

Android: Accelerometer false detection


I have a code snippet to detect accelerometer movements. It works some times by properly detecting slight movements, but sometimes it detects movements when I kept my device idle too. Are there any problems with built-in accelerometer detection on Android?

I use an HTC G-1 device. My code snippet is below. How do I resolve it so I can detect small device movements but not detect anything when the device is idle?

private static final int SHAKE_THRESHOLD = 50;

public void onSensorChanged(int sensor, float[] values) {

    if (sensor == SensorManager.SENSOR_ACCELEROMETER) {
        long curTime = System.currentTimeMillis();
        // only allow one update every 100ms.
        if ((curTime - lastUpdate) > 100) {
            long diffTime = (curTime - lastUpdate);
            lastUpdate = curTime;

            x = values[SensorManager.DATA_X];
            y = values[SensorManager.DATA_Y];
            z = values[SensorManager.DATA_Z];

            float speed = Math.abs(x+y+z - last_x - last_y - last_z) / diffTime * 10000;

            if (speed > SHAKE_THRESHOLD) { 
                long curTime = System.currentTimeMillis();
                long diff = (curTime - shakeTime);              
                shakeTime = curTime;

                if (myFlagIgnoreShakeDetection==true)  //Caused unneccessary accelerometer   
                                                       //notification looping when device is idle
                   return;

                // Doing something...
            }
         last_x = x;
         last_y = y;
         last_z = z;
        }

    }

}

Solution

  • Here are a few code discrepancies...

    • There may be a problem regarding the updating of last_x, last_y, and last_z. I believe they should be included inside the if ((curTime - lastUpdate) > 100) { statement. In other words, they are being updated every time onSensorChanged is called, not every 100 milliseconds. You should probably move the updating of those three variables into the curly brace above them.

    • On the line where you compute the speed, the formula ends with ... / diffTime * 10000; Are you wanting to multiply just diffTime by 10000, or the entire result? Since / and * typically have the same operator precedence in most languages I know of (such as Java), your equation will be evaluated from left to right, dividing first by diffTime then multiplying that result by 10000.

      I'm guessing you mean to multiply just diffTime by 10000, thus dividing the final result by that amount. This is the difference between dividing by 10000 or multiplying by 10000, which means you are probably getting values for speed that are 10^8 greater than you should, thus tripping your threshold even when the device is idle. You need to put parentheses around the multiplication, like ... / (diffTime * 10000);, to make sure it's performed before the division takes place.

      Additionally, if you are intending to scale diffTime from milliseconds to seconds, your scale factor should be 1000.