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 Feb 13 20:21:38 2019 +0000
Revision:
44:67a19da5f269
Parent:
42:ce269f988ac8
Child:
45:d6a9fd9c8200
more bme tweaking

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