R
R
RD1706D2022-04-13 22:33:30
Java
RD1706D, 2022-04-13 22:33:30

How to use RATE_VERY_FAST (Java, Android)?

Hello! I am writing a program to write data from the accelerometer to a csv file at the highest possible speed, the Android API documentation has several methods for working with the accelerometer, but I was only interested in two of them SENSOR_DELAY_FASTEST and RATE_VERY_FAST, according to the documentation, RATE_VERY_FAST should give the maximum sensor polling speed (up to 1700 Hz), but for some reason, when replacing SENSOR_DELAY_FASTEST with RATE_VERY_FAST, the polling speed becomes, on the contrary, several times lower (sometimes it can drop to 10 Hz, provided that it gives 400 Hz stable with SENSOR_DELAY_FASTEST), what's the problem?

Documentation:

https://developer.android.com/reference/android/ha...
https://developer.android.com/reference/android/ha...

Code with RATE_VERY_FAST:

spoiler
import androidx.appcompat.app.AppCompatActivity;
import android.hardware.Sensor;
import android.hardware.SensorDirectChannel;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        sm = (SensorManager) getSystemService(SENSOR_SERVICE);

        textView1 = (TextView) findViewById(R.id.Values);

        list = sm.getSensorList(Sensor.TYPE_ACCELEROMETER);
        if (list.size() > 0) {
            sm.registerListener(sel, (Sensor) list.get(0), SensorDirectChannel.RATE_VERY_FAST);
        } else {
            Toast.makeText(getBaseContext(), "Error: No Accelerometer.", Toast.LENGTH_LONG).show();
        }
    }

    SensorManager sm = null;
    TextView textView1 = null;
    List list;

    StringBuilder info = new StringBuilder();

    final SensorEventListener sel = new SensorEventListener() {
        public void onAccuracyChanged(Sensor sensor, int accuracy) {
        }

        public void onSensorChanged(SensorEvent event) {
            float[] values = event.values;
            String result0 = String.format("x: " + "%.20f", values[0]);
            String result1 = String.format("y: " + "%.20f", values[1]);
            String result2 = String.format("z: " + "%.20f", values[2]);
            info.append(result0 + "\n" + result1 + "\n" + result2 + "\n");
            //textView1.setText(result);
            textView1.setText("x: " +  values[0] + "\ny: " + values[1] + "\nz: " + values[2] + "\n");

        }
    };


    @Override
    protected void onStop() {
        if (list.size() > 0) {
            sm.unregisterListener(sel);
        }
        super.onStop();
    }
}


Code with SENSOR_DELAY_FASTEST:

spoiler
import androidx.appcompat.app.AppCompatActivity;
import android.hardware.Sensor;
import android.hardware.SensorDirectChannel;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        sm = (SensorManager) getSystemService(SENSOR_SERVICE);

        textView1 = (TextView) findViewById(R.id.Values);

        list = sm.getSensorList(Sensor.TYPE_ACCELEROMETER);
        if (list.size() > 0) {
            sm.registerListener(sel, (Sensor) list.get(0), SensorManager.SENSOR_DELAY_FASTEST);
        } else {
            Toast.makeText(getBaseContext(), "Error: No Accelerometer.", Toast.LENGTH_LONG).show();
        }
    }

    SensorManager sm = null;
    TextView textView1 = null;
    List list;

    StringBuilder info = new StringBuilder();

    final SensorEventListener sel = new SensorEventListener() {
        public void onAccuracyChanged(Sensor sensor, int accuracy) {
        }

        public void onSensorChanged(SensorEvent event) {
            float[] values = event.values;
            String result0 = String.format("x: " + "%.20f", values[0]);
            String result1 = String.format("y: " + "%.20f", values[1]);
            String result2 = String.format("z: " + "%.20f", values[2]);
            info.append(result0 + "\n" + result1 + "\n" + result2 + "\n");
            //textView1.setText(result);
            textView1.setText("x: " +  values[0] + "\ny: " + values[1] + "\nz: " + values[2] + "\n");

        }
    };


    @Override
    protected void onStop() {
        if (list.size() > 0) {
            sm.unregisterListener(sel);
        }
        super.onStop();
    }
}

Answer the question

In order to leave comments, you need to log in

1 answer(s)
M
Mercury13, 2022-04-14
@RD1706D

Let's see what RATE_XXX and SENSOR_DELAY_XXX are.
SENSOR_DELAY_FASTEST = 0
SENSOR_DELAY_GAME = 1
SENSOR_DELAY_UI = 2
SENSOR_DELAY_NORMAL = 3
RATE_STOP = 0
RATE_NORMAL = 1
RATE_FAST = 2
RATE_VERY_FAST = 3
The registerListener function requires a delay in µs, or one of the four SENSOR_DELAY constants. By setting RATE_VERY_FAST=3, you actually set it SENSOR_DELAY_NORMAL=3!
And where to put RATE? In SensorDirectChannel.configure! And the SensorDirectChannel itself can be obtained via SensorManager.createDirectChannel! Something like this - and I even understand where such an architecture comes from. Well, a system optimized for low power consumption cannot kick the user program 1700 times per second - the program receives control much less often, and information from the accelerometer is accumulated in the memory buffer.
UPD. There is also a second reason. Processing may take more than 1/1700 of a second, during which time the sensor will continue to write information to the same buffer.
UPD2. In other words, through the callback and through the buffer in memory are two different architectures. The first will provide low latency. The second is a high (and consistently high!) polling frequency, but the delay from registration to processing is likely to be longer.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question