diff --git a/bme69x.c b/bme69x.c index cfbc82d..c61c28e 100644 --- a/bme69x.c +++ b/bme69x.c @@ -31,8 +31,8 @@ * POSSIBILITY OF SUCH DAMAGE. * * @file bme69x.c -* @date 2025-07-15 -* @version v1.0.3 +* @date 2026-01-30 +* @version v1.1.0 * */ @@ -51,10 +51,10 @@ static uint8_t calc_gas_wait(uint16_t dur); #ifndef BME69X_USE_FPU /* This internal API is used to calculate the temperature in integer */ -static int16_t calc_temperature(uint32_t temp_adc, struct bme69x_dev *dev, uint32_t *t_lin); +static int16_t calc_temperature(uint32_t temp_adc, struct bme69x_dev *dev, int64_t *t_lin); /* This internal API is used to calculate the pressure in integer */ -static uint32_t calc_pressure(uint32_t pres_adc, uint32_t t_lin, const struct bme69x_dev *dev); +static uint32_t calc_pressure(uint32_t pres_adc, int64_t t_lin, const struct bme69x_dev *dev); /* This internal API is used to calculate the humidity in integer */ static uint32_t calc_humidity(uint16_t hum_adc, int16_t comp_temperature, const struct bme69x_dev *dev); @@ -305,7 +305,6 @@ int8_t bme69x_soft_reset(struct bme69x_dev *dev) int8_t bme69x_set_conf(struct bme69x_conf *conf, struct bme69x_dev *dev) { int8_t rslt; - uint8_t odr20 = 0, odr3 = 1; uint8_t current_op_mode; /* Register data starting from BME69X_REG_CTRL_GAS_1(0x71) up to BME69X_REG_CONFIG(0x75) */ @@ -359,14 +358,6 @@ int8_t bme69x_set_conf(struct bme69x_conf *conf, struct bme69x_dev *dev) data_array[3] = BME69X_SET_BITS(data_array[3], BME69X_OST, conf->os_temp); data_array[3] = BME69X_SET_BITS(data_array[3], BME69X_OSP, conf->os_pres); data_array[1] = BME69X_SET_BITS_POS_0(data_array[1], BME69X_OSH, conf->os_hum); - if (conf->odr != BME69X_ODR_NONE) - { - odr20 = conf->odr; - odr3 = 0; - } - - data_array[4] = BME69X_SET_BITS(data_array[4], BME69X_ODR20, odr20); - data_array[0] = BME69X_SET_BITS(data_array[0], BME69X_ODR3, odr3); } } @@ -710,13 +701,43 @@ int8_t bme69x_get_heatr_conf(const struct bme69x_heatr_conf *conf, struct bme69x return rslt; } +/* + * @brief Internal helper to perform a single forced measurement with given heater config and delay + */ +static int8_t bme69x_forced_measurement(const struct bme69x_heatr_conf *heatr_conf, + struct bme69x_conf *conf, + uint32_t wait_time, + struct bme69x_data *data, + struct bme69x_dev *t_dev) +{ + int8_t rslt; + uint8_t n_fields; + + rslt = bme69x_set_heatr_conf(BME69X_FORCED_MODE, heatr_conf, t_dev); + if (rslt == BME69X_OK) + { + rslt = bme69x_set_conf(conf, t_dev); + if (rslt == BME69X_OK) + { + rslt = bme69x_set_op_mode(BME69X_FORCED_MODE, t_dev); /* Trigger a measurement */ + if (rslt == BME69X_OK) + { + /* Wait for the measurement to complete */ + t_dev->delay_us(wait_time, t_dev->intf_ptr); + rslt = bme69x_get_data(BME69X_FORCED_MODE, data, &n_fields, t_dev); + } + } + } + + return rslt; +} + /* * @brief This API performs Self-test of low and high gas variants of BME69X */ int8_t bme69x_selftest_check(const struct bme69x_dev *dev) { int8_t rslt; - uint8_t n_fields; uint8_t i = 0; struct bme69x_data data[BME69X_N_MEAS] = { { 0 } }; struct bme69x_dev t_dev; @@ -749,31 +770,17 @@ int8_t bme69x_selftest_check(const struct bme69x_dev *dev) heatr_conf.enable = BME69X_ENABLE; heatr_conf.heatr_dur = BME69X_HEATR_DUR1; heatr_conf.heatr_temp = BME69X_HIGH_TEMP; - rslt = bme69x_set_heatr_conf(BME69X_FORCED_MODE, &heatr_conf, &t_dev); + + rslt = bme69x_forced_measurement(&heatr_conf, &conf, BME69X_HEATR_DUR1_DELAY, &data[0], &t_dev); if (rslt == BME69X_OK) { - rslt = bme69x_set_conf(&conf, &t_dev); - if (rslt == BME69X_OK) + if ((data[0].idac != 0x00) && (data[0].idac != 0xFF) && (data[0].status & BME69X_GASM_VALID_MSK)) { - rslt = bme69x_set_op_mode(BME69X_FORCED_MODE, &t_dev); /* Trigger a measurement */ - if (rslt == BME69X_OK) - { - /* Wait for the measurement to complete */ - t_dev.delay_us(BME69X_HEATR_DUR1_DELAY, t_dev.intf_ptr); - rslt = bme69x_get_data(BME69X_FORCED_MODE, &data[0], &n_fields, &t_dev); - if (rslt == BME69X_OK) - { - if ((data[0].idac != 0x00) && (data[0].idac != 0xFF) && - (data[0].status & BME69X_GASM_VALID_MSK)) - { - rslt = BME69X_OK; - } - else - { - rslt = BME69X_E_SELF_TEST; - } - } - } + rslt = BME69X_OK; + } + else + { + rslt = BME69X_E_SELF_TEST; } } @@ -789,22 +796,7 @@ int8_t bme69x_selftest_check(const struct bme69x_dev *dev) heatr_conf.heatr_temp = BME69X_LOW_TEMP; /* Lower temperature */ } - rslt = bme69x_set_heatr_conf(BME69X_FORCED_MODE, &heatr_conf, &t_dev); - if (rslt == BME69X_OK) - { - rslt = bme69x_set_conf(&conf, &t_dev); - if (rslt == BME69X_OK) - { - rslt = bme69x_set_op_mode(BME69X_FORCED_MODE, &t_dev); /* Trigger a measurement */ - if (rslt == BME69X_OK) - { - /* Wait for the measurement to complete */ - t_dev.delay_us(BME69X_HEATR_DUR2_DELAY, t_dev.intf_ptr); - rslt = bme69x_get_data(BME69X_FORCED_MODE, &data[i], &n_fields, &t_dev); - } - } - } - + rslt = bme69x_forced_measurement(&heatr_conf, &conf, BME69X_HEATR_DUR2_DELAY, &data[i], &t_dev); i++; } @@ -821,7 +813,7 @@ int8_t bme69x_selftest_check(const struct bme69x_dev *dev) #ifndef BME69X_USE_FPU /* @brief This internal API is used to calculate the temperature value. */ -static int16_t calc_temperature(uint32_t temp_adc, struct bme69x_dev *dev, uint32_t *t_lin) +static int16_t calc_temperature(uint32_t temp_adc, struct bme69x_dev *dev, int64_t *t_lin) { int64_t partial_data1; int64_t partial_data2; @@ -831,20 +823,20 @@ static int16_t calc_temperature(uint32_t temp_adc, struct bme69x_dev *dev, uint3 int64_t partial_data6; int64_t tem_comp; - partial_data1 = (int64_t)(temp_adc - (256U * dev->calib.par_t1)); - partial_data2 = (int64_t)(partial_data1 * (int64_t)dev->calib.par_t2); + partial_data1 = (int64_t)(temp_adc - ((int64_t)BME69X_TEMPADC_SCALE * dev->calib.par_t1)); + partial_data2 = (int64_t)(partial_data1 * dev->calib.par_t2); partial_data3 = (int64_t)(partial_data1 * partial_data1); - partial_data4 = (int64_t)(partial_data3 * (int64_t)dev->calib.par_t3); - partial_data5 = (int64_t)((int64_t)(partial_data2 * 262144UL) + partial_data4); - partial_data6 = (int64_t)(partial_data5 / 4294967296ULL); - *t_lin = (uint32_t)partial_data6; - tem_comp = (int64_t)((partial_data6 * 25U) / 16384UL); + partial_data4 = (int64_t)(partial_data3 * dev->calib.par_t3); + partial_data5 = (int64_t)((int64_t)(partial_data2 * BME69X_TEMPCOMP_SCALE1) + partial_data4); + partial_data6 = (int64_t)((int64_t)partial_data5 / (int64_t)BME69X_TEMPCOMP_SCALE2); + *t_lin = (int64_t)partial_data6; + tem_comp = (int64_t)((partial_data6 * BME69X_TEMPCOMP_SCALE3) / BME69X_TEMPCOMP_SCALE4); return (int16_t)(tem_comp); } /* @brief This internal API is used to calculate the pressure value. */ -static uint32_t calc_pressure(uint32_t pres_adc, uint32_t t_lin, const struct bme69x_dev *dev) +static uint32_t calc_pressure(uint32_t pres_adc, int64_t t_lin, const struct bme69x_dev *dev) { int64_t partial_data1; int64_t partial_data2; @@ -857,7 +849,7 @@ static uint32_t calc_pressure(uint32_t pres_adc, uint32_t t_lin, const struct bm int64_t press_comp; int64_t t_lin_64; - t_lin_64 = (int64_t)t_lin; + t_lin_64 = t_lin; partial_data1 = t_lin_64 * t_lin_64; partial_data2 = partial_data1 / 64; @@ -902,7 +894,7 @@ static uint32_t calc_humidity(uint16_t hum_adc, int16_t comp_temperature, const var_H = (((((hum_64 * 16384UL) - (dev->calib.par_h1 * 1048576UL) - (dev->calib.par_h2 * var_H)) + 16384UL) / 32768UL) * ((((((var_H * dev->calib.par_h4) / 1024UL) * ((var_H * dev->calib.par_h3) / 2048UL + 32768UL)) / 1024UL) + - 2097152ULL) * dev->calib.par_h5 + 8192UL) / 16384UL); + 2097152LL) * dev->calib.par_h5 + 8192UL) / 16384UL); var_H = var_H - (((((var_H / 32768UL) * (var_H / 32768UL)) / 128UL) * dev->calib.par_h6) / 16UL); @@ -971,7 +963,8 @@ static uint8_t calc_res_heat(uint16_t temp, const struct bme69x_dev *dev) /* @brief This internal API is used to calculate the temperature value. */ static float calc_temperature(uint32_t temp_adc, const struct bme69x_dev *dev) { - int32_t do1, cf; + int32_t do1; + double cf; double dtk1, dtk2, temp1, temp2; double calc_temp; @@ -979,7 +972,7 @@ static float calc_temperature(uint32_t temp_adc, const struct bme69x_dev *dev) dtk1 = (double)dev->calib.par_t2 / (double)(1ULL << 30); dtk2 = (double)dev->calib.par_t3 / (double)(1ULL << 48); - cf = temp_adc - do1; + cf = (double)temp_adc - (double)do1; temp1 = (double)(cf * dtk1); temp2 = (double)cf * (double)cf * dtk2; @@ -1032,14 +1025,13 @@ static float calc_pressure(uint32_t pres_adc, float comp_temperature, const stru return (float)calc_pres; } -/* This internal API is used to calculate the humidity in integer */ +/* This internal API is used to calculate the humidity in float */ static float calc_humidity(uint16_t hum_adc, float comp_temperature, const struct bme69x_dev *dev) { double oh, tk10h, sh; double tk1sh, tk2sh, hlin2; double hoff, hsens; double temp_comp, calc_hum, hum_float_val; - int32_t hum_int_val; temp_comp = (comp_temperature * 5120) - 76800; @@ -1054,16 +1046,19 @@ static float calc_humidity(uint16_t hum_adc, float comp_temperature, const struc hsens = hoff * sh * (1 + (tk1sh * temp_comp) + (tk1sh * tk2sh * temp_comp * temp_comp)); hum_float_val = hsens * (1 - hlin2 * hsens); - /* Avoid direct floating-point comparison by using integer scaling */ - hum_int_val = (int32_t)(hum_float_val * 1000.0f); - - if (hum_int_val >= 100000) + /* Humidity Limit Implementation */ + if (hum_float_val < 0.0) + { + hum_float_val = 0.0; + } + else if (hum_float_val >= 100.00) { hum_float_val = 100.0; } - else if (hum_int_val < 0) + else { - hum_float_val = 0.0; + /* range with in the limit */ + /* Do Nothing */ } calc_hum = hum_float_val; @@ -1269,6 +1264,12 @@ static int8_t read_all_field_data(struct bme69x_data * const data[], struct bme6 data[i]->status |= buff[off + 16] & BME69X_GASM_VALID_MSK; data[i]->status |= buff[off + 16] & BME69X_HEAT_STAB_MSK; + /* Clamp gas_index to valid range [0,9] to prevent out-of-bounds access */ + if (data[i]->gas_index > 9) + { + data[i]->gas_index = 9; + } + data[i]->idac = set_val[data[i]->gas_index]; data[i]->res_heat = set_val[10 + data[i]->gas_index]; data[i]->gas_wait = set_val[20 + data[i]->gas_index]; diff --git a/bme69x.h b/bme69x.h index 4525615..3d68de8 100644 --- a/bme69x.h +++ b/bme69x.h @@ -31,8 +31,8 @@ * POSSIBILITY OF SUCH DAMAGE. * * @file bme69x.h -* @date 2025-07-15 -* @version v1.0.3 +* @date 2026-01-30 +* @version v1.1.0 * */ diff --git a/bme69x_defs.h b/bme69x_defs.h index 58ccb6e..4892987 100644 --- a/bme69x_defs.h +++ b/bme69x_defs.h @@ -31,8 +31,8 @@ * POSSIBILITY OF SUCH DAMAGE. * * @file bme69x_defs.h -* @date 2025-07-15 -* @version v1.0.3 +* @date 2026-01-30 +* @version v1.1.0 * */ @@ -97,6 +97,13 @@ #define BME69X_PERIOD_POLL UINT32_C(10000) #endif +/* Macros to calculate temperature*/ +#define BME69X_TEMPADC_SCALE 256U +#define BME69X_TEMPCOMP_SCALE1 262144UL +#define BME69X_TEMPCOMP_SCALE2 4294967296ULL +#define BME69X_TEMPCOMP_SCALE3 25U +#define BME69X_TEMPCOMP_SCALE4 16384UL + /* BME69X unique chip identifier */ #define BME69X_CHIP_ID UINT8_C(0x61) @@ -353,58 +360,58 @@ /* Coefficient T3 position */ #define BME69X_IDX_DTK2_C (2) -/* Coefficient P1 LSB position */ +/* Coefficient P5 LSB position */ #define BME69X_IDX_S_C_LSB (4) -/* Coefficient P1 MSB position */ +/* Coefficient P5 MSB position */ #define BME69X_IDX_S_C_MSB (5) -/* Coefficient P2 LSB position */ +/* Coefficient P6 LSB position */ #define BME69X_IDX_TK1S_C_LSB (6) -/* Coefficient P2 MSB position */ +/* Coefficient P6 MSB position */ #define BME69X_IDX_TK1S_C_MSB (7) -/* Coefficient P3 position */ +/* Coefficient P7 position */ #define BME69X_IDX_TK2S_C (8) -/* Coefficient TK3S position */ +/* Coefficient P8 position */ #define BME69X_IDX_TK3S_C (9) -/* Coefficient P4 LSB position */ +/* Coefficient P1 LSB position */ #define BME69X_IDX_O_C_LSB (10) -/* Coefficient P4 MSB position */ +/* Coefficient P1 MSB position */ #define BME69X_IDX_O_C_MSB (11) -/* Coefficient P5 LSB position */ +/* Coefficient P2 LSB position */ #define BME69X_IDX_TK10_C_LSB (12) -/* Coefficient P5 MSB position */ +/* Coefficient P2 MSB position */ #define BME69X_IDX_TK10_C_MSB (13) -/* Coefficient P7 position */ +/* Coefficient P3 position */ #define BME69X_IDX_TK20_C (14) -/* Coefficient P6 position */ +/* Coefficient P4 position */ #define BME69X_IDX_TK30_C (15) -/* Coefficient P8 LSB position */ +/* Coefficient P9 LSB position */ #define BME69X_IDX_NLS_C_LSB (18) -/* Coefficient P8 MSB position */ +/* Coefficient P9 MSB position */ #define BME69X_IDX_NLS_C_MSB (19) -/* Coefficient P9 LSB position */ +/* Coefficient P10 position */ #define BME69X_IDX_TKNLS_C (20) -/* Coefficient P10 position */ +/* Coefficient P11 position */ #define BME69X_IDX_NLS3_C (21) -/* Coefficient H2 MSB position */ +/* Coefficient H5 MSB position */ #define BME69X_IDX_S_H_MSB (23) -/* Coefficient H2 LSB position */ +/* Coefficient H5 LSB position */ #define BME69X_IDX_S_H_LSB (24) /* Coefficient H1 LSB position */ @@ -413,13 +420,13 @@ /* Coefficient H1 MSB position */ #define BME69X_IDX_O_H_MSB (25) -/* Coefficient H3 position */ +/* Coefficient H2 position */ #define BME69X_IDX_TK10H_C (26) /* Coefficient H4 position */ #define BME69X_IDX_par_h4 (27) -/* Coefficient H5 position */ +/* Coefficient H3 position */ #define BME69X_IDX_par_h3 (28) /* Coefficient H6 position */ @@ -758,7 +765,7 @@ struct bme69x_data uint32_t gas_resistance; /*! Intermediate temperature co-efficient for pressure calculation */ - uint32_t t_lin; + int64_t t_lin; #else /*! Temperature in degree celsius */ diff --git a/examples/sequential_mode/Makefile b/examples/sequential_mode/Makefile deleted file mode 100644 index 0c206be..0000000 --- a/examples/sequential_mode/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -COINES_INSTALL_PATH ?= ../../../.. - -EXAMPLE_FILE ?= sequential_mode.c - -API_LOCATION ?= ../.. - -C_SRCS += \ -$(API_LOCATION)/bme69x.c \ -../common/common.c - -INCLUDEPATHS += \ -$(API_LOCATION) \ -../common - -COINES_BACKEND?=COINES_BRIDGE - -include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/examples/sequential_mode/sequential_mode.c b/examples/sequential_mode/sequential_mode.c deleted file mode 100644 index dd499b6..0000000 --- a/examples/sequential_mode/sequential_mode.c +++ /dev/null @@ -1,125 +0,0 @@ -/** - * Copyright (C) 2025 Bosch Sensortec GmbH - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#include - -#include "bme69x.h" -#include "common.h" -#include "coines.h" - -/***********************************************************************/ -/* Macros */ -/***********************************************************************/ - -/* Macro for count of samples to be displayed */ -#define SAMPLE_COUNT UINT8_C(300) - -/***********************************************************************/ -/* Test code */ -/***********************************************************************/ - -int main(void) -{ - struct bme69x_dev bme; - int8_t rslt; - struct bme69x_conf conf; - struct bme69x_heatr_conf heatr_conf; - struct bme69x_data data[3]; - uint32_t del_period; - uint32_t time_ms = 0; - uint8_t n_fields; - uint16_t sample_count = 1; - - /* Heater temperature in degree Celsius */ - uint16_t temp_prof[10] = { 200, 240, 280, 320, 360, 360, 320, 280, 240, 200 }; - - /* Heating duration in milliseconds */ - uint16_t dur_prof[10] = { 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 }; - - /* Interface preference is updated as a parameter - * For I2C : BME69X_I2C_INTF - * For SPI : BME69X_SPI_INTF - */ - rslt = bme69x_interface_init(&bme, BME69X_SPI_INTF); - bme69x_check_rslt("bme69x_interface_init", rslt); - - rslt = bme69x_init(&bme); - bme69x_check_rslt("bme69x_init", rslt); - - /* Check if rslt == BME69X_OK, report or handle if otherwise */ - rslt = bme69x_get_conf(&conf, &bme); - bme69x_check_rslt("bme69x_get_conf", rslt); - - /* Check if rslt == BME69X_OK, report or handle if otherwise */ - conf.filter = BME69X_FILTER_OFF; - conf.odr = BME69X_ODR_NONE; /* This parameter defines the sleep duration after each profile */ - conf.os_hum = BME69X_OS_16X; - conf.os_pres = BME69X_OS_1X; - conf.os_temp = BME69X_OS_2X; - rslt = bme69x_set_conf(&conf, &bme); - bme69x_check_rslt("bme69x_set_conf", rslt); - - /* Check if rslt == BME69X_OK, report or handle if otherwise */ - heatr_conf.enable = BME69X_ENABLE; - heatr_conf.heatr_temp_prof = temp_prof; - heatr_conf.heatr_dur_prof = dur_prof; - heatr_conf.profile_len = 10; - rslt = bme69x_set_heatr_conf(BME69X_SEQUENTIAL_MODE, &heatr_conf, &bme); - bme69x_check_rslt("bme69x_set_heatr_conf", rslt); - - /* Check if rslt == BME69X_OK, report or handle if otherwise */ - rslt = bme69x_set_op_mode(BME69X_SEQUENTIAL_MODE, &bme); - bme69x_check_rslt("bme69x_set_op_mode", rslt); - - /* Check if rslt == BME69X_OK, report or handle if otherwise */ - printf( - "Sample, TimeStamp(ms), Temperature(deg C), Pressure(Pa), Humidity(%%), Gas resistance(ohm), Status, Profile index, Measurement index\n"); - while (sample_count <= SAMPLE_COUNT) - { - /* Calculate delay period in microseconds */ - del_period = bme69x_get_meas_dur(BME69X_SEQUENTIAL_MODE, &conf, &bme) + (heatr_conf.heatr_dur_prof[0] * 1000); - bme.delay_us(del_period, bme.intf_ptr); - - time_ms = coines_get_millis(); - - rslt = bme69x_get_data(BME69X_SEQUENTIAL_MODE, data, &n_fields, &bme); - bme69x_check_rslt("bme69x_get_data", rslt); - - /* Check if rslt == BME69X_OK, report or handle if otherwise */ - for (uint8_t i = 0; i < n_fields; i++) - { -#ifdef BME69X_USE_FPU - printf("%u,%lu,%.2f,%.2f,%.2f,%.2f,0x%x,%d,%d\n", - sample_count, - (long unsigned int)time_ms + (i * (del_period / 2000)), - data[i].temperature, - data[i].pressure, - data[i].humidity, - data[i].gas_resistance, - data[i].status, - data[i].gas_index, - data[i].meas_index); -#else - printf("%u, %lu, %d, %lu, %lu, %lu, 0x%x, %d, %d\n", - sample_count, - (long unsigned int)time_ms + (i * (del_period / 2000)), - (data[i].temperature), - (long unsigned int)data[i].pressure, - (long unsigned int)(data[i].humidity), - (long unsigned int)data[i].gas_resistance, - data[i].status, - data[i].gas_index, - data[i].meas_index); -#endif - sample_count++; - } - } - - bme69x_coines_deinit(); - - return 0; -}