#ifdef HAS_BME #include "bme680mems.h" // Local logging tag static const char TAG[] = "main"; bmeStatus_t bme_status; TaskHandle_t BmeTask; bsec_virtual_sensor_t sensorList[10] = { BSEC_OUTPUT_RAW_TEMPERATURE, BSEC_OUTPUT_RAW_PRESSURE, BSEC_OUTPUT_RAW_HUMIDITY, BSEC_OUTPUT_RAW_GAS, BSEC_OUTPUT_IAQ, BSEC_OUTPUT_STATIC_IAQ, BSEC_OUTPUT_CO2_EQUIVALENT, BSEC_OUTPUT_BREATH_VOC_EQUIVALENT, BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE, BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY, }; uint8_t bsecstate_buffer[BSEC_MAX_STATE_BLOB_SIZE] = {0}; uint16_t stateUpdateCounter = 0; Bsec iaqSensor; // initialize BME680 sensor int bme_init(void) { // return = 0 -> error / return = 1 -> success // block i2c bus access if (xSemaphoreTake(I2Caccess, (DISPLAYREFRESH_MS / portTICK_PERIOD_MS)) == pdTRUE) { Wire.begin(HAS_BME); iaqSensor.begin(BME_ADDR, Wire); ESP_LOGI(TAG, "BSEC v%d.%d.%d.%d", iaqSensor.version.major, iaqSensor.version.minor, iaqSensor.version.major_bugfix, iaqSensor.version.minor_bugfix); iaqSensor.setConfig(bsec_config_iaq); if (checkIaqSensorStatus()) ESP_LOGI(TAG, "BME680 sensor found and initialized"); else { ESP_LOGE(TAG, "BME680 sensor not found"); goto error; } loadState(); iaqSensor.setTemperatureOffset((float)BME_TEMP_OFFSET); iaqSensor.updateSubscription(sensorList, 10, BSEC_SAMPLE_RATE_LP); if (checkIaqSensorStatus()) ESP_LOGI(TAG, "BSEC subscription succesful"); else { ESP_LOGE(TAG, "BSEC subscription error"); goto error; } } else { ESP_LOGE(TAG, "I2c bus busy - BME680 initialization error"); goto error; } xSemaphoreGive(I2Caccess); // release i2c bus access return 1; error: xSemaphoreGive(I2Caccess); // release i2c bus access return 0; } // bme_init() // Helper function definitions int checkIaqSensorStatus(void) { int rslt = 1; // true = 1 = no error, false = 0 = error if (iaqSensor.status != BSEC_OK) { rslt = 0; if (iaqSensor.status < BSEC_OK) ESP_LOGE(TAG, "BSEC error %d", iaqSensor.status); else ESP_LOGW(TAG, "BSEC warning %d", iaqSensor.status); } if (iaqSensor.bme680Status != BME680_OK) { rslt = 0; if (iaqSensor.bme680Status < BME680_OK) ESP_LOGE(TAG, "BME680 error %d", iaqSensor.bme680Status); else ESP_LOGW(TAG, "BME680 warning %d", iaqSensor.bme680Status); } return rslt; } // checkIaqSensorStatus() // loop function which reads and processes data based on sensor settings void bme_loop(void *pvParameters) { configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check #ifdef HAS_BME // block i2c bus access while (xSemaphoreTake(I2Caccess, portMAX_DELAY) == pdTRUE) { if (iaqSensor.run()) { // If new data is available bme_status.raw_temperature = iaqSensor.rawTemperature; bme_status.raw_humidity = iaqSensor.rawHumidity; bme_status.temperature = iaqSensor.temperature; bme_status.humidity = iaqSensor.humidity; bme_status.pressure = (iaqSensor.pressure / 100.0); // conversion Pa -> hPa bme_status.iaq = iaqSensor.iaqEstimate; bme_status.iaq_accuracy = iaqSensor.iaqAccuracy; bme_status.gas = iaqSensor.gasResistance; updateState(); } xSemaphoreGive(I2Caccess); // release i2c bus access } // while #endif ESP_LOGE(TAG, "BME task ended"); vTaskDelete(BmeTask); // should never be reached } // bme_loop() void loadState(void) { if (cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE] == BSEC_MAX_STATE_BLOB_SIZE) { // Existing state in NVS stored ESP_LOGI(TAG, "restoring BSEC state from NVRAM"); memcpy(bsecstate_buffer, cfg.bsecstate, BSEC_MAX_STATE_BLOB_SIZE); iaqSensor.setState(bsecstate_buffer); checkIaqSensorStatus(); } else // no state stored ESP_LOGI(TAG, "no BSEC state stored in NVRAM, starting sensor with defaults"); } void updateState(void) { bool update = false; if (stateUpdateCounter == 0) { // first state update when IAQ accuracy is >= 1 if (iaqSensor.iaqAccuracy >= 1) { update = true; stateUpdateCounter++; } } else { /* Update every STATE_SAVE_PERIOD minutes */ if ((stateUpdateCounter * STATE_SAVE_PERIOD) < millis()) { update = true; stateUpdateCounter++; } } if (update) { iaqSensor.getState(bsecstate_buffer); checkIaqSensorStatus(); memcpy(cfg.bsecstate, bsecstate_buffer, BSEC_MAX_STATE_BLOB_SIZE); cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE] = BSEC_MAX_STATE_BLOB_SIZE; ESP_LOGI(TAG, "saving BSEC state to NVRAM"); saveConfig(); } } #endif // HAS_BME