From 28666dc55a0163d175f02a393ca5d206d31607a3 Mon Sep 17 00:00:00 2001 From: Bosch Sensortec Date: Mon, 29 Jan 2018 08:36:51 +0100 Subject: [PATCH] - Floating point support added for the API - Lower temperature cap removed in "calc_heater_res" API - Added typecast for overflow check in "calc_pressure" API --- README.md | 16 +++- bme680.c | 236 ++++++++++++++++++++++++++++++++++++++++++++++++-- bme680.h | 4 +- bme680_defs.h | 30 ++++++- changelog.md | 5 ++ 5 files changed, 276 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index f5042bf..6821c32 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,9 @@ The sensor driver package includes bme680.h, bme680.c and bme680_defs.h files ## Version File | Version | Date --------------|---------|------------- -bme680.c | 3.5.5 | 20 Nov 2017 -bme680.h | 3.5.5 | 20 Nov 2017 -bme680_defs.h | 3.5.5 | 20 Nov 2017 +bme680.c | 3.5.6 | 19 Jan 2018 +bme680.h | 3.5.6 | 19 Jan 2018 +bme680_defs.h | 3.5.6 | 19 Jan 2018 ## Integration details * Integrate bme680.h, bme680_defs.h and bme680.c file in to your project. @@ -62,6 +62,16 @@ fill in the various parameters as shown below rslt = bme680_init(&gas_sensor); ``` +Regarding compensation functions for temperature, pressure, humidity and gas we have two implementations. + + - Integer version + - floating point version + +By default, Integer version is used in the API + +If the user needs the floating point version, the user has to un-comment BME680_FLOAT_POINT_COMPENSATION macro +in bme680_defs.h file or to add it in the compiler flags. + ### Configuring the sensor #### Example for configuring the sensor in forced mode ``` c diff --git a/bme680.c b/bme680.c index b68e20e..d41d16e 100644 --- a/bme680.c +++ b/bme680.c @@ -40,8 +40,8 @@ * patent rights of the copyright holder. * * File bme680.c - * @date 20 Nov 2017 - * @version 3.5.5 + * @date 19 Jan 2018 + * @version 3.5.6 * */ @@ -107,6 +107,8 @@ static int8_t get_gas_config(struct bme680_dev *dev); */ static uint8_t calc_heater_dur(uint16_t dur); +#ifndef BME680_FLOAT_POINT_COMPENSATION + /*! * @brief This internal API is used to calculate the temperature value. * @@ -151,13 +153,72 @@ static uint32_t calc_gas_resistance(uint16_t gas_res_adc, uint8_t gas_range, con /*! * @brief This internal API is used to calculate the Heat Resistance value. * - * @param[in] dev :Structure instance of bme680_dev. - * @param[in] temp :Contains the temporary value. + * @param[in] dev : Structure instance of bme680_dev + * @param[in] temp : Contains the target temperature value. * * @return uint8_t calculated heater resistance. */ static uint8_t calc_heater_res(uint16_t temp, const struct bme680_dev *dev); +#else +/*! + * @brief This internal API is used to calculate the + * temperature value value in float format + * + * @param[in] dev :Structure instance of bme680_dev. + * @param[in] temp_adc :Contains the temperature ADC value . + * + * @return Calculated temperature in float + */ +static float calc_temperature(uint32_t temp_adc, struct bme680_dev *dev); + +/*! + * @brief This internal API is used to calculate the + * pressure value value in float format + * + * @param[in] dev :Structure instance of bme680_dev. + * @param[in] pres_adc :Contains the pressure ADC value . + * + * @return Calculated pressure in float. + */ +static float calc_pressure(uint32_t pres_adc, const struct bme680_dev *dev); + +/*! + * @brief This internal API is used to calculate the + * humidity value value in float format + * + * @param[in] dev :Structure instance of bme680_dev. + * @param[in] hum_adc :Contains the humidity ADC value. + * + * @return Calculated humidity in float. + */ +static float calc_humidity(uint16_t hum_adc, const struct bme680_dev *dev); + +/*! + * @brief This internal API is used to calculate the + * gas resistance value value in float format + * + * @param[in] dev :Structure instance of bme680_dev. + * @param[in] gas_res_adc :Contains the Gas Resistance ADC value. + * @param[in] gas_range :Contains the range of gas values. + * + * @return Calculated gas resistance in float. + */ +static float calc_gas_resistance(uint16_t gas_res_adc, uint8_t gas_range, const struct bme680_dev *dev); + +/*! + * @brief This internal API is used to calculate the + * heater resistance value in float format + * + * @param[in] temp : Contains the target temperature value. + * @param[in] dev : Structure instance of bme680_dev. + * + * @return Calculated heater resistance in float. + */ +static float calc_heater_res(uint16_t temp, const struct bme680_dev *dev); + +#endif + /*! * @brief This internal API is used to calculate the field data of sensor. * @@ -818,6 +879,8 @@ static int8_t get_gas_config(struct bme680_dev *dev) return rslt; } +#ifndef BME680_FLOAT_POINT_COMPENSATION + /*! * @brief This internal API is used to calculate the temperature value. */ @@ -861,7 +924,7 @@ static uint32_t calc_pressure(uint32_t pres_adc, const struct bme680_dev *dev) var1 = ((32768 + var1) * (int32_t)dev->calib.par_p1) >> 15; pressure_comp = 1048576 - pres_adc; pressure_comp = (int32_t)((pressure_comp - (var2 >> 12)) * ((uint32_t)3125)); - var4 = (1 << 31); + var4 = (INT32_C(1) << 31); if (pressure_comp >= var4) pressure_comp = ((pressure_comp / (uint32_t)var1) << 1); else @@ -949,9 +1012,7 @@ static uint8_t calc_heater_res(uint16_t temp, const struct bme680_dev *dev) int32_t var5; int32_t heatr_res_x100; - if (temp < 200) /* Cap temperature */ - temp = 200; - else if (temp > 400) + if (temp > 400) /* Cap temperature */ temp = 400; var1 = (((int32_t) dev->amb_temp * dev->calib.par_gh3) / 1000) * 256; @@ -965,6 +1026,165 @@ static uint8_t calc_heater_res(uint16_t temp, const struct bme680_dev *dev) return heatr_res; } +#else + + +/*! + * @brief This internal API is used to calculate the + * temperature value in float format + */ +static float calc_temperature(uint32_t temp_adc, struct bme680_dev *dev) +{ + float var1 = 0; + float var2 = 0; + float calc_temp = 0; + + /* calculate var1 data */ + var1 = ((((float)temp_adc / 16384.0f) - ((float)dev->calib.par_t1 / 1024.0f)) + * ((float)dev->calib.par_t2)); + + /* calculate var2 data */ + var2 = (((((float)temp_adc / 131072.0f) - ((float)dev->calib.par_t1 / 8192.0f)) * + (((float)temp_adc / 131072.0f) - ((float)dev->calib.par_t1 / 8192.0f))) * + ((float)dev->calib.par_t3 * 16.0f)); + + /* t_fine value*/ + dev->calib.t_fine = (var1 + var2); + + /* compensated temperature data*/ + calc_temp = ((dev->calib.t_fine) / 5120.0f); + + return calc_temp; +} + +/*! + * @brief This internal API is used to calculate the + * pressure value in float format + */ +static float calc_pressure(uint32_t pres_adc, const struct bme680_dev *dev) +{ + float var1 = 0; + float var2 = 0; + float var3 = 0; + float calc_pres = 0; + + var1 = (((float)dev->calib.t_fine / 2.0f) - 64000.0f); + var2 = var1 * var1 * (((float)dev->calib.par_p6) / (131072.0f)); + var2 = var2 + (var1 * ((float)dev->calib.par_p5) * 2.0f); + var2 = (var2 / 4.0f) + (((float)dev->calib.par_p4) * 65536.0f); + var1 = (((((float)dev->calib.par_p3 * var1 * var1) / 16384.0f) + + ((float)dev->calib.par_p2 * var1)) / 524288.0f); + var1 = ((1.0f + (var1 / 32768.0f)) * ((float)dev->calib.par_p1)); + calc_pres = (1048576.0f - ((float)pres_adc)); + + /* Avoid exception caused by division by zero */ + if ((int)var1 != 0) { + calc_pres = (((calc_pres - (var2 / 4096.0f)) * 6250.0f) / var1); + var1 = (((float)dev->calib.par_p9) * calc_pres * calc_pres) / 2147483648.0f; + var2 = calc_pres * (((float)dev->calib.par_p8) / 32768.0f); + var3 = ((calc_pres / 256.0f) * (calc_pres / 256.0f) * (calc_pres / 256.0f) + * (dev->calib.par_p10 / 131072.0f)); + calc_pres = (calc_pres + (var1 + var2 + var3 + ((float)dev->calib.par_p7 * 128.0f)) / 16.0f); + } else { + calc_pres = 0; + } + + return calc_pres; +} + +/*! + * @brief This internal API is used to calculate the + * humidity value in float format + */ +static float calc_humidity(uint16_t hum_adc, const struct bme680_dev *dev) +{ + float calc_hum = 0; + float var1 = 0; + float var2 = 0; + float var3 = 0; + float var4 = 0; + float temp_comp; + + /* compensated temperature data*/ + temp_comp = ((dev->calib.t_fine) / 5120.0f); + + var1 = (float)((float)hum_adc) - (((float)dev->calib.par_h1 * 16.0f) + (((float)dev->calib.par_h3 / 2.0f) + * temp_comp)); + + var2 = var1 * ((float)(((float) dev->calib.par_h2 / 262144.0f) * (1.0f + (((float)dev->calib.par_h4 / 16384.0f) + * temp_comp) + (((float)dev->calib.par_h5 / 1048576.0f) * temp_comp * temp_comp)))); + + var3 = (float) dev->calib.par_h6 / 16384.0f; + + var4 = (float) dev->calib.par_h7 / 2097152.0f; + + calc_hum = var2 + ((var3 + (var4 * temp_comp)) * var2 * var2); + + if (calc_hum > 100.0f) + calc_hum = 100.0f; + else if (calc_hum < 0.0f) + calc_hum = 0.0f; + + return calc_hum; +} + +/*! + * @brief This internal API is used to calculate the + * gas resistance value in float format + */ +static float calc_gas_resistance(uint16_t gas_res_adc, uint8_t gas_range, const struct bme680_dev *dev) +{ + float calc_gas_res; + float var1 = 0; + float var2 = 0; + float var3 = 0; + + const float lookup_k1_range[16] = { + 0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, -0.8, + 0.0, 0.0, -0.2, -0.5, 0.0, -1.0, 0.0, 0.0}; + const float lookup_k2_range[16] = { + 0.0, 0.0, 0.0, 0.0, 0.1, 0.7, 0.0, -0.8, + -0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; + + var1 = (1340.0f + (5.0f * dev->calib.range_sw_err)); + var2 = (var1) * (1.0f + lookup_k1_range[gas_range]/100.0f); + var3 = 1.0f + (lookup_k2_range[gas_range]/100.0f); + + calc_gas_res = 1.0f / (float)(var3 * (0.000000125f) * (float)(1 << gas_range) * (((((float)gas_res_adc) + - 512.0f)/var2) + 1.0f)); + + return calc_gas_res; +} + +/*! + * @brief This internal API is used to calculate the + * heater resistance value in float format + */ +static float calc_heater_res(uint16_t temp, const struct bme680_dev *dev) +{ + float var1 = 0; + float var2 = 0; + float var3 = 0; + float var4 = 0; + float var5 = 0; + float res_heat = 0; + + if (temp > 400) /* Cap temperature */ + temp = 400; + + var1 = (((float)dev->calib.par_gh1 / (16.0f)) + 49.0f); + var2 = ((((float)dev->calib.par_gh2 / (32768.0f)) * (0.0005f)) + 0.00235f); + var3 = ((float)dev->calib.par_gh3 / (1024.0f)); + var4 = (var1 * (1.0f + (var2 * (float)temp))); + var5 = (var4 + (var3 * (float)dev->amb_temp)); + res_heat = (uint8_t)(3.4f * ((var5 * (4 / (4 + (float)dev->calib.res_heat_range)) * + (1/(1 + ((float) dev->calib.res_heat_val * 0.002f)))) - 25)); + + return res_heat; +} + +#endif + /*! * @brief This internal API is used to calculate the Heat duration value. */ diff --git a/bme680.h b/bme680.h index 7196058..8079697 100644 --- a/bme680.h +++ b/bme680.h @@ -40,8 +40,8 @@ * patent rights of the copyright holder. * * @file bme680.h - * @date 20 Nov 2017 - * @version 3.5.5 + * @date 19 Jan 2018 + * @version 3.5.6 * @brief * */ diff --git a/bme680_defs.h b/bme680_defs.h index 0cf581b..630b70d 100644 --- a/bme680_defs.h +++ b/bme680_defs.h @@ -40,8 +40,8 @@ * patent rights of the copyright holder. * * @file bme680_defs.h - * @date 20 Nov 2017 - * @version 3.5.5 + * @date 19 Jan 2018 + * @version 3.5.6 * @brief * */ @@ -100,6 +100,12 @@ #endif #endif +/** BME680 configuration macros */ +/** Enable or un-comment the macro to provide floating point data output */ +#ifndef BME680_FLOAT_POINT_COMPENSATION +/* #define BME680_FLOAT_POINT_COMPENSATION */ +#endif + /** BME680 General config */ #define BME680_POLL_PERIOD_MS UINT8_C(10) @@ -367,6 +373,8 @@ struct bme680_field_data { uint8_t gas_index; /*! Measurement index to track order */ uint8_t meas_index; + +#ifndef BME680_FLOAT_POINT_COMPENSATION /*! Temperature in degree celsius x100 */ int16_t temperature; /*! Pressure in Pascal */ @@ -375,6 +383,18 @@ struct bme680_field_data { uint32_t humidity; /*! Gas resistance in Ohms */ uint32_t gas_resistance; +#else + /*! Temperature in degree celsius */ + float temperature; + /*! Pressure in Pascal */ + float pressure; + /*! Humidity in % relative humidity x1000 */ + float humidity; + /*! Gas resistance in Ohms */ + float gas_resistance; + +#endif + }; /*! @@ -427,8 +447,14 @@ struct bme680_calib_data { int16_t par_p9; /*! Variable to store calibrated pressure data */ uint8_t par_p10; + +#ifndef BME680_FLOAT_POINT_COMPENSATION /*! Variable to store t_fine size */ int32_t t_fine; +#else + /*! Variable to store t_fine size */ + float t_fine; +#endif /*! Variable to store heater resistance range */ uint8_t res_heat_range; /*! Variable to store heater resistance value */ diff --git a/changelog.md b/changelog.md index fd357da..e3fd739 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,11 @@ # Change Log All notable changes to the BME680 Sensor API will be documented in this file. +## v3.5.6, 19 Jan 2018 +### Added + - Floating point support added for the API + - Lower temperature cap removed in "calc_heater_res" APIs + ## v3.5.5, 20 Nov 2017 ### Changed - Updated the buffer size in "get_calib_data" API