Reputation: 17279
I'm trying to detect correct phone shake by this below code, but that its not work correctly, for example often when i shake phone to left i get RIGHT
or get both of RIGHT
and LEFT
:
@Override
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) > 200) {
long diffTime = (curTime - lastUpdate);
lastUpdate = curTime;
x = values[SensorManager.DATA_X];
y = values[SensorManager.DATA_Y];
z = values[SensorManager.DATA_Z];
if (Round(x, 4) > 10.0000) {
Toast.makeText(this, "Right shake detected", Toast.LENGTH_SHORT).show();
} else if (Round(x, 4) < -10.0000) {
Toast.makeText(this, "Left shake detected", Toast.LENGTH_SHORT).show();
}
last_x = x;
last_y = y;
last_z = z;
}
}
}
POST UPDATED:
if (Utils.Round(x, 4) > 8.0000) {
//left
} else if (Utils.Round(x, 4) < -8.0000) {
//right
} else if (z > 9 && z < 10)
//down
else if (z > -10 && z < -9)
//up
Upvotes: 3
Views: 299
Reputation: 93542
Think about how an accelerometer works. It detects acceleration. When you move the phone to the right, you'll get an acceleration to the right, then 0 as you move at constant speed. THen when your hand stops, you'll see a negative acceleration (acceleration to the left) as you slow down, with the acceleration hitting 0 again when you stop.
In other words, you will always see positive/negative pairs for each motion. when you see both, that's because each of them were strong enough to trigger the filter. When you see the wrong one, that means the acceleration was too slow to trigger it, but the deceleration was fast enough to. You aren't debouncing for nearly long enough- for your shake to not detect the deceleration it would have to be a movement to the right that starts and ends in 200ms. Not long enough. You should look into DSP algorithms if you want really good results, but going over all those concepts is a small book in and of itself.
Also remember that accelerations ring. The way the accelerometer works physically- image a spring stretched by a weight. it will overshoot the median, then bounce back and do that several times. The interference of that wave with later data can bring odd results. It may even be possible for a strong ring to trip your filter several times.
Oh, also you should NOT be using currentTimeMillis here. THe sensor event has a time field. That's when the event actually happened. Which may be several hundred milliseconds before the event is processed if the system is busy. Use the time in the event field, not the time you're processing it at. Fixing that may help a bit, although it leaves other problems.
Upvotes: 2