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:
Fri Jun 03 17:05:56 2022 +0000
Revision:
60:6b21ca38ee7c
Parent:
46:2fed2865a0f3
cleanup

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