#include #include "bsec.h" #include /* Configure the BSEC library with information about the sensor 18v/33v = Voltage at Vdd. 1.8V or 3.3V 3s/300s = BSEC operating mode, BSEC_SAMPLE_RATE_LP or BSEC_SAMPLE_RATE_ULP 4d/28d = Operating age of the sensor in days generic_18v_3s_4d generic_18v_3s_28d generic_18v_300s_4d generic_18v_300s_28d generic_33v_3s_4d generic_33v_3s_28d generic_33v_300s_4d generic_33v_300s_28d */ const uint8_t bsec_config_iaq[] = { #include "config/generic_33v_3s_4d/bsec_iaq.txt" }; #define STATE_SAVE_PERIOD UINT32_C(360 * 60 * 1000) // 360 minutes - 4 times a day #define LED_BUILTIN 5 // Helper functions declarations void checkIaqSensorStatus(void); void errLeds(void); void loadState(void); void updateState(void); // Create an object of the class Bsec Bsec iaqSensor; uint8_t bsecState[BSEC_MAX_STATE_BLOB_SIZE] = {0}; uint16_t stateUpdateCounter = 0; String output; // Entry point for the example void setup(void) { EEPROM.begin(BSEC_MAX_STATE_BLOB_SIZE + 1); // 1st address for the length Serial.begin(115200); Wire.begin(); iaqSensor.begin(BME680_I2C_ADDR_PRIMARY, Wire); output = "\nBSEC library version " + String(iaqSensor.version.major) + "." + String(iaqSensor.version.minor) + "." + String(iaqSensor.version.major_bugfix) + "." + String(iaqSensor.version.minor_bugfix); Serial.println(output); checkIaqSensorStatus(); iaqSensor.setConfig(bsec_config_iaq); checkIaqSensorStatus(); loadState(); 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, }; iaqSensor.updateSubscription(sensorList, 10, BSEC_SAMPLE_RATE_LP); checkIaqSensorStatus(); // Print the header output = "Timestamp [ms], raw temperature [°C], pressure [hPa], raw relative humidity [%], gas [Ohm], IAQ, IAQ accuracy, temperature [°C], relative humidity [%]"; Serial.println(output); } // Function that is looped forever void loop(void) { static unsigned long lastTransmission = 0; static unsigned long lastBME680Polling = 0; static unsigned long loopStart = 0; unsigned long now = millis(); // Update sensor data every 3 seconds if (now - lastBME680Polling >= 3000) { lastBME680Polling = now; if (iaqSensor.run()) { updateState(); } else { checkIaqSensorStatus(); } } // Transmit sensor data every minute if (now - lastTransmission >= 60000) { lastTransmission = now; String output = String(now); output += "," + String(iaqSensor.rawTemperature); output += "," + String(iaqSensor.pressure); output += "," + String(iaqSensor.rawHumidity); output += "," + String(iaqSensor.gasResistance); output += "," + String(iaqSensor.iaq); output += "," + String(iaqSensor.iaqAccuracy); output += "," + String(iaqSensor.temperature); output += "," + String(iaqSensor.humidity); output += "," + String(iaqSensor.staticIaq); output += "," + String(iaqSensor.co2Equivalent); output += "," + String(iaqSensor.breathVocEquivalent); Serial.println(output); } if (now - loopStart >= 15000) { // Go to sleep for 45 seconds esp_sleep_enable_timer_wakeup(45000000); // Time in microseconds esp_light_sleep_start(); // Reset the loop start time loopStart = millis(); } } // Helper function definitions void checkIaqSensorStatus(void) { if (iaqSensor.status != BSEC_OK) { if (iaqSensor.status < BSEC_OK) { output = "BSEC error code : " + String(iaqSensor.status); Serial.println(output); for (;;) errLeds(); /* Halt in case of failure */ } else { output = "BSEC warning code : " + String(iaqSensor.status); Serial.println(output); } } if (iaqSensor.bme680Status != BME680_OK) { if (iaqSensor.bme680Status < BME680_OK) { output = "BME680 error code : " + String(iaqSensor.bme680Status); Serial.println(output); for (;;) errLeds(); /* Halt in case of failure */ } else { output = "BME680 warning code : " + String(iaqSensor.bme680Status); Serial.println(output); } } iaqSensor.status = BSEC_OK; } void errLeds(void) { pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, HIGH); delay(100); digitalWrite(LED_BUILTIN, LOW); delay(100); } void loadState(void) { if (EEPROM.read(0) == BSEC_MAX_STATE_BLOB_SIZE) { // Existing state in EEPROM Serial.println("Reading state from EEPROM"); for (uint8_t i = 0; i < BSEC_MAX_STATE_BLOB_SIZE; i++) { bsecState[i] = EEPROM.read(i + 1); Serial.println(bsecState[i], HEX); } iaqSensor.setState(bsecState); checkIaqSensorStatus(); } else { // Erase the EEPROM with zeroes Serial.println("Erasing EEPROM"); for (uint8_t i = 0; i < BSEC_MAX_STATE_BLOB_SIZE + 1; i++) EEPROM.write(i, 0); EEPROM.commit(); } } void updateState(void) { bool update = false; /* Set a trigger to save the state. Here, the state is saved every STATE_SAVE_PERIOD with the first state being saved once the algorithm achieves full calibration, i.e. iaqAccuracy = 3 */ if (stateUpdateCounter == 0) { if (iaqSensor.iaqAccuracy >= 3) { update = true; stateUpdateCounter++; } } else { /* Update every STATE_SAVE_PERIOD milliseconds */ if ((stateUpdateCounter * STATE_SAVE_PERIOD) < millis()) { update = true; stateUpdateCounter++; } } if (update) { iaqSensor.getState(bsecState); checkIaqSensorStatus(); Serial.println("Writing state to EEPROM"); for (uint8_t i = 0; i < BSEC_MAX_STATE_BLOB_SIZE ; i++) { EEPROM.write(i + 1, bsecState[i]); Serial.println(bsecState[i], HEX); } EEPROM.write(0, BSEC_MAX_STATE_BLOB_SIZE); EEPROM.commit(); } }