Bosch Sensortec Community

    cancel
    Showing results for 
    Search instead for 
    Did you mean: 
    SOLVED

    BME 680 IAQ stuck at 25 and accuracy always zero on Arduino MKR1000

    BME 680 IAQ stuck at 25 and accuracy always zero on Arduino MKR1000

    Fernando
    Member

    Recently I have acquired from Adrafuit two BME680 boards for my Indoor Air Quality Monitor station project. 

    After following the  BSEC-Arduino-library README file, I have compiled the library with success on the Arduino MKR1000 using Platformio.

    However, after running this library for 24 hours, the IAQ, eVOC and eCO2 read values are always the same. The accuracy retrieved by the sensor is stuck at 0, and I don't know how to fix this. I have already tested the two different sensors and nothing has changed.

    To mislead, I have downloaded the official library from https://www.bosch-sensortec.com/ (which is currently on version 1.4.8.0) and I have replaced the compiled libalgobsec.a for the Cortex-M0+ processors, but the problem persists. Temperature, humidity, pressure, and gas values look good so it is just a problem with the internal calibration of the sensor... 

    Any suggestion? Thank you.

    Arduino MKR1000 MCU details:

    - SAMD21 Cortex-M0+ 32bit low power ARM MCU

    Code:

    IAQ-Monitor-MKR1000 

    5 REPLIES 5

    Minhwan
    Community Moderator
    Community Moderator

    Hello Fernando, 

     

    Are you using NVM? 

    If yes, what is your IAQ type? LP or ULP?

    Would you upload your BME680 here? 

    Thanks, 

    Hello Minhwan,

    Thank you very much for answering me.

    Regarding the NVM, yes I'm using a piece of my flash memory to emulate an EEPROM.

    I have already tested all three modes, LP, ULP, and Normal mode (present in the latest version of the bsec library). However, currently, I'm using it in LP mode.

    The code is the following (you can also check it out in my GitHub😞

    // Bosch Sensor BME680
    #include "bsec.h"
    #include "config/generic_33v_3s_4d/bsec_serialized_configurations_iaq.h"
     
    // Bme680 sensor
    Bsec iaqSensor; // I2C
    uint8_t bsecState[BSEC_MAX_STATE_BLOB_SIZE] = {0};
    uint16_t stateUpdateCounter = 0;
     
    void setup(){
    /// BME680
    //// begin library and retreive the library version
    iaqSensor.begin(BME680_I2C_ADDR_SECONDARY, Wire);
    _printf((char*)"\nBSEC library version %u.%u.%u.%u \r\n",iaqSensor.version.major,iaqSensor.version.minor,iaqSensor.version.major_bugfix,iaqSensor.version.minor_bugfix);
    //// check if bme680 is connected
    checkIaqSensorStatus();
    /// Apply configs to bsec sensor
    iaqSensor.setConfig(bsec_config_iaq);
    checkIaqSensorStatus();
    /// load state from EEPROM
    loadState();
    //// specify the desired outputs
    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,
    };
    //// update subscription
    iaqSensor.updateSubscription(sensorList, 10, BSEC_SAMPLE_RATE_LP);
    checkIaqSensorStatus();
    }
     
    void loop() {
     
    if((millis() - bmeLastReading) > BME_680_PERIOD){
    bmeLastReading = millis();
     
     
    if (iaqSensor.run()) {
    // Temperature
    payload = myFTOA(iaqSensor.temperature,3,10);
    mqttClient.beginMessage(outTopic[2], payload.length(), retained, qos, dup);
    mqttClient.print(payload);
    mqttClient.endMessage();

    // Humidity
    payload = myFTOA(iaqSensor.humidity,3,10);
    mqttClient.beginMessage(outTopic[3], payload.length(), retained, qos, dup);
    mqttClient.print(payload);
    mqttClient.endMessage();

    // raw Temperature
    payload = myFTOA(iaqSensor.rawTemperature,3,10);
    mqttClient.beginMessage(outTopic[11], payload.length(), retained, qos, dup);
    mqttClient.print(payload);
    mqttClient.endMessage();

    // raw Humidity
    payload = myFTOA(iaqSensor.rawHumidity,3,10);
    mqttClient.beginMessage(outTopic[12], payload.length(), retained, qos, dup);
    mqttClient.print(payload);
    mqttClient.endMessage();

    // Pressure
    payload = myFTOA(iaqSensor.pressure/100.0f,3,10);
    mqttClient.beginMessage(outTopic[4], payload.length(), retained, qos, dup);
    mqttClient.print(payload);
    mqttClient.endMessage();

    // IAQ
    payload = myFTOA(iaqSensor.iaq,3,10);
    mqttClient.beginMessage(outTopic[5], payload.length(), retained, qos, dup);
    mqttClient.print(payload);
    mqttClient.endMessage();
     
    // Static IAQ
    //payload = myFTOA(iaqSensor.staticIaq,3,10);
    //mqttClient.beginMessage(outTopic[6], payload.length(), retained, qos, dup);
    //mqttClient.print(payload);
    //mqttClient.endMessage();

    // Static equivalent CO2
    //payload = myFTOA(iaqSensor.co2Equivalent,3,10);
    //mqttClient.beginMessage(outTopic[7], payload.length(), retained, qos, dup);
    //mqttClient.print(payload);
    //mqttClient.endMessage();

    // Static equivalent breath VOCs
    //payload = myFTOA(iaqSensor.breathVocEquivalent,3,10);
    //mqttClient.beginMessage(outTopic[8], payload.length(), retained, qos, dup);
    //mqttClient.print(payload);
    //mqttClient.endMessage();

    updateState();

    /*
    _printf((char*)"IAQ Accuracy %u \r\n",iaqSensor.iaqAccuracy);
    _printf((char*)"Breath Voc Accuracy %u \r\n",iaqSensor.breathVocAccuracy);
    _printf((char*)"Co2 Accuracy %u \r\n",iaqSensor.co2Accuracy);
    _printf((char*)"Static Iaq Accuracy %u \r\n",iaqSensor.staticIaqAccuracy);
    */
    } else {
    checkIaqSensorStatus();
    }
     
    }
     
    }
     
    // Helper function definitions
    void checkIaqSensorStatus(void){
    if (iaqSensor.status != BSEC_OK) {
    if (iaqSensor.status < BSEC_OK) {
    _printf((char*)"BSEC error code : %d \r\n",iaqSensor.status);
    for (;;)
    errLeds(); /* Halt in case of failure */
    } else {
    _printf((char*)"BSEC warning code : %d \r\n",iaqSensor.status);
    }
    }

    if (iaqSensor.bme680Status != BME680_OK) {
    if (iaqSensor.bme680Status < BME680_OK) {
    _printf((char*)"BSEC error code : %d \r\n",iaqSensor.bme680Status);
    for (;;)
    errLeds(); /* Halt in case of failure */
    } else {
    _printf((char*)"BSEC warning code : %d \r\n",iaqSensor.bme680Status);
    }
    }
    }

    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 {
    uint8_t isEepromErased = 1;
    for (uint8_t i = 0; i < BSEC_MAX_STATE_BLOB_SIZE; i++) {
    if(EEPROM.read(i + 1) != 0){
    isEepromErased = 0;
    break;
    }
    }
    if(!isEepromErased){
    // 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();
    }
    }
     

     

    Minhwan
    Community Moderator
    Community Moderator

    Hello Fernando, 

     

    Could you test with my code? 

    It should get IAQ. You can also check IAQ accuracy value as well. 

    Please let me know if you have any questions. 

    Thanks, 

    Hello Minhwan,

    Thank you very much for your help!

    Tested and indeed it is now working.

    Best regards.

    Icon--AD-black-48x48Icon--address-consumer-data-black-48x48Icon--appointment-black-48x48Icon--back-left-black-48x48Icon--calendar-black-48x48Icon--center-alignedIcon--Checkbox-checkIcon--clock-black-48x48Icon--close-black-48x48Icon--compare-black-48x48Icon--confirmation-black-48x48Icon--dealer-details-black-48x48Icon--delete-black-48x48Icon--delivery-black-48x48Icon--down-black-48x48Icon--download-black-48x48Ic-OverlayAlertIcon--externallink-black-48x48Icon-Filledforward-right_adjustedIcon--grid-view-black-48x48IC_gd_Check-Circle170821_Icons_Community170823_Bosch_Icons170823_Bosch_Icons170821_Icons_CommunityIC-logout170821_Icons_Community170825_Bosch_Icons170821_Icons_CommunityIC-shopping-cart2170821_Icons_CommunityIC-upIC_UserIcon--imageIcon--info-i-black-48x48Icon--left-alignedIcon--Less-minimize-black-48x48Icon-FilledIcon--List-Check-grennIcon--List-Check-blackIcon--List-Cross-blackIcon--list-view-mobile-black-48x48Icon--list-view-black-48x48Icon--More-Maximize-black-48x48Icon--my-product-black-48x48Icon--newsletter-black-48x48Icon--payment-black-48x48Icon--print-black-48x48Icon--promotion-black-48x48Icon--registration-black-48x48Icon--Reset-black-48x48Icon--right-alignedshare-circle1Icon--share-black-48x48Icon--shopping-bag-black-48x48Icon-shopping-cartIcon--start-play-black-48x48Icon--store-locator-black-48x48Ic-OverlayAlertIcon--summary-black-48x48tumblrIcon-FilledvineIc-OverlayAlertwhishlist