Search code examples
javaandroidandroid-sensorssensor-fusion

How to log data from Android Motion Sensors at a fixed rate


I'm learning the Basics of Android programming.

I have a simple android test application in which i log the accelerometer,magnetometer and the orientation data to an external file while also displaying it. I initiate the logging process on click of a Start button (registerListener for relevant sensors) by calling a method initLogger.

Which looks something similar to this...

public void initLogger(View view)
{
    boolean bFlag = false;

    Button btnStart = (Button)findViewById(R.id.btnStartLog);
    Button btnStop = (Button)findViewById(R.id.btnStopLog);

    btnStart.setEnabled(bFlag);
    btnStop.setEnabled(!bFlag);

    bEnableLogging = true;
    //Start reading the sensor values
    sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_UI);
    sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_UI);

   //so on.... 

There is also a Stop button, which shall stop the logging process (and finally unregister by calling unregisterListener for each sensor)

The data retrieval process happens inside the onSensorChanged handler which shall retrieve the data from the relevant sensors, sets the value to the respective UI elements and finally log the data to an external .csv file.

onSensorChanged eventhandler looks something like this ...

public void onSensorChanged(SensorEvent event) {


    // TODO Auto-generated method stub
    // accelerometer
    TextView tAX = (TextView) findViewById(R.id.txtViewAxValue);
    TextView tAY = (TextView) findViewById(R.id.txtViewAyValue);
    TextView tAZ = (TextView) findViewById(R.id.txtViewAzValue);

    // magnetic field
    TextView tMX = (TextView) findViewById(R.id.txtViewMx);
    TextView tMY = (TextView) findViewById(R.id.txtViewMy);
    TextView tMZ = (TextView) findViewById(R.id.txtViewMz);

    if (bEnableLogging) {
        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {

            accelerometerdata = event.values.clone();

            tAX.setText(Double.toString(accelerometerdata[0]));
            tAY.setText(Double.toString(accelerometerdata[1]));
            tAZ.setText(Double.toString(accelerometerdata[2]));


        }

        if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {

            magneticmatrixdata = event.values.clone();

            tMX.setText(Double.toString(magneticmatrixdata[0]));
            tMY.setText(Double.toString(magneticmatrixdata[1]));
            tMZ.setText(Double.toString(magneticmatrixdata[2]));

        }

               // so on ....

Although i receive the data from all the configured sensors, i do not have the control over the rate at which the data is received. i.e

I know SensorChanged event is fired as and when the Sensor data is changed. However i want this event to be fired at a fixed rate. For ex: every 40ms

Question:

  1. How to ensure the SensorChanged event is fired at constant rate ?
  2. Is the class TimerTask in Java of any help in this case ?

Experts out here in SO.Please help me :)


Solution

  • Since you know that if there was no SensorChanged Event fired, there was no change, you can just use your old value. As you asked for LOG data in specific intervals, i would not do any output in the onSensorChanged Method just clone the new data to your accelerometerdata variable. And than log the value of accelerometerdata every 40ms. This way you are logging the actual value every 40ms even if the data didnt change....

    Note: According to Ridcullys Answer it also seem to be possible to get Sensor data "delivered" in specific time intervals. But since there is an delay on these "Deliveries" as always with sensor-data on Android, with my solution you will be more exactly on the 40ms interval. On the other hand it could happen that if the sensor data changes in the moment you log, it might happen that you delay the new data for one interval. And i guess (not sure about this point) - since its just about logging and not about sth like "get it as fast as possible in realtime", so this is not an requirement - the Timer-Solution causes less CPU-Load.