.. _bme680: 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 :c:func:`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 :c:func:`bme680_get_measurement_duration()` or wait as long as function :c:func:`bme680_is_measuring()` returns true. - Fetch the results as fixed point values with function :c:func:`bme680_get_results_fixed()` or as floating point values with function :c:func:`bme680_get_results_float()`. .. code-block:: C ... // 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 :c:func:`bme680_is_measuring()`. .. code-block:: C ... 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 :c:func:`bme680_measure_float()` or :c:func:`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 :c:func:`vTaskDelay()`. .. code-block:: C ... // 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 :c:func:`bme680_get_results_fixed()` or function :c:func:`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: .. list-table:: :header-rows: 1 * - 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: .. list-table:: :header-rows: 1 * - 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 :c:func:`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. .. code-block:: C ... // 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 :c:func:`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. .. code-block:: C ... // 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 :c:func:`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 :c:func:`bme680_use_heater_profile`. If -1 or `BME680_HEATER_NOT_USED` is used as heater profile, gas measurement is deactivated completely. .. code-block:: C ... // 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 :c:func:`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 :c:func:`bme680_use_heater_profile()`. For example, if there were 5 heater profiles defined with following code during the setup. .. code-block:: C 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: .. code-block:: C ... 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 :c:func:`bme680_set_ambient_temperature()`, the ambient temperature either determined from the sensor itself or from another temperature sensor can be set. .. code-block:: C ... bme680_set_ambient_temperature(sensor, ambient); ... .. doxygengroup:: bme680 :members: