I'm reading out the accelerometer sensor on a Sony Smartwatch 3. Since the Android Wear 1.5 update the sampling rate won't drop below about 60hz, regardless weather I use SENSOR_DELAY_NORMAL, SENSOR_DELAY_UI or SENSOR_DELAY_GAME. Before the update SENSOR_DELAY_NORMAL resulted in a sampling rate of about 18 samples/seconds.
accelerometer.getMaxDelay()still returns 62500, which would be 16 samples/sec. I also tried setting the desired delay directly, when registering the sensor with sensorManager.registerSensor(this, accelerometer, 62500) but this doesn't work either.
Has anybody any idea of how I can reduce the sampling rate? It's very important for my app to be energy efficient, thats why the low sampling rate is important.
Docs say next about samplingPeriodUs:
This is only a hint to the system. Events may be received faster or
slower than the specified rate. Usually events are received faster.
So, IMHO you should just ignore some amount of sensor events, as was proposed by Alex. Dry run for sensor event (i.e. without actual processing shouldn't be very power consuming).
How could it have been different: Not the Android update changed the behavior, it was my misunderstanding.
For everyone who might have problems with sensor batching or sampling rates:
The sampling rate might be different, when the display is on or off. In my case it was 60hz when on and 18hz when off.
Sensor batching might not be working, when the device is connected to a power source. For me I head to unplug the USB-cable. Bluetooth debugging might be helpful in that case.
Related
As in the title, I am wondering whether the pre-defined sampling rates of sensors could change when I updated the android version on my device from API 26 to API 28, for example?
In detail, assume I put the sampling rate for the accelerometer and gyroscope sensors at 100 Hz when the device Galaxy Samsung S8's android version has API 26. Then if I update the Android version to API 28, would that change or affect the sampling rates of the two sensors?
I searched a lot but could not find an official answer or resources.
Please, if could answer or share some useful links, that would be highly appreciated.
In short -- No, an API Level Change won't influence your sensor sampling rate. Nothing has changed in that field since API Level 3 (esp. adding the possibility to specifiy your own sampling rate). The main link for this topic is on Monitoring Sensor Events in the official Android Dev Docs.
A bit extensive quoting for your interest:
The data delay (or sampling rate) controls the interval at which sensor events are sent to your application via the onSensorChanged() callback method. The default data delay is suitable for monitoring typical screen orientation changes and uses a delay of 200,000 microseconds. You can specify other data delays, such as SENSOR_DELAY_GAME (20,000 microsecond delay), SENSOR_DELAY_UI (60,000 microsecond delay), or SENSOR_DELAY_FASTEST (0 microsecond delay). As of Android 3.0 (API Level 11) you can also specify the delay as an absolute value (in microseconds).
But pay attention, that specifying 100 Hz (so a delay of 10 microseconds) doesn't guarantee that rate anyway:
The delay that you specify is only a suggested delay. The Android system and other applications can alter this delay. As a best practice, you should specify the largest delay that you can because the system typically uses a smaller delay than the one you specify (that is, you should choose the slowest sampling rate that still meets the needs of your application). Using a larger delay imposes a lower load on the processor and therefore uses less power.
Of course the question arises, what rate do one get:
There is no public method for determining the rate at which the sensor framework is sending sensor events to your application; however, you can use the timestamps that are associated with each sensor event to calculate the sampling rate over several events.
Therefore you can write a small test program or use an existing one, there are plenty of them on Github.
But the mere update of the API Level shouldn't change anything.
I am developing an app that I would like to have constantly monitor accelerometer sensor data, even when the screen is off, but I would also like my battery to last longer than 5 hours :/ The most obvious thing of course is to set the sampling rate very low. I have tried to register the accelerometer with both SENSOR_DELAY_NORMAL and with a microsecond value of 1000000 (once per second) using
senSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
senAccelerometer = senSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
senSensorManager.registerListener(this, senAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
but the Android OS quickly (after I jiggle the phone for a couple seconds) decides to override these suggested sampling rates and starts sending my app non-stop accelerometer sensor events at about 100/second, even when I turn the screen off. Needless to say, this is not good for the battery life.
What I have tried for now is a bit of a hack, and I'm wondering if 1. there is a better, Android appoved way to do it, and 2. if what I've done is going to not actually work the way that I want it to. My current solution is to immediate unregister the accelerometer after the first reading (from within the listener callback), record the time of unregistering and then to have a separate timer loop that re-registers the accelerometer listener after a half-second has passed. This seems to work, but I don't know if it's going to cause problems on some devices, or maybe the registerListener function itself drains batteries on some devices? Any advice from anybody else who has made a non-battery-draining always-on background accelerometer listener would be greatly appreciated. Thanks.
EDIT 9/7/2016:
The hack that I described above does seem to work and does seem to save significantly on battery, as long as I slow down the sampling speed to about 0.5 or 1.0 seconds. If I have any more experience, good or bad, with this technique I'll let you all know. (If it matters, I'm testing this on a Note 4, Android 5.1.1) (also added a bit more explanatory code up above)
You might want to look at how it's handled in this project:
https://github.com/alanszlosek/androidstudio-accelerometer-gps/blob/master/app/src/main/java/com/alanszlosek/whenmoving/MainService.java
Seems to be using alarms to schedule logging. Bit of a different situation with even lower sampling frequency, so I'm not sure what method is more efficient.
Would it be possible for you to stick your logger code up on github or somewhere? I'm trying to do accelerometer tracking for a grant project and having trouble getting the services and wakelocks to play well together.
I write a simple app to read accelerometer data and I found that sampling rate is too low(even one sample 5 seconds) when I put phone on the table and keep quiet. I set sampling rate as FASTEST it's sampling rate always is high.
I want to know why and how does Android do this? I guess jni or hardware always read data but it discard data when it find there is no change between two sample.
As you can see from the documentation of the sensor listener the procedure onSensorChanged is called when the sensor changed. This means that if you hold the device still the sensor values won't change.
I have to admit that most phones add noise to sensor values and these values are always changing; you should be 'proud' of your phone - it doesn't add a lot of noise.
I own a samsung galaxy tab 10.1 4g lte-- and am starting to play with the sensors onboard. I looked up the mems gyro on board and found that (you can see for yourself on pg 9) that there are 4 different condition settings to change the sensitivity of the gyro from 250 degrees per second to up to like 2500 degrees per second. I am pretty sure that the lower setting will allow for a finer resolution of reading, while the higher settings can account for larger amounts of motions ( the reading at highest resolution (250) would probably max out at 250). Does anyone know what the default setting is and how to change it? If i had to guess I would bet the setting is on +-500 or +-1000 by default.
Thanks for the help in advance.
On registering your listener, you can specify the rate at which the events should be received.
registerListener (SensorEventListener listener, Sensor sensor, int rate)
You can choose from a variety of rates enumerated by SensorManager class:
SENSOR_DELAY_NORMAL, SENSOR_DELAY_UI, SENSOR_DELAY_GAME, or SENSOR_DELAY_FASTEST
Moreover, even the rate values are just a hint for the system, it's not necessarily receiving events at your specified rate.
I am working on a project using HTC magic which requires the data from the electronic compass, including both the accelerometer and magnetic sensor. But I find that there is a significant latency between the move of the phone and the trigger of the sensorChanged event. In other word, the acceleration and magnetic data obtained from sensor are updated about half of a second after my motion. And I have several questions about the problem as follow.
Are the orientation data computed by the acceleration and magnetic data? Or are there a physical sensor for orientation?
Does the latency result from the android API (using the event) or the physical limitation of the electronic compass?
It is said that the model of the electronic compass is AK8976A from Asahi Kasei. Does anybody have the datasheet or know the frequency of the sampling?
Any idea to improve the real-time experience?
Thank you in advance!
When you register the SensorEventListener what rate are you using? You should be using SENSOR_DELAY_GAME to get the best balance between frequent updates and not overdriving the update queue which can actually cause updated to be slower if SENSOR_DELAY_FASTEST.
As to your other questions I think they're kind of moot. Whether the update delay you're seeing is due to the API, or the actual compass itself you can't change it.
I did figure this out. Turns out that in 2.2 you can't use sensor rates other than the standard SENSOR_DELAY_UI, SENSOR_DELAY_NORMAL, etc. The documentation claims you can also specify the number of microseconds between notifications, but they are lying.
Once I used the standard constants it started working on 2.2