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;
}
}
}
I personally, in my augmented reality library, use a rolling average for the updates:
This tends to smooth out the data pretty well, and you can tweak the filtering factor to get the responsiveness you want.
rawZValue is the raw value coming in from the accelerometer.
Here are a few code discrepancies...
There may be a problem regarding the updating of
last_x
,last_y
, andlast_z
. I believe they should be included inside theif ((curTime - lastUpdate) > 100) {
statement. In other words, they are being updated every timeonSensorChanged
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 justdiffTime
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 bydiffTime
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 forspeed
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.