bme680 - Driver for BME680 digital environmental sensor

About the sensor

BME680 is an ultra-low-power environmental sensor that integrates temperature, pressure, humidity and gas sensors in only one unit.

Communication interfaces

The BME680 sensor can be connected using I2C or SPI. Currently, driver only supports I2C.

The I2C interface supports data rates up to 3.4 Mbps. It is possible to connect multiple BME680 sensors with different I2C slave addresses to the same I2C bus or to different I2C buses. Possible I2C slave addresses are 0x76 and 0x77.

Interface selection is done automatically by the sensor using the SPI CS signal. As long as the CS signal keeps high after power-on reset, the I2C interface is used. Once the CS signal has been pulled down, SPI interface is used until next power-on reset.

Measurement process

Once the BME680 has been initialized, it can be used for measurements. The BME680 operates in two different modes, the sleep mode and the forced mode.

The sensor starts after power-up automatically in the sleep mode where it does not perform any measurement and consumes only 0.15 μA. Measurements are only done in forced mode.

Please note: There are two further undocumented modes, the parallel and the sequential mode. They can’t be supported by the driver, since it is not clear what they do and how to use them.

Measurement cylce

To perform measurements, the BME680 sensor has to be triggered to switch to the forced mode. In this mode, it performs exactly one measurement of temperature, pressure, humidity, and gas in that order, the so-called TPHG measurement cycle. After the execution of this TPHG measurement cycle, raw sensor data become available and the sensor returns automatically back to sleep mode.

Each of the individual measurements can be configured or skipped separately via the sensor settings, see section Measurement settings. Dependent on the configuration, the duration of a TPHG measurement cycle can vary from some milliseconds up to about 4.5 seconds, especially if gas measurement is enabled.

To avoid the blocking of the user task during measurements, the measurement process is therefore separated into the following steps:

  • Trigger the sensor with function bme680_force_measurement() to switch to forced mode in which it performs exactly one THPG measurement cycle.

  • Wait the measurement duration using function vTaskDelay and the value returned from function bme680_get_measurement_duration() or wait as long as function bme680_is_measuring() returns true.

  • Fetch the results as fixed point values with function bme680_get_results_fixed() or as floating point values with function bme680_get_results_float().

...
// as long as sensor configuration isn't changed, the duration can be considered as constant
uint32_t duration = bme680_get_measurement_duration(sensor);
...
if (bme680_force_measurement(sensor) == ESP_OK) // STEP 1
{
    // STEP 2: passive waiting until measurement results are available
    vTaskDelay(duration);

    // STEP 3: get the results and do something with them
    if (bme680_get_results_float(sensor, &values) == ESP_OK)
        ...
}
...

Alternatively, busy waiting can be realized using function bme680_is_measuring().

...
if (bme680_force_measurement(sensor) == ESP_OK) // STEP 1
{
    // STEP 2: busy waiting until measurement results are available
    bool busy;
    do
    {
        if (bme680_is_measuring(sensor, &busy) != ESP_OK)
            break;
    }
    while (busy);

    // STEP 3: get the results and do something with them
    if (bme680_get_results_float (sensor, &values) == ESP_OK)
        ...
}
...

For convenience, it is also possible to use the high-level functions bme680_measure_float() or bme680_measure_fixed(). These functions combine all 3 steps above within a single function and are therefore very easy to use. Please note that these functions must not be used when they are called from a software timer callback function since the calling task is delayed using function vTaskDelay().

...
// ONE STEP: measure, wait, get the results and do something with them
if (bme680_measure_float(sensor, &values) == ESP_OK)
    ...
...

Measurement results

Once the sensor has finished the measurement raw data are available at the sensor. Either function bme680_get_results_fixed() or function bme680_get_results_float() can be used to fetch the results. Both functions read raw data from the sensor and converts them into utilizable fixed point or floating point sensor values.

Note

Conversion of raw sensor data into the final sensor values is based on very complex calculations that use a large number of calibration parameters. Therefore, the driver does not provide functions that only return the raw sensor data.

Dependent on sensor value representation, measurement results contain different dimensions:

Value

Fixed Point

Floating Point

Conversion

temperature

1/100 °C

°C

float = fixed / 100

pressure

Pascal

hPascal

float = fixed / 100

humidity

1/1000 %

%

float = fixed / 1000

gas_resistance

Ohm

Ohm

float = fixed

The gas resistance value in Ohm represents the resistance of sensor’s gas sensitive layer.

If the TPHG measurement cycle or fetching the results fails, invalid sensor values are returned:

Invalid Value

Fixed Point

Floating Point

temperature

INT16_MIN

-327.68

pressure

0

0.0

humidity

0

0.0

gas_resistance

0

0.0

Measurement settings

The sensor allows to change a lot of measurement parameters.

Oversampling rates

To increase the resolution of raw sensor data, the sensor supports oversampling for temperature, pressure, and humidity measurements. Using function bme680_set_oversampling_rates(), individual oversampling rates can be defined for these measurements. With an oversampling rate osr, the resolution of the according raw sensor data can be increased from 16 bit to 16+ld(osr) bit.

Possible oversampling rates are 1x (default by the driver) 2x, 4x, 8x and 16x. It is also possible to define an oversampling rate of 0. This deactivates the corresponding measurement and the output values become invalid.

...
// Changes the oversampling rate for temperature to 4x and for
//  pressure to 2x. Humidity measurement is skipped.
bme680_set_oversampling_rates(sensor, BME680_OSR_4X, BME680_OSR_2X, BME680_OSR_NONE);
...

IIR Filter

The sensor also integrates an internal IIR filter (low pass filter) to reduce short-term changes in sensor output values caused by external disturbances. It effectively reduces the bandwidth of the sensor output values.

The filter can optionally be used for pressure and temperature data that are subject to many short-term changes. With the IIR filter the resolution of pressure and temperature data increases to 20 bit. Humidity and gas inside the sensor does not fluctuate rapidly and does not require such a low pass filtering.

Using function bme680_set_filter_size(), the user task can change the size of the filter. The default size is 3. If the size of the filter becomes 0, the filter is not used.

...
// Change the IIR filter size for temperature and pressure to 7.
bme680_set_filter_size(sensor, BME680_IIR_SIZE_7);
...
// Don't use IIR filter
bme680_set_filter_size(sensor, BME680_IIR_SIZE_0);
...

Heater profile

For the gas measurement, the sensor integrates a heater. Parameters for this heater are defined by heater profiles. The sensor supports up to 10 such heater profiles, which are numbered from 0 to 9. Each profile consists of a temperature set-point (the target temperature) and a heating duration. By default, only the heater profile 0 with 320 degree Celsius as target temperature and 150 ms heating duration is defined.

Note

According to the data sheet, target temperatures between 200 and 400 degrees Celsius are typical and about 20 to 30 ms are necessary for the heater to reach the desired target temperature.

Function bme680_set_heater_profile() can be used to set the parameters for one of the heater profiles 0..9. Once the parameters of a heater profile are defined, the gas measurement can be activated with that heater profile using function bme680_use_heater_profile(). If -1 or BME680_HEATER_NOT_USED is used as heater profile, gas measurement is deactivated completely.

...
// Change the heater profile 1 to 300 degree Celsius for 100 ms and activate it
bme680_set_heater_profile(sensor, 1, 300, 100);
bme680_use_heater_profile(sensor, 1);
...
// Deactivate gas measurement completely
bme680_use_heater_profile(sensor, BME680_HEATER_NOT_USED);
...

If several heater profiles have been defined with function bme680_set_heater_profile(), a sequence of gas measurements with different heater parameters can be realized by a sequence of activations of different heater profiles for successive TPHG measurements using function bme680_use_heater_profile().

For example, if there were 5 heater profiles defined with following code during the setup.

bme680_set_heater_profile(sensor, 0, 200, 100);
bme680_set_heater_profile(sensor, 1, 250, 120);
bme680_set_heater_profile(sensor, 2, 300, 140);
bme680_set_heater_profile(sensor, 3, 350, 160);
bme680_set_heater_profile(sensor, 4, 400, 180);

the user task could use them as a sequence like following:

...
while (1)
{
    switch (count++ % 5)
    {
        case 0: bme680_use_heater_profile(sensor, 0); break;
        case 1: bme680_use_heater_profile(sensor, 1); break;
        case 2: bme680_use_heater_profile(sensor, 2); break;
        case 3: bme680_use_heater_profile(sensor, 3); break;
        case 4: bme680_use_heater_profile(sensor, 4); break;
    }

    // measurement duration changes in each cycle
    uint32_t duration = bme680_get_measurement_duration(sensor);

    // trigger the sensor to start one TPHG measurement cycle
    if (bme680_force_measurement(sensor))
    {
        vTaskDelay(duration);

        // get the results and do something with them
        if (bme680_get_results_float(sensor, &values))
            ...
    }
    ...
}
...

Ambient temperature

The heater resistance calculation algorithm takes into account the ambient temperature of the sensor. Using function bme680_set_ambient_temperature(), the ambient temperature either determined from the sensor itself or from another temperature sensor can be set.

...
bme680_set_ambient_temperature(sensor, ambient);
...
group bme680

ESP-IDF driver for BME680 digital environmental sensor.

Forked from https://github.com/gschorcht/bme680-esp-idf

Copyright (C) 2017 Gunar Schorcht https://github.com/gschorcht

Copyright (C) 2019 Ruslan V. Uss

https://github.com/UncleRus

BSD Licensed as described in the file LICENSE

Defines

BME680_I2C_ADDR_0
BME680_I2C_ADDR_1
BME680_MAX_OVERFLOW_VAL
BME680_HEATER_TEMP_MIN

min.

200 degree Celsius

BME680_HEATER_TEMP_MAX

max.

200 degree Celsius

BME680_HEATER_PROFILES

max.

10 heater profiles 0 … 9

BME680_HEATER_NOT_USED

heater not used profile

Enums

enum bme680_filter_size_t

Filter size.

Values:

enumerator BME680_IIR_SIZE_0

Filter is not used.

enumerator BME680_IIR_SIZE_1
enumerator BME680_IIR_SIZE_3
enumerator BME680_IIR_SIZE_7
enumerator BME680_IIR_SIZE_15
enumerator BME680_IIR_SIZE_31
enumerator BME680_IIR_SIZE_63
enumerator BME680_IIR_SIZE_127
enum bme680_oversampling_rate_t

Oversampling rate.

Values:

enumerator BME680_OSR_NONE

Measurement is skipped, output values are invalid.

enumerator BME680_OSR_1X

Default oversampling rates.

enumerator BME680_OSR_2X
enumerator BME680_OSR_4X
enumerator BME680_OSR_8X
enumerator BME680_OSR_16X

Functions

esp_err_t bme680_init_desc(bme680_t *dev, uint8_t addr, i2c_port_t port, gpio_num_t sda_gpio, gpio_num_t scl_gpio)

Initialize device descriptor.

Return

ESP_OK on success

Parameters
  • dev: Device descriptor

  • addr: BMP280 address

  • port: I2C port number

  • sda_gpio: GPIO pin for SDA

  • scl_gpio: GPIO pin for SCL

esp_err_t bme680_free_desc(bme680_t *dev)

Free device descriptor.

Return

ESP_OK on success

Parameters
  • dev: Device descriptor

esp_err_t bme680_init_sensor(bme680_t *dev)

Initialize a BME680 sensor.

The function initializes the sensor device data structure, probes the sensor, soft resets the sensor, and configures the sensor with the the following default settings:

  • Oversampling rate for temperature, pressure, humidity is osr_1x

  • Filter size for pressure and temperature is iir_size 3

  • Heater profile 0 with 320 degree C and 150 ms duration

The sensor must be connected to an I2C bus.

Return

ESP_OK on success

Parameters
  • dev: Device descriptor

esp_err_t bme680_force_measurement(bme680_t *dev)

Force one single TPHG measurement.

The function triggers the sensor to start one THPG measurement cycle. Parameters for the measurement like oversampling rates, IIR filter sizes and heater profile can be configured before.

Once the TPHG measurement is started, the user task has to wait for the results. The duration of the TPHG measurement can be determined with function bme680_get_measurement_duration.

Return

ESP_OK on success

Parameters
  • dev: Device descriptor

esp_err_t bme680_get_measurement_duration(const bme680_t *dev, uint32_t *duration)

Get estimated duration of a TPHG measurement.

The function returns an estimated duration of the TPHG measurement cycle in RTOS ticks for the current configuration of the sensor.

This duration is the time required by the sensor for one TPHG measurement until the results are available. It strongly depends on which measurements are performed in the THPG measurement cycle and what configuration parameters were set. It can vary from 1 RTOS (10 ms) tick up to 4500 RTOS ticks (4.5 seconds).

If the measurement configuration is not changed, the duration can be considered as constant.

Return

ESP_OK on success

Parameters
  • dev: Device descriptor

  • [out] duration: Duration of TPHG measurement cycle in ticks or 0 on error

esp_err_t bme680_is_measuring(bme680_t *dev, bool *busy)

Get the measurement status.

The function can be used to test whether a measurement that was started before is still running.

Return

ESP_OK on success

Parameters
  • dev: Device descriptor

  • [out] busy: true if measurement is still running or false otherwise

esp_err_t bme680_get_results_fixed(bme680_t *dev, bme680_values_fixed_t *results)

Get results of a measurement in fixed point representation.

The function returns the results of a TPHG measurement that has been started before. If the measurement is still running, the function fails and returns invalid values (see type declaration).

Return

ESP_OK on success

Parameters
  • dev: Device descriptor

  • [out] results: pointer to a data structure that is filled with results

esp_err_t bme680_get_results_float(bme680_t *dev, bme680_values_float_t *results)

Get results of a measurement in floating point representation.

The function returns the results of a TPHG measurement that has been started before. If the measurement is still running, the function fails and returns invalid values (see type declaration).

Return

ESP_OK on success

Parameters
  • dev: Device descriptor

  • [out] results: pointer to a data structure that is filled with results

esp_err_t bme680_measure_fixed(bme680_t *dev, bme680_values_fixed_t *results)

Start a measurement, wait and return the results (fixed point)

This function is a combination of functions above. For convenience it starts a TPHG measurement using bme680_force_measurement(), then it waits the measurement duration for the results using vTaskDelay() and finally it returns the results using function bme680_get_results_fixed().

Note: Since the calling task is delayed using function vTaskDelay(), this function must not be used when it is called from a software timer callback function.

Return

ESP_OK on success

Parameters
  • dev: Device descriptor

  • [out] results: pointer to a data structure that is filled with results

esp_err_t bme680_measure_float(bme680_t *dev, bme680_values_float_t *results)

Start a measurement, wait and return the results (floating point)

This function is a combination of functions above. For convenience it starts a TPHG measurement using bme680_force_measurement(), then it waits the measurement duration for the results using vTaskDelay and finally it returns the results using function bme680_get_results_float().

Note: Since the calling task is delayed using function vTaskDelay(), this function must not be used when it is called from a software timer callback function.

Return

ESP_OK on success

Parameters
  • dev: Device descriptor

  • [out] results: pointer to a data structure that is filled with results

esp_err_t bme680_set_oversampling_rates(bme680_t *dev, bme680_oversampling_rate_t osr_t, bme680_oversampling_rate_t osr_p, bme680_oversampling_rate_t osr_h)

Set the oversampling rates for measurements.

The BME680 sensor allows to define individual oversampling rates for the measurements of temperature, pressure and humidity. Using an oversampling rate of osr, the resolution of raw sensor data can be increased by ld(osr) bits.

Possible oversampling rates are 1x (default), 2x, 4x, 8x, 16x, see type bme680_oversampling_rate_t. The default oversampling rate is 1.

Please note: Use BME680_OSR_NONE to skip the corresponding measurement.

Return

ESP_OK on success

Parameters
  • dev: Device descriptor

  • osr_t: oversampling rate for temperature measurements

  • osr_p: oversampling rate for pressure measurements

  • osr_h: oversampling rate for humidity measurements

esp_err_t bme680_set_filter_size(bme680_t *dev, bme680_filter_size_t size)

Set the size of the IIR filter.

The sensor integrates an internal IIR filter (low pass filter) to reduce short-term changes in sensor output values caused by external disturbances. It effectively reduces the bandwidth of the sensor output values.

The filter can optionally be used for pressure and temperature data that are subject to many short-term changes. Using the IIR filter, increases the resolution of pressure and temperature data to 20 bit. Humidity and gas inside the sensor does not fluctuate rapidly and does not require such a low pass filtering.

The default filter size is 3 (BME680_IIR_SIZE_3).

Please note: If the size of the filter is 0, the filter is not used.

Return

ESP_OK on success

Parameters
  • dev: Device descriptor

  • size: IIR filter size

esp_err_t bme680_set_heater_profile(bme680_t *dev, uint8_t profile, uint16_t temperature, uint16_t duration)

Set a heater profile for gas measurements.

The sensor integrates a heater for the gas measurement. Parameters for this heater are defined by so called heater profiles. The sensor supports up to 10 heater profiles, which are numbered from 0 to 9. Each profile consists of a temperature set-point (the target temperature) and a heating duration.

This function sets the parameters for one of the heater profiles 0 … 9. To activate the gas measurement with this profile, use function bme680_use_heater_profile(), see below.

Please note: According to the data sheet, a target temperatures of between 200 and 400 degrees Celsius are typical and about 20 to 30 ms are necessary for the heater to reach the desired target temperature.

Return

ESP_OK on success

Parameters
  • dev: Device descriptor

  • profile: heater profile 0 … 9

  • temperature: target temperature in degree Celsius

  • duration: heating duration in milliseconds

esp_err_t bme680_use_heater_profile(bme680_t *dev, int8_t profile)

Activate gas measurement with a given heater profile.

The function activates the gas measurement with one of the heater profiles 0 … 9 or deactivates the gas measurement completely when -1 or BME680_HEATER_NOT_USED is used as heater profile.

Parameters of the activated heater profile have to be set before with function bme680_set_heater_profile() otherwise the function fails.

If several heater profiles have been defined with function bme680_set_heater_profile(), a sequence of gas measurements with different heater parameters can be realized by a sequence of activations of different heater profiles for successive TPHG measurements using this function.

Return

ESP_OK on success

Parameters
  • dev: Device descriptor

  • profile: 0 … 9 to activate or -1 to deactivate gas measure

esp_err_t bme680_set_ambient_temperature(bme680_t *dev, int16_t temperature)

Set ambient temperature.

The heater resistance calculation algorithm takes into account the ambient temperature of the sensor. This function can be used to set this ambient temperature. Either values determined from the sensor itself or from another temperature sensor can be used. The default ambient temperature is 25 degree Celsius.

Return

ESP_OK on success

Parameters
  • dev: Device descriptor

  • temperature: ambient temperature in degree Celsius

struct bme680_values_fixed_t
#include <bme680.h>

Fixed point sensor values (fixed THPG values)

struct bme680_values_float_t
#include <bme680.h>

Floating point sensor values (real THPG values)

struct bme680_settings_t
#include <bme680.h>

Sensor parameters that configure the TPHG measurement cycle.

T - temperature measurement P - pressure measurement H - humidity measurement G - gas measurement

struct bme680_calib_data_t
#include <bme680.h>

Data structure for calibration parameters.

These calibration parameters are used in compensation algorithms to convert raw sensor data to measurement results.

struct bme680_t
#include <bme680.h>

BME680 sensor device data structure type.