- minor changes
- changes to use the same source code with ESP8266 (esp-open-rtos) and ESP32 (ESP-IDF)
This commit is contained in:
parent
c3ae04c93f
commit
07f3c08244
10 changed files with 398 additions and 254 deletions
|
@ -1,6 +1,9 @@
|
|||
# Driver for **BME680** digital **environmental sensor**
|
||||
|
||||
This driver is written for usage with the ESP8266 and FreeRTOS. It supports multiple BME680 sensors which are either connected to the SPI or to different I2C interfaces with different addresses.
|
||||
The driver supports multiple BME680 sensors which are either connected to the SPI or to the same or different I2C interfaces with different addresses.
|
||||
|
||||
It is for the usage with the ESP8266 and [esp-open-rtos](https://github.com/SuperHouse/esp-open-rtos).
|
||||
The driver is also working with ESP32 and [ESP-IDF](https://github.com/espressif/esp-idf.git) using a wrapper component for ESP8266 functions, see folder ```components/esp8266_wrapper```, as well as Linux based systems using a wrapper library.
|
||||
|
||||
## About the sensor
|
||||
|
||||
|
@ -18,9 +21,9 @@ Interface selection is done automatically by the sensor using the SPI CS signal.
|
|||
|
||||
## 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**.
|
||||
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*.
|
||||
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.
|
||||
|
||||
|
@ -81,7 +84,7 @@ if (bme680_measure_float (sensor, &values))
|
|||
|
||||
#### 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.
|
||||
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.
|
||||
|
||||
**Please 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.
|
||||
|
||||
|
@ -112,7 +115,7 @@ 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.
|
||||
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.
|
||||
|
||||
|
@ -190,7 +193,7 @@ while (1)
|
|||
// measurement duration changes in each cycle
|
||||
uint32_t duration = bme680_get_measurement_duration(sensor);
|
||||
|
||||
// trigger the sensor to start one TPHG measurement cycle
|
||||
// trigger the sensor to start one TPHG measurement cycle
|
||||
if (bme680_force_measurement (sensor))
|
||||
{
|
||||
vTaskDelay (duration);
|
||||
|
@ -216,7 +219,7 @@ bme680_set_ambient_temperature (sensor, ambient);
|
|||
|
||||
## Error Handling
|
||||
|
||||
Most driver functions return a simple boolean value to indicate whether its execution was successful or an error happened. In the latter case, the member ```error_code``` of the sensor device data structure is set which indicates what error happened.
|
||||
Most driver functions return a simple boolean value to indicate whether its execution was successful or an error happened. In the latter case, the member ```error_code``` of the sensor device data structure is set which indicates what error happened.
|
||||
|
||||
There are two different error levels that are ORed into one single *error_code*, errors in the I2C or SPI communication and errors of the BME680 sensor itself. To test for a certain error, first you can AND the *error_code* with one of the error masks, ```BME680_INT_ERROR_MASK``` for I2C or SPI errors and ```BME680_DRV_ERROR_MASK``` for other errors. Then you can test the result for a certain error code.
|
||||
|
||||
|
@ -234,8 +237,8 @@ else
|
|||
|
||||
switch (sensor->error_code & BME680_INT_ERROR_MASK)
|
||||
{
|
||||
case BME680_INT_BUSY: ...
|
||||
case BME680_INT_READ_FAILED: ...
|
||||
case BME680_I2C_BUSY: ...
|
||||
case BME680_I2C_READ_FAILED: ...
|
||||
...
|
||||
}
|
||||
switch (sensor->error_code & BME680_DRV_ERROR_MASK)
|
||||
|
@ -258,58 +261,62 @@ The driver supports multiple BME680 sensors at the same time that are connected
|
|||
First figure shows the configuration with only one sensor at I2C bus 0.
|
||||
|
||||
```
|
||||
+-------------------------+ +--------+
|
||||
| ESP8266 Bus 0 | | BME680 |
|
||||
| GPIO 5 (SCL) +---->+ SCL |
|
||||
| GPIO 4 (SDA) +-----+ SDA |
|
||||
| | +--------+
|
||||
+-------------------------+
|
||||
+------------------+ +----------+
|
||||
| ESP8266 / ESP32 | | BME680 |
|
||||
| | | |
|
||||
| GPIO 14 (SCL) ----> SCL |
|
||||
| GPIO 13 (SDA) <---> SDA |
|
||||
+------------------+ +----------+
|
||||
```
|
||||
|
||||
Next figure shows the configuration with only one sensor at SPI bus using GPIO2 as CS signal.
|
||||
Next figure shows the configuration with only one sensor at SPI bus.
|
||||
|
||||
```
|
||||
+-------------------------+ +--------+
|
||||
| Bus 1 | | BME680 |
|
||||
| GPIO 12 (MISO) <------ SDO |
|
||||
| GPIO 13 (MOSI) >-----> SDI |
|
||||
| GPIO 14 (SCK) >-----> SCK |
|
||||
| GPIO 2 (CS) >-----> CS |
|
||||
+-------------------------+ +--------+
|
||||
+------------------+ +----------+ +-----------------+ +----------+
|
||||
| ESP8266 / ESP32 | | BME680 | | ESP32 | | BME680 |
|
||||
| | | | | | | |
|
||||
| GPIO 14 (SCK) ----> SCK | | GPIO 16 (SCK) ----> SCK |
|
||||
| GPIO 13 (MOSI) ----> SDI | | GPIO 17 (MOSI)----> SDI |
|
||||
| GPIO 12 (MISO) <---- SDO | | GPIO 18 (MISO)<---- SDO |
|
||||
| GPIO 2 (CS) ----> CS | | GPIO 19 (CS) ----> CS |
|
||||
+------------------+ +---------+ +-----------------+ +----------+
|
||||
```
|
||||
|
||||
**Please note:**
|
||||
|
||||
1. Since the system flash memory is connected to SPI bus 0, the sensor has to be connected to SPI bus 1.
|
||||
|
||||
2. GPIO15 which is used as CS signal of SPI bus 1 does not work correctly together with the BME680. Therefore, the user has to specify another GPIO pin as CS signal, e.g., GPIO2.
|
||||
2. GPIO15 which is used as CS signal of SPI bus 1 on ESP8266 does not work correctly together with the BME680. Therefore, the user has to specify another GPIO pin as CS signal, e.g., GPIO2.
|
||||
Next figure shows a possible configuration with two I2C buses. In that case, the sensors can have same or different I2C slave addresses.
|
||||
|
||||
```
|
||||
+-------------------------+ +----------+
|
||||
| ESP8266 Bus 0 | | BME680_1 |
|
||||
| GPIO 5 (SCL) ------> SCL |
|
||||
| GPIO 4 (SDA) ------- SDA |
|
||||
| | +----------+
|
||||
| Bus 1 | | BME680_2 |
|
||||
| GPIO 14 (SCL) ------> SCL |
|
||||
| GPIO 12 (SDA) ------- SDA |
|
||||
+-------------------------+ +----------+
|
||||
+------------------+ +----------+
|
||||
| ESP8266 / ESP32 | | BME680_1 |
|
||||
| | | |
|
||||
| GPIO 14 (SCL) ----> SCL |
|
||||
| GPIO 13 (SDA) <---> SDA |
|
||||
| | +----------+
|
||||
| | | BME680_2 |
|
||||
| | | |
|
||||
| GPIO 5 (SCL) ----> SCL |
|
||||
| GPIO 4 (SDA) <---> SDA |
|
||||
+------------------+ +----------+
|
||||
```
|
||||
|
||||
Last figure shows a possible configuration using I2C bus 0 and SPI bus 1 at the same time.
|
||||
```
|
||||
+-------------------------+ +----------+
|
||||
| ESP8266 Bus 0 | | BME680_1 |
|
||||
| GPIO 5 (SCL) ------> SCL |
|
||||
| GPIO 4 (SDA) ------- SDA |
|
||||
| | +----------+
|
||||
| Bus 1 | | BME680_2 |
|
||||
| GPIO 12 (MISO) <------ SDO |
|
||||
| GPIO 13 (MOSI) >-----> SDI |
|
||||
| GPIO 14 (SCK) >-----> SCK |
|
||||
| GPIO 2 (CS) >-----> CS |
|
||||
+-------------------------+ +----------+
|
||||
+------------------+ +----------+ +------------------+ +----------+
|
||||
| ESP8266 | | BME680_1 | | ESP8266 | | BME680_1 |
|
||||
| | | | | | | |
|
||||
| GPIO 5 (SCL) ----> SCL | | GPIO 5 (SCL) ----> SCL |
|
||||
| GPIO 4 (SDA) <---> SDA | | GPIO 4 (SDA) <---> SDA |
|
||||
| | +----------+ | | +----------+
|
||||
| | | BME680_2 | | | | BME680_2 |
|
||||
| GPIO 14 (SCK) ----> SCK | | GPIO 16 (SCK) ----> SCK |
|
||||
| GPIO 13 (MOSI) ----> SDI | | GPIO 17 (MOSI) ----> SDI |
|
||||
| GPIO 12 (MISO) <---- SDO | | GPIO 18 (MISO) <---- SDO |
|
||||
| GPIO 2 (CS) ----> CS | | GPIO 19 (CS) ----> CS |
|
||||
+------------------+ +---------+ +------------------+ +----------+
|
||||
```
|
||||
|
||||
Further configurations are possible, e.g., two sensors that are connected at the same I2C bus with different slave addresses.
|
||||
|
@ -326,13 +333,13 @@ Dependent on the hardware configuration, the communication interface settings ha
|
|||
|
||||
// define I2C interface for BME680 sensors
|
||||
#define I2C_BUS 0
|
||||
#define I2C_SCL_PIN 5
|
||||
#define I2C_SDA_PIN 4
|
||||
#define I2C_SCL_PIN 14
|
||||
#define I2C_SDA_PIN 13
|
||||
#endif
|
||||
|
||||
```
|
||||
|
||||
### Main program
|
||||
### Main programm
|
||||
|
||||
If I2C interfaces are used, they have to be initialized first.
|
||||
|
||||
|
@ -446,38 +453,55 @@ Once the measurement results are available, they can be fetched as fixed point o
|
|||
## Full Example
|
||||
|
||||
```
|
||||
// Uncomment to use SPI
|
||||
/* -- use following constants to define the example mode ----------- */
|
||||
|
||||
// #define SPI_USED
|
||||
|
||||
#include "espressif/esp_common.h"
|
||||
#include "esp/uart.h"
|
||||
/* -- includes ----------------------------------------------------- */
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "bme680.h"
|
||||
|
||||
// include communication interface driver
|
||||
#include "esp/spi.h"
|
||||
#include "i2c/i2c.h"
|
||||
/* -- platform dependent definitions ------------------------------- */
|
||||
|
||||
// include BME680 driver
|
||||
#include "bme680/bme680.h"
|
||||
#ifdef ESP_PLATFORM // ESP32 (ESP-IDF)
|
||||
|
||||
#ifdef SPI_USED
|
||||
// define SPI interface for BME680 sensors
|
||||
#define SPI_BUS 1
|
||||
#define SPI_CS_GPIO 2 // GPIO 15, the default CS of SPI bus 1, can't be used
|
||||
#else
|
||||
// define I2C interface for BME680 sensors
|
||||
#define I2C_BUS 0
|
||||
#define I2C_SCL_PIN 5
|
||||
#define I2C_SDA_PIN 4
|
||||
#endif
|
||||
// user task stack depth for ESP32
|
||||
#define TASK_STACK_DEPTH 2048
|
||||
|
||||
static bme680_sensor_t* sensor;
|
||||
// SPI interface definitions for ESP32
|
||||
#define SPI_BUS HSPI_HOST
|
||||
#define SPI_SCK_GPIO 16
|
||||
#define SPI_MOSI_GPIO 17
|
||||
#define SPI_MISO_GPIO 18
|
||||
#define SPI_CS_GPIO 19
|
||||
|
||||
#else // ESP8266 (esp-open-rtos)
|
||||
|
||||
// user task stack depth for ESP8266
|
||||
#define TASK_STACK_DEPTH 256
|
||||
|
||||
// SPI interface definitions for ESP8266
|
||||
#define SPI_BUS 1
|
||||
#define SPI_SCK_GPIO 14
|
||||
#define SPI_MOSI_GPIO 13
|
||||
#define SPI_MISO_GPIO 12
|
||||
#define SPI_CS_GPIO 2 // GPIO 15, the default CS of SPI bus 1, can't be used
|
||||
|
||||
#endif // ESP_PLATFORM
|
||||
|
||||
// I2C interface defintions for ESP32 and ESP8266
|
||||
#define I2C_BUS 0
|
||||
#define I2C_SCL_PIN 14
|
||||
#define I2C_SDA_PIN 13
|
||||
#define I2C_FREQ I2C_FREQ_100K
|
||||
|
||||
/* -- user tasks --------------------------------------------------- */
|
||||
|
||||
static bme680_sensor_t* sensor = 0;
|
||||
|
||||
/*
|
||||
* User task that triggers measurements of sensor every seconds. It uses
|
||||
* function *vTaskDelay* to wait for measurement results. Busy waiting
|
||||
* function *vTaskDelay* to wait for measurement results. Busy wating
|
||||
* alternative is shown in comments
|
||||
*/
|
||||
void user_task(void *pvParameters)
|
||||
|
@ -492,51 +516,58 @@ void user_task(void *pvParameters)
|
|||
while (1)
|
||||
{
|
||||
// trigger the sensor to start one TPHG measurement cycle
|
||||
bme680_force_measurement (sensor);
|
||||
if (bme680_force_measurement (sensor))
|
||||
{
|
||||
// passive waiting until measurement results are available
|
||||
vTaskDelay (duration);
|
||||
|
||||
// passive waiting until measurement results are available
|
||||
vTaskDelay (duration);
|
||||
|
||||
// alternatively: busy waiting until measurement results are available
|
||||
// while (bme680_is_measuring (sensor)) ;
|
||||
|
||||
// get the results and do something with them
|
||||
if (bme680_get_results_float (sensor, &values))
|
||||
printf("%.3f BME680 Sensor: %.2f °C, %.2f %%, %.2f hPa, %.2f Ohm\n",
|
||||
(double)sdk_system_get_time()*1e-3,
|
||||
values.temperature, values.humidity,
|
||||
values.pressure, values.gas_resistance);
|
||||
// alternatively: busy waiting until measurement results are available
|
||||
// while (bme680_is_measuring (sensor)) ;
|
||||
|
||||
// get the results and do something with them
|
||||
if (bme680_get_results_float (sensor, &values))
|
||||
printf("%.3f BME680 Sensor: %.2f °C, %.2f %%, %.2f hPa, %.2f Ohm\n",
|
||||
(double)sdk_system_get_time()*1e-3,
|
||||
values.temperature, values.humidity,
|
||||
values.pressure, values.gas_resistance);
|
||||
}
|
||||
// passive waiting until 1 second is over
|
||||
vTaskDelayUntil(&last_wakeup, 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
/* -- main program ------------------------------------------------- */
|
||||
|
||||
void user_init(void)
|
||||
{
|
||||
// Set UART Parameter
|
||||
// Set UART Parameter.
|
||||
uart_set_baud(0, 115200);
|
||||
// Give the UART some time to settle
|
||||
sdk_os_delay_us(500);
|
||||
|
||||
vTaskDelay(1);
|
||||
|
||||
/** -- MANDATORY PART -- */
|
||||
|
||||
#ifdef SPI_USED
|
||||
// Init the sensor connected either to SPI.
|
||||
sensor = bme680_init_sensor (SPI_BUS, 0, SPI_CS_GPIO);
|
||||
#else
|
||||
// Init all I2C bus interfaces at which BME680 sensors are connected
|
||||
i2c_init(I2C_BUS, I2C_SCL_PIN, I2C_SDA_PIN, I2C_FREQ_100K);
|
||||
|
||||
// Init the sensor connected either to I2C.
|
||||
spi_bus_init (SPI_BUS, SPI_SCK_GPIO, SPI_MISO_GPIO, SPI_MOSI_GPIO);
|
||||
|
||||
// init the sensor connected to SPI_BUS with SPI_CS_GPIO as chip select.
|
||||
sensor = bme680_init_sensor (SPI_BUS, 0, SPI_CS_GPIO);
|
||||
|
||||
#else // I2C
|
||||
|
||||
// Init all I2C bus interfaces at which BME680 sensors are connected
|
||||
i2c_init(I2C_BUS, I2C_SCL_PIN, I2C_SDA_PIN, I2C_FREQ);
|
||||
|
||||
// init the sensor with slave address BME680_I2C_ADDRESS_2 connected to I2C_BUS.
|
||||
sensor = bme680_init_sensor (I2C_BUS, BME680_I2C_ADDRESS_2, 0);
|
||||
#endif
|
||||
|
||||
#endif // SPI_USED
|
||||
|
||||
if (sensor)
|
||||
{
|
||||
// Create a task that uses the sensor
|
||||
xTaskCreate(user_task, "user_task", 256, NULL, 2, NULL);
|
||||
xTaskCreate(user_task, "user_task", TASK_STACK_DEPTH, NULL, 2, NULL);
|
||||
|
||||
/** -- OPTIONAL PART -- */
|
||||
|
||||
|
@ -550,6 +581,10 @@ void user_init(void)
|
|||
// Change the heater profile 0 to 200 degree Celcius for 100 ms.
|
||||
bme680_set_heater_profile (sensor, 0, 200, 100);
|
||||
bme680_use_heater_profile (sensor, 0);
|
||||
|
||||
// Set ambient temperature to 10 degree Celsius
|
||||
bme680_set_ambient_temperature (sensor, 10);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue