Giter Site home page Giter Site logo

adafruit_circuitpython_bme680's Introduction

Introduction

Documentation Status Discord Build Status Code Style: Ruff

CircuitPython driver for BME680 sensor over I2C

Dependencies

This driver depends on:

Please ensure all dependencies are available on the CircuitPython filesystem. This is easily achieved by downloading the Adafruit library and driver bundle.

Installing from PyPI

On supported GNU/Linux systems like the Raspberry Pi, you can install the driver locally from PyPI. To install for current user:

pip3 install adafruit-circuitpython-bme680

To install system-wide (this may be required in some cases):

sudo pip3 install adafruit-circuitpython-bme680

To install in a virtual environment in your current project:

mkdir project-name && cd project-name
python3 -m venv .venv
source .venv/bin/activate
pip3 install adafruit-circuitpython-bme680

Usage Example

import adafruit_bme680
import time
import board

# Create sensor object, communicating over the board's default I2C bus
i2c = board.I2C()   # uses board.SCL and board.SDA
bme680 = adafruit_bme680.Adafruit_BME680_I2C(i2c)

# change this to match the location's pressure (hPa) at sea level
bme680.sea_level_pressure = 1013.25

while True:
    print("\nTemperature: %0.1f C" % bme680.temperature)
    print("Gas: %d ohm" % bme680.gas)
    print("Humidity: %0.1f %%" % bme680.relative_humidity)
    print("Pressure: %0.3f hPa" % bme680.pressure)
    print("Altitude = %0.2f meters" % bme680.altitude)

    time.sleep(2)

Documentation

API documentation for this library can be found on Read the Docs.

For information on building library documentation, please check out this guide.

Contributing

Contributions are welcome! Please read our Code of Conduct before contributing to help this project stay welcoming.

adafruit_circuitpython_bme680's People

Contributors

anecdata avatar billvanleeuwen424 avatar brennen avatar caternuson avatar ctho9305 avatar dhalbert avatar evaherrada avatar foamyguy avatar garberw avatar graeme-winter avatar jerryneedell avatar jposada202020 avatar jraber avatar justmobilize avatar kattni avatar ladyada avatar makermelissa avatar markpatterson27 avatar mrmcwethy avatar patcher-ms avatar robert-hh avatar sommersoft avatar tannewt avatar tayden avatar tdicola avatar tekktrik avatar thekitty avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

adafruit_circuitpython_bme680's Issues

Wrong conversion result for register 0x04

I checked out the Adafruit Circuit Python Module for the BME680 sensor from https://pypi.org/project/adafruit-circuitpython-bme680/#files to compare the results with my C driver for the BME680.
I add some code to the Adafruit library to print the calibration value for the range switching error in the Adafruit library and I got the result 15.0

self._sw_err = (self._read_byte(0x04) & 0xF0) / 16
print(self._sw_err)

When I read the whole register at address 0x04, I got the result 243 which is โ€ญ1111 0011โ€ฌ. Bosch writes the following in the device datasheet (Page 22):

  1. Read range switching error from register address 0x04<7:4>(signed 4 bit)

So I take the upper nibble of the byte 243, which is 1111, and handle this as a signed 4-bit value which should be -1 and not 15.

SPI broken?

I tried to implement this library in order to read the data form this sensor.
Here's my code:

import sys, time
import board
import busio
import digitalio
import adafruit_bme680

cs = digitalio.DigitalInOut(board.D5)
spi = busio.SPI(board.SCLK, board.MOSI, board.MISO)

bme680 = adafruit_bme680.Adafruit_BME680_SPI(spi, cs)
...

I get the error "Failed to find BME680! Chip ID 0xff"
Changing the value in line 45 of adafruit_bme680.py didn't help me.
I checked my wiring many times and also got myself a second sensor, which didn't work (with SPI) either.
Strangely both of them work, when connected via I2C.

I'm running a Raspberry Pi Zero W (Yes, SPI and I2C are enabled via raspi-config) with openHABian, but I also tried it on a Raspberry Pi 3 B+ with Raspbian, just to get the same error.

Pressure value wrong

The pressure values are slightly wrong. They are about 10hPa too high, compared against calibrated device and other implementations. The reason is a wrong code. Lines 192-194 should be:

        var1 = (((((var1 / 4) * (var1 / 4)) / 8192) *
                (self._pressure_calibration[2] * 32) / 8) +
                ((self._pressure_calibration[1] * var1) / 2))

Compared against the Bosch reference code. After the change, the result matches the reference pressure value substantially better and also matches other implementations.
P.S.: I should note that the humidity reading of my Adafruit sensor are completely wrong, 83.3% instead of 75.5% over a saturated NaCl solution, and that with every driver I tried. I had that with a BME280 too. After re-conditioning, the situation improved.

Method to disable heater please

To get a more reliable temperature reading, optionally disable heater for gas sensor (my use case is for Adafruit_BME680_I2C)

Error during __init__ - Failed to find BME680! Chip ID 0x0

I just plugged in the BME688, copied over this lib and the adafruit_bus_device lib, and tested out the sample code but I get the following error. I checked the datasheet for the BME688 to confirm the chip ID is still stored at the 0xD0 register for I2C.

>>> bme680 = adafruit_bme680.Adafruit_BME680_I2C(i2c, debug=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "adafruit_bme680.py", line 436, in __init__
  File "adafruit_bme680.py", line 136, in __init__
RuntimeError: Failed to find BME680! Chip ID 0x0
>>> import board
>>> import adafruit_bme680
>>> i2c = board.I2C()
>>> sensor = adafruit_bme680.Adafruit_BME680_I2C(i2c)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "adafruit_bme680.py", line 436, in __init__
  File "adafruit_bme680.py", line 136, in __init__
RuntimeError: Failed to find BME680! Chip ID 0x0
>>>

Please explain filter_size in documentation

The current documentation (https://circuitpython.readthedocs.io/projects/bme680/en/latest/api.html) describes filter_size as:

filter_size
The filter size for the built in IIR filter

Sorry but I don't understand what this means. Does it refer to the sensors current status (e.g. calibrating)?

https://www.home-assistant.io/integrations/bme680 documents it as:

filter_size
(integer)(Optional)
IIR filter size as described in the sensor datasheet. Can be 0 (off), 1, 3, 7, 15, 31, 63 or 127.
Default value: 3

But a bit more information (what does it do?) would be really helpful.

Wrong formula for gas_wait causing huge sampling delays

A typo in the code makes the gas sampling take over 4 seconds in most cases.

As per datasheet, _calc_gas_wait(100) should be 0x59 but we always get 0xff instead -- I suggest adding a test with this known-good value.

The code currently reads

durval: UINT8 = 0xFF  # Max duration
if dur < 0xFC0:
    return durval

but it should be

durval: UINT8 = 0xFF  # Max duration
if dur >= 0xFC0:
    return durval

cf https://github.com/boschsensortec/BME68x-Sensor-API/blob/master/bme68x.c#L1181C13-L1181C13

That's probably the root cause of #65 and does not help #66 either (because we block waiting for sleep while gas wait is active).

i2c fails on raspberry pi

With latest release from PyPI, on Raspberry Pi 3 model B:

(blinkenlight) pi@raspberrypi:~/blinkenlight $ cat bme680.py 
import board
import busio
import time
 
import adafruit_bme680
 
# Initialize I2C bus and create sensor instance.
i2c = busio.I2C(board.SCL, board.SDA)
sensor = adafruit_bme680.Adafruit_BME680_I2C(i2c)
 
# Main loop prints sensor values every second.
while True:
    print('Temperature: {} degrees C'.format(sensor.temperature))
    print('Gas: {} ohms'.format(sensor.gas))
    print('Humidity: {}%'.format(sensor.humidity))
    print('Pressure: {}hPa'.format(sensor.pressure))
    time.sleep(1.0)

(blinkenlight) pi@raspberrypi:~/blinkenlight $ python3 bme680.py 
Traceback (most recent call last):
  File "bme680.py", line 10, in <module>
    sensor = adafruit_bme680.Adafruit_BME680_I2C(i2c)
  File "/home/pi/blinkenlight/lib/python3.5/site-packages/adafruit_bme680.py", line 330, in __init__
    super().__init__(refresh_rate=refresh_rate)
  File "/home/pi/blinkenlight/lib/python3.5/site-packages/adafruit_bme680.py", line 105, in __init__
    self._read_calibration()
  File "/home/pi/blinkenlight/lib/python3.5/site-packages/adafruit_bme680.py", line 291, in _read_calibration
    coeff = list(struct.unpack('<hbBHhbBhhbbHhhBBBHbbbBbHhbb', bytes(coeff[1:])))
struct.error: unpack requires a bytes object of length 38

v3.4.12 always returns wrong/nonsenical, static number for temperature, humidity, and pressure on first reading. Gas also seems wrong

Using v3.4.7 of adafruit_bme680.py, I always get reaonable values for: temperature, humidity, pressure and gas.
But v3.4.12 returns non-sensical values for all the above parameters.
Specifically,

  1. Temperature is fixed at a high value regardless of actual (indoor) temperature -- typically > 90 degF while actual temperature is in the high 60's
  2. Humidity is fixed either at 100% or some other number in the high 90's (even though inside humidity is in the low 30's)
  3. Pressure is nonsensical, typically 19-21 inHg
  4. Gas varies but is way off

I have tried this with 4 different BME680 modules on several different Raspberry PI's (RPi4, RPi5)

  • All work find under 3.4.7
  • All fail as above under 3.4.12

The only difference in both the calling routine and in the Python3 setup is the version of adafruit_bme680.py
Using a fresh venv install with pip doesn't solve the problem.

Reverting the v.3.4.7 version of adafruit_bme680.py restores sane values...

Gas resistance calculation showing incorrect results for BME688

While the BME680 library is recommended for the BME688, it appears the calculations for gas resistance are different for the two sensors per @adafruit_support_carter in this support forum thread post on July 13.

Suggest either splitting the 688 into its own library, or adding logic to the combined library to detect the chip type and use the appropriate calculation. The former will save a bit on library size, but would require the BME688 project pages to be updated.

Constant Gas reading

I've acquired recently an Adafruit BME680, with a Pi Zero W.
During the first day the sensor was able to get a resistance reading for the gas, currently the reading is stuck to 45556 whatever atmosphere is. (I've tried alcohol & black marker)

I'm wondering if it's a bug or the sensor burnt.
As you can see below, the sensors jumped between stuck and reading and now it seems staying stuck.
image
The humidity and temperature reading give a relevant feedback.
I'm not recalling specific intervention from me able to act on the resistance reading.

Thanks

SPI not implemented

With latest release from PyPI, on Raspberry Pi 3 model B, using example code from the BME680 guide:

(blinkenlight) pi@raspberrypi:~/blinkenlight $ cat bme680_spi.py 
import board
import busio
import digitalio
import time
 
import adafruit_bme680

spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
cs = digitalio.DigitalInOut(board.D5)
sensor = adafruit_bme680.Adafruit_BME680_SPI(spi, cs)
 
# Main loop prints sensor values every second.
while True:
    print('Temperature: {} degrees C'.format(sensor.temperature))
    print('Gas: {} ohms'.format(sensor.gas))
    print('Humidity: {}%'.format(sensor.humidity))
    print('Pressure: {}hPa'.format(sensor.pressure))
    time.sleep(1.0)

(blinkenlight) pi@raspberrypi:~/blinkenlight $ python3 bme680_spi.py 
Traceback (most recent call last):
  File "bme680_spi.py", line 10, in <module>
      sensor = adafruit_bme680.Adafruit_BME680_SPI(spi, cs)
      AttributeError: module 'adafruit_bme680' has no attribute 'Adafruit_BME680_SPI'

adafruit_bme680.py, class Adafruit_BME680, _perform_reading(): infinite loop

We have an environmental test setup here with several BME680s attached via a TCA9548A. On rare occasions when attempting to read a BME680, we can see _perform_reading() getting stuck in the loop shown below, which effectively halts the data acquisition. Normally each device takes exactly 8 iterations of this loop to collect a value. If we force the loop to terminate after N=20 iterations, successive device reads are successful.

The code below assumes that it will eventually receive new_data, though it seems this isn't always the case. Perhaps this could be modified to address the assumption, and to handle the case that a no-new-data event occurs on the first device read and the values for temp/rh/press/... will be unset?

while not new_data:
    data = self._read(_BME680_REG_MEAS_STATUS, 17)
    new_data = data[0] & 0x80 != 0
    time.sleep(0.005)

Newest example needs licensed

It seems the wires got crossed a bit between #38 and #36. The former added a new example, and the latter moved to pre-commit and added license information to everything.

Since these occured at roughly the same time the newest example from #38 did not get included when the actions ran on #36 so it did pass at the time it ran, but the repo currently failing due to missing license on this new example.

@caternuson if you are around and can PR the the copyright / license lines into that example go ahead and do that. If not, no worries I can circle back later tonight and make one to add these.

Missing Type Annotations

There are missing type annotations for some functions in this library.

The typing module does not exist on CircuitPython devices so the import needs to be wrapped in try/except to catch the error for missing import. There is an example of how that is done here:

try:
    from typing import List, Tuple
except ImportError:
    pass

Once imported the typing annotations for the argument type(s), and return type(s) can be added to the function signature. Here is an example of a function that has had this done already:

def wrap_text_to_pixels(
    string: str, max_width: int, font=None, indent0: str = "", indent1: str = ""
) -> List[str]:

If you are new to Git or Github we have a guide about contributing to our projects here: https://learn.adafruit.com/contribute-to-circuitpython-with-git-and-github

There is also a guide that covers our CI utilities and how to run them locally to ensure they will pass in Github Actions here: https://learn.adafruit.com/creating-and-sharing-a-circuitpython-library/check-your-code In particular the pages: Sharing docs on ReadTheDocs and Check your code with pre-commit contain the tools to install and commands to run locally to run the checks.

If you are attempting to resolve this issue and need help, you can post a comment on this issue and tag both @FoamyGuy and @kattni or reach out to us on Discord: https://adafru.it/discord in the #circuitpython-dev channel.

The following locations are reported by mypy to be missing type annotations:

  • adafruit_bme680.py:111
  • adafruit_bme680.py:127
  • adafruit_bme680.py:169
  • adafruit_bme680.py:181
  • adafruit_bme680.py:193
  • adafruit_bme680.py:205
  • adafruit_bme680.py:372
  • adafruit_bme680.py:376
  • adafruit_bme680.py:379
  • adafruit_bme680.py:428
  • adafruit_bme680.py:438
  • adafruit_bme680.py:448
  • adafruit_bme680.py:509
  • adafruit_bme680.py:518
  • adafruit_bme680.py:533
  • adafruit_bme680.py:548

Please add __version__ and __repo__ metadata. Thank you!

For this module to work with the upcoming circup utility (see https://github.com/ntoll/circup), there needs to be two bits of metadata expressed as "dunder" objects within the module.

Specifically, circup looks for something like the following:

__version__ = "1.2.3"
__repo__ = "https://github.com/adafruit/SomeLibrary.git"

The __version__ should be a correct semantic-version value (see: https://semver.org/).

The __repo__ should be the HTTPS URL used for cloning this repository.

You can see an example of this behaviour in an existing project here.

Please don't hesitate to ping me if you have any questions. Thank you! ๐Ÿ โค๏ธ ๐Ÿ‘

cc/@ladyada

Adafruit library shows different values than BSEC library

I did some comparison between using the Adafruit CircuitPython BME680 python module and the compiled BSEC library from Bosch (using https://github.com/alexh-name/bsec_bme680_linux) and the values retrieved from the sensor differ.

$ cat adafruit_example.py 
import board
import busio
import adafruit_bme680
i2c = busio.I2C(board.SCL, board.SDA)
sensor = adafruit_bme680.Adafruit_BME680_I2C(i2c)
print('Temperature: {} degrees C'.format(sensor.temperature))
print('Gas: {} ohms'.format(sensor.gas))
print('Humidity: {}%'.format(sensor.humidity))
print('Pressure: {}hPa'.format(sensor.pressure))

Results:

$ python3 adafruit_example.py 
Temperature: 4.6993359375 degrees C
Gas: 1578360 ohms
Humidity: 57.53554887071429%
Pressure: 947.7445084251684hPa

The binary compiled with BSEC library shows different values:

2020-04-02 10:02:13,[IAQ (0)]: 25.00,[T degC]: -0.29,[H %rH]: 82.23,[P hPa]: 947.72,[G Ohms]: 104297,[S]: 0,[eCO2 ppm]: 500.000000000000000,[bVOCe ppm]: 0.4999999403953552246093750

Temperature: BSEC is right. I know it's currently below 0 outside.
Humidity: BSEC is more rightish, when I compare the Live Weather maps (https://kachelmannwetter.com/de/analyse/superhd/thurgau/luftfeuchtigkeit/20200402-0720z.html). The reading from 40 mins ago says between 70 and 80% humidity where I live.
Pressure: Both values are the same, look correct
Gas: Large difference! 104297 from BSEC and 1578360 from Adafruit

Are the calculations/calibrations in the Adafruit library incorrect? Do you have a partnership with Bosch to take a closer look at this?

Screenshot humidity map for comparison:

image

Slow refresh rate

Between 3.4.13 and 3.5 release, the rate at which the sensor returns readings has drastically slowed. I can get a new reading every ~0.3 seconds (the sensor can return readings much faster than this, but they only update about every 0.3 seconds). Whereas when I change to 3.5.0 the readings only update about every 4 seconds.

I tried the following minimal code using a QtPY ESP32-S2 and a BME688 and the only thing I'm changing is the version of the BME680 library loaded on the board.

import board
import busio
import time
from adafruit_bme680 import Adafruit_BME680_I2C as BME688

i2c = busio.I2C(board.SCL1, board.SDA1)
sensor = BME688(i2c)

while True:
    print('Temp: {} C \tPres: {} hPa\t{}'.format(sensor.temperature, sensor.pressure, time.monotonic()))
    #time.sleep(.25)

Error in filter_size setter

The filter_size property is being set with the value of the desired filter size when it should be getting set with the index of the value in the available filter size array.

When the filter_size is accessed, it throws an error since it again tries to lookup the filter size as if it was set with an index.

SPI

Hi,

Sample program is available for only I2C. Can you guys release a sample python program to test BME680 in Raspberrypi via SPI?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.