Johnny-five: BME280 wrong readings / oversampling mode

Created on 14 Jan 2017  路  17Comments  路  Source: rwaldron/johnny-five

Hi and thanks for the excellent work!

I was trying out j5 on my Raspberry Pi 2 Model B and noticed that the readings for Multi as well as `Barometer' and 'Humidity' return wrong values for a Sparkfun BME280 breakout.

As I am new in the IoT scene, I am assuming that I am doing something wrong or have not read enough, but here are some assumptions followed by some questions:

  1. Using the python library Adafruit_Python_BME280 I get the following results:
Temp      = 24.140 deg C
Pressure  = 991.88 hPa
Humidity  = 41.53 %
  1. Using another python library I get similar results:
Chip ID     : 96
Version     : 0
Temperature :  24.14 C
Pressure :  991.880802123 hPa
Humidity :  41.5296441194 %
  1. But when I use NodeJS with j5 and Multi I get:
--------------------------------------
Thermometer
  celsius      :  21.55
--------------------------------------
Barometer
  pressure     :  76.27
--------------------------------------
Hygrometer
  humidity     :  71.061
--------------------------------------

I noticed that both python libraries set (by default) the oversampling mode or oversampling rate to 8 . When I set it to 1, even with python I get similar wrong values.

For reference I am using an external/handheld barometer and 2 different hygrometers which all report similar values to the oversampled ones (i.e. relative humidity ~ 42 and pressure ~ 992 hPa)

My questions are:

  1. Is there a way to set the oversampling rate in j5?
  2. Why does the BME280 need such a high oversampling mode in order to provide correct values?
  3. Can you point me to some reading material about oversampling and how/why it affects the readings so much?
  4. I notice that even the temperature is off a bit, can I assume that this is a normal fluctuation?
  5. After getting data with node/j5 one of the two python libraries also reports wrong data: i.e.
Chip ID     : 96
Version     : 0
Temperature :  21.55 C
Pressure :  762.681500693 hPa
Humidity :  71.0611180087 %

but then I run the Adafruit lib again and it corrects/resets it. Its like the JS code messes with the sensor in a way I can't explain...

Bug Hardware Required Needs Attention

All 17 comments

Thanks for the report! When I wrote the BME280 controller-driver I verified output against the output of existing C/C++ libraries, but not Adafruit_Python_BME280. Our implementation is written against the datasheet, instead of as a "port" of any existing code base.

I'm going to spend some time today with Adafruit_Python_BME280 to see what I can learn

Great!

If it is any help while researching I found that similar results are returned when using this js implementation by @skylarstein, but only the first result has wrong data, all consecutive results seem correct.

This goes hand-in-hand with the (pretty untechnical) FAQ answer found here which states:

The BMx280 'saves' the last reading in memory for you to query. Just read twice in a row and toss out the first reading!

Also, the only difference I found in the Adafruit_Python_BME280 library is that they use oversampling *8 which might be just taking 8 samples and returning the mean value of those (instead of "tossing" out the first), which in a way would also affect the results when the first result is off by that much.

I suspect that your hunch about oversampling settings might be the right path to explore. Here's what I've done so far:

  1. Using just an Arduino UNO...
  2. With Adafruit_BME280_Library, I ran the following program:

    #include <Wire.h>
    #include <Adafruit_Sensor.h>
    #include <Adafruit_BME280.h>
    
    Adafruit_BME280 bme;
    
    void setup() {
      Serial.begin(9600);
      Serial.println(F("BME280 test"));
    
      if (!bme.begin()) {
        while (1);
      }
    }
    
    void loop() {
      Serial.print("Temperature = ");
      Serial.print(bme.readTemperature());
      Serial.println(" *C");
    
      Serial.print("Pressure = ");
      Serial.print(bme.readPressure() / 1000.0F);
      Serial.println(" kPa");
    
      Serial.print("Humidity = ");
      Serial.print(bme.readHumidity());
      Serial.println(" %");
    
      Serial.println();
      delay(2000);
    }
    

    Here are the first 10 readings output by that program:

    BME280 test
    Temperature = 19.68 *C
    Pressure = 102.80 kPa
    Humidity = 25.97 %
    
    Temperature = 19.67 *C
    Pressure = 102.79 kPa
    Humidity = 25.83 %
    
    Temperature = 19.67 *C
    Pressure = 102.79 kPa
    Humidity = 25.67 %
    
    Temperature = 19.67 *C
    Pressure = 102.79 kPa
    Humidity = 25.67 %
    
    Temperature = 19.67 *C
    Pressure = 102.79 kPa
    Humidity = 25.78 %
    
    Temperature = 19.68 *C
    Pressure = 102.80 kPa
    Humidity = 25.99 %
    
    Temperature = 19.67 *C
    Pressure = 102.79 kPa
    Humidity = 26.07 %
    
    Temperature = 19.68 *C
    Pressure = 102.79 kPa
    Humidity = 25.92 %
    
    Temperature = 19.69 *C
    Pressure = 102.80 kPa
    Humidity = 26.09 %
    
    Temperature = 19.69 *C
    Pressure = 102.80 kPa
    Humidity = 26.45 %
    
  3. Next, I uploaded StandardFirmata to the board.

  4. With Johnny-Five, I ran the following program:

    var five = require("johnny-five");
    var board = new five.Board();
    
    board.on("ready", function() {
      var multi = new five.Multi({
        controller: "BME280"
      });
    
      multi.on("data", function() {
        console.log(`Temperature: ${this.thermometer.celsius} C`);
        console.log(`Pressure: ${this.barometer.pressure} kPa`);
        console.log(`Humidity: ${this.hygrometer.relativeHumidity} %`);
        console.log();
      });
    });
    

    Here are the first 10 readings output by that program:

    Temperature: 22.23 C
    Pressure: 70.796 kPa
    Humidity: 54.003 %
    
    Temperature: 22.23 C
    Pressure: 70.796 kPa
    Humidity: 54.003 %
    
    Temperature: 22.23 C
    Pressure: 70.796 kPa
    Humidity: 54.003 %
    
    Temperature: 19.64 C
    Pressure: 102.795 kPa
    Humidity: 25.749 %
    
    Temperature: 19.64 C
    Pressure: 102.795 kPa
    Humidity: 25.749 %
    
    Temperature: 19.64 C
    Pressure: 102.795 kPa
    Humidity: 25.749 %
    
    Temperature: 19.64 C
    Pressure: 102.795 kPa
    Humidity: 25.749 %
    
    Temperature: 19.64 C
    Pressure: 102.795 kPa
    Humidity: 25.749 %
    
    Temperature: 19.65 C
    Pressure: 102.794 kPa
    Humidity: 25.792 %
    
    Temperature: 19.65 C
    Pressure: 102.794 kPa
    Humidity: 25.792 %
    

Notes about the above:

  1. They are both using the same over-sampling rate (16x). I will next explore different oversampling rates.
  2. J5 does a soft reset, which appears to cause the erroneous initial readings. I will fix this.

Is there a branch where you could commit the soft reset fix or perhaps point me to the code so that I can fork?

I am also currently running into a problem with the BME280 where my temperature readings are 5掳C too high. The first reading seems to be correct (~22掳C, which is close to the actual temperature in my appartment). It then starts reading 27-28掳C.. Sensor works, if I place my finger on it, the temperature rises again. Is there a fix for this yet? Thanks!

@cabaret just FYI, the BME280 data sheet has this to say:

"Temperature measured by the internal temperature sensor. This temperature value depends on the PCB temperature, sensor element self-heating and ambient temperature and is typically above ambient temperature."

Your first readings from cold start are accurate since it's been unused and at ambient temperature, but as soon as you start using the sensor it begins to generate its own heat.

Other factors such as proximity to the CPU, installation inside an enclosure, etc can also contribute to divergence from ambient.

@xeroxoid sorry for the delay, I was on parental leave from January 20th until last week and I'm still trying to catch up with everything.

Is there a branch where you could commit the soft reset fix or perhaps point me to the code so that I can fork?

I will be working on resolving issues as quickly as I can and will ping you here once I have this fixed. Thank you for your patience 鉂わ笍

Yay thanks, no worries! Congrats on the kid 馃槂

Whats the status of this problem?

@Arthedian I will try to resolve this week, if I have time.

Revisiting this issue... When running the Arduino code I gave above, I can actually reproduce the behavior that Johnny-Five is also displaying:

  1. Disconnect 3.3V, then Reconnect
  2. Press RESET button on Arduino
BME280 test
Temperature = 22.23 *C
Pressure = 70.79 kPa
Humidity = 54.00 %

Temperature = 23.63 *C
Pressure = 101.44 kPa
Humidity = 50.18 %

Temperature = 23.64 *C
Pressure = 101.44 kPa
Humidity = 50.11 %

Temperature = 23.64 *C
Pressure = 101.44 kPa
Humidity = 50.07 %

Temperature = 23.64 *C
Pressure = 101.44 kPa
Humidity = 50.04 %

...

Next...

  1. Upload StandardFirmata to the Arduino
  2. Disconnect 3.3V, then Reconnect
$ node eg/multi-BME280-1274.js
1493394045968 Available /dev/cu.usbmodem1411
1493394045990 Connected /dev/cu.usbmodem1411
1493394047709 Repl Initialized
>> Temperature: 22.23 C
Pressure: 70.796 kPa
Humidity: 54.003 %

Temperature: 22.23 C
Pressure: 70.796 kPa
Humidity: 54.003 %

Temperature: 22.23 C
Pressure: 70.796 kPa
Humidity: 54.003 %

Temperature: 22.23 C
Pressure: 70.796 kPa
Humidity: 54.003 %

Temperature: 23.28 C
Pressure: 101.438 kPa
Humidity: 50.207 %

Temperature: 23.28 C
Pressure: 101.438 kPa
Humidity: 50.207 %

Temperature: 23.28 C
Pressure: 101.438 kPa
Humidity: 50.207 %

Nearly identical results for the first few seconds.

Of course the status register is not in contiguous order with the pressure and temp registers (which are)...

0xF3 status
0xF4 crtl_meas
0xF5 config
0xF6 -
0xF7 MSB Pressure 
0xF8 LSB Pressure
0xF9 XLSB Pressure
0xFA MSB Temperature 
0xFB LSB Temperature
0xFC XLSB Temperature

Setting oversampling to x8 instead of x16 and following the same procedures shown here: https://github.com/rwaldron/johnny-five/issues/1274#issuecomment-298033220 produces nearly identical results; specifically: the incorrect pressure and humidity, which evens off after a 2-3 seconds

Just to address the original report:

Its like the JS code messes with the sensor in a way I can't explain...

Yes, this is the soft reset, which the Adafruit library is not doing

I believe I found the answer on Page 8, 1.2 Humidity parameter specification:

| Parameter | Symbol | Condition | Min | Typ | Max | Unit |
| --------- | ------ | --------- | --- | --- | --- | ---- |
| Response time to complete 63% of step | 63% | 90->0 or 0->90 %RH, 25掳C | | 1 | | s |

If I prevent any readings from being emitted until after a complete step, which is ~1587ms, then all readings are always accurate!

Same outcome when I limit the standby time to the 63% of 1 second

Great! Thanks for taking the time to solve this issue and document it in such detail!

Was this page helpful?
0 / 5 - 0 ratings