mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
edc43201db
This should not change any generated binary
326 lines
11 KiB
C
326 lines
11 KiB
C
/*
|
|
* Copyright (C) 2019 Mesotic SAS
|
|
* 2020 Gunar Schorcht
|
|
*
|
|
* This file is subject to the terms and conditions of the GNU Lesser
|
|
* General Public License v2.1. See the file LICENSE in the top level
|
|
* directory for more details.
|
|
*/
|
|
|
|
/**
|
|
* @defgroup drivers_bme680 BME680 Temperature/Humidity/Pressure/Gas sensor
|
|
* @ingroup drivers_sensors
|
|
* @brief Driver for the Bosch BME680 sensor
|
|
*
|
|
* ### Introduction
|
|
*
|
|
* The driver allows the use of BME680 sensors connected either via I2C or SPI.
|
|
* Instead of implementing a complete driver, it simply uses the
|
|
* [BME680 vendor driver](https://github.com/BoschSensortec/BME680_driver)
|
|
* written and maintained by Bosch Sensortec as a package.
|
|
*
|
|
* Even though this driver interface provides an easy-to-use API, the vendor's
|
|
* driver API can still be used directly. This becomes necessary, for example,
|
|
* if the settings of the ambient temperature have to be updated from
|
|
* measurements with other sensors for gas measurement.
|
|
*
|
|
* All functions of the vendor's driver API require a reference to a
|
|
* sensor device structure of type `struct bme680_dev`. Use macro
|
|
* @ref BME680_SENSOR(dev) for a given device descriptor of type
|
|
* @ref bme680_t to the according sensor device structure of type
|
|
* `struct bme680_dev`, for example:
|
|
*
|
|
* ```c
|
|
* bme680_t dev;
|
|
* ...
|
|
* BME680_SENSOR(dev).amb_temp = value_from_other_sensor;
|
|
* bme680_set_sensor_settings(BME680_GAS_MEAS_SEL, &BME680_SENSOR(dev));
|
|
* ```
|
|
*
|
|
* Refer to the code documentation at
|
|
* [GitHub](https://github.com/BoschSensortec/BME680_driver)
|
|
* for detailed information on the API of the vendor driver.
|
|
*
|
|
* ### Sensor Operation Modes
|
|
*
|
|
* The BME680 sensor supports only two modes, sleep mode and forced mode, in
|
|
* which measurements are taken. After the power-on sequence, the sensor
|
|
* automatically starts in sleep mode. To start a measurement, the sensor
|
|
* must switch to forced mode. In this mode it performs exactly one
|
|
* measurement of temperature, pressure, humidity and gas in this order, the
|
|
* so-called TPHG measurement cycle. After executing this TPHG measurement
|
|
* cycle, the raw data from the sensor is available and the sensor
|
|
* automatically returns to sleep mode
|
|
*
|
|
* ### Ambient Temperature
|
|
*
|
|
* The sensor is initialized with a fixed ambient temperature defined by the
|
|
* parameter settings in @ref bme680_params. However, precise gas measurements
|
|
* require the calculation of the heating resistance based on the ambient
|
|
* temperature.
|
|
*
|
|
* The temperature of the internal temperature sensor is typically higher
|
|
* than the actual ambient temperature due to the self-heating of the sensor.
|
|
* element. It should therefore not be used to set the ambient temperature
|
|
* unless gas measurements are very infrequent and self-heating is negligible.
|
|
* Rather another temperature sensor should be used for that purpose.
|
|
*
|
|
* Function @ref bme680_set_ambient_temp can be used to change the ambient
|
|
* temperature.
|
|
*
|
|
* ### Using the Sensor
|
|
*
|
|
* Using the BME680 consists of the following steps
|
|
*
|
|
* 1. Trigger the sensor with @ref bme680_force_measurement to change to the
|
|
* forced mode and perform a THPG cycle.
|
|
* 2. Wait at least the time returned by @ref bme680_get_duration until the
|
|
* THPG cycle is finished.
|
|
* 3. Use @ref bme680_get_data to fetch raw sensor data and convert them to the
|
|
* resulting sensor values
|
|
*
|
|
* ### Driver Configuration
|
|
*
|
|
* BME680 sensors are connected either via I2C or SPI. Which interface is used
|
|
* by which BME680 sensor is defined by the parameters in @ref bme680_params.
|
|
* The respective driver implementation is enabled by the modules `bme680_i2c`
|
|
* and `bme680_spi`. Several BME680 sensors and a mixed configuration of I2C
|
|
* and SPI can be used in one application.
|
|
* ```
|
|
* USEMODULE='bme680_spi bme680_i2c' make BOARD=... -C tests/drivers/bme680
|
|
* ```
|
|
*
|
|
* The vendor driver allows the use of floating point conversions. In order
|
|
* to use these floating point conversions, module `bme680_fp` has to
|
|
* be enabled:
|
|
* ```
|
|
* USEMODULE='bme680_fp bme680_i2c' make BOARD=... -C tests/drivers/bme680
|
|
* ```
|
|
*
|
|
* @{
|
|
* @file
|
|
* @brief Interface definition for the Bosch BME680 sensor
|
|
*
|
|
* @author Dylan Laduranty <dylan.laduranty@mesotic.com>
|
|
* @author Gunar Schorcht <gunar@schorcht.net>
|
|
*/
|
|
|
|
#ifndef BME680_H
|
|
#define BME680_H
|
|
|
|
#include "periph/i2c.h"
|
|
#include "periph/spi.h"
|
|
|
|
#ifdef MODULE_BME680_FP
|
|
#define BME680_FLOAT_POINT_COMPENSATION
|
|
#endif
|
|
|
|
#include "bme680_hal.h"
|
|
#include "bme680_internal.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/**
|
|
* @brief I2C address when SDO pin is LOW
|
|
*/
|
|
#define BME680_I2C_ADDR_1 (0x76)
|
|
|
|
/**
|
|
* @brief I2C address when SDO pin is HIGH
|
|
*/
|
|
#define BME680_I2C_ADDR_2 (0x77)
|
|
|
|
/**
|
|
* @brief Converts a BME680 device descriptor to the BME680 sensor device
|
|
* structure for the vendor BME680 device driver.
|
|
*/
|
|
#define BME680_SENSOR(d) (*((struct bme680_dev *)d))
|
|
|
|
/**
|
|
* @brief Named return values
|
|
*/
|
|
enum {
|
|
BME680_NULL_PTR = -1, /**< NULL pointer check failed. */
|
|
BME680_COM_FAILED = -2, /**< Communication with the device failed. */
|
|
BME680_NO_DEV = -3, /**< Device doesn't exist. */
|
|
BME680_INVALID = -4, /**< Invalid value or length. */
|
|
BME680_NO_NEW_DATA = -5, /**< No new data. */
|
|
};
|
|
|
|
#ifdef DOXYGEN
|
|
/**
|
|
* @brief BME680 sensor field data
|
|
*/
|
|
typedef struct bme680_field_data {
|
|
uint8_t status; /**< Status for new data, gas measurement valid and
|
|
heater stable. Use `BME680_NEW_DATA_MSK`,
|
|
`BME680_GASM_VALID_MSK` and BME680_HEAT_STAB_MSK
|
|
to check for the status. */
|
|
uint8_t gas_index; /**< Index of used heater profile */
|
|
uint8_t meas_index; /**< Measurement index */
|
|
#ifndef MODULE_BME680_FP
|
|
int16_t temperature; /**< Temperature in degree Celsius x 100 */
|
|
uint32_t pressure; /**< Pressure in Pascal */
|
|
uint32_t humidity; /**< Relative humidity in percent x 1000 */
|
|
uint32_t gas_resistance; /**< Gas resistance in ohms */
|
|
#else /* MODULE_BME680_FP */
|
|
float temperature; /**< Temperature in degree Celsius */
|
|
float pressure; /**< Pressure in Pascal */
|
|
float humidity; /**< Relative humidity in percent */
|
|
float gas_resistance; /**< Gas resistance in ohms */
|
|
#endif /* MODULE_BME680_FP */
|
|
};
|
|
|
|
#endif /* DOXYGEN */
|
|
|
|
/**
|
|
* @brief Shortcut type definition for BME680 sensor field data
|
|
*/
|
|
typedef struct bme680_field_data bme680_field_data_t;
|
|
|
|
/**
|
|
* @brief Shortcut type definition for BME680 sensor device structure
|
|
* @see [struct bme680_dev](https://github.com/BoschSensortec/BME680_driver/blob/9014031fa00a5cc1eea1498c4cd1f94ec4b8ab11/bme680_defs.h#L496-L530)
|
|
*/
|
|
typedef struct bme680_dev bme680_dev_t;
|
|
|
|
/**
|
|
* @brief BME680 I2C parameters
|
|
*/
|
|
typedef struct {
|
|
i2c_t dev; /**< I2C device which is used */
|
|
uint8_t addr; /**< I2C address */
|
|
} bme680_intf_i2c_t;
|
|
|
|
/**
|
|
* @brief BME680 SPI parameters
|
|
*/
|
|
typedef struct {
|
|
spi_t dev; /**< SPI device which is used */
|
|
gpio_t nss_pin; /**< Chip Select pin */
|
|
} bme680_intf_spi_t;
|
|
|
|
/**
|
|
* @brief BME680 Hardware interface parameters union
|
|
*/
|
|
typedef union {
|
|
bme680_intf_i2c_t i2c; /**< I2C specific interface parameters */
|
|
bme680_intf_spi_t spi; /**< SPI specific interface parameters */
|
|
} bme680_intf_t;
|
|
|
|
/**
|
|
* @brief BME680 device initialization parameters
|
|
*/
|
|
typedef struct {
|
|
uint8_t ifsel; /**< Interface selection */
|
|
uint8_t temp_os; /**< Temperature oversampling */
|
|
uint8_t hum_os; /**< Humidity oversampling */
|
|
uint8_t pres_os; /**< Pressure oversampling */
|
|
uint8_t filter; /**< IIR filter coefficient */
|
|
uint8_t gas_measure; /**< Enable gas measurement */
|
|
uint16_t heater_dur; /**< Heater duration in ms */
|
|
uint16_t heater_temp; /**< Heater temperature in °C */
|
|
uint8_t power_mode; /**< Power mode (sleep or forced) */
|
|
uint8_t settings; /**< Settings used */
|
|
bme680_intf_t intf; /**< Hardware interface parameters */
|
|
} bme680_params_t;
|
|
|
|
/**
|
|
* @brief BME680 device descriptor
|
|
*/
|
|
typedef struct {
|
|
struct bme680_dev sensor; /**< Inherited device structure from vendor API */
|
|
bme680_intf_t intf; /**< Device interface */
|
|
} bme680_t;
|
|
|
|
/**
|
|
* @brief References to BME680 sensor devices used by the HAL functions
|
|
*/
|
|
extern bme680_t *bme680_devs[];
|
|
|
|
/**
|
|
* @brief Number of initialized BME680 sensor devices in bme680_devs
|
|
*/
|
|
extern unsigned int bme680_devs_numof;
|
|
|
|
/**
|
|
* @brief Initialize the BME680 sensor.
|
|
*
|
|
* @param[in,out] dev device descriptor of the sensor to initialize
|
|
* @param[in] params configuration parameters
|
|
*
|
|
* @return 0 on success
|
|
* @return < 0 on error
|
|
*/
|
|
int bme680_init(bme680_t *dev, const bme680_params_t *params);
|
|
|
|
/**
|
|
* @brief Force a single TPHG measurement cycle
|
|
*
|
|
* The function triggers the sensor to start one THPG measurement cycle. The
|
|
* duration of the TPHG measurement cycle depends on the selected parameters.
|
|
* It can vary from 1.25 ms to 4.5 seconds. The duration of the measurement
|
|
* cycle can be determined with the #bme680_get_duration function.
|
|
*
|
|
* @param[in,out] dev device descriptor of the sensor
|
|
*
|
|
* @return 0 on success
|
|
* @return < 0 on error
|
|
*/
|
|
int bme680_force_measurement(bme680_t *dev);
|
|
|
|
/**
|
|
* @brief Duration one THPG measurement cycle
|
|
*
|
|
* This function determines the duration of one THPG measurement cycle
|
|
* according to the selected parameter settings. The duration can be used
|
|
* to wait for the measurement results once a THPG measurement has been
|
|
* started with #bme680_force_measurement.
|
|
*
|
|
* @param[in,out] dev device descriptor of the sensor
|
|
*
|
|
* @return duration of one THPG measurement cycle in milliseconds.
|
|
* @return < 0 on error
|
|
*/
|
|
int bme680_get_duration(bme680_t* dev);
|
|
|
|
/**
|
|
* @brief Get results of a TPHG measurement
|
|
*
|
|
* The function returns the results of a TPHG measurement that has been
|
|
* started before with #bme680_force_measurement. For that purpose, the
|
|
* function fetches the raw sensor data and converts them into sensor values.
|
|
* If the measurement is still running, the function fails and returns
|
|
* invalid values.
|
|
*
|
|
* @param[in,out] dev device descriptor of the sensor
|
|
* @param[out] data pointer to a data structure with the field data
|
|
*
|
|
* @return 0 on success
|
|
* @return < 0 on error
|
|
*/
|
|
int bme680_get_data(bme680_t* dev, bme680_field_data_t *data);
|
|
|
|
/**
|
|
* @brief Set the ambient temperature
|
|
*
|
|
* The function sets the ambient temperature for the calculation of the heater
|
|
* resistance.
|
|
*
|
|
* @param[in,out] dev device descriptor of the sensor
|
|
* @param[in] temp ambient temperature in degC.
|
|
*
|
|
* @return 0 on success
|
|
* @return < 0 on error
|
|
*/
|
|
int bme680_set_ambient_temp(bme680_t* dev, int8_t temp);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* BME680_H */
|
|
/** @} */
|