2011-06-11 15 views
5

He intentado detectar un evento de sacudida con el acelerómetro. He descubierto que cuando doy un batido continuo oa al teléfono, la diferencia de valor de la aceleración es bastante estable. Pero cuando gira el teléfono, siempre hay un gran cambio en el valor (el valor es por lo general más grande que "sacudir sin rotación"). Quiero centrarme en el evento de agitación, no en el evento de rotación. ¿Hay alguna manera de resolver el problema?¿Existe una forma estable de detectar el evento de temblor?

aquí es mi código para que compartiran con nosotros detección

public void onSensorChanged(SensorEvent event) 
    { 
     if (event.sensor.getType() == SensorManager.SENSOR_ACCELEROMETER) 
     { 
      nowTime = System.currentTimeMillis(); 

      float x = event.values[SensorManager.DATA_X]; 
      float y = event.values[SensorManager.DATA_Y]; 
      float z = event.values[SensorManager.DATA_Z]; 
      nowAcc = Math.sqrt(x*x+y*y+z*z); 
      accDiff = Math.abs(nowAcc - preAcc); 
      timeDiff = (nowTime - preTime); 
         // try to get the sum of 10 samplings of accDiff 
      tempAccDiff10 = tempAccDiff9; 
      tempAccDiff9 = tempAccDiff8; 
      tempAccDiff8 = tempAccDiff7; 
      tempAccDiff7 = tempAccDiff6; 
      tempAccDiff6 = tempAccDiff5; 
      tempAccDiff5 = tempAccDiff4; 
      tempAccDiff4 = tempAccDiff3; 
      tempAccDiff3 = tempAccDiff2; 
      tempAccDiff2 = tempAccDiff1; 
      tempAccDiff1 = accDiff; 
      sumAcc = tempAccDiff10+tempAccDiff9+tempAccDiff8+tempAccDiff7+tempAccDiff6+ 
        tempAccDiff5+tempAccDiff4+tempAccDiff3+tempAccDiff2+tempAccDiff1; 
      Log.i("SSSS",String.valueOf(sumAcc)); 
         //when I give the phone a big & continuous "shake", it returns 
         //a value about 30~40, but when I give the phone a small 
         //"rotation", it returns a value of 80~120 
      preAcc = nowAcc; 
      preTime = nowTime; 
      if (sumAcc>100) 
      { 
       SM.unregisterListener(sensorListener, sensor); 
      } 

      //123 
     } 


    }//end of onSensorChanged(); 

es posible descuidar el caso de la rotación utilizando el acelerómetro? O debería tratar de conseguir el cambio de orientación y hacer algunos cálculos en el Sumacc?

Respuesta

3

Debe utilizar un filtro para eliminar la influencia de la gravedad, hay algún tipo de tutorial on the docs to do so. Hice algo similar, en mi caso también estaba tratando de detectar otros movimientos, por lo que su tarea parece un poco más simple. Puedo publicar el código el próximo lunes (si lo recuerdo).

¡Buena suerte!


estoy editando la respuesta a añadir puede utilizar un Sensor TYPE_LINEAR_ACCELERATION si estás en Android 2.3 o superior. Es un sensor de aceleración normal que descarta el efecto de la gravedad , que definitivamente no necesita detectar un evento de vibración.

respecto


Edición 13/06 -> prometí publicar mi código para detectar temblores, pero en su lugar, creo que es una mejor idea para publicar this link, lo que da piezas de muestra de código en una variedad de respuestas. Mi código es muy similar a uno de los publicados allí.

¡Buena suerte!

+0

Gracias por su consejo! Estoy esperando el código. ¡Espero poder resolver este problema pronto! – Jim31837

+0

He intentado cambiar el alfa (constante de filtro de paso alto), pero un pequeño evento de rotación resulta en un valor mayor que un gran temblor. En realidad, estoy usando Android 2.2. Probaré el medidor de aceleración lineal si tengo la oportunidad de usar 2.3 dispositivos. – Jim31837

0

Desde el punto de vista de código, es necesario poner en práctica el SensorListener:

public class ShakeActivity extends Activity implements SensorListener 

Usted tendrá que adquirir una SensorManager:

sensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE); 

y registrar este sensor con banderas deseadas:

ensorMgr.registerListener(this, 
SensorManager.SENSOR_ACCELEROMETER, 
SensorManager.SENSOR_DELAY_GAME); 

En su onSensorChange método(), a determinar si se trata de un batido o no:

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) { 
     Log.d("sensor", "shake detected w/ speed: " + speed); 
     Toast.makeText(this, "shake detected w/ speed: " + speed, Toast.LENGTH_SHORT).show(); 
     } 
     last_x = x; 
     last_y = y; 
     last_z = z; 
    } 
    } 
} 

El umbral de sacudida se define como:

private static final int SHAKE_THRESHOLD = 800; 

hay demasiados algunos otros métodos, para detectar el movimiento de agitación. mira esto link. (Si ese enlace no funciona o el enlace está muerto, look at this web archive).

Gracias.

Cuestiones relacionadas