uses BBC micro:bit to measure and display indoor air quality using Bosch BME680 and/or Sensirion SGP30

Dependencies:   microbit

uses Bosch BME680 and/or Sensirion SGP30 sensors to measure indor air quality

sensors should be connected to BBC micro:bit using i2c

commands are received and data is being sent using uBit / nordic radio protocol

display ---

last line always indicates: - first dot: bme680 detected - second dot: sgp30 detected - third dot: sgp 30 setting humidity/temperature - fourth dor: sgp30 measuring - fith dot: bme680 measuring

the detect dots should be in a stable state (not blinking) the measuring dots should be blinking (constant light means: measurement failed)

if only one bme680 is present: - first 3 lines indicate gas resistence (air quality / more dots == worse quality) - fourth line indicates humidity level

if only sgp30 is present: - first two lines indicate SGP30 VOC level - third and fourth line indicate sgp30 CO2 level

if both sensors are present: - first line indicates SGP30 VOC level - second line line indicates sgp30 CO2 level - third line indicates bme680 gas resistence (air quality) - fourth line indicates bme 680 humidity level

buttons - B display state, switches betweeen - full bright - low light - display off

AB reset sgp30 baseline in non volatile storage

data logging -- during measurements the minimum and mximum values for each measured value (temperature, air pressure, humidity,gas resistance, VOC, CO2) are being stored in non volatile storage those (and the last measurement results) are being shown when btn A has been pressed

Committer:
jsa1969
Date:
Wed Dec 05 10:50:53 2018 +0000
Revision:
14:71060505061e
Parent:
3:6084ab9ff0c9
Child:
42:ce269f988ac8
more flexible nvstore

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jsa1969 0:cef60cc92da0 1 #include "bme680.h"
jsa1969 0:cef60cc92da0 2
jsa1969 0:cef60cc92da0 3 Bme680::Bme680(I2cCallbacks *callbacks) {
jsa1969 0:cef60cc92da0 4 _dev = new bme680_dev;
jsa1969 0:cef60cc92da0 5 _dev->dev_id = BME680_I2C_ADDR_PRIMARY<<1;
jsa1969 0:cef60cc92da0 6 _i2cCallbacks = callbacks;
jsa1969 0:cef60cc92da0 7 }
jsa1969 0:cef60cc92da0 8
jsa1969 0:cef60cc92da0 9 int Bme680::init() {
jsa1969 0:cef60cc92da0 10 int rslt = soft_reset();
jsa1969 0:cef60cc92da0 11 if (rslt!=BME680_OK) return rslt;
jsa1969 0:cef60cc92da0 12
jsa1969 0:cef60cc92da0 13 rslt = get_regs(BME680_CHIP_ID_ADDR, &(_dev->chip_id), 1);
jsa1969 0:cef60cc92da0 14 if (rslt!=BME680_OK) return rslt;
jsa1969 0:cef60cc92da0 15
jsa1969 0:cef60cc92da0 16 if (_dev->chip_id == BME680_CHIP_ID) {
jsa1969 0:cef60cc92da0 17 rslt = get_calib_data();
jsa1969 0:cef60cc92da0 18 } else {
jsa1969 0:cef60cc92da0 19 rslt = BME680_E_DEV_NOT_FOUND;
jsa1969 0:cef60cc92da0 20 }
jsa1969 0:cef60cc92da0 21
jsa1969 0:cef60cc92da0 22 return rslt;
jsa1969 0:cef60cc92da0 23 }
jsa1969 0:cef60cc92da0 24
jsa1969 14:71060505061e 25 int Bme680::measure(struct bme680_field_data* data, const int ambTemp, const uint16_t heatr_dur, const uint16_t heatr_temp){
jsa1969 0:cef60cc92da0 26 int rslt = null_ptr_check();
jsa1969 0:cef60cc92da0 27 if (rslt!=BME680_OK) return rslt;
jsa1969 0:cef60cc92da0 28
jsa1969 0:cef60cc92da0 29 _dev->amb_temp = ambTemp;
jsa1969 0:cef60cc92da0 30 _dev->power_mode = BME680_FORCED_MODE;
jsa1969 0:cef60cc92da0 31
jsa1969 0:cef60cc92da0 32 _dev->tph_sett.os_hum = BME680_OS_1X;
jsa1969 0:cef60cc92da0 33 _dev->tph_sett.os_pres = BME680_OS_16X;
jsa1969 0:cef60cc92da0 34 _dev->tph_sett.os_temp = BME680_OS_2X;
jsa1969 0:cef60cc92da0 35
jsa1969 0:cef60cc92da0 36 _dev->gas_sett.run_gas = BME680_ENABLE_GAS_MEAS;
jsa1969 0:cef60cc92da0 37 _dev->gas_sett.heatr_dur = heatr_dur;
jsa1969 0:cef60cc92da0 38 _dev->gas_sett.heatr_temp = heatr_temp;
jsa1969 0:cef60cc92da0 39
jsa1969 0:cef60cc92da0 40 uint16_t settings_sel = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_GAS_SENSOR_SEL;
jsa1969 0:cef60cc92da0 41
jsa1969 0:cef60cc92da0 42 uint16_t profile_dur = 0;
jsa1969 0:cef60cc92da0 43 get_profile_dur(&profile_dur);
jsa1969 0:cef60cc92da0 44
jsa1969 0:cef60cc92da0 45 rslt = set_sensor_settings(settings_sel);
jsa1969 0:cef60cc92da0 46
jsa1969 0:cef60cc92da0 47 if (rslt == BME680_OK) {
jsa1969 0:cef60cc92da0 48 rslt = set_sensor_mode();
jsa1969 0:cef60cc92da0 49 _i2cCallbacks->delay_ms(profile_dur);
jsa1969 0:cef60cc92da0 50 rslt = get_sensor_data(data);
jsa1969 0:cef60cc92da0 51
jsa1969 0:cef60cc92da0 52 if (rslt == BME680_OK) {
jsa1969 0:cef60cc92da0 53 rslt = analyze_sensor_data(data);
jsa1969 0:cef60cc92da0 54 }
jsa1969 0:cef60cc92da0 55 }
jsa1969 0:cef60cc92da0 56
jsa1969 0:cef60cc92da0 57 return rslt;
jsa1969 0:cef60cc92da0 58 }
jsa1969 0:cef60cc92da0 59
jsa1969 0:cef60cc92da0 60 int Bme680::analyze_sensor_data(struct bme680_field_data *data)
jsa1969 0:cef60cc92da0 61 {
jsa1969 0:cef60cc92da0 62 int rslt = BME680_OK;
jsa1969 0:cef60cc92da0 63 uint8_t self_test_failed = 0;
jsa1969 0:cef60cc92da0 64
jsa1969 0:cef60cc92da0 65 const int16_t MIN_TEMPERATURE = INT16_C(0); /* 0 degree Celsius */
jsa1969 0:cef60cc92da0 66 const int16_t MAX_TEMPERATURE = INT16_C(6000); /* 60 degree Celsius */
jsa1969 0:cef60cc92da0 67
jsa1969 0:cef60cc92da0 68 const uint32_t MIN_PRESSURE = UINT32_C(90000); /* 900 hecto Pascals */
jsa1969 0:cef60cc92da0 69 const uint32_t MAX_PRESSURE = UINT32_C(110000); /* 1100 hecto Pascals */
jsa1969 0:cef60cc92da0 70
jsa1969 0:cef60cc92da0 71 const uint32_t MIN_HUMIDITY = UINT32_C(1000); /* 20% relative humidity */
jsa1969 0:cef60cc92da0 72 const uint32_t MAX_HUMIDITY = UINT32_C(100000); /* 80% relative humidity*/
jsa1969 0:cef60cc92da0 73
jsa1969 0:cef60cc92da0 74 if ((data->temperature < MIN_TEMPERATURE) || (data->temperature > MAX_TEMPERATURE))
jsa1969 0:cef60cc92da0 75 self_test_failed++;
jsa1969 0:cef60cc92da0 76
jsa1969 0:cef60cc92da0 77 if ((data->pressure < MIN_PRESSURE) || (data->pressure > MAX_PRESSURE))
jsa1969 0:cef60cc92da0 78 self_test_failed++;
jsa1969 0:cef60cc92da0 79
jsa1969 0:cef60cc92da0 80 if ((data->humidity < MIN_HUMIDITY) || (data->humidity > MAX_HUMIDITY))
jsa1969 0:cef60cc92da0 81 self_test_failed++;
jsa1969 0:cef60cc92da0 82
jsa1969 0:cef60cc92da0 83 if (!(data->status & BME680_GASM_VALID_MSK))
jsa1969 0:cef60cc92da0 84 self_test_failed++;
jsa1969 0:cef60cc92da0 85
jsa1969 0:cef60cc92da0 86 if (self_test_failed)
jsa1969 0:cef60cc92da0 87 rslt = BME680_W_SELF_TEST_FAILED;
jsa1969 0:cef60cc92da0 88
jsa1969 0:cef60cc92da0 89 return rslt;
jsa1969 0:cef60cc92da0 90 }
jsa1969 0:cef60cc92da0 91
jsa1969 0:cef60cc92da0 92 int Bme680::soft_reset() {
jsa1969 0:cef60cc92da0 93 int rslt = null_ptr_check();
jsa1969 0:cef60cc92da0 94 if (rslt!=BME680_OK) return rslt;
jsa1969 0:cef60cc92da0 95
jsa1969 0:cef60cc92da0 96 uint8_t reg_addr = BME680_SOFT_RESET_ADDR;
jsa1969 0:cef60cc92da0 97 uint8_t soft_rst_cmd = BME680_SOFT_RESET_CMD;
jsa1969 0:cef60cc92da0 98 rslt = set_regs(&reg_addr, &soft_rst_cmd, 1);
jsa1969 0:cef60cc92da0 99
jsa1969 0:cef60cc92da0 100 if (rslt==BME680_OK) {
jsa1969 0:cef60cc92da0 101 _i2cCallbacks->delay_ms(BME680_RESET_PERIOD);
jsa1969 0:cef60cc92da0 102 }
jsa1969 0:cef60cc92da0 103
jsa1969 0:cef60cc92da0 104 return rslt;
jsa1969 0:cef60cc92da0 105 }
jsa1969 0:cef60cc92da0 106
jsa1969 0:cef60cc92da0 107 int Bme680::get_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
jsa1969 0:cef60cc92da0 108 {
jsa1969 0:cef60cc92da0 109 int rslt = null_ptr_check();
jsa1969 0:cef60cc92da0 110 if (rslt!=BME680_OK) return rslt;
jsa1969 0:cef60cc92da0 111
jsa1969 0:cef60cc92da0 112 _dev->com_rslt = _i2cCallbacks->read(_dev->dev_id, reg_addr, reg_data, len);
jsa1969 0:cef60cc92da0 113 if (_dev->com_rslt != 0)
jsa1969 0:cef60cc92da0 114 rslt = BME680_E_COM_FAIL;
jsa1969 0:cef60cc92da0 115 return rslt;
jsa1969 0:cef60cc92da0 116 }
jsa1969 0:cef60cc92da0 117
jsa1969 0:cef60cc92da0 118
jsa1969 0:cef60cc92da0 119 /*
jsa1969 0:cef60cc92da0 120 int8_t Bme680::get_mem_page()
jsa1969 0:cef60cc92da0 121 {
jsa1969 0:cef60cc92da0 122 int8_t rslt = null_ptr_check();
jsa1969 0:cef60cc92da0 123 if (rslt!=BME680_OK) return rslt;
jsa1969 0:cef60cc92da0 124
jsa1969 0:cef60cc92da0 125 uint8_t reg;
jsa1969 0:cef60cc92da0 126
jsa1969 0:cef60cc92da0 127 _dev->com_rslt = _i2cCallbacks->read(_dev->dev_id, BME680_MEM_PAGE_ADDR | BME680_SPI_RD_MSK, &reg, 1);
jsa1969 0:cef60cc92da0 128 if (_dev->com_rslt != 0)
jsa1969 0:cef60cc92da0 129 rslt = BME680_E_COM_FAIL;
jsa1969 0:cef60cc92da0 130 else
jsa1969 0:cef60cc92da0 131 _dev->mem_page = reg & BME680_MEM_PAGE_MSK;
jsa1969 0:cef60cc92da0 132
jsa1969 0:cef60cc92da0 133 return rslt;
jsa1969 0:cef60cc92da0 134 }
jsa1969 0:cef60cc92da0 135 */
jsa1969 0:cef60cc92da0 136
jsa1969 0:cef60cc92da0 137 int Bme680::set_regs(const uint8_t *reg_addr, const uint8_t *reg_data, uint8_t len)
jsa1969 0:cef60cc92da0 138 {
jsa1969 0:cef60cc92da0 139 int rslt = null_ptr_check();
jsa1969 0:cef60cc92da0 140 if (rslt!=BME680_OK) return rslt;
jsa1969 0:cef60cc92da0 141
jsa1969 0:cef60cc92da0 142 /* Length of the temporary buffer is 2*(length of register)*/
jsa1969 0:cef60cc92da0 143 uint8_t tmp_buff[BME680_TMP_BUFFER_LENGTH] = { 0 };
jsa1969 0:cef60cc92da0 144 uint16_t index;
jsa1969 0:cef60cc92da0 145
jsa1969 0:cef60cc92da0 146 if ((len > 0) && (len < BME680_TMP_BUFFER_LENGTH / 2)) {
jsa1969 0:cef60cc92da0 147 /* Interleave the 2 arrays */
jsa1969 0:cef60cc92da0 148 for (index = 0; index < len; index++) {
jsa1969 0:cef60cc92da0 149 tmp_buff[(2 * index)] = reg_addr[index];
jsa1969 0:cef60cc92da0 150 tmp_buff[(2 * index) + 1] = reg_data[index];
jsa1969 0:cef60cc92da0 151 }
jsa1969 0:cef60cc92da0 152 /* Write the interleaved array */
jsa1969 0:cef60cc92da0 153 _dev->com_rslt = _i2cCallbacks->write(_dev->dev_id, tmp_buff[0], &tmp_buff[1], (2 * len) - 1);
jsa1969 0:cef60cc92da0 154 if (_dev->com_rslt != 0) {
jsa1969 0:cef60cc92da0 155 rslt = BME680_E_COM_FAIL;
jsa1969 0:cef60cc92da0 156 }
jsa1969 0:cef60cc92da0 157 } else {
jsa1969 0:cef60cc92da0 158 rslt = BME680_E_INVALID_LENGTH;
jsa1969 0:cef60cc92da0 159 }
jsa1969 0:cef60cc92da0 160
jsa1969 0:cef60cc92da0 161 return rslt;
jsa1969 0:cef60cc92da0 162 }
jsa1969 0:cef60cc92da0 163
jsa1969 0:cef60cc92da0 164 int Bme680::null_ptr_check()
jsa1969 0:cef60cc92da0 165 {
jsa1969 0:cef60cc92da0 166 if (_dev == NULL || _i2cCallbacks == NULL) {
jsa1969 0:cef60cc92da0 167 /* Device structure pointer is not valid */
jsa1969 0:cef60cc92da0 168 return BME680_E_NULL_PTR;
jsa1969 0:cef60cc92da0 169 } else {
jsa1969 0:cef60cc92da0 170 /* Device structure is fine */
jsa1969 0:cef60cc92da0 171 return BME680_OK;
jsa1969 0:cef60cc92da0 172 }
jsa1969 0:cef60cc92da0 173 }
jsa1969 0:cef60cc92da0 174
jsa1969 0:cef60cc92da0 175 int Bme680::get_calib_data()
jsa1969 0:cef60cc92da0 176 {
jsa1969 0:cef60cc92da0 177 int rslt;
jsa1969 0:cef60cc92da0 178 uint8_t coeff_array[BME680_COEFF_SIZE] = { 0 };
jsa1969 0:cef60cc92da0 179 uint8_t temp_var = 0; /* Temporary variable */
jsa1969 0:cef60cc92da0 180
jsa1969 0:cef60cc92da0 181 /* Check for null pointer in the device structure*/
jsa1969 0:cef60cc92da0 182 rslt = null_ptr_check();
jsa1969 0:cef60cc92da0 183 if (rslt == BME680_OK) {
jsa1969 0:cef60cc92da0 184 rslt = get_regs(BME680_COEFF_ADDR1, coeff_array, BME680_COEFF_ADDR1_LEN);
jsa1969 0:cef60cc92da0 185 /* Append the second half in the same array */
jsa1969 0:cef60cc92da0 186 if (rslt == BME680_OK)
jsa1969 0:cef60cc92da0 187 rslt = get_regs(BME680_COEFF_ADDR2, &coeff_array[BME680_COEFF_ADDR1_LEN]
jsa1969 0:cef60cc92da0 188 , BME680_COEFF_ADDR2_LEN);
jsa1969 0:cef60cc92da0 189
jsa1969 0:cef60cc92da0 190 /* Temperature related coefficients */
jsa1969 0:cef60cc92da0 191 _dev->calib.par_t1 = (uint16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_T1_MSB_REG],
jsa1969 0:cef60cc92da0 192 coeff_array[BME680_T1_LSB_REG]));
jsa1969 0:cef60cc92da0 193 _dev->calib.par_t2 = (int16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_T2_MSB_REG],
jsa1969 0:cef60cc92da0 194 coeff_array[BME680_T2_LSB_REG]));
jsa1969 0:cef60cc92da0 195 _dev->calib.par_t3 = (int8_t) (coeff_array[BME680_T3_REG]);
jsa1969 0:cef60cc92da0 196
jsa1969 0:cef60cc92da0 197 /* Pressure related coefficients */
jsa1969 0:cef60cc92da0 198 _dev->calib.par_p1 = (uint16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_P1_MSB_REG],
jsa1969 0:cef60cc92da0 199 coeff_array[BME680_P1_LSB_REG]));
jsa1969 0:cef60cc92da0 200 _dev->calib.par_p2 = (int16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_P2_MSB_REG],
jsa1969 0:cef60cc92da0 201 coeff_array[BME680_P2_LSB_REG]));
jsa1969 0:cef60cc92da0 202 _dev->calib.par_p3 = (int8_t) coeff_array[BME680_P3_REG];
jsa1969 0:cef60cc92da0 203 _dev->calib.par_p4 = (int16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_P4_MSB_REG],
jsa1969 0:cef60cc92da0 204 coeff_array[BME680_P4_LSB_REG]));
jsa1969 0:cef60cc92da0 205 _dev->calib.par_p5 = (int16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_P5_MSB_REG],
jsa1969 0:cef60cc92da0 206 coeff_array[BME680_P5_LSB_REG]));
jsa1969 0:cef60cc92da0 207 _dev->calib.par_p6 = (int8_t) (coeff_array[BME680_P6_REG]);
jsa1969 0:cef60cc92da0 208 _dev->calib.par_p7 = (int8_t) (coeff_array[BME680_P7_REG]);
jsa1969 0:cef60cc92da0 209 _dev->calib.par_p8 = (int16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_P8_MSB_REG],
jsa1969 0:cef60cc92da0 210 coeff_array[BME680_P8_LSB_REG]));
jsa1969 0:cef60cc92da0 211 _dev->calib.par_p9 = (int16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_P9_MSB_REG],
jsa1969 0:cef60cc92da0 212 coeff_array[BME680_P9_LSB_REG]));
jsa1969 0:cef60cc92da0 213 _dev->calib.par_p10 = (uint8_t) (coeff_array[BME680_P10_REG]);
jsa1969 0:cef60cc92da0 214
jsa1969 0:cef60cc92da0 215 /* Humidity related coefficients */
jsa1969 0:cef60cc92da0 216 _dev->calib.par_h1 = (uint16_t) (((uint16_t) coeff_array[BME680_H1_MSB_REG] << BME680_HUM_REG_SHIFT_VAL)
jsa1969 0:cef60cc92da0 217 | (coeff_array[BME680_H1_LSB_REG] & BME680_BIT_H1_DATA_MSK));
jsa1969 0:cef60cc92da0 218 _dev->calib.par_h2 = (uint16_t) (((uint16_t) coeff_array[BME680_H2_MSB_REG] << BME680_HUM_REG_SHIFT_VAL)
jsa1969 0:cef60cc92da0 219 | ((coeff_array[BME680_H2_LSB_REG]) >> BME680_HUM_REG_SHIFT_VAL));
jsa1969 0:cef60cc92da0 220 _dev->calib.par_h3 = (int8_t) coeff_array[BME680_H3_REG];
jsa1969 0:cef60cc92da0 221 _dev->calib.par_h4 = (int8_t) coeff_array[BME680_H4_REG];
jsa1969 0:cef60cc92da0 222 _dev->calib.par_h5 = (int8_t) coeff_array[BME680_H5_REG];
jsa1969 0:cef60cc92da0 223 _dev->calib.par_h6 = (uint8_t) coeff_array[BME680_H6_REG];
jsa1969 0:cef60cc92da0 224 _dev->calib.par_h7 = (int8_t) coeff_array[BME680_H7_REG];
jsa1969 0:cef60cc92da0 225
jsa1969 0:cef60cc92da0 226 /* Gas heater related coefficients */
jsa1969 0:cef60cc92da0 227 _dev->calib.par_gh1 = (int8_t) coeff_array[BME680_GH1_REG];
jsa1969 0:cef60cc92da0 228 _dev->calib.par_gh2 = (int16_t) (BME680_CONCAT_BYTES(coeff_array[BME680_GH2_MSB_REG],
jsa1969 0:cef60cc92da0 229 coeff_array[BME680_GH2_LSB_REG]));
jsa1969 0:cef60cc92da0 230 _dev->calib.par_gh3 = (int8_t) coeff_array[BME680_GH3_REG];
jsa1969 0:cef60cc92da0 231
jsa1969 0:cef60cc92da0 232 /* Other coefficients */
jsa1969 0:cef60cc92da0 233 if (rslt == BME680_OK) {
jsa1969 0:cef60cc92da0 234 rslt = get_regs(BME680_ADDR_RES_HEAT_RANGE_ADDR, &temp_var, 1);
jsa1969 0:cef60cc92da0 235
jsa1969 0:cef60cc92da0 236 _dev->calib.res_heat_range = ((temp_var & BME680_RHRANGE_MSK) / 16);
jsa1969 0:cef60cc92da0 237 if (rslt == BME680_OK) {
jsa1969 0:cef60cc92da0 238 rslt = get_regs(BME680_ADDR_RES_HEAT_VAL_ADDR, &temp_var, 1);
jsa1969 0:cef60cc92da0 239
jsa1969 0:cef60cc92da0 240 _dev->calib.res_heat_val = (int8_t) temp_var;
jsa1969 0:cef60cc92da0 241 if (rslt == BME680_OK)
jsa1969 0:cef60cc92da0 242 rslt = get_regs(BME680_ADDR_RANGE_SW_ERR_ADDR, &temp_var, 1);
jsa1969 0:cef60cc92da0 243 }
jsa1969 0:cef60cc92da0 244 }
jsa1969 0:cef60cc92da0 245 _dev->calib.range_sw_err = ((int8_t) temp_var & (int8_t) BME680_RSERROR_MSK) / 16;
jsa1969 0:cef60cc92da0 246 }
jsa1969 0:cef60cc92da0 247
jsa1969 0:cef60cc92da0 248 return rslt;
jsa1969 0:cef60cc92da0 249 }
jsa1969 0:cef60cc92da0 250
jsa1969 0:cef60cc92da0 251 void Bme680::set_profile_dur(uint16_t duration)
jsa1969 0:cef60cc92da0 252 {
jsa1969 0:cef60cc92da0 253 uint32_t tph_dur; /* Calculate in us */
jsa1969 0:cef60cc92da0 254 uint32_t meas_cycles;
jsa1969 0:cef60cc92da0 255 uint8_t os_to_meas_cycles[6] = {0, 1, 2, 4, 8, 16};
jsa1969 0:cef60cc92da0 256
jsa1969 0:cef60cc92da0 257 meas_cycles = os_to_meas_cycles[_dev->tph_sett.os_temp];
jsa1969 0:cef60cc92da0 258 meas_cycles += os_to_meas_cycles[_dev->tph_sett.os_pres];
jsa1969 0:cef60cc92da0 259 meas_cycles += os_to_meas_cycles[_dev->tph_sett.os_hum];
jsa1969 0:cef60cc92da0 260
jsa1969 0:cef60cc92da0 261 /* TPH measurement duration */
jsa1969 0:cef60cc92da0 262 tph_dur = meas_cycles * UINT32_C(1963);
jsa1969 0:cef60cc92da0 263 tph_dur += UINT32_C(477 * 4); /* TPH switching duration */
jsa1969 0:cef60cc92da0 264 tph_dur += UINT32_C(477 * 5); /* Gas measurement duration */
jsa1969 0:cef60cc92da0 265 tph_dur += UINT32_C(500); /* Get it to the closest whole number.*/
jsa1969 0:cef60cc92da0 266 tph_dur /= UINT32_C(1000); /* Convert to ms */
jsa1969 0:cef60cc92da0 267
jsa1969 0:cef60cc92da0 268 tph_dur += UINT32_C(1); /* Wake up duration of 1ms */
jsa1969 0:cef60cc92da0 269 /* The remaining time should be used for heating */
jsa1969 0:cef60cc92da0 270 _dev->gas_sett.heatr_dur = duration - (uint16_t) tph_dur;
jsa1969 0:cef60cc92da0 271 }
jsa1969 0:cef60cc92da0 272
jsa1969 0:cef60cc92da0 273 void Bme680::get_profile_dur(uint16_t *duration)
jsa1969 0:cef60cc92da0 274 {
jsa1969 0:cef60cc92da0 275 uint32_t tph_dur; /* Calculate in us */
jsa1969 0:cef60cc92da0 276 uint32_t meas_cycles;
jsa1969 0:cef60cc92da0 277 uint8_t os_to_meas_cycles[6] = {0, 1, 2, 4, 8, 16};
jsa1969 0:cef60cc92da0 278
jsa1969 0:cef60cc92da0 279 meas_cycles = os_to_meas_cycles[_dev->tph_sett.os_temp];
jsa1969 0:cef60cc92da0 280 meas_cycles += os_to_meas_cycles[_dev->tph_sett.os_pres];
jsa1969 0:cef60cc92da0 281 meas_cycles += os_to_meas_cycles[_dev->tph_sett.os_hum];
jsa1969 0:cef60cc92da0 282
jsa1969 0:cef60cc92da0 283 /* TPH measurement duration */
jsa1969 0:cef60cc92da0 284 tph_dur = meas_cycles * UINT32_C(1963);
jsa1969 0:cef60cc92da0 285 tph_dur += UINT32_C(477 * 4); /* TPH switching duration */
jsa1969 0:cef60cc92da0 286 tph_dur += UINT32_C(477 * 5); /* Gas measurement duration */
jsa1969 0:cef60cc92da0 287 tph_dur += UINT32_C(500); /* Get it to the closest whole number.*/
jsa1969 0:cef60cc92da0 288 tph_dur /= UINT32_C(1000); /* Convert to ms */
jsa1969 0:cef60cc92da0 289
jsa1969 0:cef60cc92da0 290 tph_dur += UINT32_C(1); /* Wake up duration of 1ms */
jsa1969 0:cef60cc92da0 291
jsa1969 0:cef60cc92da0 292 *duration = (uint16_t) tph_dur;
jsa1969 0:cef60cc92da0 293
jsa1969 0:cef60cc92da0 294 /* Get the gas duration only when the run gas is enabled */
jsa1969 0:cef60cc92da0 295 if (_dev->gas_sett.run_gas) {
jsa1969 0:cef60cc92da0 296 /* The remaining time should be used for heating */
jsa1969 0:cef60cc92da0 297 *duration += _dev->gas_sett.heatr_dur;
jsa1969 0:cef60cc92da0 298 }
jsa1969 0:cef60cc92da0 299 }
jsa1969 0:cef60cc92da0 300
jsa1969 0:cef60cc92da0 301 int Bme680::get_sensor_data(struct bme680_field_data *data)
jsa1969 0:cef60cc92da0 302 {
jsa1969 0:cef60cc92da0 303 int rslt = null_ptr_check();
jsa1969 0:cef60cc92da0 304 if (rslt!=BME680_OK) return rslt;
jsa1969 0:cef60cc92da0 305
jsa1969 0:cef60cc92da0 306 /* Reading the sensor data in forced mode only */
jsa1969 0:cef60cc92da0 307 rslt = read_field_data(data);
jsa1969 0:cef60cc92da0 308 if (rslt == BME680_OK) {
jsa1969 0:cef60cc92da0 309 if (data->status & BME680_NEW_DATA_MSK)
jsa1969 0:cef60cc92da0 310 _dev->new_fields = 1;
jsa1969 0:cef60cc92da0 311 else
jsa1969 0:cef60cc92da0 312 _dev->new_fields = 0;
jsa1969 0:cef60cc92da0 313 }
jsa1969 0:cef60cc92da0 314
jsa1969 0:cef60cc92da0 315 return rslt;
jsa1969 0:cef60cc92da0 316 }
jsa1969 0:cef60cc92da0 317
jsa1969 0:cef60cc92da0 318 int Bme680::read_field_data(struct bme680_field_data *data){
jsa1969 0:cef60cc92da0 319 int rslt = null_ptr_check();
jsa1969 0:cef60cc92da0 320 if (rslt!=BME680_OK) return rslt;
jsa1969 0:cef60cc92da0 321
jsa1969 0:cef60cc92da0 322 uint8_t buff[BME680_FIELD_LENGTH] = { 0 };
jsa1969 0:cef60cc92da0 323 uint8_t gas_range;
jsa1969 0:cef60cc92da0 324 uint32_t adc_temp;
jsa1969 0:cef60cc92da0 325 uint32_t adc_pres;
jsa1969 0:cef60cc92da0 326 uint16_t adc_hum;
jsa1969 0:cef60cc92da0 327 uint16_t adc_gas_res;
jsa1969 0:cef60cc92da0 328 uint8_t tries = 10;
jsa1969 0:cef60cc92da0 329
jsa1969 0:cef60cc92da0 330 do {
jsa1969 0:cef60cc92da0 331 if (rslt == BME680_OK) {
jsa1969 0:cef60cc92da0 332 rslt = get_regs(((uint8_t) (BME680_FIELD0_ADDR)), buff, (uint16_t) BME680_FIELD_LENGTH);
jsa1969 0:cef60cc92da0 333
jsa1969 0:cef60cc92da0 334 data->status = buff[0] & BME680_NEW_DATA_MSK;
jsa1969 0:cef60cc92da0 335 data->gas_index = buff[0] & BME680_GAS_INDEX_MSK;
jsa1969 0:cef60cc92da0 336 data->meas_index = buff[1];
jsa1969 0:cef60cc92da0 337
jsa1969 0:cef60cc92da0 338 /* read the raw data from the sensor */
jsa1969 0:cef60cc92da0 339 adc_pres = (uint32_t) (((uint32_t) buff[2] * 4096) | ((uint32_t) buff[3] * 16)
jsa1969 0:cef60cc92da0 340 | ((uint32_t) buff[4] / 16));
jsa1969 0:cef60cc92da0 341 adc_temp = (uint32_t) (((uint32_t) buff[5] * 4096) | ((uint32_t) buff[6] * 16)
jsa1969 0:cef60cc92da0 342 | ((uint32_t) buff[7] / 16));
jsa1969 0:cef60cc92da0 343 adc_hum = (uint16_t) (((uint32_t) buff[8] * 256) | (uint32_t) buff[9]);
jsa1969 0:cef60cc92da0 344 adc_gas_res = (uint16_t) ((uint32_t) buff[13] * 4 | (((uint32_t) buff[14]) / 64));
jsa1969 0:cef60cc92da0 345 gas_range = buff[14] & BME680_GAS_RANGE_MSK;
jsa1969 0:cef60cc92da0 346
jsa1969 0:cef60cc92da0 347 data->status |= buff[14] & BME680_GASM_VALID_MSK;
jsa1969 0:cef60cc92da0 348 data->status |= buff[14] & BME680_HEAT_STAB_MSK;
jsa1969 0:cef60cc92da0 349
jsa1969 0:cef60cc92da0 350 if (data->status & BME680_NEW_DATA_MSK) {
jsa1969 0:cef60cc92da0 351 data->temperature = calc_temperature(adc_temp);
jsa1969 0:cef60cc92da0 352 data->pressure = calc_pressure(adc_pres);
jsa1969 0:cef60cc92da0 353 data->humidity = calc_humidity(adc_hum);
jsa1969 0:cef60cc92da0 354 data->gas_resistance = calc_gas_resistance(adc_gas_res, gas_range);
jsa1969 0:cef60cc92da0 355 break;
jsa1969 0:cef60cc92da0 356 }
jsa1969 0:cef60cc92da0 357 /* Delay to poll the data */
jsa1969 0:cef60cc92da0 358 _i2cCallbacks->delay_ms(BME680_POLL_PERIOD_MS);
jsa1969 0:cef60cc92da0 359 }
jsa1969 0:cef60cc92da0 360 tries--;
jsa1969 0:cef60cc92da0 361 } while (tries);
jsa1969 0:cef60cc92da0 362
jsa1969 0:cef60cc92da0 363 if (!tries){
jsa1969 0:cef60cc92da0 364 rslt = BME680_W_NO_NEW_DATA;
jsa1969 0:cef60cc92da0 365 }
jsa1969 0:cef60cc92da0 366
jsa1969 0:cef60cc92da0 367 return rslt;
jsa1969 0:cef60cc92da0 368 }
jsa1969 0:cef60cc92da0 369
jsa1969 0:cef60cc92da0 370 int Bme680::get_sensor_mode(struct bme680_dev *dev)
jsa1969 0:cef60cc92da0 371 {
jsa1969 0:cef60cc92da0 372 int rslt = null_ptr_check();
jsa1969 0:cef60cc92da0 373 if (rslt!=BME680_OK) return rslt;
jsa1969 0:cef60cc92da0 374
jsa1969 0:cef60cc92da0 375 uint8_t mode;
jsa1969 0:cef60cc92da0 376
jsa1969 0:cef60cc92da0 377 rslt = get_regs(BME680_CONF_T_P_MODE_ADDR, &mode, 1);
jsa1969 0:cef60cc92da0 378 /* Masking the other register bit info*/
jsa1969 0:cef60cc92da0 379 _dev->power_mode = mode & BME680_MODE_MSK;
jsa1969 0:cef60cc92da0 380
jsa1969 0:cef60cc92da0 381 return rslt;
jsa1969 0:cef60cc92da0 382 }
jsa1969 0:cef60cc92da0 383
jsa1969 0:cef60cc92da0 384 int Bme680::set_sensor_mode()
jsa1969 0:cef60cc92da0 385 {
jsa1969 0:cef60cc92da0 386 int rslt = null_ptr_check();
jsa1969 0:cef60cc92da0 387 if (rslt!=BME680_OK) return rslt;
jsa1969 0:cef60cc92da0 388
jsa1969 0:cef60cc92da0 389 uint8_t tmp_pow_mode;
jsa1969 0:cef60cc92da0 390 uint8_t pow_mode = 0;
jsa1969 0:cef60cc92da0 391 uint8_t reg_addr = BME680_CONF_T_P_MODE_ADDR;
jsa1969 0:cef60cc92da0 392
jsa1969 0:cef60cc92da0 393 /* Call repeatedly until in sleep */
jsa1969 0:cef60cc92da0 394 do {
jsa1969 0:cef60cc92da0 395 rslt = get_regs(BME680_CONF_T_P_MODE_ADDR, &tmp_pow_mode, 1);
jsa1969 0:cef60cc92da0 396 if (rslt == BME680_OK) {
jsa1969 0:cef60cc92da0 397 /* Put to sleep before changing mode */
jsa1969 0:cef60cc92da0 398 pow_mode = (tmp_pow_mode & BME680_MODE_MSK);
jsa1969 0:cef60cc92da0 399
jsa1969 0:cef60cc92da0 400 if (pow_mode != BME680_SLEEP_MODE) {
jsa1969 0:cef60cc92da0 401 tmp_pow_mode = tmp_pow_mode & (~BME680_MODE_MSK); /* Set to sleep */
jsa1969 0:cef60cc92da0 402 rslt = set_regs(&reg_addr, &tmp_pow_mode, 1);
jsa1969 0:cef60cc92da0 403 _i2cCallbacks->delay_ms(BME680_POLL_PERIOD_MS);
jsa1969 0:cef60cc92da0 404 }
jsa1969 0:cef60cc92da0 405 }
jsa1969 0:cef60cc92da0 406 } while (pow_mode != BME680_SLEEP_MODE);
jsa1969 0:cef60cc92da0 407
jsa1969 0:cef60cc92da0 408 /* Already in sleep */
jsa1969 0:cef60cc92da0 409 if (_dev->power_mode != BME680_SLEEP_MODE) {
jsa1969 0:cef60cc92da0 410 tmp_pow_mode = (tmp_pow_mode & ~BME680_MODE_MSK) | (_dev->power_mode & BME680_MODE_MSK);
jsa1969 0:cef60cc92da0 411 if (rslt == BME680_OK) {
jsa1969 0:cef60cc92da0 412 rslt = set_regs(&reg_addr, &tmp_pow_mode, 1);
jsa1969 0:cef60cc92da0 413 }
jsa1969 0:cef60cc92da0 414 }
jsa1969 0:cef60cc92da0 415
jsa1969 0:cef60cc92da0 416 return rslt;
jsa1969 0:cef60cc92da0 417 }
jsa1969 0:cef60cc92da0 418
jsa1969 0:cef60cc92da0 419 int Bme680::set_gas_config()
jsa1969 0:cef60cc92da0 420 {
jsa1969 0:cef60cc92da0 421 int rslt = null_ptr_check();
jsa1969 0:cef60cc92da0 422 if (rslt!=BME680_OK) return rslt;
jsa1969 0:cef60cc92da0 423
jsa1969 0:cef60cc92da0 424 uint8_t reg_addr[2] = {0};
jsa1969 0:cef60cc92da0 425 uint8_t reg_data[2] = {0};
jsa1969 0:cef60cc92da0 426
jsa1969 0:cef60cc92da0 427 if (_dev->power_mode == BME680_FORCED_MODE) {
jsa1969 0:cef60cc92da0 428 reg_addr[0] = BME680_RES_HEAT0_ADDR;
jsa1969 0:cef60cc92da0 429 reg_data[0] = calc_heater_res(_dev->gas_sett.heatr_temp);
jsa1969 0:cef60cc92da0 430 reg_addr[1] = BME680_GAS_WAIT0_ADDR;
jsa1969 0:cef60cc92da0 431 reg_data[1] = calc_heater_dur(_dev->gas_sett.heatr_dur);
jsa1969 0:cef60cc92da0 432 _dev->gas_sett.nb_conv = 0;
jsa1969 0:cef60cc92da0 433 } else {
jsa1969 0:cef60cc92da0 434 rslt = BME680_W_DEFINE_PWR_MODE;
jsa1969 0:cef60cc92da0 435 }
jsa1969 0:cef60cc92da0 436
jsa1969 0:cef60cc92da0 437 if (rslt == BME680_OK) {
jsa1969 0:cef60cc92da0 438 rslt = set_regs(reg_addr, reg_data, 2);
jsa1969 0:cef60cc92da0 439 }
jsa1969 0:cef60cc92da0 440
jsa1969 0:cef60cc92da0 441 return rslt;
jsa1969 0:cef60cc92da0 442 }
jsa1969 0:cef60cc92da0 443
jsa1969 0:cef60cc92da0 444 uint8_t Bme680::calc_heater_dur(uint16_t dur)
jsa1969 0:cef60cc92da0 445 {
jsa1969 0:cef60cc92da0 446 uint8_t factor = 0;
jsa1969 0:cef60cc92da0 447 uint8_t durval;
jsa1969 0:cef60cc92da0 448
jsa1969 0:cef60cc92da0 449 if (dur >= 0xfc0) {
jsa1969 0:cef60cc92da0 450 durval = 0xff; /* Max duration*/
jsa1969 0:cef60cc92da0 451 } else {
jsa1969 0:cef60cc92da0 452 while (dur > 0x3F) {
jsa1969 0:cef60cc92da0 453 dur = dur / 4;
jsa1969 0:cef60cc92da0 454 factor += 1;
jsa1969 0:cef60cc92da0 455 }
jsa1969 0:cef60cc92da0 456 durval = (uint8_t) (dur + (factor * 64));
jsa1969 0:cef60cc92da0 457 }
jsa1969 0:cef60cc92da0 458
jsa1969 0:cef60cc92da0 459 return durval;
jsa1969 0:cef60cc92da0 460 }
jsa1969 0:cef60cc92da0 461
jsa1969 0:cef60cc92da0 462
jsa1969 0:cef60cc92da0 463 uint8_t Bme680::calc_heater_res(uint16_t temp)
jsa1969 0:cef60cc92da0 464 {
jsa1969 0:cef60cc92da0 465 uint8_t heatr_res;
jsa1969 0:cef60cc92da0 466 int32_t var1;
jsa1969 0:cef60cc92da0 467 int32_t var2;
jsa1969 0:cef60cc92da0 468 int32_t var3;
jsa1969 0:cef60cc92da0 469 int32_t var4;
jsa1969 0:cef60cc92da0 470 int32_t var5;
jsa1969 0:cef60cc92da0 471 int32_t heatr_res_x100;
jsa1969 0:cef60cc92da0 472
jsa1969 0:cef60cc92da0 473 if (temp > 400) {
jsa1969 0:cef60cc92da0 474 temp = 400;
jsa1969 0:cef60cc92da0 475 }
jsa1969 0:cef60cc92da0 476
jsa1969 0:cef60cc92da0 477 var1 = (((int32_t) _dev->amb_temp * _dev->calib.par_gh3) / 1000) * 256;
jsa1969 0:cef60cc92da0 478 var2 = (_dev->calib.par_gh1 + 784) * (((((_dev->calib.par_gh2 + 154009) * temp * 5) / 100) + 3276800) / 10);
jsa1969 0:cef60cc92da0 479 var3 = var1 + (var2 / 2);
jsa1969 0:cef60cc92da0 480 var4 = (var3 / (_dev->calib.res_heat_range + 4));
jsa1969 0:cef60cc92da0 481 var5 = (131 * _dev->calib.res_heat_val) + 65536;
jsa1969 0:cef60cc92da0 482 heatr_res_x100 = (int32_t) (((var4 / var5) - 250) * 34);
jsa1969 0:cef60cc92da0 483 heatr_res = (uint8_t) ((heatr_res_x100 + 50) / 100);
jsa1969 0:cef60cc92da0 484
jsa1969 0:cef60cc92da0 485 return heatr_res;
jsa1969 0:cef60cc92da0 486 }
jsa1969 0:cef60cc92da0 487
jsa1969 0:cef60cc92da0 488 int Bme680::boundary_check(uint8_t *value, uint8_t min, uint8_t max) {
jsa1969 0:cef60cc92da0 489 int rslt = BME680_OK;
jsa1969 0:cef60cc92da0 490
jsa1969 0:cef60cc92da0 491 if (value != NULL) {
jsa1969 0:cef60cc92da0 492 // Check if value is below minimum value
jsa1969 0:cef60cc92da0 493 if (*value < min) {
jsa1969 0:cef60cc92da0 494 // Auto correct the invalid value to minimum value
jsa1969 0:cef60cc92da0 495 *value = min;
jsa1969 0:cef60cc92da0 496 _dev->info_msg |= BME680_I_MIN_CORRECTION;
jsa1969 0:cef60cc92da0 497 }
jsa1969 0:cef60cc92da0 498 // Check if value is above maximum value
jsa1969 0:cef60cc92da0 499 if (*value > max) {
jsa1969 0:cef60cc92da0 500 // Auto correct the invalid value to maximum value
jsa1969 0:cef60cc92da0 501 *value = max;
jsa1969 0:cef60cc92da0 502 _dev->info_msg |= BME680_I_MAX_CORRECTION;
jsa1969 0:cef60cc92da0 503 }
jsa1969 0:cef60cc92da0 504 } else {
jsa1969 0:cef60cc92da0 505 rslt = BME680_E_NULL_PTR;
jsa1969 0:cef60cc92da0 506 }
jsa1969 0:cef60cc92da0 507
jsa1969 0:cef60cc92da0 508 return rslt;
jsa1969 0:cef60cc92da0 509 }
jsa1969 0:cef60cc92da0 510
jsa1969 0:cef60cc92da0 511 int Bme680::set_sensor_settings(uint16_t desired_settings)
jsa1969 0:cef60cc92da0 512 {
jsa1969 0:cef60cc92da0 513 int rslt = null_ptr_check();
jsa1969 0:cef60cc92da0 514 if (rslt!=BME680_OK) return rslt;
jsa1969 0:cef60cc92da0 515
jsa1969 0:cef60cc92da0 516 uint8_t reg_addr;
jsa1969 0:cef60cc92da0 517 uint8_t data = 0;
jsa1969 0:cef60cc92da0 518 uint8_t count = 0;
jsa1969 0:cef60cc92da0 519 uint8_t reg_array[BME680_REG_BUFFER_LENGTH] = { 0 };
jsa1969 0:cef60cc92da0 520 uint8_t data_array[BME680_REG_BUFFER_LENGTH] = { 0 };
jsa1969 0:cef60cc92da0 521 uint8_t intended_power_mode = _dev->power_mode; // Save intended power mode
jsa1969 0:cef60cc92da0 522
jsa1969 0:cef60cc92da0 523 // Check for null pointer in the device structure
jsa1969 0:cef60cc92da0 524
jsa1969 0:cef60cc92da0 525 if (desired_settings & BME680_GAS_MEAS_SEL) {
jsa1969 0:cef60cc92da0 526 rslt = set_gas_config();
jsa1969 0:cef60cc92da0 527 }
jsa1969 0:cef60cc92da0 528
jsa1969 0:cef60cc92da0 529 _dev->power_mode = BME680_SLEEP_MODE;
jsa1969 0:cef60cc92da0 530 if (rslt == BME680_OK) {
jsa1969 0:cef60cc92da0 531 rslt = set_sensor_mode();
jsa1969 0:cef60cc92da0 532 }
jsa1969 0:cef60cc92da0 533
jsa1969 0:cef60cc92da0 534 // Selecting the filter
jsa1969 0:cef60cc92da0 535 if (desired_settings & BME680_FILTER_SEL) {
jsa1969 0:cef60cc92da0 536 rslt = boundary_check(&(_dev->tph_sett.filter), BME680_FILTER_SIZE_0, BME680_FILTER_SIZE_127);
jsa1969 0:cef60cc92da0 537 reg_addr = BME680_CONF_ODR_FILT_ADDR;
jsa1969 0:cef60cc92da0 538
jsa1969 0:cef60cc92da0 539 if (rslt == BME680_OK) {
jsa1969 0:cef60cc92da0 540 rslt = get_regs(reg_addr, &data, 1);
jsa1969 0:cef60cc92da0 541 }
jsa1969 0:cef60cc92da0 542
jsa1969 0:cef60cc92da0 543 if (desired_settings & BME680_FILTER_SEL) {
jsa1969 0:cef60cc92da0 544 data = BME680_SET_BITS(data, BME680_FILTER, _dev->tph_sett.filter);
jsa1969 0:cef60cc92da0 545 }
jsa1969 0:cef60cc92da0 546
jsa1969 0:cef60cc92da0 547 reg_array[count] = reg_addr; // Append configuration
jsa1969 0:cef60cc92da0 548 data_array[count] = data;
jsa1969 0:cef60cc92da0 549 count++;
jsa1969 0:cef60cc92da0 550 }
jsa1969 0:cef60cc92da0 551
jsa1969 0:cef60cc92da0 552 // Selecting heater control for the sensor
jsa1969 0:cef60cc92da0 553 if (desired_settings & BME680_HCNTRL_SEL) {
jsa1969 0:cef60cc92da0 554 rslt = boundary_check(&(_dev->gas_sett.heatr_ctrl), BME680_ENABLE_HEATER,
jsa1969 0:cef60cc92da0 555 BME680_DISABLE_HEATER);
jsa1969 0:cef60cc92da0 556 reg_addr = BME680_CONF_HEAT_CTRL_ADDR;
jsa1969 0:cef60cc92da0 557
jsa1969 0:cef60cc92da0 558 if (rslt == BME680_OK){
jsa1969 0:cef60cc92da0 559 rslt = get_regs(reg_addr, &data, 1);
jsa1969 0:cef60cc92da0 560 }
jsa1969 0:cef60cc92da0 561
jsa1969 0:cef60cc92da0 562 data = BME680_SET_BITS_POS_0(data, BME680_HCTRL, _dev->gas_sett.heatr_ctrl);
jsa1969 0:cef60cc92da0 563
jsa1969 0:cef60cc92da0 564 reg_array[count] = reg_addr; // Append configuration
jsa1969 0:cef60cc92da0 565 data_array[count] = data;
jsa1969 0:cef60cc92da0 566 count++;
jsa1969 0:cef60cc92da0 567 }
jsa1969 0:cef60cc92da0 568
jsa1969 0:cef60cc92da0 569 // Selecting heater T,P oversampling for the sensor
jsa1969 0:cef60cc92da0 570 if (desired_settings & (BME680_OST_SEL | BME680_OSP_SEL)) {
jsa1969 0:cef60cc92da0 571 rslt = boundary_check(&(_dev->tph_sett.os_temp), BME680_OS_NONE, BME680_OS_16X);
jsa1969 0:cef60cc92da0 572 reg_addr = BME680_CONF_T_P_MODE_ADDR;
jsa1969 0:cef60cc92da0 573
jsa1969 0:cef60cc92da0 574 if (rslt == BME680_OK) {
jsa1969 0:cef60cc92da0 575 rslt = get_regs(reg_addr, &data, 1);
jsa1969 0:cef60cc92da0 576 }
jsa1969 0:cef60cc92da0 577
jsa1969 0:cef60cc92da0 578 if (desired_settings & BME680_OST_SEL) {
jsa1969 0:cef60cc92da0 579 data = BME680_SET_BITS(data, BME680_OST, _dev->tph_sett.os_temp);
jsa1969 0:cef60cc92da0 580 }
jsa1969 0:cef60cc92da0 581
jsa1969 0:cef60cc92da0 582 if (desired_settings & BME680_OSP_SEL) {
jsa1969 0:cef60cc92da0 583 data = BME680_SET_BITS(data, BME680_OSP, _dev->tph_sett.os_pres);
jsa1969 0:cef60cc92da0 584 }
jsa1969 0:cef60cc92da0 585
jsa1969 0:cef60cc92da0 586 reg_array[count] = reg_addr;
jsa1969 0:cef60cc92da0 587 data_array[count] = data;
jsa1969 0:cef60cc92da0 588 count++;
jsa1969 0:cef60cc92da0 589 }
jsa1969 0:cef60cc92da0 590
jsa1969 0:cef60cc92da0 591 // Selecting humidity oversampling for the sensor
jsa1969 0:cef60cc92da0 592 if (desired_settings & BME680_OSH_SEL) {
jsa1969 0:cef60cc92da0 593 rslt = boundary_check(&(_dev->tph_sett.os_hum), BME680_OS_NONE, BME680_OS_16X);
jsa1969 0:cef60cc92da0 594 reg_addr = BME680_CONF_OS_H_ADDR;
jsa1969 0:cef60cc92da0 595
jsa1969 0:cef60cc92da0 596 if (rslt == BME680_OK) {
jsa1969 0:cef60cc92da0 597 rslt = get_regs(reg_addr, &data, 1);
jsa1969 0:cef60cc92da0 598 }
jsa1969 0:cef60cc92da0 599
jsa1969 0:cef60cc92da0 600 data = BME680_SET_BITS_POS_0(data, BME680_OSH, _dev->tph_sett.os_hum);
jsa1969 0:cef60cc92da0 601
jsa1969 0:cef60cc92da0 602 reg_array[count] = reg_addr; // Append configuration
jsa1969 0:cef60cc92da0 603 data_array[count] = data;
jsa1969 0:cef60cc92da0 604 count++;
jsa1969 0:cef60cc92da0 605 }
jsa1969 0:cef60cc92da0 606
jsa1969 0:cef60cc92da0 607 // Selecting the runGas and NB conversion settings for the sensor
jsa1969 0:cef60cc92da0 608 if (desired_settings & (BME680_RUN_GAS_SEL | BME680_NBCONV_SEL)) {
jsa1969 0:cef60cc92da0 609 rslt = boundary_check(&(_dev->gas_sett.run_gas), BME680_RUN_GAS_DISABLE,
jsa1969 0:cef60cc92da0 610 BME680_RUN_GAS_ENABLE);
jsa1969 0:cef60cc92da0 611
jsa1969 0:cef60cc92da0 612 if (rslt == BME680_OK) {
jsa1969 0:cef60cc92da0 613 // Validate boundary conditions
jsa1969 0:cef60cc92da0 614 rslt = boundary_check(&(_dev->gas_sett.nb_conv), BME680_NBCONV_MIN,
jsa1969 0:cef60cc92da0 615 BME680_NBCONV_MAX);
jsa1969 0:cef60cc92da0 616 }
jsa1969 0:cef60cc92da0 617
jsa1969 0:cef60cc92da0 618 reg_addr = BME680_CONF_ODR_RUN_GAS_NBC_ADDR;
jsa1969 0:cef60cc92da0 619
jsa1969 0:cef60cc92da0 620 if (rslt == BME680_OK)
jsa1969 0:cef60cc92da0 621 rslt = get_regs(reg_addr, &data, 1);
jsa1969 0:cef60cc92da0 622
jsa1969 0:cef60cc92da0 623 if (desired_settings & BME680_RUN_GAS_SEL)
jsa1969 0:cef60cc92da0 624 data = BME680_SET_BITS(data, BME680_RUN_GAS, _dev->gas_sett.run_gas);
jsa1969 0:cef60cc92da0 625
jsa1969 0:cef60cc92da0 626 if (desired_settings & BME680_NBCONV_SEL)
jsa1969 0:cef60cc92da0 627 data = BME680_SET_BITS_POS_0(data, BME680_NBCONV, _dev->gas_sett.nb_conv);
jsa1969 0:cef60cc92da0 628
jsa1969 0:cef60cc92da0 629 reg_array[count] = reg_addr; // Append configuration
jsa1969 0:cef60cc92da0 630 data_array[count] = data;
jsa1969 0:cef60cc92da0 631 count++;
jsa1969 0:cef60cc92da0 632 }
jsa1969 0:cef60cc92da0 633
jsa1969 0:cef60cc92da0 634 if (rslt == BME680_OK)
jsa1969 0:cef60cc92da0 635 rslt = set_regs(reg_array, data_array, count);
jsa1969 0:cef60cc92da0 636
jsa1969 0:cef60cc92da0 637 // Restore previous intended power mode
jsa1969 0:cef60cc92da0 638 _dev->power_mode = intended_power_mode;
jsa1969 0:cef60cc92da0 639
jsa1969 0:cef60cc92da0 640 return rslt;
jsa1969 0:cef60cc92da0 641 }
jsa1969 0:cef60cc92da0 642
jsa1969 0:cef60cc92da0 643 int Bme680::get_sensor_settings(uint16_t desired_settings)
jsa1969 0:cef60cc92da0 644 {
jsa1969 0:cef60cc92da0 645 int rslt = null_ptr_check();
jsa1969 0:cef60cc92da0 646 if (rslt!=BME680_OK) return rslt;
jsa1969 0:cef60cc92da0 647
jsa1969 0:cef60cc92da0 648 /* starting address of the register array for burst read*/
jsa1969 0:cef60cc92da0 649 uint8_t reg_addr = BME680_CONF_HEAT_CTRL_ADDR;
jsa1969 0:cef60cc92da0 650 uint8_t data_array[BME680_REG_BUFFER_LENGTH] = { 0 };
jsa1969 0:cef60cc92da0 651
jsa1969 0:cef60cc92da0 652
jsa1969 0:cef60cc92da0 653 rslt = get_regs(reg_addr, data_array, BME680_REG_BUFFER_LENGTH);
jsa1969 0:cef60cc92da0 654
jsa1969 0:cef60cc92da0 655 if (rslt == BME680_OK) {
jsa1969 0:cef60cc92da0 656 if (desired_settings & BME680_GAS_MEAS_SEL)
jsa1969 0:cef60cc92da0 657 rslt = get_gas_config();
jsa1969 0:cef60cc92da0 658
jsa1969 0:cef60cc92da0 659 /* get the T,P,H ,Filter,ODR settings here */
jsa1969 0:cef60cc92da0 660 if (desired_settings & BME680_FILTER_SEL)
jsa1969 0:cef60cc92da0 661 _dev->tph_sett.filter = BME680_GET_BITS(data_array[BME680_REG_FILTER_INDEX],
jsa1969 0:cef60cc92da0 662 BME680_FILTER);
jsa1969 0:cef60cc92da0 663
jsa1969 0:cef60cc92da0 664 if (desired_settings & (BME680_OST_SEL | BME680_OSP_SEL)) {
jsa1969 0:cef60cc92da0 665 _dev->tph_sett.os_temp = BME680_GET_BITS(data_array[BME680_REG_TEMP_INDEX], BME680_OST);
jsa1969 0:cef60cc92da0 666 _dev->tph_sett.os_pres = BME680_GET_BITS(data_array[BME680_REG_PRES_INDEX], BME680_OSP);
jsa1969 0:cef60cc92da0 667 }
jsa1969 0:cef60cc92da0 668
jsa1969 0:cef60cc92da0 669 if (desired_settings & BME680_OSH_SEL)
jsa1969 0:cef60cc92da0 670 _dev->tph_sett.os_hum = BME680_GET_BITS_POS_0(data_array[BME680_REG_HUM_INDEX],
jsa1969 0:cef60cc92da0 671 BME680_OSH);
jsa1969 0:cef60cc92da0 672
jsa1969 0:cef60cc92da0 673 /* get the gas related settings */
jsa1969 0:cef60cc92da0 674 if (desired_settings & BME680_HCNTRL_SEL)
jsa1969 0:cef60cc92da0 675 _dev->gas_sett.heatr_ctrl = BME680_GET_BITS_POS_0(data_array[BME680_REG_HCTRL_INDEX],
jsa1969 0:cef60cc92da0 676 BME680_HCTRL);
jsa1969 0:cef60cc92da0 677
jsa1969 0:cef60cc92da0 678 if (desired_settings & (BME680_RUN_GAS_SEL | BME680_NBCONV_SEL)) {
jsa1969 0:cef60cc92da0 679 _dev->gas_sett.nb_conv = BME680_GET_BITS_POS_0(data_array[BME680_REG_NBCONV_INDEX],
jsa1969 0:cef60cc92da0 680 BME680_NBCONV);
jsa1969 0:cef60cc92da0 681 _dev->gas_sett.run_gas = BME680_GET_BITS(data_array[BME680_REG_RUN_GAS_INDEX],
jsa1969 0:cef60cc92da0 682 BME680_RUN_GAS);
jsa1969 0:cef60cc92da0 683 }
jsa1969 0:cef60cc92da0 684 }
jsa1969 0:cef60cc92da0 685
jsa1969 0:cef60cc92da0 686 return rslt;
jsa1969 0:cef60cc92da0 687 }
jsa1969 0:cef60cc92da0 688
jsa1969 0:cef60cc92da0 689 int Bme680::get_gas_config()
jsa1969 0:cef60cc92da0 690 {
jsa1969 0:cef60cc92da0 691 int rslt = null_ptr_check();
jsa1969 0:cef60cc92da0 692 if (rslt!=BME680_OK) return rslt;
jsa1969 0:cef60cc92da0 693
jsa1969 0:cef60cc92da0 694 /* starting address of the register array for burst read*/
jsa1969 0:cef60cc92da0 695 uint8_t reg_addr1 = BME680_ADDR_SENS_CONF_START;
jsa1969 0:cef60cc92da0 696 uint8_t reg_addr2 = BME680_ADDR_GAS_CONF_START;
jsa1969 0:cef60cc92da0 697 uint8_t reg_data = 0;
jsa1969 0:cef60cc92da0 698
jsa1969 0:cef60cc92da0 699 if (rslt == BME680_OK) {
jsa1969 0:cef60cc92da0 700 rslt = get_regs(reg_addr1, &reg_data, 1);
jsa1969 0:cef60cc92da0 701 if (rslt == BME680_OK) {
jsa1969 0:cef60cc92da0 702 _dev->gas_sett.heatr_temp = reg_data;
jsa1969 0:cef60cc92da0 703 rslt = get_regs(reg_addr2, &reg_data, 1);
jsa1969 0:cef60cc92da0 704 if (rslt == BME680_OK) {
jsa1969 0:cef60cc92da0 705 /* Heating duration register value */
jsa1969 0:cef60cc92da0 706 _dev->gas_sett.heatr_dur = reg_data;
jsa1969 0:cef60cc92da0 707 }
jsa1969 0:cef60cc92da0 708 }
jsa1969 0:cef60cc92da0 709 }
jsa1969 0:cef60cc92da0 710
jsa1969 0:cef60cc92da0 711 return rslt;
jsa1969 0:cef60cc92da0 712 }
jsa1969 0:cef60cc92da0 713
jsa1969 0:cef60cc92da0 714 int16_t Bme680::calc_temperature(uint32_t temp_adc)
jsa1969 0:cef60cc92da0 715 {
jsa1969 0:cef60cc92da0 716 int64_t var1;
jsa1969 0:cef60cc92da0 717 int64_t var2;
jsa1969 0:cef60cc92da0 718 int64_t var3;
jsa1969 0:cef60cc92da0 719 int16_t calc_temp;
jsa1969 0:cef60cc92da0 720
jsa1969 0:cef60cc92da0 721 var1 = ((int32_t) temp_adc >> 3) - ((int32_t) _dev->calib.par_t1 << 1);
jsa1969 0:cef60cc92da0 722 var2 = (var1 * (int32_t) _dev->calib.par_t2) >> 11;
jsa1969 0:cef60cc92da0 723 var3 = ((var1 >> 1) * (var1 >> 1)) >> 12;
jsa1969 0:cef60cc92da0 724 var3 = ((var3) * ((int32_t) _dev->calib.par_t3 << 4)) >> 14;
jsa1969 0:cef60cc92da0 725 _dev->calib.t_fine = (int32_t) (var2 + var3);
jsa1969 0:cef60cc92da0 726 calc_temp = (int16_t) (((_dev->calib.t_fine * 5) + 128) >> 8);
jsa1969 0:cef60cc92da0 727
jsa1969 0:cef60cc92da0 728 return calc_temp;
jsa1969 0:cef60cc92da0 729 }
jsa1969 0:cef60cc92da0 730
jsa1969 0:cef60cc92da0 731 uint32_t Bme680::calc_pressure(uint32_t pres_adc)
jsa1969 0:cef60cc92da0 732 {
jsa1969 0:cef60cc92da0 733 int32_t var1 = 0;
jsa1969 0:cef60cc92da0 734 int32_t var2 = 0;
jsa1969 0:cef60cc92da0 735 int32_t var3 = 0;
jsa1969 0:cef60cc92da0 736 int32_t pressure_comp = 0;
jsa1969 0:cef60cc92da0 737
jsa1969 0:cef60cc92da0 738 var1 = (((int32_t)_dev->calib.t_fine) >> 1) - 64000;
jsa1969 0:cef60cc92da0 739 var2 = ((((var1 >> 2) * (var1 >> 2)) >> 11) *
jsa1969 0:cef60cc92da0 740 (int32_t)_dev->calib.par_p6) >> 2;
jsa1969 0:cef60cc92da0 741 var2 = var2 + ((var1 * (int32_t)_dev->calib.par_p5) << 1);
jsa1969 0:cef60cc92da0 742 var2 = (var2 >> 2) + ((int32_t)_dev->calib.par_p4 << 16);
jsa1969 0:cef60cc92da0 743 var1 = (((((var1 >> 2) * (var1 >> 2)) >> 13) *
jsa1969 0:cef60cc92da0 744 ((int32_t)_dev->calib.par_p3 << 5)) >> 3) +
jsa1969 0:cef60cc92da0 745 (((int32_t)_dev->calib.par_p2 * var1) >> 1);
jsa1969 0:cef60cc92da0 746 var1 = var1 >> 18;
jsa1969 0:cef60cc92da0 747 var1 = ((32768 + var1) * (int32_t)_dev->calib.par_p1) >> 15;
jsa1969 0:cef60cc92da0 748 pressure_comp = 1048576 - pres_adc;
jsa1969 0:cef60cc92da0 749 pressure_comp = (int32_t)((pressure_comp - (var2 >> 12)) * ((uint32_t)3125));
jsa1969 0:cef60cc92da0 750 if (pressure_comp >= BME680_MAX_OVERFLOW_VAL)
jsa1969 0:cef60cc92da0 751 pressure_comp = ((pressure_comp / (uint32_t)var1) << 1);
jsa1969 0:cef60cc92da0 752 else
jsa1969 0:cef60cc92da0 753 pressure_comp = ((pressure_comp << 1) / (uint32_t)var1);
jsa1969 0:cef60cc92da0 754 var1 = ((int32_t)_dev->calib.par_p9 * (int32_t)(((pressure_comp >> 3) *
jsa1969 0:cef60cc92da0 755 (pressure_comp >> 3)) >> 13)) >> 12;
jsa1969 0:cef60cc92da0 756 var2 = ((int32_t)(pressure_comp >> 2) *
jsa1969 0:cef60cc92da0 757 (int32_t)_dev->calib.par_p8) >> 13;
jsa1969 0:cef60cc92da0 758 var3 = ((int32_t)(pressure_comp >> 8) * (int32_t)(pressure_comp >> 8) *
jsa1969 0:cef60cc92da0 759 (int32_t)(pressure_comp >> 8) *
jsa1969 0:cef60cc92da0 760 (int32_t)_dev->calib.par_p10) >> 17;
jsa1969 0:cef60cc92da0 761
jsa1969 0:cef60cc92da0 762 pressure_comp = (int32_t)(pressure_comp) + ((var1 + var2 + var3 +
jsa1969 0:cef60cc92da0 763 ((int32_t)_dev->calib.par_p7 << 7)) >> 4);
jsa1969 0:cef60cc92da0 764
jsa1969 0:cef60cc92da0 765 return (uint32_t)pressure_comp;
jsa1969 0:cef60cc92da0 766
jsa1969 0:cef60cc92da0 767 }
jsa1969 0:cef60cc92da0 768
jsa1969 0:cef60cc92da0 769 uint32_t Bme680::calc_humidity(uint16_t hum_adc)
jsa1969 0:cef60cc92da0 770 {
jsa1969 0:cef60cc92da0 771 int32_t var1;
jsa1969 0:cef60cc92da0 772 int32_t var2;
jsa1969 0:cef60cc92da0 773 int32_t var3;
jsa1969 0:cef60cc92da0 774 int32_t var4;
jsa1969 0:cef60cc92da0 775 int32_t var5;
jsa1969 0:cef60cc92da0 776 int32_t var6;
jsa1969 0:cef60cc92da0 777 int32_t temp_scaled;
jsa1969 0:cef60cc92da0 778 int32_t calc_hum;
jsa1969 0:cef60cc92da0 779
jsa1969 0:cef60cc92da0 780 temp_scaled = (((int32_t) _dev->calib.t_fine * 5) + 128) >> 8;
jsa1969 0:cef60cc92da0 781 var1 = (int32_t) (hum_adc - ((int32_t) ((int32_t) _dev->calib.par_h1 * 16)))
jsa1969 0:cef60cc92da0 782 - (((temp_scaled * (int32_t) _dev->calib.par_h3) / ((int32_t) 100)) >> 1);
jsa1969 0:cef60cc92da0 783 var2 = ((int32_t) _dev->calib.par_h2
jsa1969 0:cef60cc92da0 784 * (((temp_scaled * (int32_t) _dev->calib.par_h4) / ((int32_t) 100))
jsa1969 0:cef60cc92da0 785 + (((temp_scaled * ((temp_scaled * (int32_t) _dev->calib.par_h5) / ((int32_t) 100))) >> 6)
jsa1969 0:cef60cc92da0 786 / ((int32_t) 100)) + (int32_t) (1 << 14))) >> 10;
jsa1969 0:cef60cc92da0 787 var3 = var1 * var2;
jsa1969 0:cef60cc92da0 788 var4 = (int32_t) _dev->calib.par_h6 << 7;
jsa1969 0:cef60cc92da0 789 var4 = ((var4) + ((temp_scaled * (int32_t) _dev->calib.par_h7) / ((int32_t) 100))) >> 4;
jsa1969 0:cef60cc92da0 790 var5 = ((var3 >> 14) * (var3 >> 14)) >> 10;
jsa1969 0:cef60cc92da0 791 var6 = (var4 * var5) >> 1;
jsa1969 0:cef60cc92da0 792 calc_hum = (((var3 + var6) >> 10) * ((int32_t) 1000)) >> 12;
jsa1969 0:cef60cc92da0 793
jsa1969 0:cef60cc92da0 794 if (calc_hum > 100000) /* Cap at 100%rH */
jsa1969 0:cef60cc92da0 795 calc_hum = 100000;
jsa1969 0:cef60cc92da0 796 else if (calc_hum < 0)
jsa1969 0:cef60cc92da0 797 calc_hum = 0;
jsa1969 0:cef60cc92da0 798
jsa1969 0:cef60cc92da0 799 return (uint32_t) calc_hum;
jsa1969 0:cef60cc92da0 800 }
jsa1969 0:cef60cc92da0 801
jsa1969 0:cef60cc92da0 802 uint32_t Bme680::calc_gas_resistance(uint16_t gas_res_adc, uint8_t gas_range)
jsa1969 0:cef60cc92da0 803 {
jsa1969 0:cef60cc92da0 804 int64_t var1;
jsa1969 0:cef60cc92da0 805 uint64_t var2;
jsa1969 0:cef60cc92da0 806 int64_t var3;
jsa1969 0:cef60cc92da0 807 uint32_t calc_gas_res;
jsa1969 0:cef60cc92da0 808 /**Look up table 1 for the possible gas range values */
jsa1969 0:cef60cc92da0 809 uint32_t lookupTable1[16] = { UINT32_C(2147483647), UINT32_C(2147483647), UINT32_C(2147483647), UINT32_C(2147483647),
jsa1969 0:cef60cc92da0 810 UINT32_C(2147483647), UINT32_C(2126008810), UINT32_C(2147483647), UINT32_C(2130303777),
jsa1969 0:cef60cc92da0 811 UINT32_C(2147483647), UINT32_C(2147483647), UINT32_C(2143188679), UINT32_C(2136746228),
jsa1969 0:cef60cc92da0 812 UINT32_C(2147483647), UINT32_C(2126008810), UINT32_C(2147483647), UINT32_C(2147483647) };
jsa1969 0:cef60cc92da0 813 /**Look up table 2 for the possible gas range values */
jsa1969 0:cef60cc92da0 814 uint32_t lookupTable2[16] = { UINT32_C(4096000000), UINT32_C(2048000000), UINT32_C(1024000000), UINT32_C(512000000),
jsa1969 0:cef60cc92da0 815 UINT32_C(255744255), UINT32_C(127110228), UINT32_C(64000000), UINT32_C(32258064), UINT32_C(16016016),
jsa1969 0:cef60cc92da0 816 UINT32_C(8000000), UINT32_C(4000000), UINT32_C(2000000), UINT32_C(1000000), UINT32_C(500000),
jsa1969 0:cef60cc92da0 817 UINT32_C(250000), UINT32_C(125000) };
jsa1969 0:cef60cc92da0 818
jsa1969 0:cef60cc92da0 819 var1 = (int64_t) ((1340 + (5 * (int64_t) _dev->calib.range_sw_err)) *
jsa1969 0:cef60cc92da0 820 ((int64_t) lookupTable1[gas_range])) >> 16;
jsa1969 0:cef60cc92da0 821 var2 = (((int64_t) ((int64_t) gas_res_adc << 15) - (int64_t) (16777216)) + var1);
jsa1969 0:cef60cc92da0 822 var3 = (((int64_t) lookupTable2[gas_range] * (int64_t) var1) >> 9);
jsa1969 0:cef60cc92da0 823 calc_gas_res = (uint32_t) ((var3 + ((int64_t) var2 >> 1)) / (int64_t) var2);
jsa1969 0:cef60cc92da0 824
jsa1969 0:cef60cc92da0 825 return calc_gas_res;
jsa1969 0:cef60cc92da0 826 }
jsa1969 0:cef60cc92da0 827
jsa1969 0:cef60cc92da0 828