BME680 driver trailing whitespaces removed

This commit is contained in:
Gunar Schorcht 2017-10-28 17:17:54 +02:00
parent 1af3f2e033
commit f431f831f6
8 changed files with 318 additions and 325 deletions

View file

@ -6,7 +6,7 @@ These examples demonstrate the usage of the BME680 driver with only one and mult
There are examples that are using either I2C or SPI with one or two sensors. There are examples that are using either I2C or SPI with one or two sensors.
For examples using BME680 sensor as I2C slave, just use GPIO5 (SCL) and GPIO4 (SDA) to connect to the BME680 sensor's I2C interface. For examples using BME680 sensor as I2C slave, just use GPIO5 (SCL) and GPIO4 (SDA) to connect to the BME680 sensor's I2C interface.
``` ```
+-------------------------+ +--------+ +-------------------------+ +--------+

View file

@ -10,7 +10,7 @@
* | GPIO 4 (SDA) ------- SDA | * | GPIO 4 (SDA) ------- SDA |
* +-------------------------+ +----------+ * +-------------------------+ +----------+
*/ */
#include "espressif/esp_common.h" #include "espressif/esp_common.h"
#include "esp/uart.h" #include "esp/uart.h"
@ -31,7 +31,7 @@
static bme680_sensor_t* sensor; static bme680_sensor_t* sensor;
/* /*
* User task that triggers measurements of sensor every seconds. It uses * User task that triggers measurements of sensor every seconds. It uses
* function *vTaskDelay* to wait for measurement results and changes the * function *vTaskDelay* to wait for measurement results and changes the
* heating profile in each cycle. * heating profile in each cycle.
*/ */
@ -40,10 +40,10 @@ void user_task(void *pvParameters)
bme680_values_float_t values; bme680_values_float_t values;
TickType_t last_wakeup = xTaskGetTickCount(); TickType_t last_wakeup = xTaskGetTickCount();
uint32_t count = 0; uint32_t count = 0;
while (1) while (1)
{ {
if (count++ < 60) if (count++ < 60)
// disable gas measurement for cycle counter < 60 // disable gas measurement for cycle counter < 60
@ -62,7 +62,7 @@ void user_task(void *pvParameters)
// measurement duration changes in each cycle // measurement duration changes in each cycle
uint32_t duration = bme680_get_measurement_duration(sensor); 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)) if (bme680_force_measurement (sensor))
{ {
// passive waiting until measurement results are available // passive waiting until measurement results are available
@ -70,9 +70,9 @@ void user_task(void *pvParameters)
// get the results and do something with them // get the results and do something with them
if (bme680_get_results_float (sensor, &values)) if (bme680_get_results_float (sensor, &values))
printf("%.3f BME680 Sensor: %.2f °C, %.2f %%, %.2f hPa, %.2f Ohm\n", printf("%.3f BME680 Sensor: %.2f °C, %.2f %%, %.2f hPa, %.2f Ohm\n",
(double)sdk_system_get_time()*1e-3, (double)sdk_system_get_time()*1e-3,
values.temperature, values.humidity, values.temperature, values.humidity,
values.pressure, values.gas_resistance); values.pressure, values.gas_resistance);
} }
// passive waiting until 1 second is over // passive waiting until 1 second is over
@ -87,9 +87,9 @@ void user_init(void)
uart_set_baud(0, 115200); uart_set_baud(0, 115200);
// Give the UART some time to settle // Give the UART some time to settle
sdk_os_delay_us(500); sdk_os_delay_us(500);
/** -- MANDATORY PART -- */ /** -- MANDATORY PART -- */
#ifdef SPI_USED #ifdef SPI_USED
// Init the sensor connected either to SPI. // Init the sensor connected either to SPI.
sensor = bme680_init_sensor (SPI_BUS, 0, SPI_CS_GPIO); sensor = bme680_init_sensor (SPI_BUS, 0, SPI_CS_GPIO);
@ -107,11 +107,11 @@ void user_init(void)
xTaskCreate(user_task, "user_task", 256, NULL, 2, NULL); xTaskCreate(user_task, "user_task", 256, NULL, 2, NULL);
/** -- OPTIONAL PART -- */ /** -- OPTIONAL PART -- */
// Changes the oversampling rates to 4x oversampling for temperature // Changes the oversampling rates to 4x oversampling for temperature
// and 2x oversampling for humidity. Pressure measurement is skipped. // and 2x oversampling for humidity. Pressure measurement is skipped.
bme680_set_oversampling_rates(sensor, osr_4x, osr_none, osr_2x); bme680_set_oversampling_rates(sensor, osr_4x, osr_none, osr_2x);
// Change the IIR filter size for temperature and pressure to 7. // Change the IIR filter size for temperature and pressure to 7.
bme680_set_filter_size(sensor, iir_size_7); bme680_set_filter_size(sensor, iir_size_7);
@ -123,4 +123,3 @@ void user_init(void)
bme680_set_heater_profile (sensor, 4, 400, 180); bme680_set_heater_profile (sensor, 4, 400, 180);
} }
} }

View file

@ -9,7 +9,7 @@
* | GPIO 5 (SCL) ------> SCL | * | GPIO 5 (SCL) ------> SCL |
* | GPIO 4 (SDA) ------- SDA | * | GPIO 4 (SDA) ------- SDA |
* +-------------------------+ +----------+ * +-------------------------+ +----------+
* *
* SPI +-------------------------+ +----------+ * SPI +-------------------------+ +----------+
* | ESP8266 Bus 1 | | BME680 | * | ESP8266 Bus 1 | | BME680 |
* | GPIO 12 (MISO) <-----< SDO | * | GPIO 12 (MISO) <-----< SDO |
@ -18,10 +18,10 @@
* | GPIO 2 (CS) >-----> CS | * | GPIO 2 (CS) >-----> CS |
* +-------------------------+ +----------+ * +-------------------------+ +----------+
*/ */
// Uncomment to use SPI // Uncomment to use SPI
// #define SPI_USED // #define SPI_USED
#include "espressif/esp_common.h" #include "espressif/esp_common.h"
#include "esp/uart.h" #include "esp/uart.h"
@ -49,7 +49,7 @@
static bme680_sensor_t* sensor; static bme680_sensor_t* sensor;
/* /*
* User task that triggers measurements of sensor every seconds. It uses * User task that triggers measurements of sensor every seconds. It uses
* function *vTaskDelay* to wait for measurement results. Busy wating * function *vTaskDelay* to wait for measurement results. Busy wating
* alternative is shown in comments * alternative is shown in comments
*/ */
@ -58,26 +58,26 @@ void user_task(void *pvParameters)
bme680_values_float_t values; bme680_values_float_t values;
TickType_t last_wakeup = xTaskGetTickCount(); TickType_t last_wakeup = xTaskGetTickCount();
// as long as sensor configuration isn't changed, duration is constant // as long as sensor configuration isn't changed, duration is constant
uint32_t duration = bme680_get_measurement_duration(sensor); uint32_t duration = bme680_get_measurement_duration(sensor);
while (1) while (1)
{ {
// trigger the sensor to start one TPHG measurement cycle // trigger the sensor to start one TPHG measurement cycle
if (bme680_force_measurement (sensor)) if (bme680_force_measurement (sensor))
{ {
// passive waiting until measurement results are available // passive waiting until measurement results are available
vTaskDelay (duration); vTaskDelay (duration);
// alternatively: busy waiting until measurement results are available // alternatively: busy waiting until measurement results are available
// while (bme680_is_measuring (sensor)) ; // while (bme680_is_measuring (sensor)) ;
// get the results and do something with them // get the results and do something with them
if (bme680_get_results_float (sensor, &values)) if (bme680_get_results_float (sensor, &values))
printf("%.3f BME680 Sensor: %.2f °C, %.2f %%, %.2f hPa, %.2f Ohm\n", printf("%.3f BME680 Sensor: %.2f °C, %.2f %%, %.2f hPa, %.2f Ohm\n",
(double)sdk_system_get_time()*1e-3, (double)sdk_system_get_time()*1e-3,
values.temperature, values.humidity, values.temperature, values.humidity,
values.pressure, values.gas_resistance); values.pressure, values.gas_resistance);
} }
// passive waiting until 1 second is over // passive waiting until 1 second is over
@ -92,9 +92,9 @@ void user_init(void)
uart_set_baud(0, 115200); uart_set_baud(0, 115200);
// Give the UART some time to settle // Give the UART some time to settle
sdk_os_delay_us(500); sdk_os_delay_us(500);
/** -- MANDATORY PART -- */ /** -- MANDATORY PART -- */
#ifdef SPI_USED #ifdef SPI_USED
// Init the sensor connected either to SPI. // Init the sensor connected either to SPI.
sensor = bme680_init_sensor (SPI_BUS, 0, SPI_CS_GPIO); sensor = bme680_init_sensor (SPI_BUS, 0, SPI_CS_GPIO);
@ -112,11 +112,11 @@ void user_init(void)
xTaskCreate(user_task, "user_task", 256, NULL, 2, NULL); xTaskCreate(user_task, "user_task", 256, NULL, 2, NULL);
/** -- OPTIONAL PART -- */ /** -- OPTIONAL PART -- */
// Changes the oversampling rates to 4x oversampling for temperature // Changes the oversampling rates to 4x oversampling for temperature
// and 2x oversampling for humidity. Pressure measurement is skipped. // and 2x oversampling for humidity. Pressure measurement is skipped.
bme680_set_oversampling_rates(sensor, osr_4x, osr_none, osr_2x); bme680_set_oversampling_rates(sensor, osr_4x, osr_none, osr_2x);
// Change the IIR filter size for temperature and pressure to 7. // Change the IIR filter size for temperature and pressure to 7.
bme680_set_filter_size(sensor, iir_size_7); bme680_set_filter_size(sensor, iir_size_7);
@ -128,4 +128,3 @@ void user_init(void)
bme680_set_ambient_temperature (sensor, 10); bme680_set_ambient_temperature (sensor, 10);
} }
} }

View file

@ -19,7 +19,7 @@
* | GPIO 2 (CS) >-----> CS | * | GPIO 2 (CS) >-----> CS |
* +-------------------------+ +----------+ * +-------------------------+ +----------+
*/ */
#include "espressif/esp_common.h" #include "espressif/esp_common.h"
#include "esp/uart.h" #include "esp/uart.h"
@ -36,7 +36,7 @@
// define I2C interface for BME680 sensor 1 // define I2C interface for BME680 sensor 1
#define SPI_BUS 1 #define SPI_BUS 1
#define SPI_CS_GPIO 2 // GPIO 15, the default CS of SPI bus 1, can't be used #define SPI_CS_GPIO 2 // GPIO 15, the default CS of SPI bus 1, can't be used
// define SPI interface for BME680 sensor 2 // define SPI interface for BME680 sensor 2
#define I2C_BUS 0 #define I2C_BUS 0
#define I2C_SCL_PIN 5 #define I2C_SCL_PIN 5
#define I2C_SDA_PIN 4 #define I2C_SDA_PIN 4
@ -45,7 +45,7 @@ static bme680_sensor_t* sensor1;
static bme680_sensor_t* sensor2; static bme680_sensor_t* sensor2;
/* /*
* User task that triggers measurements of sensor1 every 5 seconds and * User task that triggers measurements of sensor1 every 5 seconds and
* uses *vTaskDelay* to wait for measurement results. * uses *vTaskDelay* to wait for measurement results.
*/ */
void user_task_sensor1(void *pvParameters) void user_task_sensor1(void *pvParameters)
@ -53,26 +53,26 @@ void user_task_sensor1(void *pvParameters)
bme680_values_float_t values; bme680_values_float_t values;
TickType_t last_wakeup = xTaskGetTickCount(); TickType_t last_wakeup = xTaskGetTickCount();
uint32_t duration = bme680_get_measurement_duration (sensor1); uint32_t duration = bme680_get_measurement_duration (sensor1);
while (1) while (1)
{ {
// trigger the sensor to start one TPHG measurement cycle // trigger the sensor to start one TPHG measurement cycle
if (bme680_force_measurement (sensor1)) if (bme680_force_measurement (sensor1))
{ {
// passive waiting until measurement results are available // passive waiting until measurement results are available
vTaskDelay (duration); vTaskDelay (duration);
// get the results and so something with them // get the results and so something with them
if (bme680_get_results_float (sensor1, &values)) if (bme680_get_results_float (sensor1, &values))
printf("%.3f BME680 Sensor1: %.2f °C, %.2f %%, %.2f hPa, %.2f Ohm\n", printf("%.3f BME680 Sensor1: %.2f °C, %.2f %%, %.2f hPa, %.2f Ohm\n",
(double)sdk_system_get_time()*1e-3, (double)sdk_system_get_time()*1e-3,
values.temperature, values.humidity, values.temperature, values.humidity,
values.pressure, values.gas_resistance); values.pressure, values.gas_resistance);
} }
// passive waiting until 5 seconds are over // passive waiting until 5 seconds are over
vTaskDelayUntil(&last_wakeup, 5000 / portTICK_PERIOD_MS); vTaskDelayUntil(&last_wakeup, 5000 / portTICK_PERIOD_MS);
} }
@ -87,10 +87,10 @@ void user_task_sensor2(void *pvParameters)
bme680_values_float_t values; bme680_values_float_t values;
TickType_t last_wakeup = xTaskGetTickCount(); TickType_t last_wakeup = xTaskGetTickCount();
while (1) while (1)
{ {
// trigger the sensor to start one TPHG measurement cycle // trigger the sensor to start one TPHG measurement cycle
if (bme680_force_measurement (sensor2)) if (bme680_force_measurement (sensor2))
{ {
// busy waiting until measurement results are available // busy waiting until measurement results are available
@ -100,10 +100,10 @@ void user_task_sensor2(void *pvParameters)
if (bme680_get_results_float (sensor2, &values)) if (bme680_get_results_float (sensor2, &values))
printf("%.3f BME680 Sensor2: %.2f °C, %.2f %%, %.2f hPa, %.2f Ohm\n", printf("%.3f BME680 Sensor2: %.2f °C, %.2f %%, %.2f hPa, %.2f Ohm\n",
(double)sdk_system_get_time()*1e-3, (double)sdk_system_get_time()*1e-3,
values.temperature, values.humidity, values.temperature, values.humidity,
values.pressure, values.gas_resistance); values.pressure, values.gas_resistance);
} }
// passive waiting until 2 seconds are over // passive waiting until 2 seconds are over
vTaskDelayUntil(&last_wakeup, 2000 / portTICK_PERIOD_MS); vTaskDelayUntil(&last_wakeup, 2000 / portTICK_PERIOD_MS);
} }
@ -116,9 +116,9 @@ void user_init(void)
uart_set_baud(0, 115200); uart_set_baud(0, 115200);
// Give the UART some time to settle // Give the UART some time to settle
sdk_os_delay_us(500); sdk_os_delay_us(500);
/** -- MANDATORY PART -- */ /** -- MANDATORY PART -- */
// Init all I2C bus interfaces at which BME680 sensors are connected // Init all I2C bus interfaces at which BME680 sensors are connected
i2c_init(I2C_BUS, I2C_SCL_PIN, I2C_SDA_PIN, I2C_FREQ_100K); i2c_init(I2C_BUS, I2C_SCL_PIN, I2C_SDA_PIN, I2C_FREQ_100K);
@ -131,15 +131,15 @@ void user_init(void)
// Create the tasks that use the sensors // Create the tasks that use the sensors
xTaskCreate(user_task_sensor1, "user_task_sensor1", 256, NULL, 2, 0); xTaskCreate(user_task_sensor1, "user_task_sensor1", 256, NULL, 2, 0);
xTaskCreate(user_task_sensor2, "user_task_sensor2", 256, NULL, 2, 0); xTaskCreate(user_task_sensor2, "user_task_sensor2", 256, NULL, 2, 0);
// That's it. // That's it.
/** -- OPTIONAL PART -- */ /** -- OPTIONAL PART -- */
// Changes the oversampling rates for both sensor to different values // Changes the oversampling rates for both sensor to different values
bme680_set_oversampling_rates(sensor1, osr_4x, osr_2x, osr_1x); bme680_set_oversampling_rates(sensor1, osr_4x, osr_2x, osr_1x);
bme680_set_oversampling_rates(sensor2, osr_8x, osr_8x, osr_8x); bme680_set_oversampling_rates(sensor2, osr_8x, osr_8x, osr_8x);
// Change the IIR filter size for temperature and and pressure to 7. // Change the IIR filter size for temperature and and pressure to 7.
bme680_set_filter_size(sensor1, iir_size_7); bme680_set_filter_size(sensor1, iir_size_7);
bme680_set_filter_size(sensor2, iir_size_7); bme680_set_filter_size(sensor2, iir_size_7);
@ -147,10 +147,9 @@ void user_init(void)
// Change the heater profile 0 to 200 degree Celcius for 150 ms. // Change the heater profile 0 to 200 degree Celcius for 150 ms.
bme680_set_heater_profile (sensor1, 0, 200, 150); bme680_set_heater_profile (sensor1, 0, 200, 150);
bme680_set_heater_profile (sensor2, 0, 200, 150); bme680_set_heater_profile (sensor2, 0, 200, 150);
// Activate the heater profile 0 // Activate the heater profile 0
bme680_use_heater_profile (sensor1, 0); bme680_use_heater_profile (sensor1, 0);
bme680_use_heater_profile (sensor2, 0); bme680_use_heater_profile (sensor2, 0);
} }
} }

View file

@ -18,9 +18,9 @@ Interface selection is done automatically by the sensor using the SPI CS signal.
## Measurement process ## 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. **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.
@ -47,7 +47,7 @@ if (bme680_force_measurement (sensor)) // STEP 1
{ {
// STEP 2: passive waiting until measurement results are available // STEP 2: passive waiting until measurement results are available
vTaskDelay (duration); vTaskDelay (duration);
// STEP 3: get the results and do something with them // STEP 3: get the results and do something with them
if (bme680_get_results_float (sensor, &values)) if (bme680_get_results_float (sensor, &values))
... ...
@ -61,7 +61,7 @@ if (bme680_force_measurement (sensor)) // STEP 1
{ {
// STEP 2: busy waiting until measurement results are available // STEP 2: busy waiting until measurement results are available
while (bme680_is_measuring (sensor)) ; while (bme680_is_measuring (sensor)) ;
// STEP 3: get the results and do something with them // STEP 3: get the results and do something with them
if (bme680_get_results_float (sensor, &values)) if (bme680_get_results_float (sensor, &values))
... ...
@ -81,7 +81,7 @@ if (bme680_measure_float (sensor, &values))
#### Measurement results #### 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. **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 +112,7 @@ The sensor allows to change a lot of measurement parameters.
#### Oversampling rates #### 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. 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.
@ -140,11 +140,11 @@ bme680_set_filter_size(sensor, iir_size_7);
bme680_set_filter_size(sensor, iir_size_0); bme680_set_filter_size(sensor, iir_size_0);
... ...
``` ```
#### Heater profile #### 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. 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.
**Please 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. **Please 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. 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.
@ -176,7 +176,7 @@ the user task could use them as a sequence like following:
``` ```
... ...
while (1) while (1)
{ {
switch (count++ % 5) switch (count++ % 5)
{ {
@ -190,11 +190,11 @@ while (1)
// measurement duration changes in each cycle // measurement duration changes in each cycle
uint32_t duration = bme680_get_measurement_duration(sensor); 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)) if (bme680_force_measurement (sensor))
{ {
vTaskDelay (duration); vTaskDelay (duration);
// get the results and do something with them // get the results and do something with them
if (bme680_get_results_float (sensor, &values)) if (bme680_get_results_float (sensor, &values))
... ...
@ -216,7 +216,7 @@ bme680_set_ambient_temperature (sensor, ambient);
## Error Handling ## 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. 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.
@ -231,11 +231,11 @@ if (bme680_get_results_float (sensor, &values))
else else
{ {
// error happened // error happened
switch (sensor->error_code & BME680_INT_ERROR_MASK) switch (sensor->error_code & BME680_INT_ERROR_MASK)
{ {
case BME680_I2C_BUSY: ... case BME680_INT_BUSY: ...
case BME680_I2C_READ_FAILED: ... case BME680_INT_READ_FAILED: ...
... ...
} }
switch (sensor->error_code & BME680_DRV_ERROR_MASK) switch (sensor->error_code & BME680_DRV_ERROR_MASK)
@ -247,7 +247,7 @@ else
} }
``` ```
## Usage ## Usage
First, the hardware configuration has to be established. This can differ dependent on the communication interface and the number of sensors used. First, the hardware configuration has to be established. This can differ dependent on the communication interface and the number of sensors used.
@ -278,9 +278,9 @@ Next figure shows the configuration with only one sensor at SPI bus using GPIO2
+-------------------------+ +--------+ +-------------------------+ +--------+
``` ```
**Please note:** **Please note:**
1. Since the system flash memory is connected to SPI bus 0, the sensor has to be connected to SPI bus 1. 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 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. Next figure shows a possible configuration with two I2C buses. In that case, the sensors can have same or different I2C slave addresses.
@ -332,7 +332,7 @@ Dependent on the hardware configuration, the communication interface settings ha
``` ```
### Main programm ### Main program
If I2C interfaces are used, they have to be initialized first. If I2C interfaces are used, they have to be initialized first.
@ -375,18 +375,18 @@ if (sensor)
xTaskCreate(user_task, "user_task", 256, NULL, 2, NULL); xTaskCreate(user_task, "user_task", 256, NULL, 2, NULL);
/** -- OPTIONAL PART -- */ /** -- OPTIONAL PART -- */
// Changes the oversampling rates to 4x oversampling for temperature // Changes the oversampling rates to 4x oversampling for temperature
// and 2x oversampling for humidity. Pressure measurement is skipped. // and 2x oversampling for humidity. Pressure measurement is skipped.
bme680_set_oversampling_rates(sensor, osr_4x, osr_none, osr_2x); bme680_set_oversampling_rates(sensor, osr_4x, osr_none, osr_2x);
// Change the IIR filter size for temperature and pressure to 7. // Change the IIR filter size for temperature and pressure to 7.
bme680_set_filter_size(sensor, iir_size_7); bme680_set_filter_size(sensor, iir_size_7);
// Change the heater profile 0 to 200 degree Celsius for 100 ms. // Change the heater profile 0 to 200 degree Celsius for 100 ms.
bme680_set_heater_profile (sensor, 0, 200, 100); bme680_set_heater_profile (sensor, 0, 200, 100);
bme680_use_heater_profile (sensor, 0); bme680_use_heater_profile (sensor, 0);
... ...
} }
``` ```
@ -407,26 +407,26 @@ void user_task(void *pvParameters)
bme680_values_float_t values; bme680_values_float_t values;
TickType_t last_wakeup = xTaskGetTickCount(); TickType_t last_wakeup = xTaskGetTickCount();
// as long as sensor configuration isn't changed, duration is constant // as long as sensor configuration isn't changed, duration is constant
uint32_t duration = bme680_get_measurement_duration(sensor); uint32_t duration = bme680_get_measurement_duration(sensor);
while (1) while (1)
{ {
// trigger the sensor to start one TPHG measurement cycle // trigger the sensor to start one TPHG measurement cycle
bme680_force_measurement (sensor); bme680_force_measurement (sensor);
// passive waiting until measurement results are available // passive waiting until measurement results are available
vTaskDelay (duration); vTaskDelay (duration);
// alternatively: busy waiting until measurement results are available // alternatively: busy waiting until measurement results are available
// while (bme680_is_measuring (sensor)) ; // while (bme680_is_measuring (sensor)) ;
// get the results and do something with them // get the results and do something with them
if (bme680_get_results_float (sensor, &values)) if (bme680_get_results_float (sensor, &values))
printf("%.3f BME680 Sensor: %.2f °C, %.2f %%, %.2f hPa, %.2f Ohm\n", printf("%.3f BME680 Sensor: %.2f °C, %.2f %%, %.2f hPa, %.2f Ohm\n",
(double)sdk_system_get_time()*1e-3, (double)sdk_system_get_time()*1e-3,
values.temperature, values.humidity, values.temperature, values.humidity,
values.pressure, values.gas_resistance); values.pressure, values.gas_resistance);
// passive waiting until 1 second is over // passive waiting until 1 second is over
@ -435,7 +435,7 @@ void user_task(void *pvParameters)
} }
``` ```
Function ```bme680_force_measurement``` is called inside the task loop to perform exactly one measurement in each cycle. Function ```bme680_force_measurement``` is called inside the task loop to perform exactly one measurement in each cycle.
The task is then delayed using function ```vTaskDelay``` and the value returned from function ```bme680_get_measurement_duration``` or as long as function ```bme680_is_measuring``` returns true. The task is then delayed using function ```vTaskDelay``` and the value returned from function ```bme680_get_measurement_duration``` or as long as function ```bme680_is_measuring``` returns true.
@ -448,7 +448,7 @@ Once the measurement results are available, they can be fetched as fixed point o
``` ```
// Uncomment to use SPI // Uncomment to use SPI
// #define SPI_USED // #define SPI_USED
#include "espressif/esp_common.h" #include "espressif/esp_common.h"
#include "esp/uart.h" #include "esp/uart.h"
@ -476,7 +476,7 @@ Once the measurement results are available, they can be fetched as fixed point o
static bme680_sensor_t* sensor; static bme680_sensor_t* sensor;
/* /*
* User task that triggers measurements of sensor every seconds. It uses * 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 waiting
* alternative is shown in comments * alternative is shown in comments
*/ */
@ -485,26 +485,26 @@ void user_task(void *pvParameters)
bme680_values_float_t values; bme680_values_float_t values;
TickType_t last_wakeup = xTaskGetTickCount(); TickType_t last_wakeup = xTaskGetTickCount();
// as long as sensor configuration isn't changed, duration is constant // as long as sensor configuration isn't changed, duration is constant
uint32_t duration = bme680_get_measurement_duration(sensor); uint32_t duration = bme680_get_measurement_duration(sensor);
while (1) while (1)
{ {
// trigger the sensor to start one TPHG measurement cycle // trigger the sensor to start one TPHG measurement cycle
bme680_force_measurement (sensor); bme680_force_measurement (sensor);
// passive waiting until measurement results are available // passive waiting until measurement results are available
vTaskDelay (duration); vTaskDelay (duration);
// alternatively: busy waiting until measurement results are available // alternatively: busy waiting until measurement results are available
// while (bme680_is_measuring (sensor)) ; // while (bme680_is_measuring (sensor)) ;
// get the results and do something with them // get the results and do something with them
if (bme680_get_results_float (sensor, &values)) if (bme680_get_results_float (sensor, &values))
printf("%.3f BME680 Sensor: %.2f °C, %.2f %%, %.2f hPa, %.2f Ohm\n", printf("%.3f BME680 Sensor: %.2f °C, %.2f %%, %.2f hPa, %.2f Ohm\n",
(double)sdk_system_get_time()*1e-3, (double)sdk_system_get_time()*1e-3,
values.temperature, values.humidity, values.temperature, values.humidity,
values.pressure, values.gas_resistance); values.pressure, values.gas_resistance);
// passive waiting until 1 second is over // passive waiting until 1 second is over
@ -519,9 +519,9 @@ void user_init(void)
uart_set_baud(0, 115200); uart_set_baud(0, 115200);
// Give the UART some time to settle // Give the UART some time to settle
sdk_os_delay_us(500); sdk_os_delay_us(500);
/** -- MANDATORY PART -- */ /** -- MANDATORY PART -- */
#ifdef SPI_USED #ifdef SPI_USED
// Init the sensor connected either to SPI. // Init the sensor connected either to SPI.
sensor = bme680_init_sensor (SPI_BUS, 0, SPI_CS_GPIO); sensor = bme680_init_sensor (SPI_BUS, 0, SPI_CS_GPIO);
@ -539,11 +539,11 @@ void user_init(void)
xTaskCreate(user_task, "user_task", 256, NULL, 2, NULL); xTaskCreate(user_task, "user_task", 256, NULL, 2, NULL);
/** -- OPTIONAL PART -- */ /** -- OPTIONAL PART -- */
// Changes the oversampling rates to 4x oversampling for temperature // Changes the oversampling rates to 4x oversampling for temperature
// and 2x oversampling for humidity. Pressure measurement is skipped. // and 2x oversampling for humidity. Pressure measurement is skipped.
bme680_set_oversampling_rates(sensor, osr_4x, osr_none, osr_2x); bme680_set_oversampling_rates(sensor, osr_4x, osr_none, osr_2x);
// Change the IIR filter size for temperature and pressure to 7. // Change the IIR filter size for temperature and pressure to 7.
bme680_set_filter_size(sensor, iir_size_7); bme680_set_filter_size(sensor, iir_size_7);
@ -553,4 +553,3 @@ void user_init(void)
} }
} }
``` ```

View file

@ -13,7 +13,7 @@
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* 1. Redistributions of source code must retain the above copyright notice, * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
* *
@ -21,7 +21,7 @@
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* 3. Neither the name of the copyright holder nor the names of its * 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this * contributors may be used to endorse or promote products derived from this
* software without specific prior written permission. * software without specific prior written permission.
* *
@ -29,7 +29,7 @@
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
@ -46,7 +46,7 @@
*/ */
#include <string.h> #include <string.h>
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
@ -200,9 +200,9 @@
#define BME680_CDM_OFF2 BME680_REG_CD1_LEN #define BME680_CDM_OFF2 BME680_REG_CD1_LEN
#define BME680_CDM_OFF3 BME680_CDM_OFF2 + BME680_REG_CD2_LEN #define BME680_CDM_OFF3 BME680_CDM_OFF2 + BME680_REG_CD2_LEN
// calibration parameter offsets in calibration data map // calibration parameter offsets in calibration data map
// calibration data from 0x89 // calibration data from 0x89
#define BME680_CDM_T2 1 #define BME680_CDM_T2 1
#define BME680_CDM_T3 3 #define BME680_CDM_T3 3
#define BME680_CDM_P1 5 #define BME680_CDM_P1 5
#define BME680_CDM_P2 7 #define BME680_CDM_P2 7
@ -229,7 +229,7 @@
// device specific calibration data from 0x00 // device specific calibration data from 0x00
#define BME680_CDM_RHV 41 // 0x00 - res_heat_val #define BME680_CDM_RHV 41 // 0x00 - res_heat_val
#define BME680_CDM_RHR 43 // 0x02 - res_heat_range #define BME680_CDM_RHR 43 // 0x02 - res_heat_range
#define BME680_CDM_RSWE 45 // 0x04 - range_sw_error #define BME680_CDM_RSWE 45 // 0x04 - range_sw_error
/** /**
@ -239,13 +239,13 @@ typedef struct {
bool gas_valid; // indicate that gas measurement results are valid bool gas_valid; // indicate that gas measurement results are valid
bool heater_stable; // indicate that heater temperature was stable bool heater_stable; // indicate that heater temperature was stable
uint32_t temperature; // degree celsius x100 uint32_t temperature; // degree celsius x100
uint32_t pressure; // pressure in Pascal uint32_t pressure; // pressure in Pascal
uint16_t humidity; // relative humidity x1000 in % uint16_t humidity; // relative humidity x1000 in %
uint16_t gas_resistance; // gas resistance data uint16_t gas_resistance; // gas resistance data
uint8_t gas_range; // gas resistance range uint8_t gas_range; // gas resistance range
uint8_t gas_index; // heater profile used (0 ... 9) uint8_t gas_index; // heater profile used (0 ... 9)
uint8_t meas_index; uint8_t meas_index;
@ -284,10 +284,10 @@ static bool bme680_spi_write (bme680_sensor_t* dev, uint8_t reg, uint8_t *da
bme680_sensor_t* bme680_init_sensor(uint8_t bus, uint8_t addr, uint8_t cs) bme680_sensor_t* bme680_init_sensor(uint8_t bus, uint8_t addr, uint8_t cs)
{ {
bme680_sensor_t* dev; bme680_sensor_t* dev;
if ((dev = malloc (sizeof(bme680_sensor_t))) == NULL) if ((dev = malloc (sizeof(bme680_sensor_t))) == NULL)
return NULL; return NULL;
// init sensor data structure // init sensor data structure
dev->bus = bus; dev->bus = bus;
dev->addr = addr; dev->addr = addr;
@ -302,22 +302,22 @@ bme680_sensor_t* bme680_init_sensor(uint8_t bus, uint8_t addr, uint8_t cs)
dev->settings.heater_profile = BME680_HEATER_NOT_USED; dev->settings.heater_profile = BME680_HEATER_NOT_USED;
memset(dev->settings.heater_temperature, 0, sizeof(uint16_t)*10); memset(dev->settings.heater_temperature, 0, sizeof(uint16_t)*10);
memset(dev->settings.heater_duration, 0, sizeof(uint16_t)*10); memset(dev->settings.heater_duration, 0, sizeof(uint16_t)*10);
if (!addr) if (!addr)
{ {
// SPI interface used // SPI interface used
gpio_enable(dev->spi_cs_pin, GPIO_OUTPUT); gpio_enable(dev->spi_cs_pin, GPIO_OUTPUT);
gpio_write (dev->spi_cs_pin, true); gpio_write (dev->spi_cs_pin, true);
} }
// reset the sensor // reset the sensor
if (!bme680_reset(dev)) if (!bme680_reset(dev))
{ {
error_dev ("Could not reset the sensor device.", __FUNCTION__, dev); error_dev ("Could not reset the sensor device.", __FUNCTION__, dev);
free (dev); free (dev);
return NULL; return NULL;
} }
// check availability of the sensor // check availability of the sensor
if (!bme680_is_available (dev)) if (!bme680_is_available (dev))
{ {
@ -327,7 +327,7 @@ bme680_sensor_t* bme680_init_sensor(uint8_t bus, uint8_t addr, uint8_t cs)
} }
uint8_t buf[BME680_CDM_SIZE]; uint8_t buf[BME680_CDM_SIZE];
// read all calibration parameters from sensor // read all calibration parameters from sensor
if (bme680_read_reg(dev, BME680_REG_CD1_ADDR, buf+BME680_CDM_OFF1, BME680_REG_CD1_LEN) && if (bme680_read_reg(dev, BME680_REG_CD1_ADDR, buf+BME680_CDM_OFF1, BME680_REG_CD1_LEN) &&
bme680_read_reg(dev, BME680_REG_CD2_ADDR, buf+BME680_CDM_OFF2, BME680_REG_CD2_LEN) && bme680_read_reg(dev, BME680_REG_CD2_ADDR, buf+BME680_CDM_OFF2, BME680_REG_CD2_LEN) &&
@ -344,15 +344,15 @@ bme680_sensor_t* bme680_init_sensor(uint8_t bus, uint8_t addr, uint8_t cs)
dev->calib_data.par_p4 = lsb_msb_to_type ( int16_t, buf, BME680_CDM_P4); dev->calib_data.par_p4 = lsb_msb_to_type ( int16_t, buf, BME680_CDM_P4);
dev->calib_data.par_p5 = lsb_msb_to_type ( int16_t, buf, BME680_CDM_P5); dev->calib_data.par_p5 = lsb_msb_to_type ( int16_t, buf, BME680_CDM_P5);
dev->calib_data.par_p6 = lsb_to_type ( int8_t, buf, BME680_CDM_P6); dev->calib_data.par_p6 = lsb_to_type ( int8_t, buf, BME680_CDM_P6);
dev->calib_data.par_p7 = lsb_to_type ( int8_t, buf, BME680_CDM_P7); dev->calib_data.par_p7 = lsb_to_type ( int8_t, buf, BME680_CDM_P7);
dev->calib_data.par_p8 = lsb_msb_to_type ( int16_t, buf, BME680_CDM_P8); dev->calib_data.par_p8 = lsb_msb_to_type ( int16_t, buf, BME680_CDM_P8);
dev->calib_data.par_p9 = lsb_msb_to_type ( int16_t, buf, BME680_CDM_P9); dev->calib_data.par_p9 = lsb_msb_to_type ( int16_t, buf, BME680_CDM_P9);
dev->calib_data.par_p10 = lsb_to_type ( uint8_t, buf, BME680_CDM_P10); dev->calib_data.par_p10 = lsb_to_type ( uint8_t, buf, BME680_CDM_P10);
// humidity compensation parameters // humidity compensation parameters
dev->calib_data.par_h1 = (uint16_t)(((uint16_t)buf[BME680_CDM_H1+1] << 4) | dev->calib_data.par_h1 = (uint16_t)(((uint16_t)buf[BME680_CDM_H1+1] << 4) |
(buf[BME680_CDM_H1] & 0x0F)); (buf[BME680_CDM_H1] & 0x0F));
dev->calib_data.par_h2 = (uint16_t)(((uint16_t)buf[BME680_CDM_H2] << 4) | dev->calib_data.par_h2 = (uint16_t)(((uint16_t)buf[BME680_CDM_H2] << 4) |
(buf[BME680_CDM_H2+1] >> 4)); (buf[BME680_CDM_H2+1] >> 4));
dev->calib_data.par_h3 = lsb_to_type ( int8_t, buf, BME680_CDM_H3); dev->calib_data.par_h3 = lsb_to_type ( int8_t, buf, BME680_CDM_H3);
dev->calib_data.par_h4 = lsb_to_type ( int8_t, buf, BME680_CDM_H4); dev->calib_data.par_h4 = lsb_to_type ( int8_t, buf, BME680_CDM_H4);
@ -365,11 +365,11 @@ bme680_sensor_t* bme680_init_sensor(uint8_t bus, uint8_t addr, uint8_t cs)
dev->calib_data.par_gh2 = lsb_msb_to_type ( int16_t, buf, BME680_CDM_GH2); dev->calib_data.par_gh2 = lsb_msb_to_type ( int16_t, buf, BME680_CDM_GH2);
dev->calib_data.par_gh3 = lsb_to_type ( int8_t, buf, BME680_CDM_GH3); dev->calib_data.par_gh3 = lsb_to_type ( int8_t, buf, BME680_CDM_GH3);
dev->calib_data.res_heat_range = (lsb_to_type (uint8_t, buf ,BME680_CDM_RHR) & dev->calib_data.res_heat_range = (lsb_to_type (uint8_t, buf ,BME680_CDM_RHR) &
BME680_RHR_BITS) >> BME680_RHR_BITS) >>
BME680_RHR_SHIFT; BME680_RHR_SHIFT;
dev->calib_data.res_heat_val = (lsb_to_type ( int8_t, buf, BME680_CDM_RHV)); dev->calib_data.res_heat_val = (lsb_to_type ( int8_t, buf, BME680_CDM_RHV));
dev->calib_data.range_sw_err = (lsb_to_type ( int8_t, buf, BME680_CDM_RSWE) & dev->calib_data.range_sw_err = (lsb_to_type ( int8_t, buf, BME680_CDM_RSWE) &
BME680_RSWE_BITS) >> BME680_RSWE_BITS) >>
BME680_RSWE_SHIFT; BME680_RSWE_SHIFT;
} }
@ -379,13 +379,13 @@ bme680_sensor_t* bme680_init_sensor(uint8_t bus, uint8_t addr, uint8_t cs)
dev->error_code |= BME680_READ_CALIB_DATA_FAILED; dev->error_code |= BME680_READ_CALIB_DATA_FAILED;
free (dev); free (dev);
return NULL; return NULL;
} }
// Set the default temperature, pressure and humidity settings // Set the default temperature, pressure and humidity settings
if (!bme680_set_oversampling_rates (dev, osr_1x, osr_1x, osr_1x) || if (!bme680_set_oversampling_rates (dev, osr_1x, osr_1x, osr_1x) ||
!bme680_set_filter_size (dev, iir_size_3)) !bme680_set_filter_size (dev, iir_size_3))
{ {
error_dev ("Could not configure default sensor settings for TPH.", __FUNCTION__, dev); error_dev ("Could not configure default sensor settings for TPH.", __FUNCTION__, dev);
free (dev); free (dev);
return NULL; return NULL;
@ -393,7 +393,7 @@ bme680_sensor_t* bme680_init_sensor(uint8_t bus, uint8_t addr, uint8_t cs)
// Set ambient temperature of sensor to default value (25 degree C) // Set ambient temperature of sensor to default value (25 degree C)
dev->settings.ambient_temperature = 25; dev->settings.ambient_temperature = 25;
// Set heater default profile 0 to 320 degree Celcius for 150 ms // Set heater default profile 0 to 320 degree Celcius for 150 ms
if (!bme680_set_heater_profile (dev, 0, 320, 150)) if (!bme680_set_heater_profile (dev, 0, 320, 150))
{ {
@ -401,21 +401,21 @@ bme680_sensor_t* bme680_init_sensor(uint8_t bus, uint8_t addr, uint8_t cs)
free (dev); free (dev);
return NULL; return NULL;
} }
if (!bme680_use_heater_profile (dev, 0)) if (!bme680_use_heater_profile (dev, 0))
{ {
error_dev ("Could not configure default heater profile.", __FUNCTION__, dev); error_dev ("Could not configure default heater profile.", __FUNCTION__, dev);
free (dev); free (dev);
return NULL; return NULL;
} }
return dev; return dev;
} }
bool bme680_force_measurement (bme680_sensor_t* dev) bool bme680_force_measurement (bme680_sensor_t* dev)
{ {
if (!dev) return false; if (!dev) return false;
dev->error_code = BME680_OK; dev->error_code = BME680_OK;
// return remaining time when measurement is already running // return remaining time when measurement is already running
@ -433,14 +433,14 @@ bool bme680_force_measurement (bme680_sensor_t* dev)
dev->error_code |= BME680_FORCE_MODE_FAILED; dev->error_code |= BME680_FORCE_MODE_FAILED;
return false; return false;
} }
dev->meas_started = true; dev->meas_started = true;
dev->meas_start_tick = xTaskGetTickCount (); // system time in RTOS ticks dev->meas_start_tick = xTaskGetTickCount (); // system time in RTOS ticks
dev->meas_status = 0; dev->meas_status = 0;
debug_dev ("Started measurement at %.3f.", __FUNCTION__, dev, debug_dev ("Started measurement at %.3f.", __FUNCTION__, dev,
(double)sdk_system_get_time()*1e-3); (double)sdk_system_get_time()*1e-3);
return true; return true;
} }
@ -456,20 +456,20 @@ bool bme680_force_measurement (bme680_sensor_t* dev)
uint32_t bme680_get_measurement_duration (const bme680_sensor_t *dev) uint32_t bme680_get_measurement_duration (const bme680_sensor_t *dev)
{ {
if (!dev) return 0; if (!dev) return 0;
int32_t duration = 0; /* Calculate in us */ int32_t duration = 0; /* Calculate in us */
// wake up duration from sleep into forced mode // wake up duration from sleep into forced mode
duration += 1250; duration += 1250;
// THP cycle duration which consumes 1963 µs for each measurement at maximum // THP cycle duration which consumes 1963 µs for each measurement at maximum
if (dev->settings.osr_temperature) duration += (1 << (dev->settings.osr_temperature-1)) * 2300; if (dev->settings.osr_temperature) duration += (1 << (dev->settings.osr_temperature-1)) * 2300;
if (dev->settings.osr_pressure ) duration += (1 << (dev->settings.osr_pressure-1)) * 2300 + 575; if (dev->settings.osr_pressure ) duration += (1 << (dev->settings.osr_pressure-1)) * 2300 + 575;
if (dev->settings.osr_humidity ) duration += (1 << (dev->settings.osr_humidity-1)) * 2300 + 575; if (dev->settings.osr_humidity ) duration += (1 << (dev->settings.osr_humidity-1)) * 2300 + 575;
// if gas measurement is used // if gas measurement is used
if (dev->settings.heater_profile != BME680_HEATER_NOT_USED && if (dev->settings.heater_profile != BME680_HEATER_NOT_USED &&
dev->settings.heater_duration[dev->settings.heater_profile] && dev->settings.heater_duration[dev->settings.heater_profile] &&
dev->settings.heater_temperature[dev->settings.heater_profile]) dev->settings.heater_temperature[dev->settings.heater_profile])
{ {
// gas heating time // gas heating time
@ -477,19 +477,19 @@ uint32_t bme680_get_measurement_duration (const bme680_sensor_t *dev)
// gas measurement duration; // gas measurement duration;
duration += 2300 + 575; duration += 2300 + 575;
} }
// round up to next ms (1 us ... 1000 us => 1 ms) // round up to next ms (1 us ... 1000 us => 1 ms)
duration += 999; duration += 999;
duration /= 1000; duration /= 1000;
// some ms tolerance // some ms tolerance
duration += 5; duration += 5;
// ceil to next integer value that is divisible by portTICK_PERIOD_MS and // ceil to next integer value that is divisible by portTICK_PERIOD_MS and
// compute RTOS ticks (1 ... portTICK_PERIOD_MS = 1 tick) // compute RTOS ticks (1 ... portTICK_PERIOD_MS = 1 tick)
duration = (duration + portTICK_PERIOD_MS-1) / portTICK_PERIOD_MS; duration = (duration + portTICK_PERIOD_MS-1) / portTICK_PERIOD_MS;
// Since first RTOS tick can be shorter than the half of defined tick period, // Since first RTOS tick can be shorter than the half of defined tick period,
// the delay caused by vTaskDelay(duration) might be 1 or 2 ms shorter than // the delay caused by vTaskDelay(duration) might be 1 or 2 ms shorter than
// computed duration in rare cases. Since the duration is computed for maximum // computed duration in rare cases. Since the duration is computed for maximum
// and not for the typical durations and therefore tends to be too long, this // and not for the typical durations and therefore tends to be too long, this
@ -512,16 +512,16 @@ bool bme680_is_measuring (bme680_sensor_t* dev)
} }
uint8_t raw[2]; uint8_t raw[2];
// read maesurment status from sensor // read maesurment status from sensor
if (!bme680_read_reg(dev, BME680_REG_MEAS_STATUS_0, raw, 2)) if (!bme680_read_reg(dev, BME680_REG_MEAS_STATUS_0, raw, 2))
{ {
error_dev ("Could not read measurement status from sensor.", __FUNCTION__, dev); error_dev ("Could not read measurement status from sensor.", __FUNCTION__, dev);
return false; return false;
} }
dev->meas_status = raw[0]; dev->meas_status = raw[0];
// test whether measuring bit is set // test whether measuring bit is set
return (dev->meas_status & BME680_MEASURING_BITS); return (dev->meas_status & BME680_MEASURING_BITS);
} }
@ -544,10 +544,10 @@ bool bme680_get_results_fixed (bme680_sensor_t* dev, bme680_values_fixed_t* resu
if (!bme680_get_raw_data(dev, &raw)) if (!bme680_get_raw_data(dev, &raw))
// return invalid values // return invalid values
return false; return false;
// use compensation algorithms to compute sensor values in fixed point format // use compensation algorithms to compute sensor values in fixed point format
if (dev->settings.osr_temperature) if (dev->settings.osr_temperature)
results->temperature = bme680_convert_temperature (dev, raw.temperature); results->temperature = bme680_convert_temperature (dev, raw.temperature);
if (dev->settings.osr_pressure) if (dev->settings.osr_pressure)
@ -557,7 +557,7 @@ bool bme680_get_results_fixed (bme680_sensor_t* dev, bme680_values_fixed_t* resu
results->humidity = bme680_convert_humidity (dev, raw.humidity); results->humidity = bme680_convert_humidity (dev, raw.humidity);
if (dev->settings.heater_profile != BME680_HEATER_NOT_USED) if (dev->settings.heater_profile != BME680_HEATER_NOT_USED)
{ {
// convert gas only if raw data are valid and heater was stable // convert gas only if raw data are valid and heater was stable
if (raw.gas_valid && raw.heater_stable) if (raw.gas_valid && raw.heater_stable)
results->gas_resistance = bme680_convert_gas (dev, raw.gas_resistance, results->gas_resistance = bme680_convert_gas (dev, raw.gas_resistance,
@ -568,7 +568,7 @@ bool bme680_get_results_fixed (bme680_sensor_t* dev, bme680_values_fixed_t* resu
dev->error_code = BME680_HEATER_NOT_STABLE; dev->error_code = BME680_HEATER_NOT_STABLE;
} }
debug_dev ("Fixed point sensor valus - %d ms: %d/100 C, %d/1000 Percent, %d Pascal, %d Ohm", debug_dev ("Fixed point sensor valus - %d ms: %d/100 C, %d/1000 Percent, %d Pascal, %d Ohm",
__FUNCTION__, dev, sdk_system_get_time (), __FUNCTION__, dev, sdk_system_get_time (),
results->temperature, results->temperature,
results->humidity, results->humidity,
@ -584,15 +584,15 @@ bool bme680_get_results_float (bme680_sensor_t* dev, bme680_values_float_t* resu
if (!dev || !results) return false; if (!dev || !results) return false;
bme680_values_fixed_t fixed; bme680_values_fixed_t fixed;
if (!bme680_get_results_fixed (dev, &fixed)) if (!bme680_get_results_fixed (dev, &fixed))
return false; return false;
results->temperature = fixed.temperature / 100.0f; results->temperature = fixed.temperature / 100.0f;
results->pressure = fixed.pressure / 100.0f; results->pressure = fixed.pressure / 100.0f;
results->humidity = fixed.humidity / 1000.0f; results->humidity = fixed.humidity / 1000.0f;
results->gas_resistance = fixed.gas_resistance; results->gas_resistance = fixed.gas_resistance;
return true; return true;
} }
@ -600,13 +600,13 @@ bool bme680_get_results_float (bme680_sensor_t* dev, bme680_values_float_t* resu
bool bme680_measure_fixed (bme680_sensor_t* dev, bme680_values_fixed_t* results) bool bme680_measure_fixed (bme680_sensor_t* dev, bme680_values_fixed_t* results)
{ {
int32_t duration = bme680_force_measurement (dev); int32_t duration = bme680_force_measurement (dev);
if (duration == BME680_NOK) if (duration == BME680_NOK)
return false; // measurment couldn't be started return false; // measurment couldn't be started
else if (duration > 0) // wait for results else if (duration > 0) // wait for results
vTaskDelay (duration); vTaskDelay (duration);
return bme680_get_results_fixed (dev, results); return bme680_get_results_fixed (dev, results);
} }
@ -614,13 +614,13 @@ bool bme680_measure_fixed (bme680_sensor_t* dev, bme680_values_fixed_t* results)
bool bme680_measure_float (bme680_sensor_t* dev, bme680_values_float_t* results) bool bme680_measure_float (bme680_sensor_t* dev, bme680_values_float_t* results)
{ {
int32_t duration = bme680_force_measurement (dev); int32_t duration = bme680_force_measurement (dev);
if (duration == BME680_NOK) if (duration == BME680_NOK)
return false; // measurment couldn't be started return false; // measurment couldn't be started
else if (duration > 0) // wait for results else if (duration > 0) // wait for results
vTaskDelay (duration); vTaskDelay (duration);
return bme680_get_results_float (dev, results); return bme680_get_results_float (dev, results);
} }
@ -629,7 +629,7 @@ bool bme680_measure_float (bme680_sensor_t* dev, bme680_values_float_t* results)
#define bme_set_reg_bit(byte, bitname, bit) ( (byte & ~bitname##_BITS) | \ #define bme_set_reg_bit(byte, bitname, bit) ( (byte & ~bitname##_BITS) | \
((bit << bitname##_SHIFT) & bitname##_BITS) ) ((bit << bitname##_SHIFT) & bitname##_BITS) )
#define bme_get_reg_bit(byte, bitname) ( (byte & bitname##_BITS) >> bitname##_SHIFT ) #define bme_get_reg_bit(byte, bitname) ( (byte & bitname##_BITS) >> bitname##_SHIFT )
bool bme680_set_oversampling_rates (bme680_sensor_t* dev, bool bme680_set_oversampling_rates (bme680_sensor_t* dev,
bme680_oversampling_rate_t ost, bme680_oversampling_rate_t ost,
bme680_oversampling_rate_t osp, bme680_oversampling_rate_t osp,
@ -642,7 +642,7 @@ bool bme680_set_oversampling_rates (bme680_sensor_t* dev,
bool ost_changed = dev->settings.osr_temperature != ost; bool ost_changed = dev->settings.osr_temperature != ost;
bool osp_changed = dev->settings.osr_pressure != osp; bool osp_changed = dev->settings.osr_pressure != osp;
bool osh_changed = dev->settings.osr_humidity != osh; bool osh_changed = dev->settings.osr_humidity != osh;
if (!ost_changed && !osp_changed && !osh_changed) if (!ost_changed && !osp_changed && !osh_changed)
return true; return true;
@ -650,7 +650,7 @@ bool bme680_set_oversampling_rates (bme680_sensor_t* dev,
dev->settings.osr_temperature = ost; dev->settings.osr_temperature = ost;
dev->settings.osr_pressure = osp; dev->settings.osr_pressure = osp;
dev->settings.osr_humidity = osh; dev->settings.osr_humidity = osh;
uint8_t reg; uint8_t reg;
if (ost_changed || osp_changed) if (ost_changed || osp_changed)
@ -658,7 +658,7 @@ bool bme680_set_oversampling_rates (bme680_sensor_t* dev,
// read the current register value // read the current register value
if (!bme680_read_reg(dev, BME680_REG_CTRL_MEAS, &reg, 1)) if (!bme680_read_reg(dev, BME680_REG_CTRL_MEAS, &reg, 1))
return false; return false;
// set changed bit values // set changed bit values
if (ost_changed) reg = bme_set_reg_bit (reg, BME680_OSR_T, ost); if (ost_changed) reg = bme_set_reg_bit (reg, BME680_OSR_T, ost);
if (osp_changed) reg = bme_set_reg_bit (reg, BME680_OSR_P, osp); if (osp_changed) reg = bme_set_reg_bit (reg, BME680_OSR_P, osp);
@ -667,7 +667,7 @@ bool bme680_set_oversampling_rates (bme680_sensor_t* dev,
if (!bme680_write_reg(dev, BME680_REG_CTRL_MEAS, &reg, 1)) if (!bme680_write_reg(dev, BME680_REG_CTRL_MEAS, &reg, 1))
return false; return false;
} }
if (osh_changed) if (osh_changed)
{ {
// read the current register value // read the current register value
@ -676,18 +676,18 @@ bool bme680_set_oversampling_rates (bme680_sensor_t* dev,
// set changed bit value // set changed bit value
reg = bme_set_reg_bit (reg, BME680_OSR_H, osh); reg = bme_set_reg_bit (reg, BME680_OSR_H, osh);
// write back the new register value // write back the new register value
if (!bme680_write_reg(dev, BME680_REG_CTRL_HUM, &reg, 1)) if (!bme680_write_reg(dev, BME680_REG_CTRL_HUM, &reg, 1))
return false; return false;
} }
debug_dev ("Setting oversampling rates done: osrt=%d osp=%d osrh=%d", debug_dev ("Setting oversampling rates done: osrt=%d osp=%d osrh=%d",
__FUNCTION__, dev, __FUNCTION__, dev,
dev->settings.osr_temperature, dev->settings.osr_temperature,
dev->settings.osr_pressure, dev->settings.osr_pressure,
dev->settings.osr_humidity); dev->settings.osr_humidity);
return true; return true;
} }
@ -699,7 +699,7 @@ bool bme680_set_filter_size(bme680_sensor_t* dev, bme680_filter_size_t size)
dev->error_code = BME680_OK; dev->error_code = BME680_OK;
bool size_changed = dev->settings.filter_size != size; bool size_changed = dev->settings.filter_size != size;
if (!size_changed) return true; if (!size_changed) return true;
/* Set the temperature, pressure and humidity settings */ /* Set the temperature, pressure and humidity settings */
@ -713,18 +713,18 @@ bool bme680_set_filter_size(bme680_sensor_t* dev, bme680_filter_size_t size)
// set changed bit value // set changed bit value
reg = bme_set_reg_bit (reg, BME680_FILTER, size); reg = bme_set_reg_bit (reg, BME680_FILTER, size);
// write back the new register value // write back the new register value
if (!bme680_write_reg(dev, BME680_REG_CONFIG, &reg, 1)) if (!bme680_write_reg(dev, BME680_REG_CONFIG, &reg, 1))
return false; return false;
debug_dev ("Setting filter size done: size=%d", __FUNCTION__, dev, debug_dev ("Setting filter size done: size=%d", __FUNCTION__, dev,
dev->settings.filter_size); dev->settings.filter_size);
return true; return true;
} }
bool bme680_set_heater_profile (bme680_sensor_t* dev, uint8_t profile, bool bme680_set_heater_profile (bme680_sensor_t* dev, uint8_t profile,
uint16_t temperature, uint16_t duration) uint16_t temperature, uint16_t duration)
{ {
if (!dev) return false; if (!dev) return false;
@ -751,23 +751,23 @@ bool bme680_set_heater_profile (bme680_sensor_t* dev, uint8_t profile,
// compute internal gas sensor configuration parameters // compute internal gas sensor configuration parameters
uint8_t heat_dur = bme680_heater_duration(duration); // internal duration value uint8_t heat_dur = bme680_heater_duration(duration); // internal duration value
uint8_t heat_res = bme680_heater_resistance(dev, temperature); // internal temperature value uint8_t heat_res = bme680_heater_resistance(dev, temperature); // internal temperature value
// set internal gas sensor configuration parameters if changed // set internal gas sensor configuration parameters if changed
if (temperature_changed && if (temperature_changed &&
!bme680_write_reg(dev, BME680_REG_RES_HEAT_BASE+profile, &heat_res, 1)) !bme680_write_reg(dev, BME680_REG_RES_HEAT_BASE+profile, &heat_res, 1))
return false; return false;
if (duration_changed && if (duration_changed &&
!bme680_write_reg(dev, BME680_REG_GAS_WAIT_BASE+profile, &heat_dur, 1)) !bme680_write_reg(dev, BME680_REG_GAS_WAIT_BASE+profile, &heat_dur, 1))
return false; return false;
debug_dev ("Setting heater profile %d done: temperature=%d duration=%d " debug_dev ("Setting heater profile %d done: temperature=%d duration=%d "
"heater_resistance=%02x heater_duration=%02x", "heater_resistance=%02x heater_duration=%02x",
__FUNCTION__, dev, profile, __FUNCTION__, dev, profile,
dev->settings.heater_temperature[profile], dev->settings.heater_temperature[profile],
dev->settings.heater_duration[profile], dev->settings.heater_duration[profile],
heat_dur, heat_res); heat_dur, heat_res);
return true; return true;
} }
@ -784,21 +784,21 @@ bool bme680_use_heater_profile (bme680_sensor_t* dev, int8_t profile)
if (dev->settings.heater_profile == profile) if (dev->settings.heater_profile == profile)
return false; return false;
dev->settings.heater_profile = profile; dev->settings.heater_profile = profile;
uint8_t reg = 0; // set uint8_t reg = 0; // set
// set active profile // set active profile
reg = bme_set_reg_bit (reg, BME680_NB_CONV, profile != BME680_HEATER_NOT_USED ? profile : 0); reg = bme_set_reg_bit (reg, BME680_NB_CONV, profile != BME680_HEATER_NOT_USED ? profile : 0);
// enable or disable gas measurement // enable or disable gas measurement
reg = bme_set_reg_bit (reg, BME680_RUN_GAS, (profile != BME680_HEATER_NOT_USED && reg = bme_set_reg_bit (reg, BME680_RUN_GAS, (profile != BME680_HEATER_NOT_USED &&
dev->settings.heater_temperature[profile] && dev->settings.heater_temperature[profile] &&
dev->settings.heater_duration[profile])); dev->settings.heater_duration[profile]));
if (!bme680_write_reg(dev, BME680_REG_CTRL_GAS_1, &reg, 1)) if (!bme680_write_reg(dev, BME680_REG_CTRL_GAS_1, &reg, 1))
return false; return false;
return true; return true;
} }
@ -816,15 +816,15 @@ bool bme680_set_ambient_temperature (bme680_sensor_t* dev, int16_t ambient)
// set ambient temperature configuration // set ambient temperature configuration
dev->settings.ambient_temperature = ambient; // degree Celsius dev->settings.ambient_temperature = ambient; // degree Celsius
// update all valid heater profiles // update all valid heater profiles
// takes 894 us for only one defined profile and 1585 us for 10 defined profiles // takes 894 us for only one defined profile and 1585 us for 10 defined profiles
uint8_t data[10]; uint8_t data[10];
for (int i = 0; i < BME680_HEATER_PROFILES; i++) for (int i = 0; i < BME680_HEATER_PROFILES; i++)
{ {
data[i] = dev->settings.heater_temperature[i] ? data[i] = dev->settings.heater_temperature[i] ?
bme680_heater_resistance(dev, dev->settings.heater_temperature[i]) : 0; bme680_heater_resistance(dev, dev->settings.heater_temperature[i]) : 0;
} }
if (!bme680_write_reg(dev, BME680_REG_RES_HEAT_BASE, data, 10)) if (!bme680_write_reg(dev, BME680_REG_RES_HEAT_BASE, data, 10))
@ -835,31 +835,31 @@ bool bme680_set_ambient_temperature (bme680_sensor_t* dev, int16_t ambient)
for (int i = 0; i < BME680_HEATER_PROFILES; i++) for (int i = 0; i < BME680_HEATER_PROFILES; i++)
if (dev->settings.heater_temperature[i]) if (dev->settings.heater_temperature[i])
{ {
uint8_t heat_res = bme680_heater_resistance(dev, dev->settings.heater_temperature[i]); uint8_t heat_res = bme680_heater_resistance(dev, dev->settings.heater_temperature[i]);
if (!bme680_write_reg(dev, BME680_REG_RES_HEAT_BASE+i, &heat_res, 1)) if (!bme680_write_reg(dev, BME680_REG_RES_HEAT_BASE+i, &heat_res, 1))
return false; return false;
} }
*/ */
debug_dev ("Setting heater ambient temperature done: ambient=%d", debug_dev ("Setting heater ambient temperature done: ambient=%d",
__FUNCTION__, dev, dev->settings.ambient_temperature); __FUNCTION__, dev, dev->settings.ambient_temperature);
return true; return true;
} }
bool bme680_set_mode (bme680_sensor_t *dev, uint8_t mode) bool bme680_set_mode (bme680_sensor_t *dev, uint8_t mode)
{ {
if (!dev) return false; if (!dev) return false;
dev->error_code = BME680_OK; dev->error_code = BME680_OK;
uint8_t reg; uint8_t reg;
if (!bme680_read_reg(dev, BME680_REG_CTRL_MEAS, &reg, 1)) if (!bme680_read_reg(dev, BME680_REG_CTRL_MEAS, &reg, 1))
return false; return false;
reg = bme_set_reg_bit (reg, BME680_MODE, mode); reg = bme_set_reg_bit (reg, BME680_MODE, mode);
if (!bme680_write_reg(dev, BME680_REG_CTRL_MEAS, &reg, 1)) if (!bme680_write_reg(dev, BME680_REG_CTRL_MEAS, &reg, 1))
return false; return false;
@ -877,19 +877,19 @@ static bool bme680_is_available (bme680_sensor_t* dev)
uint8_t chip_id; uint8_t chip_id;
if (!dev) return false; if (!dev) return false;
dev->error_code = BME680_OK; dev->error_code = BME680_OK;
if (!bme680_read_reg (dev, BME680_REG_ID, &chip_id, 1)) if (!bme680_read_reg (dev, BME680_REG_ID, &chip_id, 1))
return false; return false;
if (chip_id != 0x61) if (chip_id != 0x61)
{ {
error_dev ("Chip id %02x is wrong, should be 0x61.", __FUNCTION__, dev, chip_id); error_dev ("Chip id %02x is wrong, should be 0x61.", __FUNCTION__, dev, chip_id);
dev->error_code = BME680_WRONG_CHIP_ID; dev->error_code = BME680_WRONG_CHIP_ID;
return false; return false;
} }
return true; return true;
} }
@ -897,7 +897,7 @@ static bool bme680_is_available (bme680_sensor_t* dev)
static bool bme680_reset (bme680_sensor_t* dev) static bool bme680_reset (bme680_sensor_t* dev)
{ {
if (!dev) return false; if (!dev) return false;
dev->error_code = BME680_OK; dev->error_code = BME680_OK;
uint8_t reg = BME680_RESET_CMD; uint8_t reg = BME680_RESET_CMD;
@ -905,7 +905,7 @@ static bool bme680_reset (bme680_sensor_t* dev)
// send reset command // send reset command
if (!bme680_write_reg(dev, BME680_REG_RESET, &reg, 1)) if (!bme680_write_reg(dev, BME680_REG_RESET, &reg, 1))
return false; return false;
// wait the time the sensor needs for reset // wait the time the sensor needs for reset
bme680_delay_ms (BME680_RESET_PERIOD); bme680_delay_ms (BME680_RESET_PERIOD);
@ -929,15 +929,15 @@ static int16_t bme680_convert_temperature (bme680_sensor_t *dev, uint32_t raw_te
if (!dev) return 0; if (!dev) return 0;
bme680_calib_data_t* cd = &dev->calib_data; bme680_calib_data_t* cd = &dev->calib_data;
int64_t var1; int64_t var1;
int64_t var2; int64_t var2;
int16_t temperature; int16_t temperature;
var1 = ((((raw_temperature >> 3) - ((int32_t)cd->par_t1 << 1))) * var1 = ((((raw_temperature >> 3) - ((int32_t)cd->par_t1 << 1))) *
((int32_t)cd->par_t2)) >> 11; ((int32_t)cd->par_t2)) >> 11;
var2 = (((((raw_temperature >> 4) - ((int32_t)cd->par_t1)) * var2 = (((((raw_temperature >> 4) - ((int32_t)cd->par_t1)) *
((raw_temperature >> 4) - ((int32_t)cd->par_t1))) >> 12) * ((raw_temperature >> 4) - ((int32_t)cd->par_t1))) >> 12) *
((int32_t)cd->par_t3)) >> 14; ((int32_t)cd->par_t3)) >> 14;
cd->t_fine = (int32_t)(var1 + var2); cd->t_fine = (int32_t)(var1 + var2);
temperature = (cd->t_fine * 5 + 128) >> 8; temperature = (cd->t_fine * 5 + 128) >> 8;
@ -968,13 +968,13 @@ static uint32_t bme680_convert_pressure (bme680_sensor_t *dev, uint32_t raw_pres
int32_t var3; int32_t var3;
int32_t var4; int32_t var4;
int32_t pressure; int32_t pressure;
var1 = (((int32_t) cd->t_fine) >> 1) - 64000; var1 = (((int32_t) cd->t_fine) >> 1) - 64000;
var2 = ((((var1 >> 2) * (var1 >> 2)) >> 11) * (int32_t) cd->par_p6) >> 2; var2 = ((((var1 >> 2) * (var1 >> 2)) >> 11) * (int32_t) cd->par_p6) >> 2;
var2 = ((var2) * (int32_t) cd->par_p6) >> 2; var2 = ((var2) * (int32_t) cd->par_p6) >> 2;
var2 = var2 + ((var1 * (int32_t)cd->par_p5) << 1); var2 = var2 + ((var1 * (int32_t)cd->par_p5) << 1);
var2 = (var2 >> 2) + ((int32_t) cd->par_p4 << 16); var2 = (var2 >> 2) + ((int32_t) cd->par_p4 << 16);
var1 = (((var1 >> 2) * (var1 >> 2)) >> 13); var1 = (((var1 >> 2) * (var1 >> 2)) >> 13);
var1 = (((var1) * ((int32_t) cd->par_p3 << 5)) >> 3) + (((int32_t) cd->par_p2 * var1) >> 1); var1 = (((var1) * ((int32_t) cd->par_p3 << 5)) >> 3) + (((int32_t) cd->par_p2 * var1) >> 1);
var1 = var1 >> 18; var1 = var1 >> 18;
var1 = ((32768 + var1) * (int32_t) cd->par_p1) >> 15; var1 = ((32768 + var1) * (int32_t) cd->par_p1) >> 15;
@ -985,8 +985,8 @@ static uint32_t bme680_convert_pressure (bme680_sensor_t *dev, uint32_t raw_pres
: ((pressure << 1) / (uint32_t) var1); : ((pressure << 1) / (uint32_t) var1);
var1 = ((int32_t) cd->par_p9 * (int32_t) (((pressure >> 3) * (pressure >> 3)) >> 13)) >> 12; var1 = ((int32_t) cd->par_p9 * (int32_t) (((pressure >> 3) * (pressure >> 3)) >> 13)) >> 12;
var2 = ((int32_t)(pressure >> 2) * (int32_t) cd->par_p8) >> 13; var2 = ((int32_t)(pressure >> 2) * (int32_t) cd->par_p8) >> 13;
var3 = ((int32_t)(pressure >> 8) * (int32_t)(pressure >> 8) var3 = ((int32_t)(pressure >> 8) * (int32_t)(pressure >> 8)
* (int32_t)(pressure >> 8) * (int32_t)(pressure >> 8)
* (int32_t)cd->par_p10) >> 17; * (int32_t)cd->par_p10) >> 17;
pressure = (int32_t)(pressure) + ((var1 + var2 + var3 + ((int32_t)cd->par_p7 << 7)) >> 4); pressure = (int32_t)(pressure) + ((var1 + var2 + var3 + ((int32_t)cd->par_p7 << 7)) >> 4);
@ -1008,7 +1008,7 @@ static uint32_t bme680_convert_humidity (bme680_sensor_t *dev, uint16_t raw_humi
if (!dev) return 0; if (!dev) return 0;
bme680_calib_data_t* cd = &dev->calib_data; bme680_calib_data_t* cd = &dev->calib_data;
int32_t var1; int32_t var1;
int32_t var2; int32_t var2;
int32_t var3; int32_t var3;
@ -1019,9 +1019,9 @@ static uint32_t bme680_convert_humidity (bme680_sensor_t *dev, uint16_t raw_humi
int32_t humidity; int32_t humidity;
temp_scaled = (((int32_t) cd->t_fine * 5) + 128) >> 8; temp_scaled = (((int32_t) cd->t_fine * 5) + 128) >> 8;
var1 = (int32_t) (raw_humidity - ((int32_t) ((int32_t) cd->par_h1 << 4))) - var1 = (int32_t) (raw_humidity - ((int32_t) ((int32_t) cd->par_h1 << 4))) -
(((temp_scaled * (int32_t) cd->par_h3) / ((int32_t) 100)) >> 1); (((temp_scaled * (int32_t) cd->par_h3) / ((int32_t) 100)) >> 1);
var2 = ((int32_t) cd->par_h2 * var2 = ((int32_t) cd->par_h2 *
(((temp_scaled * (int32_t) cd->par_h4) / ((int32_t) 100)) + (((temp_scaled * (int32_t) cd->par_h4) / ((int32_t) 100)) +
(((temp_scaled * ((temp_scaled * (int32_t) cd->par_h5) / ((int32_t) 100))) >> 6) / (((temp_scaled * ((temp_scaled * (int32_t) cd->par_h5) / ((int32_t) 100))) >> 6) /
((int32_t) 100)) + (int32_t) (1 << 14))) >> 10; ((int32_t) 100)) + (int32_t) (1 << 14))) >> 10;
@ -1073,7 +1073,7 @@ static uint32_t bme680_convert_gas (bme680_sensor_t *dev, uint16_t gas, uint8_t
if (!dev) return 0; if (!dev) return 0;
bme680_calib_data_t* cd = &dev->calib_data; bme680_calib_data_t* cd = &dev->calib_data;
float var1 = (1340.0 + 5.0 * cd->range_sw_err) * lookup_table[gas_range][0]; float var1 = (1340.0 + 5.0 * cd->range_sw_err) * lookup_table[gas_range][0];
return var1 * lookup_table[gas_range][1] / (gas - 512.0 + var1); return var1 * lookup_table[gas_range][1] / (gas - 512.0 + var1);
} }
@ -1082,7 +1082,7 @@ static uint32_t bme680_convert_gas (bme680_sensor_t *dev, uint16_t gas, uint8_t
#define msb_lsb_to_type(t,b,o) (t)(((t)b[o] << 8) | b[o+1]) #define msb_lsb_to_type(t,b,o) (t)(((t)b[o] << 8) | b[o+1])
#define BME680_RAW_P_OFF BME680_REG_PRESS_MSB_0-BME680_REG_MEAS_STATUS_0 #define BME680_RAW_P_OFF BME680_REG_PRESS_MSB_0-BME680_REG_MEAS_STATUS_0
#define BME680_RAW_T_OFF (BME680_RAW_P_OFF + BME680_REG_TEMP_MSB_0 - BME680_REG_PRESS_MSB_0) #define BME680_RAW_T_OFF (BME680_RAW_P_OFF + BME680_REG_TEMP_MSB_0 - BME680_REG_PRESS_MSB_0)
#define BME680_RAW_H_OFF (BME680_RAW_T_OFF + BME680_REG_HUM_MSB_0 - BME680_REG_TEMP_MSB_0) #define BME680_RAW_H_OFF (BME680_RAW_T_OFF + BME680_REG_HUM_MSB_0 - BME680_REG_TEMP_MSB_0)
#define BME680_RAW_G_OFF (BME680_RAW_H_OFF + BME680_REG_GAS_R_MSB_0 - BME680_REG_HUM_MSB_0) #define BME680_RAW_G_OFF (BME680_RAW_H_OFF + BME680_REG_GAS_R_MSB_0 - BME680_REG_HUM_MSB_0)
@ -1109,7 +1109,7 @@ static bool bme680_get_raw_data(bme680_sensor_t *dev, bme680_raw_data_t* raw_dat
error_dev ("Could not read measurement status from sensor.", __FUNCTION__, dev); error_dev ("Could not read measurement status from sensor.", __FUNCTION__, dev);
return false; return false;
} }
dev->meas_status = raw[0]; dev->meas_status = raw[0];
if (dev->meas_status & BME680_MEASURING_BITS) if (dev->meas_status & BME680_MEASURING_BITS)
{ {
@ -1117,7 +1117,7 @@ static bool bme680_get_raw_data(bme680_sensor_t *dev, bme680_raw_data_t* raw_dat
dev->error_code = BME680_MEAS_STILL_RUNNING; dev->error_code = BME680_MEAS_STILL_RUNNING;
return false; return false;
} }
// test whether there are new data // test whether there are new data
if (!(dev->meas_status & BME680_NEW_DATA_BITS)) if (!(dev->meas_status & BME680_NEW_DATA_BITS))
{ {
@ -1131,7 +1131,7 @@ static bool bme680_get_raw_data(bme680_sensor_t *dev, bme680_raw_data_t* raw_dat
raw_data->gas_index = (dev->meas_status & BME680_GAS_MEAS_INDEX_BITS); raw_data->gas_index = (dev->meas_status & BME680_GAS_MEAS_INDEX_BITS);
// if there are new data, read raw data from sensor // if there are new data, read raw data from sensor
if (!bme680_read_reg(dev, BME680_REG_RAW_DATA_0, raw, BME680_REG_RAW_DATA_LEN)) if (!bme680_read_reg(dev, BME680_REG_RAW_DATA_0, raw, BME680_REG_RAW_DATA_LEN))
{ {
error_dev ("Could not read raw data from sensor.", __FUNCTION__, dev); error_dev ("Could not read raw data from sensor.", __FUNCTION__, dev);
@ -1161,11 +1161,11 @@ static bool bme680_get_raw_data(bme680_sensor_t *dev, bme680_raw_data_t* raw_dat
return false; return false;
} }
*/ */
debug ("Raw data: %d %d %d %d %d",__FUNCTION__, debug ("Raw data: %d %d %d %d %d",__FUNCTION__,
raw_data->temperature, raw_data->pressure, raw_data->temperature, raw_data->pressure,
raw_data->humidity, raw_data->gas_resistance, raw_data->gas_range); raw_data->humidity, raw_data->gas_resistance, raw_data->gas_range);
return true; return true;
} }
@ -1176,7 +1176,7 @@ static bool bme680_get_raw_data(bme680_sensor_t *dev, bme680_raw_data_t* raw_dat
* *
* duration = value<5:0> * multiplier<7:6> * duration = value<5:0> * multiplier<7:6>
* *
* where the multiplier is 1, 4, 16, or 64. Maximum duration is therefore * where the multiplier is 1, 4, 16, or 64. Maximum duration is therefore
* 64*64 = 4032 ms. The function takes a real world duration value given * 64*64 = 4032 ms. The function takes a real world duration value given
* in milliseconds and computes the internal representation. * in milliseconds and computes the internal representation.
* *
@ -1186,7 +1186,7 @@ static uint8_t bme680_heater_duration (uint16_t duration)
{ {
uint8_t multiplier = 0; uint8_t multiplier = 0;
while (duration > 63) while (duration > 63)
{ {
duration = duration / 4; duration = duration / 4;
multiplier++; multiplier++;
@ -1218,23 +1218,23 @@ static uint8_t bme680_heater_resistance (const bme680_sensor_t *dev, uint16_t te
double var4; double var4;
double var5; double var5;
uint8_t res_heat_x; uint8_t res_heat_x;
var1 = ((double)cd->par_gh1 / 16.0) + 49.0; var1 = ((double)cd->par_gh1 / 16.0) + 49.0;
var2 = (((double)cd->par_gh2 / 32768.0) * 0.0005) + 0.00235; var2 = (((double)cd->par_gh2 / 32768.0) * 0.0005) + 0.00235;
var3 = (double)cd->par_gh3 / 1024.0; var3 = (double)cd->par_gh3 / 1024.0;
var4 = var1 * (1.0 + (var2 * (double) temp)); var4 = var1 * (1.0 + (var2 * (double) temp));
var5 = var4 + (var3 * (double)dev->settings.ambient_temperature); var5 = var4 + (var3 * (double)dev->settings.ambient_temperature);
res_heat_x = (uint8_t)(3.4 * ((var5 * (4.0 / (4.0 + (double)cd->res_heat_range)) * res_heat_x = (uint8_t)(3.4 * ((var5 * (4.0 / (4.0 + (double)cd->res_heat_range)) *
(1.0/(1.0 + ((double)cd->res_heat_val * 0.002)))) - 25)); (1.0/(1.0 + ((double)cd->res_heat_val * 0.002)))) - 25));
return res_heat_x; return res_heat_x;
} }
static void bme680_delay_ms(uint32_t period) static void bme680_delay_ms(uint32_t period)
{ {
uint32_t start_time = sdk_system_get_time () / 1000; uint32_t start_time = sdk_system_get_time () / 1000;
vTaskDelay((period + portTICK_PERIOD_MS-1) / portTICK_PERIOD_MS); vTaskDelay((period + portTICK_PERIOD_MS-1) / portTICK_PERIOD_MS);
while (sdk_system_get_time()/1000 - start_time < period) while (sdk_system_get_time()/1000 - start_time < period)
@ -1256,7 +1256,7 @@ static const spi_settings_t bus_settings = {
static bool bme680_read_reg(bme680_sensor_t* dev, uint8_t reg, uint8_t *data, uint16_t len) static bool bme680_read_reg(bme680_sensor_t* dev, uint8_t reg, uint8_t *data, uint16_t len)
{ {
if (!dev || !data) return false; if (!dev || !data) return false;
return (dev->addr) ? bme680_i2c_read (dev, reg, data, len) return (dev->addr) ? bme680_i2c_read (dev, reg, data, len)
: bme680_spi_read (dev, reg, data, len); : bme680_spi_read (dev, reg, data, len);
} }
@ -1265,7 +1265,7 @@ static bool bme680_read_reg(bme680_sensor_t* dev, uint8_t reg, uint8_t *data, ui
static bool bme680_write_reg(bme680_sensor_t* dev, uint8_t reg, uint8_t *data, uint16_t len) static bool bme680_write_reg(bme680_sensor_t* dev, uint8_t reg, uint8_t *data, uint16_t len)
{ {
if (!dev || !data) return false; if (!dev || !data) return false;
return (dev->addr) ? bme680_i2c_write (dev, reg, data, len) return (dev->addr) ? bme680_i2c_write (dev, reg, data, len)
: bme680_spi_write (dev, reg, data, len); : bme680_spi_write (dev, reg, data, len);
} }
@ -1277,18 +1277,18 @@ static bool bme680_write_reg(bme680_sensor_t* dev, uint8_t reg, uint8_t *data, u
static bool bme680_spi_set_mem_page (bme680_sensor_t* dev, uint8_t reg) static bool bme680_spi_set_mem_page (bme680_sensor_t* dev, uint8_t reg)
{ {
// mem pages (reg 0x00 .. 0x7f = 1, reg 0x80 ... 0xff = 0 // mem pages (reg 0x00 .. 0x7f = 1, reg 0x80 ... 0xff = 0
uint8_t mem_page = (reg < 0x80) ? BME680_BIT_SWITCH_MEM_PAGE_1 uint8_t mem_page = (reg < 0x80) ? BME680_BIT_SWITCH_MEM_PAGE_1
: BME680_BIT_SWITCH_MEM_PAGE_0; : BME680_BIT_SWITCH_MEM_PAGE_0;
debug_dev ("Set mem page for register %02x to %d.", __FUNCTION__, dev, reg, mem_page); debug_dev ("Set mem page for register %02x to %d.", __FUNCTION__, dev, reg, mem_page);
if (!bme680_spi_write (dev, BME680_REG_SWITCH_MEM_PAGE, &mem_page, 1)) if (!bme680_spi_write (dev, BME680_REG_SWITCH_MEM_PAGE, &mem_page, 1))
{ {
dev->error_code |= BME680_SPI_SET_PAGE_FAILED; dev->error_code |= BME680_SPI_SET_PAGE_FAILED;
return false; return false;
} }
// sdk_os_delay_us (100); // sdk_os_delay_us (100);
return true; return true;
} }
@ -1301,7 +1301,7 @@ static bool bme680_spi_read(bme680_sensor_t* dev, uint8_t reg, uint8_t *data, ui
{ {
dev->error_code |= BME680_SPI_BUFFER_OVERFLOW; dev->error_code |= BME680_SPI_BUFFER_OVERFLOW;
error_dev ("Error on read from SPI slave on bus 1. Tried to transfer " error_dev ("Error on read from SPI slave on bus 1. Tried to transfer "
"more than %d byte in one read operation.", "more than %d byte in one read operation.",
__FUNCTION__, dev, BME680_SPI_BUF_SIZE); __FUNCTION__, dev, BME680_SPI_BUF_SIZE);
return false; return false;
} }
@ -1309,24 +1309,24 @@ static bool bme680_spi_read(bme680_sensor_t* dev, uint8_t reg, uint8_t *data, ui
// set mem page first // set mem page first
if (!bme680_spi_set_mem_page (dev, reg)) if (!bme680_spi_set_mem_page (dev, reg))
{ {
error_dev ("Error on read from SPI slave on bus 1. Could not set mem page.", error_dev ("Error on read from SPI slave on bus 1. Could not set mem page.",
__FUNCTION__, dev); __FUNCTION__, dev);
return false; return false;
} }
reg &= 0x7f; reg &= 0x7f;
reg |= 0x80; reg |= 0x80;
spi_settings_t old_settings; spi_settings_t old_settings;
static uint8_t mosi[BME680_SPI_BUF_SIZE]; static uint8_t mosi[BME680_SPI_BUF_SIZE];
static uint8_t miso[BME680_SPI_BUF_SIZE]; static uint8_t miso[BME680_SPI_BUF_SIZE];
memset (mosi, 0xff, BME680_SPI_BUF_SIZE); memset (mosi, 0xff, BME680_SPI_BUF_SIZE);
memset (miso, 0xff, BME680_SPI_BUF_SIZE); memset (miso, 0xff, BME680_SPI_BUF_SIZE);
mosi[0] = reg; mosi[0] = reg;
spi_get_settings(dev->bus, &old_settings); spi_get_settings(dev->bus, &old_settings);
spi_set_settings(dev->bus, &bus_settings); spi_set_settings(dev->bus, &bus_settings);
gpio_write(dev->spi_cs_pin, false); gpio_write(dev->spi_cs_pin, false);
@ -1342,19 +1342,19 @@ static bool bme680_spi_read(bme680_sensor_t* dev, uint8_t reg, uint8_t *data, ui
dev->error_code |= BME680_SPI_READ_FAILED; dev->error_code |= BME680_SPI_READ_FAILED;
return false; return false;
} }
// shift data one by left, first byte received while sending register address is invalid // shift data one by left, first byte received while sending register address is invalid
for (int i=0; i < len; i++) for (int i=0; i < len; i++)
data[i] = miso[i+1]; data[i] = miso[i+1];
# ifdef BME680_DEBUG_LEVEL_2 # ifdef BME680_DEBUG_LEVEL_2
printf("BME680 %s: read the following bytes: ", __FUNCTION__); printf("BME680 %s: read the following bytes: ", __FUNCTION__);
printf("%0x ", reg); printf("%0x ", reg);
for (int i=0; i < len; i++) for (int i=0; i < len; i++)
printf("%0x ", data[i]); printf("%0x ", data[i]);
printf("\n"); printf("\n");
# endif # endif
return true; return true;
} }
@ -1364,33 +1364,33 @@ static bool bme680_spi_write(bme680_sensor_t* dev, uint8_t reg, uint8_t *data, u
if (!dev || !data) return false; if (!dev || !data) return false;
static uint8_t mosi[BME680_SPI_BUF_SIZE]; static uint8_t mosi[BME680_SPI_BUF_SIZE];
if (len >= BME680_SPI_BUF_SIZE) if (len >= BME680_SPI_BUF_SIZE)
{ {
dev->error_code |= BME680_SPI_BUFFER_OVERFLOW; dev->error_code |= BME680_SPI_BUFFER_OVERFLOW;
error_dev ("Error on write to SPI slave on bus 1. Tried to transfer more" error_dev ("Error on write to SPI slave on bus 1. Tried to transfer more"
"than %d byte in one write operation.", __FUNCTION__, dev, BME680_SPI_BUF_SIZE); "than %d byte in one write operation.", __FUNCTION__, dev, BME680_SPI_BUF_SIZE);
return false; return false;
} }
// set mem page first if not mem page register is used // set mem page first if not mem page register is used
if (reg != BME680_REG_STATUS && !bme680_spi_set_mem_page (dev, reg)) if (reg != BME680_REG_STATUS && !bme680_spi_set_mem_page (dev, reg))
{ {
error_dev ("Error on write from SPI slave on bus 1. Could not set mem page.", error_dev ("Error on write from SPI slave on bus 1. Could not set mem page.",
__FUNCTION__, dev); __FUNCTION__, dev);
return false; return false;
} }
reg &= 0x7f; reg &= 0x7f;
// first byte in output is the register address // first byte in output is the register address
mosi[0] = reg; mosi[0] = reg;
// shift data one byte right, first byte in output is the register address // shift data one byte right, first byte in output is the register address
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
mosi[i+1] = data[i]; mosi[i+1] = data[i];
# ifdef BME680_DEBUG_LEVEL_2 # ifdef BME680_DEBUG_LEVEL_2
printf("BME680 %s: Write the following bytes: ", __FUNCTION__); printf("BME680 %s: Write the following bytes: ", __FUNCTION__);
for (int i = 0; i < len+1; i++) for (int i = 0; i < len+1; i++)
@ -1399,7 +1399,7 @@ static bool bme680_spi_write(bme680_sensor_t* dev, uint8_t reg, uint8_t *data, u
# endif # endif
spi_settings_t old_settings; spi_settings_t old_settings;
spi_get_settings(dev->bus, &old_settings); spi_get_settings(dev->bus, &old_settings);
spi_set_settings(dev->bus, &bus_settings); spi_set_settings(dev->bus, &bus_settings);
gpio_write(dev->spi_cs_pin, false); gpio_write(dev->spi_cs_pin, false);
@ -1434,7 +1434,7 @@ static bool bme680_i2c_read(bme680_sensor_t* dev, uint8_t reg, uint8_t *data, ui
if (result) if (result)
{ {
dev->error_code |= (result == -EBUSY) ? BME680_I2C_BUSY : BME680_I2C_READ_FAILED; dev->error_code |= (result == -EBUSY) ? BME680_I2C_BUSY : BME680_I2C_READ_FAILED;
error_dev ("Error %d on read %d byte from I2C slave register %02x.", error_dev ("Error %d on read %d byte from I2C slave register %02x.",
__FUNCTION__, dev, result, len, reg); __FUNCTION__, dev, result, len, reg);
return false; return false;
} }
@ -1454,7 +1454,7 @@ static bool bme680_i2c_read(bme680_sensor_t* dev, uint8_t reg, uint8_t *data, ui
static bool bme680_i2c_write(bme680_sensor_t* dev, uint8_t reg, uint8_t *data, uint16_t len) static bool bme680_i2c_write(bme680_sensor_t* dev, uint8_t reg, uint8_t *data, uint16_t len)
{ {
if (!dev || !data) return false; if (!dev || !data) return false;
debug_dev ("Write %d byte to i2c slave register %02x.", __FUNCTION__, dev, len, reg); debug_dev ("Write %d byte to i2c slave register %02x.", __FUNCTION__, dev, len, reg);
int result; int result;
@ -1466,7 +1466,7 @@ static bool bme680_i2c_write(bme680_sensor_t* dev, uint8_t reg, uint8_t *data, u
if (result) if (result)
{ {
dev->error_code |= (result == -EBUSY) ? BME680_I2C_BUSY : BME680_I2C_WRITE_FAILED; dev->error_code |= (result == -EBUSY) ? BME680_I2C_BUSY : BME680_I2C_WRITE_FAILED;
error_dev ("Error %d on write %d byte to i2c slave register %02x.", error_dev ("Error %d on write %d byte to i2c slave register %02x.",
__FUNCTION__, dev, result, len, reg); __FUNCTION__, dev, result, len, reg);
return false; return false;
} }
@ -1478,8 +1478,6 @@ static bool bme680_i2c_write(bme680_sensor_t* dev, uint8_t reg, uint8_t *data, u
printf("%0x ", data[i]); printf("%0x ", data[i]);
printf("\n"); printf("\n");
# endif # endif
return true; return true;
} }

View file

@ -13,7 +13,7 @@
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* 1. Redistributions of source code must retain the above copyright notice, * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
* *
@ -21,7 +21,7 @@
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* 3. Neither the name of the copyright holder nor the names of its * 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this * contributors may be used to endorse or promote products derived from this
* software without specific prior written permission. * software without specific prior written permission.
* *
@ -29,7 +29,7 @@
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
@ -71,7 +71,7 @@
#define BME680_SPI_SET_PAGE_FAILED 7 #define BME680_SPI_SET_PAGE_FAILED 7
// BME680 driver error codes ORed with error codes for I2C and SPI interfaces // BME680 driver error codes ORed with error codes for I2C and SPI interfaces
#define BME680_RESET_CMD_FAILED ( 1 << 8) #define BME680_RESET_CMD_FAILED ( 1 << 8)
#define BME680_WRONG_CHIP_ID ( 2 << 8) #define BME680_WRONG_CHIP_ID ( 2 << 8)
#define BME680_READ_CALIB_DATA_FAILED ( 3 << 8) #define BME680_READ_CALIB_DATA_FAILED ( 3 << 8)
#define BME680_MEAS_ALREADY_RUNNING ( 4 << 8) #define BME680_MEAS_ALREADY_RUNNING ( 4 << 8)
@ -118,11 +118,11 @@ extern "C"
/** /**
* @brief Initialize a BME680 sensor * @brief Initialize a BME680 sensor
* *
* The function initializes the sensor device data structure, probes the * The function initializes the sensor device data structure, probes the
* sensor, soft resets the sensor, and configures the sensor with the * sensor, soft resets the sensor, and configures the sensor with the
* the following default settings: * the following default settings:
* *
* - Oversampling rate for temperature, pressure, humidity is osr_1x * - Oversampling rate for temperature, pressure, humidity is osr_1x
* - Filter size for pressure and temperature is iir_size 3 * - Filter size for pressure and temperature is iir_size 3
* - Heater profile 0 with 320 degree C and 150 ms duration * - Heater profile 0 with 320 degree C and 150 ms duration
@ -137,7 +137,7 @@ extern "C"
* ignored. * ignored.
* *
* If parameter *addr* is 0, the sensor is connected to a SPI bus. In that * If parameter *addr* is 0, the sensor is connected to a SPI bus. In that
* case, parameter *cs* defines the GPIO used as CS signal * case, parameter *cs* defines the GPIO used as CS signal
* *
* @param bus I2C or SPI bus at which BME680 sensor is connected * @param bus I2C or SPI bus at which BME680 sensor is connected
* @param addr I2C addr of the BME680 sensor, 0 for SPI * @param addr I2C addr of the BME680 sensor, 0 for SPI
@ -189,7 +189,7 @@ uint32_t bme680_get_measurement_duration (const bme680_sensor_t *dev);
* *
* The function can be used to test whether a measurement that was started * The function can be used to test whether a measurement that was started
* before is still running. * before is still running.
* *
* @param dev pointer to the sensor device data structure * @param dev pointer to the sensor device data structure
* @return true if measurement is still running or false otherwise * @return true if measurement is still running or false otherwise
*/ */
@ -202,12 +202,12 @@ bool bme680_is_measuring (bme680_sensor_t* dev);
* The function returns the results of a TPHG measurement that has been * The function returns the results of a TPHG measurement that has been
* started before. If the measurement is still running, the function fails * started before. If the measurement is still running, the function fails
* and returns invalid values (see type declaration). * and returns invalid values (see type declaration).
* *
* @param dev pointer to the sensor device data structure * @param dev pointer to the sensor device data structure
* @param results pointer to a data structure that is filled with results * @param results pointer to a data structure that is filled with results
* @return true on success, false on error * @return true on success, false on error
*/ */
bool bme680_get_results_fixed (bme680_sensor_t* dev, bool bme680_get_results_fixed (bme680_sensor_t* dev,
bme680_values_fixed_t* results); bme680_values_fixed_t* results);
/** /**
@ -221,7 +221,7 @@ bool bme680_get_results_fixed (bme680_sensor_t* dev,
* @param results pointer to a data structure that is filled with results * @param results pointer to a data structure that is filled with results
* @return true on success, false on error * @return true on success, false on error
*/ */
bool bme680_get_results_float (bme680_sensor_t* dev, bool bme680_get_results_float (bme680_sensor_t* dev,
bme680_values_float_t* results); bme680_values_float_t* results);
/** /**
@ -235,12 +235,12 @@ bool bme680_get_results_float (bme680_sensor_t* dev,
* Note: Since the calling task is delayed using function *vTaskDelay*, this * 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 must not be used when it is called from a software timer callback
* function. * function.
* *
* @param dev pointer to the sensor device data structure * @param dev pointer to the sensor device data structure
* @param results pointer to a data structure that is filled with results * @param results pointer to a data structure that is filled with results
* @return true on success, false on error * @return true on success, false on error
*/ */
bool bme680_measure_fixed (bme680_sensor_t* dev, bool bme680_measure_fixed (bme680_sensor_t* dev,
bme680_values_fixed_t* results); bme680_values_fixed_t* results);
@ -255,17 +255,17 @@ bool bme680_measure_fixed (bme680_sensor_t* dev,
* Note: Since the calling task is delayed using function *vTaskDelay*, this * 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 must not be used when it is called from a software timer callback
* function. * function.
* *
* @param dev pointer to the sensor device data structure * @param dev pointer to the sensor device data structure
* @param results pointer to a data structure that is filled with results * @param results pointer to a data structure that is filled with results
* @return true on success, false on error * @return true on success, false on error
*/ */
bool bme680_measure_float (bme680_sensor_t* dev, bool bme680_measure_float (bme680_sensor_t* dev,
bme680_values_float_t* results); bme680_values_float_t* results);
/** /**
* @brief Set the oversampling rates for measurements * @brief Set the oversampling rates for measurements
* *
* The BME680 sensor allows to define individual oversampling rates for * The BME680 sensor allows to define individual oversampling rates for
* the measurements of temperature, pressure and humidity. Using an * the measurements of temperature, pressure and humidity. Using an
* oversampling rate of *osr*, the resolution of raw sensor data can be * oversampling rate of *osr*, the resolution of raw sensor data can be
@ -282,7 +282,7 @@ bool bme680_measure_float (bme680_sensor_t* dev,
* @param osh oversampling rate for humidity measurements * @param osh oversampling rate for humidity measurements
* @return true on success, false on error * @return true on success, false on error
*/ */
bool bme680_set_oversampling_rates (bme680_sensor_t* dev, bool bme680_set_oversampling_rates (bme680_sensor_t* dev,
bme680_oversampling_rate_t osr_t, bme680_oversampling_rate_t osr_t,
bme680_oversampling_rate_t osr_p, bme680_oversampling_rate_t osr_p,
bme680_oversampling_rate_t osr_h); bme680_oversampling_rate_t osr_h);
@ -300,9 +300,9 @@ bool bme680_set_oversampling_rates (bme680_sensor_t* dev,
* resolution of pressure and temperature data to 20 bit. Humidity and gas * 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 * inside the sensor does not fluctuate rapidly and does not require such a
* low pass filtering. * low pass filtering.
* *
* The default filter size is 3 (*iir_size_3*). * The default filter size is 3 (*iir_size_3*).
* *
* Please note: If the size of the filter is 0, the filter is not used. * Please note: If the size of the filter is 0, the filter is not used.
* *
* @param dev pointer to the sensor device data structure * @param dev pointer to the sensor device data structure
@ -311,14 +311,14 @@ bool bme680_set_oversampling_rates (bme680_sensor_t* dev,
*/ */
bool bme680_set_filter_size(bme680_sensor_t* dev, bme680_filter_size_t size); bool bme680_set_filter_size(bme680_sensor_t* dev, bme680_filter_size_t size);
/** /**
* @brief Set a heater profile for gas measurements * @brief Set a heater profile for gas measurements
* *
* The sensor integrates a heater for the gas measurement. Parameters for this * 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 * 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 * 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. * a temperature set-point (the target temperature) and a heating duration.
* *
* This function sets the parameters for one of the heater profiles 0 ... 9. * This function sets the parameters for one of the heater profiles 0 ... 9.
* To activate the gas measurement with this profile, use function * To activate the gas measurement with this profile, use function
@ -336,7 +336,7 @@ bool bme680_set_filter_size(bme680_sensor_t* dev, bme680_filter_size_t size);
*/ */
bool bme680_set_heater_profile (bme680_sensor_t* dev, bool bme680_set_heater_profile (bme680_sensor_t* dev,
uint8_t profile, uint8_t profile,
uint16_t temperature, uint16_t temperature,
uint16_t duration); uint16_t duration);
/** /**
@ -349,12 +349,12 @@ bool bme680_set_heater_profile (bme680_sensor_t* dev,
* Parameters of the activated heater profile have to be set before with * Parameters of the activated heater profile have to be set before with
* function *bme680_set_heater_profile* otherwise the function fails. * function *bme680_set_heater_profile* otherwise the function fails.
* *
* If several heater profiles have been defined with function * If several heater profiles have been defined with function
* *bme680_set_heater_profile*, a sequence of gas measurements with different * *bme680_set_heater_profile*, a sequence of gas measurements with different
* heater parameters can be realized by a sequence of activations of different * heater parameters can be realized by a sequence of activations of different
* heater profiles for successive TPHG measurements using this function. * heater profiles for successive TPHG measurements using this function.
* *
* @param dev pointer to the sensor device data structure0 * * @param dev pointer to the sensor device data structure0 *
* @param profile 0 ... 9 to activate or -1 to deactivate gas measure * @param profile 0 ... 9 to activate or -1 to deactivate gas measure
* @return true on success, false on error * @return true on success, false on error
*/ */
@ -372,8 +372,8 @@ bool bme680_use_heater_profile (bme680_sensor_t* dev, int8_t profile);
* @param dev pointer to the sensor device data structure * @param dev pointer to the sensor device data structure
* @param temperature ambient temperature in degree Celsius * @param temperature ambient temperature in degree Celsius
* @return true on success, false on error * @return true on success, false on error
*/ */
bool bme680_set_ambient_temperature (bme680_sensor_t* dev, bool bme680_set_ambient_temperature (bme680_sensor_t* dev,
int16_t temperature); int16_t temperature);

View file

@ -13,7 +13,7 @@
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* 1. Redistributions of source code must retain the above copyright notice, * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
* *
@ -21,7 +21,7 @@
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* 3. Neither the name of the copyright holder nor the names of its * 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this * contributors may be used to endorse or promote products derived from this
* software without specific prior written permission. * software without specific prior written permission.
* *
@ -29,7 +29,7 @@
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
@ -84,7 +84,7 @@ typedef enum {
/** /**
* @brief Filter sizes * @brief Filter sizes
*/ */
typedef enum { typedef enum {
iir_size_0 = 0, // filter is not used iir_size_0 = 0, // filter is not used
@ -108,17 +108,17 @@ typedef enum {
*/ */
typedef struct { typedef struct {
uint8_t osr_temperature; // T oversampling rate (default osr_1x) uint8_t osr_temperature; // T oversampling rate (default osr_1x)
uint8_t osr_pressure; // P oversampling rate (default osr_1x) uint8_t osr_pressure; // P oversampling rate (default osr_1x)
uint8_t osr_humidity; // H oversampling rate (default osr_1x) uint8_t osr_humidity; // H oversampling rate (default osr_1x)
uint8_t filter_size; // IIR filter size (default iir_size_3) uint8_t filter_size; // IIR filter size (default iir_size_3)
int8_t heater_profile; // Heater profile used (default 0) int8_t heater_profile; // Heater profile used (default 0)
uint16_t heater_temperature[10]; // Heater temperature for G (default 320) uint16_t heater_temperature[10]; // Heater temperature for G (default 320)
uint16_t heater_duration[10]; // Heater duration for G (default 150) uint16_t heater_duration[10]; // Heater duration for G (default 150)
int8_t ambient_temperature; // Ambient temperature for G (default 25) int8_t ambient_temperature; // Ambient temperature for G (default 25)
} bme680_settings_t; } bme680_settings_t;
/** /**
@ -129,37 +129,37 @@ typedef struct {
*/ */
typedef struct { typedef struct {
uint16_t par_t1; // calibration data for temperature compensation uint16_t par_t1; // calibration data for temperature compensation
int16_t par_t2; uit16_t par_t2;
int8_t par_t3; int8_t par_t3;
uint16_t par_p1; // calibration data for pressure compensation uint16_t par_p1; // calibration data for pressure compensation
int16_t par_p2; int16_t par_p2;
int8_t par_p3; int8_t par_p3;
int16_t par_p4; int16_t par_p4;
int16_t par_p5; int16_t par_p5;
int8_t par_p7; int8_t par_p7;
int8_t par_p6; int8_t par_p6;
int16_t par_p8; int16_t par_p8;
int16_t par_p9; int16_t par_p9;
uint8_t par_p10; uint8_t par_p10;
uint16_t par_h1; // calibration data for humidity compensation uint16_t par_h1; // calibration data for humidity compensation
uint16_t par_h2; uint16_t par_h2;
int8_t par_h3; int8_t par_h3;
int8_t par_h4; int8_t par_h4;
int8_t par_h5; int8_t par_h5;
uint8_t par_h6; uint8_t par_h6;
int8_t par_h7; int8_t par_h7;
int8_t par_gh1; // calibration data for gas compensation int8_t par_gh1; // calibration data for gas compensation
int16_t par_gh2; int16_t par_gh2;
int8_t par_gh3; int8_t par_gh3;
int32_t t_fine; // temperatur correction factor for P and G int32_t t_fine; // temperatur correction factor for P and G
uint8_t res_heat_range; uint8_t res_heat_range;
int8_t res_heat_val; int8_t res_heat_val;
int8_t range_sw_err; int8_t range_sw_err;
} bme680_calib_data_t; } bme680_calib_data_t;
@ -170,7 +170,7 @@ typedef struct {
typedef struct { typedef struct {
int error_code; // contains the error code of last operation int error_code; // contains the error code of last operation
uint8_t bus; // I2C = x, SPI = 1 uint8_t bus; // I2C = x, SPI = 1
uint8_t addr; // I2C = slave address, SPI = 0 uint8_t addr; // I2C = slave address, SPI = 0
uint8_t spi_cs_pin; // GPIO used as SPI CS uint8_t spi_cs_pin; // GPIO used as SPI CS
@ -178,10 +178,10 @@ typedef struct {
bool meas_started; // indicates whether measurement started bool meas_started; // indicates whether measurement started
uint32_t meas_start_tick; // measurement start time in RTOS ticks uint32_t meas_start_tick; // measurement start time in RTOS ticks
uint8_t meas_status; // last sensor status (for internal use only) uint8_t meas_status; // last sensor status (for internal use only)
bme680_settings_t settings; // sensor settings bme680_settings_t settings; // sensor settings
bme680_calib_data_t calib_data; // calibration data of the sensor bme680_calib_data_t calib_data; // calibration data of the sensor
} bme680_sensor_t; } bme680_sensor_t;
@ -190,4 +190,3 @@ typedef struct {
#endif /* End of CPP guard */ #endif /* End of CPP guard */
#endif /* __BME680_TYPES_H__ */ #endif /* __BME680_TYPES_H__ */