08-21-2020 08:29 AM
Dear community,
I'm currently setting up a project using the BME680 with BSEC Arduino Library 1.4.7.4. I want to use the ability of sampling the different sensor parts with different rates as given in the ULP_LP_Example. LP sampling rate for T/P/H and ULP sampling rate for IAQ/bVOC/eCO2.
My first question is which bsec_config_iaq file to use? The 3s or the 300s version? In the example I see that the following was done:
#include "bsec_serialized_configurations_iaq.h"
But this can be either one of the eight config files provided, right?
My second question is more of an observation where I can't explain the reason but hope that you can help me out. I set up my two sensor lists as given in the example and provided the respective sampling rates as follows:
//just an excerpt of the full program
bsec_virtual_sensor_t sensorList_LP[3] = {
BSEC_OUTPUT_RAW_PRESSURE,
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE,
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY,
};
bsec_virtual_sensor_t sensorList_ULP[5] = {
BSEC_OUTPUT_STABILIZATION_STATUS,
BSEC_OUTPUT_RUN_IN_STATUS,
BSEC_OUTPUT_CO2_EQUIVALENT,
BSEC_OUTPUT_BREATH_VOC_EQUIVALENT,
BSEC_OUTPUT_IAQ,
};
iaqSensor.updateSubscription(sensorList_ULP, 5, BSEC_SAMPLE_RATE_ULP);
checkIaqSensorStatus();
iaqSensor.updateSubscription(sensorList_LP, 3, BSEC_SAMPLE_RATE_LP);
checkIaqSensorStatus();
void loop() {
if(iaqSensor.run()){
updateState();
Serial.print(String((uint16_t)(millis()/1000)) + "s");
Serial.print(" BSECstate: " + String(iaqSensor.status));
// Serial.print(" IAQacc: " + String(iaqSensor.iaqAccuracy));
Serial.print(" riStat: " + String(iaqSensor.runInStatus));
Serial.print(" stabStat: " + String(iaqSensor.stabStatus));
Serial.print(" IAQ: " + String(iaqSensor.iaq) + "(" + String(iaqSensor.iaqAccuracy) + ")");
Serial.print(" CO2: " + String(iaqSensor.co2Equivalent) + "(" + String(iaqSensor.co2Accuracy) + ")");
Serial.print(" bVOC: " + String(iaqSensor.breathVocEquivalent) + "(" + String(iaqSensor.breathVocAccuracy) + ")");
Serial.print(" p: " + String(iaqSensor.pressure));
Serial.print(" t: " + String(iaqSensor.temperature));
Serial.println(" h: " + String(iaqSensor.humidity));
}
else {
checkIaqSensorStatus();
}
}
Thanks,
Benedikt
08-21-2020 07:13 PM
The IAQ is in ULP mode, so you should use the configure file as 300s interval version.
If the IAQ is set to ULP mode, it should be only update at 300s interval, it should not update in 3s interval.
Also the temperature sensor should not have 2 degrees higher than environment.
The reason might be the following function execute wrongly then the sensor is not working under expected sample rate.
updateSubscription
08-28-2020 01:38 PM
So Vincent,
first of all thank you for clarifying which config file to use for this setup!
I got curious the last days and tried the basic_config_state_ULP_LP.ino example provided on Github. This is the example I initially used to set up two subscription rates for my own project. To my surprise the Github example shows the same behaviour as my own, meaning that the error must be somewhere either in the BSEC framework or in the sensor API (this is what i presume but can't confirm).
I did an other example to confirm my observations for which I attach the code and logfile to this post.
I initialize and start the BME680 with T/P/H/Gas measurements in UPL mode. At second 3500 I change the subscription rates for T/P/H to LP. After the last ULP interval (seconds 3300 -> 3600) has ended output values are returned, as expected, in 3s intervals for T/P/H BUT also for the Gas sensor.
Also from this point on the overall sensor temperature rises drastically until about 2.5°C above the before measured values (see figure attached or logfile). To me it seems as if the sensor suddenly experiences a much higher heat dissipation, like the gas heater was enabled at much higher frequency than usual. Unfortunately I don't have enough experience to trace back this behavior to either the BSEC framework or the sensor API.
Any thoughts on that?
Thanks and BR,
Ben
#include <EEPROM.h>
#include "bsec.h"
const uint8_t bsec_config_iaq[] = {
#include "config/generic_33v_300s_4d/bsec_iaq.txt"
};
#define STATE_SAVE_PERIOD UINT32_C(360 * 60 * 1000) // 360 minutes - 4 times a day
void checkIaqSensorStatus(void);
void loadState(void);
void updateState(void);
Bsec iaqSensor;
uint8_t bsecState[BSEC_MAX_STATE_BLOB_SIZE] = {0};
uint16_t stateUpdateCounter = 0;
uint8_t setLP = 0;
bsec_virtual_sensor_t sensorList_LP[3] = {
BSEC_OUTPUT_RAW_PRESSURE,
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE,
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY,
};
void setup() {
EEPROM.begin(BSEC_MAX_STATE_BLOB_SIZE + 1); // 1st address for the length
Wire.begin();
Serial.begin(115200);
iaqSensor.begin(BME680_I2C_ADDR_PRIMARY, Wire);
Serial.println("BSEC library version " + String(iaqSensor.version.major) + "." + String(iaqSensor.version.minor) + "." + String(iaqSensor.version.major_bugfix) + "." + String(iaqSensor.version.minor_bugfix));
checkIaqSensorStatus();
iaqSensor.setConfig(bsec_config_iaq);
checkIaqSensorStatus();
loadState();
bsec_virtual_sensor_t sensorList_ULP[8] = {
BSEC_OUTPUT_STABILIZATION_STATUS,
BSEC_OUTPUT_RUN_IN_STATUS,
BSEC_OUTPUT_CO2_EQUIVALENT,
BSEC_OUTPUT_BREATH_VOC_EQUIVALENT,
BSEC_OUTPUT_IAQ,
BSEC_OUTPUT_RAW_PRESSURE,
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE,
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY
};
iaqSensor.updateSubscription(sensorList_ULP, 8, BSEC_SAMPLE_RATE_ULP);
checkIaqSensorStatus();
Serial.println("Running main program");
}
void loop() {
if(iaqSensor.run()){
updateState();
Serial.print(String((uint16_t)(millis()/1000)) + "s");
Serial.print(" BSECstate: " + String(iaqSensor.status));
// Serial.print(" IAQacc: " + String(iaqSensor.iaqAccuracy));
Serial.print(" riStat: " + String(iaqSensor.runInStatus));
Serial.print(" stabStat: " + String(iaqSensor.stabStatus));
Serial.print(" IAQ: " + String(iaqSensor.iaq) + "(" + String(iaqSensor.iaqAccuracy) + ")");
Serial.print(" CO2: " + String(iaqSensor.co2Equivalent) + "(" + String(iaqSensor.co2Accuracy) + ")");
Serial.print(" bVOC: " + String(iaqSensor.breathVocEquivalent) + "(" + String(iaqSensor.breathVocAccuracy) + ")");
Serial.print(" p: " + String(iaqSensor.pressure));
Serial.print(" t: " + String(iaqSensor.temperature));
Serial.println(" h: " + String(iaqSensor.humidity));
}
else {
checkIaqSensorStatus();
}
if((millis()/1000) == 3500 && setLP == 0){
iaqSensor.updateSubscription(sensorList_LP, 3, BSEC_SAMPLE_RATE_LP);
setLP = 1;
Serial.println("LP sensors configured");
}
}
void checkIaqSensorStatus(void)
{
if (iaqSensor.status != BSEC_OK) {
if (iaqSensor.status < BSEC_OK) {
//output = "BSEC error code : " + String(iaqSensor.status);
Serial.println("BSEC error code : " + String(iaqSensor.status));
while(1);
} else {
//output = "BSEC warning code : " + String(iaqSensor.status);
Serial.println("BSEC warning code : " + String(iaqSensor.status));
}
}
if (iaqSensor.bme680Status != BME680_OK) {
if (iaqSensor.bme680Status < BME680_OK) {
//output = "BME680 error code : " + String(iaqSensor.bme680Status);
Serial.println("BME680 error code : " + String(iaqSensor.bme680Status));
while(1);
} else {
//output = "BME680 warning code : " + String(iaqSensor.bme680Status);
Serial.println("BME680 warning code : " + String(iaqSensor.bme680Status));
}
}
iaqSensor.status = BSEC_OK;
}
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();
}
}
09-03-2020 03:23 AM - edited 09-03-2020 03:30 AM
Hi,
Please don't use Arduino github example code, there is buggy now.
Instead, please use our official library and example "bsec_iot_example.ino" as url - https://www.bosch-sensortec.com/software-tools/software/bsec/
Then, you need to migrate some steps as below. ( Currently, I'm working on Arduino DUE)
1) Unzip src.zip file and copy to BSEC library src folder. Could be C:\Users\USERNAME\Documents\Arduino\libraries\BSEC-Arduino-library-master\src
2) Unzip bsec_iot_example.zip and run it.
If you want to migrate in your way, please refer to BST-BME680-Integration-Guide-AN008-48.pdf in our latest BSEC official library.
Please let me know if you have any questions.
Thanks,
Minhwan
09-04-2020 11:58 PM
By the way, found one workaround.
Please comment out bsec_init function in run function in bsec.cpp.