Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bmx280 getTemperature returns same -incorrect- value #102

Closed
plattysoft opened this issue May 11, 2018 · 9 comments
Closed

bmx280 getTemperature returns same -incorrect- value #102

plattysoft opened this issue May 11, 2018 · 9 comments
Assignees

Comments

@plattysoft
Copy link

plattysoft commented May 11, 2018

In short, if you use a SensorDriver it works fine, but if you use just the Bmx280 object and call readTemperature, you get the same value every time. It is even the same value after a restart or in different days.
The most annoying part is that if you first initilize the sensor driver (on its own Activity) to then release it, then readTemperature works properly, so it sounds like there is some initialization missing.

Steps to replicate:

  • Get the sample code that opens the sensor (i.e. from RainbowHAT)
  • Call read temperature every second (i.e. using a Handler)

Expected result:

  • The readings have some variation
  • The readings are consistent with the ones from a sensor driver

Actual result:

  • The value is always the same (it is different per chip, but constant, I've tried it in 2 boards)

Given the placement of the sensor on the Rainbow HAT (close to the CPU of the Raspberry Pi), this is very noticeable, because the temperature slowly increases.

@jdkoren
Copy link
Member

jdkoren commented May 11, 2018

if you use a SensorDriver it works fine, but if you use just the Bmx280 object and call readTemperature, you get the same value every time

The SensorDriver code is calling readTemperature internally, so there should be no difference in behavior whichever way you use it.

The most annoying part is that if you first initilize the sensor driver (on its own Activity) to then release it, then readTemperature works properly, so it sounds like there is some initialization missing.

Can you provide more information about this? Maybe some code snippets or a sample project?

@plattysoft
Copy link
Author

plattysoft commented May 11, 2018

My code is 90% the code from the example on the readme of the Rainbow HAT section. I'll post it once I get to my laptop.

I know it calls readTemperature internally, I spent more than 1 hour digging into the source code and debugging it. That's what makes this bug more strange.

@plattysoft
Copy link
Author

plattysoft commented May 11, 2018

First Example:

class TemperatureDisplayActivity: Activity() {
    private val handler = Handler()
    private lateinit var sensor: Bmx280

    val displayTemperatureRunnable = object: Runnable {
        override fun run() {
            val temperature = sensor.readTemperature().toDouble()
            Log.i(TAG, "Temperature: " +temperature)
            handler.postDelayed(this, 1000)
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        sensor = RainbowHat.openSensor()
        sensor.temperatureOversampling = Bmx280.OVERSAMPLING_1X
        handler.post(displayTemperatureRunnable)
    }

    override fun onDestroy() {
        super.onDestroy()
        handler.removeCallbacks(displayTemperatureRunnable)
        sensor.close()
    }
}

Second example:

class TemperatureSensorDriverActivity : Activity(){

    val sensorCallback = object : SensorManager.DynamicSensorCallback() {
        override fun onDynamicSensorConnected(sensor: Sensor?) {
            if (sensor?.type == Sensor.TYPE_AMBIENT_TEMPERATURE) {
                registerTemperatureListener(sensor)
            }
        }
    }

    val temperatureSensorListener = object : SensorEventListener {
        override fun onSensorChanged(event: SensorEvent) {
            Log.i(TAG, "Temperature changed: " + event.values[0])
        }

        override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {
            Log.i(TAG, "accuracy changed: $accuracy")
        }
    }

    lateinit var sensorManager : SensorManager
    lateinit var sensorDriver : Bmx280SensorDriver

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        sensorDriver = RainbowHat.createSensorDriver()
        sensorDriver.registerTemperatureSensor();

        sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
        sensorManager.registerDynamicSensorCallback(sensorCallback)
    }

    private fun registerTemperatureListener(sensor: Sensor) {
        sensorManager.registerListener(temperatureSensorListener, sensor, SensorManager.SENSOR_DELAY_NORMAL)
    }

    override fun onDestroy() {
        super.onDestroy()
        sensorManager.unregisterListener(temperatureSensorListener)
        sensorDriver.unregisterTemperatureSensor()
        sensorDriver.close()
    }
}

If I run the first example, the reading is always the same.
If I run the second example, the reading does change (and it is higher)
If after running the second example, I run the first one without powering off the device, the reading does change, and it is consistent with the values from the second example (similar range)
This is replicable every time I boot the device, on 2 different hats

That's why I think there is some initialization as part of the driver setup that is missing on the first example, the chip keeps the initialized state from the 2nd Activity and that's why running the 1st one again works..

For the record, the same issue happens with pressure.

@plattysoft
Copy link
Author

@jdkoren could you replicate this issue?

@devunwired
Copy link
Contributor

devunwired commented May 17, 2018

We can replicate the issue. The difference is that the sensor driver sets the power mode of the chip to NORMAL before attempting readings. The MVP init code for using the Bmx280 directly should actually be the following:

sensor = RainbowHat.openSensor()
sensor.temperatureOversampling = Bmx280.OVERSAMPLING_1X
sensor.setMode(Bmx280.MODE_NORMAL)

This is generally the default state of the chip, but the user shouldn't assume that. In your case, the chip is powering up in sleep mode. We'll update the usage docs to reflect this.

@plattysoft
Copy link
Author

Thanks Dave!

it really sounded like a missing initialization, but I could not find it.
I can confirm that setting the mode to normal makes it work as expected.

@plattysoft
Copy link
Author

Actually, just a thought, it would make sense to put it to sleep a part of close, or recommend to put it into sleep mode as part of the release, to save power. Does that make sense?

@devunwired
Copy link
Contributor

It's heavily use case dependent, but it might make sense to include it in the documented example for clarity. We'll think about the best way to communicate this.

We can't assume that you want to sleep the chip on close any more than we can assume you want to wake the chip immediately after opening it (the sensor driver waits until readings are required, for example). But I see your point.

@devslava
Copy link

@devunwired Thank you so much! 👍
This code should be definitely included into the Readme sample code.
I've spent some hours trying to understand why do the sensor is returning the same value. I've also tried heating the sensor, hehe.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants