12-11-2022 08:27 PM
Hello,
I would like to use the BME680 sensor with an ESP32.
Programming will be done with the BSEC library in Arduino IDE.
The ESP32 should not only evaluate the sensor, but also take over other control tasks (relays, inputs,..).
If there is an error in the process, the ESP32 restarts, which results in the BME680 arriving back in IAQ state 0.
The power supply for the sensor is not interrupted when the ESP32 is restarted.
Is it possible to run the sensor endlessly so that it is always operational without reinitializing it?
After re-initialization it takes a relatively long time before the sensor outputs usable data.
I hope you can understand my problem and maybe have a tip.
Solved! Go to Solution.
12-15-2022 03:15 AM
Hi Jo_Felus,
Github code includes examples of saving BSEC status and loading BSEC status. Save the BSEC status before restart, and load the BSEC status after restart.
updateState();
loadState();
https://github.com/boschsensortec/BSEC-Arduino-library/blob/master/examples/basic_config_state/basic...
12-15-2022 02:37 PM
Hello Robin,
thank you for your answer.. next time I'll look at all the examples.
But I have tried out the load and update function. After restarting the ESP32 the IAQ state goes directly to 0.
It look like, it doesn't overwrite the state. I printed the eeprom data (after the four Sensor has IAQ state 3) and there were a lot of hex information.
Do I anything wrong?
Here is my IDE code:
#include <EEPROM.h>
#include "bsec.h"
#include <Wire.h>
#define TCAADDR 0x70
void tcaselect(uint8_t i) {
if (i > 7) return;
Wire.beginTransmission(TCAADDR);
Wire.write(1 << i);
Wire.endTransmission();
}
/* 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(60000) // 360 minutes - 4 times a day
#define N_SENSORS 4
// Helper functions declarations
void checkIaqSensorStatus(void);
void errLeds(void);
void loadState(void);
void updateState(void);
// Create objects of the class Bsec
Bsec iaqSensor1, iaqSensor2, iaqSensor3, iaqSensor4;
uint8_t bsecState1[BSEC_MAX_STATE_BLOB_SIZE], bsecState2[BSEC_MAX_STATE_BLOB_SIZE], bsecState3[BSEC_MAX_STATE_BLOB_SIZE], bsecState4[BSEC_MAX_STATE_BLOB_SIZE];
uint16_t stateUpdateCounter = 0;
String output;
// Entry point for the example
void setup(void) {
EEPROM.begin((N_SENSORS * BSEC_MAX_STATE_BLOB_SIZE) + 1); // 1st address for the length of one state
Serial.begin(115200);
Wire.begin();
tcaselect(0);
iaqSensor1.begin(0x77, Wire);
tcaselect(1);
iaqSensor2.begin(0x77, Wire);
tcaselect(2);
iaqSensor3.begin(0x77, Wire);
tcaselect(3);
iaqSensor4.begin(0x77, Wire);
tcaselect(0);
output = "\nBSEC library version " + String(iaqSensor1.version.major) + "." + String(iaqSensor1.version.minor) + "." + String(iaqSensor1.version.major_bugfix) + "." + String(iaqSensor1.version.minor_bugfix);
Serial.println(output);
checkIaqSensorStatus();
tcaselect(0);
iaqSensor1.setConfig(bsec_config_iaq);
tcaselect(1);
iaqSensor2.setConfig(bsec_config_iaq);
tcaselect(2);
iaqSensor3.setConfig(bsec_config_iaq);
tcaselect(3);
iaqSensor4.setConfig(bsec_config_iaq);
checkIaqSensorStatus();
loadState();
bsec_virtual_sensor_t sensorList[3] = {
BSEC_OUTPUT_IAQ,
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE,
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY,
};
tcaselect(0);
iaqSensor1.updateSubscription(sensorList, 3, BSEC_SAMPLE_RATE_LP);
tcaselect(1);
iaqSensor2.updateSubscription(sensorList, 3, BSEC_SAMPLE_RATE_LP);
tcaselect(2);
iaqSensor3.updateSubscription(sensorList, 3, BSEC_SAMPLE_RATE_LP);
tcaselect(3);
iaqSensor4.updateSubscription(sensorList, 3, BSEC_SAMPLE_RATE_LP);
checkIaqSensorStatus();
// Print the header
output = "Sensor, 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) {
unsigned long time_trigger = millis();
if (iaqSensor1.run()) { // If new data is available
output = "1, " + String("EINS: ");
output += ", " + String(iaqSensor1.iaq);
output += ", " + String(iaqSensor1.iaqAccuracy);
output += ", " + String(iaqSensor1.temperature);
output += ", " + String(iaqSensor1.humidity);
Serial.println(output);
updateState();
} else {
checkIaqSensorStatus();
}
tcaselect(1);
if (iaqSensor2.run()) { // If new data is available
output = "2, " + String("ZWEI: ");
output += ", " + String(iaqSensor2.iaq);
output += ", " + String(iaqSensor2.iaqAccuracy);
output += ", " + String(iaqSensor2.temperature);
output += ", " + String(iaqSensor2.humidity);
Serial.println(output);
updateState();
} else {
checkIaqSensorStatus();
}
tcaselect(2);
if (iaqSensor3.run()) { // If new data is available
output = "1, " + String("DREI: ");
output += ", " + String(iaqSensor3.iaq);
output += ", " + String(iaqSensor3.iaqAccuracy);
output += ", " + String(iaqSensor3.temperature);
output += ", " + String(iaqSensor3.humidity);
Serial.println(output);
updateState();
} else {
checkIaqSensorStatus();
}
tcaselect(3);
if (iaqSensor4.run()) { // If new data is available
output = "2, " + String("VIER: ");
output += ", " + String(iaqSensor4.iaq);
output += ", " + String(iaqSensor4.iaqAccuracy);
output += ", " + String(iaqSensor4.temperature);
output += ", " + String(iaqSensor4.humidity);
Serial.println(output);
updateState();
} else {
checkIaqSensorStatus();
}
}
// Helper function definitions
void checkIaqSensorStatus(void) {
tcaselect(0);
if (iaqSensor1.status != BSEC_OK) {
if (iaqSensor1.status < BSEC_OK) {
output = "BSEC1 error code : " + String(iaqSensor1.status);
Serial.println(output);
// for (;;)
errLeds(); /* Halt in case of failure */
} else {
output = "BSEC warning code : " + String(iaqSensor1.status);
Serial.println(output);
}
}
if (iaqSensor1.bme680Status != BME680_OK) {
if (iaqSensor1.bme680Status < BME680_OK) {
output = "BME6801 error code : " + String(iaqSensor1.bme680Status);
Serial.println(output);
// for (;;)
errLeds(); /* Halt in case of failure */
} else {
output = "BME680 warning code : " + String(iaqSensor1.bme680Status);
Serial.println(output);
}
}
iaqSensor1.status = BSEC_OK;
tcaselect(1);
if (iaqSensor2.status != BSEC_OK) {
if (iaqSensor2.status < BSEC_OK) {
output = "BSEC error code : " + String(iaqSensor2.status);
Serial.println(output);
// for (;;)
errLeds(); /* Halt in case of failure */
} else {
output = "BSEC warning code : " + String(iaqSensor2.status);
Serial.println(output);
}
}
if (iaqSensor2.bme680Status != BME680_OK) {
if (iaqSensor2.bme680Status < BME680_OK) {
output = "BME680 error code : " + String(iaqSensor2.bme680Status);
Serial.println(output);
// for (;;)
errLeds(); /* Halt in case of failure */
} else {
output = "BME680 warning code : " + String(iaqSensor2.bme680Status);
Serial.println(output);
}
}
iaqSensor2.status = BSEC_OK;
tcaselect(2);
if (iaqSensor3.status != BSEC_OK) {
if (iaqSensor3.status < BSEC_OK) {
output = "BSEC1 error code : " + String(iaqSensor3.status);
Serial.println(output);
// for (;;)
errLeds(); /* Halt in case of failure */
} else {
output = "BSEC warning code : " + String(iaqSensor3.status);
Serial.println(output);
}
}
if (iaqSensor3.bme680Status != BME680_OK) {
if (iaqSensor3.bme680Status < BME680_OK) {
output = "BME6801 error code : " + String(iaqSensor3.bme680Status);
Serial.println(output);
// for (;;)
errLeds(); /* Halt in case of failure */
} else {
output = "BME680 warning code : " + String(iaqSensor3.bme680Status);
Serial.println(output);
}
}
iaqSensor3.status = BSEC_OK;
tcaselect(3);
if (iaqSensor4.status != BSEC_OK) {
if (iaqSensor4.status < BSEC_OK) {
output = "BSEC error code : " + String(iaqSensor4.status);
Serial.println(output);
// for (;;)
errLeds(); /* Halt in case of failure */
} else {
output = "BSEC warning code : " + String(iaqSensor4.status);
Serial.println(output);
}
}
if (iaqSensor4.bme680Status != BME680_OK) {
if (iaqSensor4.bme680Status < BME680_OK) {
output = "BME680 error code : " + String(iaqSensor4.bme680Status);
Serial.println(output);
for (;;)
errLeds(); /* Halt in case of failure */
} else {
output = "BME680 warning code : " + String(iaqSensor4.bme680Status);
Serial.println(output);
}
}
iaqSensor4.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++) {
bsecState1[i] = EEPROM.read(i + 1);
bsecState2[i] = EEPROM.read(i + 1 + BSEC_MAX_STATE_BLOB_SIZE);
bsecState3[i] = EEPROM.read(i + 1 + BSEC_MAX_STATE_BLOB_SIZE + BSEC_MAX_STATE_BLOB_SIZE);
bsecState4[i] = EEPROM.read(i + 1 + BSEC_MAX_STATE_BLOB_SIZE + BSEC_MAX_STATE_BLOB_SIZE + BSEC_MAX_STATE_BLOB_SIZE);
//Serial.println(String(bsecState1[i], HEX) + ", " + String(bsecState2[i], HEX) + ", " + String(bsecState3[i], HEX) + ", " + String(bsecState4[i], HEX));
}
tcaselect(0);
iaqSensor1.setState(bsecState1);
tcaselect(1);
iaqSensor2.setState(bsecState2);
tcaselect(2);
iaqSensor3.setState(bsecState3);
tcaselect(3);
iaqSensor4.setState(bsecState4);
checkIaqSensorStatus();
} else {
// Erase the EEPROM with zeroes
Serial.println("Erasing EEPROM");
for (uint16_t i = 0; i < (N_SENSORS * 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 ((iaqSensor1.iaqAccuracy >= 3) || (iaqSensor2.iaqAccuracy >= 3) || (iaqSensor3.iaqAccuracy >= 3) || (iaqSensor4.iaqAccuracy >= 3)) {
update = true;
stateUpdateCounter++;
}
} else {
/* Update every STATE_SAVE_PERIOD milliseconds */
if ((stateUpdateCounter * STATE_SAVE_PERIOD) < millis()) {
update = true;
stateUpdateCounter++;
}
}
if (update) {
tcaselect(0);
iaqSensor1.getState(bsecState1);
tcaselect(1);
iaqSensor2.getState(bsecState2);
tcaselect(2);
iaqSensor3.getState(bsecState3);
tcaselect(3);
iaqSensor4.getState(bsecState4);
checkIaqSensorStatus();
Serial.println("Writing state(s) to EEPROM");
for (uint16_t i = 0; i < BSEC_MAX_STATE_BLOB_SIZE; i++) {
EEPROM.write(i + 1, bsecState1[i]);
EEPROM.write(i + 1 + BSEC_MAX_STATE_BLOB_SIZE, bsecState2[i]);
EEPROM.write(i + 1 + BSEC_MAX_STATE_BLOB_SIZE + BSEC_MAX_STATE_BLOB_SIZE, bsecState3[i]);
EEPROM.write(i + 1 + BSEC_MAX_STATE_BLOB_SIZE + BSEC_MAX_STATE_BLOB_SIZE + BSEC_MAX_STATE_BLOB_SIZE, bsecState4[i]);
// Serial.println(String(bsecState1[i], HEX) + ", " + String(bsecState2[i], HEX) + ", " + String(bsecState3[i], HEX) + ", " + String(bsecState4[i], HEX));
}
EEPROM.write(0, BSEC_MAX_STATE_BLOB_SIZE);
EEPROM.commit();
}
}
12-19-2022 09:20 AM
After loading the BSEC status, you need to wait for the sensor to stabilize. Refer to the BSEC status in the integration document.
12-19-2022 11:19 AM
Thank you!
I pratcied ESP32 restarts and could see that after 5 minutes IAQ state jumped from 0 to 3.