pimoroni / bme680-python

Python library for the BME680 gas, temperature, humidity and pressure sensor.
https://shop.pimoroni.com/products/bme680
MIT License
260 stars 93 forks source link

Extremely high/negative gas resistance readings #6

Closed davea closed 6 years ago

davea commented 6 years ago

I've been getting some pretty whacky gas resistance readings from one of the BME680 sensors using this library. The values I've logged have spiked as high as 285204105.924075 and as low as -24795831.931635 which is pretty far outside the expected range as I understand it.

Here are a bunch of graphs at increasing levels of detail to illustrate the trends: render-1

render-2

render-3

Another sensor elsewhere in the house running the exact same code is returning more sensible values: render-4

For reference this is the code I'm running: https://github.com/davea/rpi-mqtt-sensors/blob/master/main.py

jorisvervuurt commented 6 years ago

That's weird. I'm assuming that it's not a bug in the software library. Have you double checked your wiring/soldering? Might be a defective sensor as well.

Perhaps you could swap the BME680 boards to see if the problem shifts?

Gadgetoid commented 6 years ago

This is possibly related: https://forums.pimoroni.com/t/bme680-breakout-negative-ohms-on-gas-sensor/6500

I would expect the negative readings are a result of an overflow.

Looking at the datasheet, the gas calculation is defined as:

var1 = (1340.0 + 5.0 * range_switching_error) * const_array1[gas_range];
gas_res = var1 * const_array2[gas_range] / (gas_r - 512.0 + var1);

With const_array1 and const_array2 being the following tables:

constarray1and2

In the code, these are defined as the following, which is the result of shifting up the decimal numbers by enough to be kinda precise (shifted up 31? places for array1 and 9 for array2):

https://github.com/pimoroni/bme680/blob/288daed781604c5581b117b4c91ca567404f9fa8/library/bme680/constants.py#L215-L224

At this point the calculation becomes difficult to follow, but presumably it's correcting the 31 place shift up on const_array1

https://github.com/BoschSensortec/BME680_driver/blob/494b3bb26b026dcc26059e512bb71b60eb364376/bme680.c#L923-L937

Notably it seems to perform all operations as int64_t, before casting the result to uint32_t. Which may be where our bug is introduced. Take the linked forum post results by way of example and cast each number to a uint32_t:

Casting to uint32_t:
131858.0 => 131858
129573.0 => 129573
129573.0 => 129573
128828.0 => 128828
127546.0 => 127546
127365.0 => 127365
124883.0 => 124883
122999.0 => 122999
123848.0 => 123848
122328.0 => 122328
123678.0 => 123678
120359.0 => 120359
120037.0 => 120037
119398.0 => 119398
120198.0 => 120198
118923.0 => 118923
118766.0 => 118766
118766.0 => 118766
118296.0 => 118296
110979.0 => 110979
-1425780.0 => 4293541516
1382577.0 => 1382577
556403.0 => 556403
414773.0 => 414773
348282.0 => 348282
314655.0 => 314655
292468.0 => 292468
298203.0 => 298203
323582.0 => 323582
353682.0 => 353682
377066.0 => 377066
418578.0 => 418578
495924.0 => 495924
495924.0 => 495924
592533.0 => 592533
608334.0 => 608334
724207.0 => 724207
800439.0 => 800439
950521.0 => 950521
1061047.0 => 1061047
1200659.0 => 1200659
1267362.0 => 1267362
1382577.0 => 1382577
1629466.0 => 1629466
3258935.0 => 3258935
3509623.0 => 3509623
3509623.0 => 3509623
4147738.0 => 4147738
11406336.0 => 11406336
-11406162.0 => 4283561134
-7604127.0 => 4287363169
-3802073.0 => 4291165223
-2683818.0 => 4292283478
-2172616.0 => 4292794680
-1520832.0 => 4293446464
-1267360.0 => 4293699936
-1036931.0 => 4293930365
-1112804.0 => 4293854492
-1061046.0 => 4293906250
-950520.0 => 4294016776
-877403.0 => 4294089893
-829545.0 => 4294137751
-786637.0 => 4294180659
-747950.0 => 4294219346
-661232.0 => 4294306064
-712890.0 => 4294254406
-773305.0 => 4294193991
-651785.0 => 4294315511
-600329.0 => 4294366967
-592532.0 => 4294374764
110432.0 => 110432
110841.0 => 110841
111948.0 => 111948
114814.0 => 114814
114520.0 => 114520
115404.0 => 115404
114961.0 => 114961

Ah... well that's one problem solved, perhaps, but this doesn't explain the high spikes!?

lowflyerUK commented 6 years ago

Hi! I have just got a BME680 and have seen these spikes. I think the problem is in line 328 of bme680/constants.py.

It is now: self.range_sw_err = (sw_error * RSERROR_MSK) // 16

and should be: self.range_sw_err = (sw_error & RSERROR_MSK) // 16

At least my results of calc_gas_res are much more consistent now!!

Gadgetoid commented 6 years ago

@lowflyerUK ... is there a GitHub facepalm emote?

🤦‍♂️

Yup!

Thank you!

davea commented 6 years ago

Aha! Thanks for tracking this down 👍 I've updated to 1.0.4 on both my devices and will see how it goes.