Bosch Sensortec Community

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

    BME688 / BSEC 2.0: Deep Sleep & Bsec2::run() not invoking callback on first call

    BME688 / BSEC 2.0: Deep Sleep & Bsec2::run() not invoking callback on first call

    iamdjango
    Member

    Hi,

    I've hit an issue I'm unable to solve whereby after deep sleeping my ESP32 and saving and loading state with RTC memory or after a manual reset using EEPROM as per the Arduino example basic_config_state.ino, my callback is not being invoked until I execute Bsec2::run() for a second time after deep sleeping. This means I have to I have to wait either 3s or 300s depending on BSEC_SAMPLE_RATE_* at full power or at least light sleep before getting a reading and returning to deep sleep.

    It seems after deep sleeping even when loading in the previous state from EEPROM the next call time remains zero. Please see the image I've attached for detailed logging of this happening in my application.

    All subsequent calls are fine and outputs look correct. Thus I can only assume there is a bug in the bsec_set_state() function that is not initialising the libraries state fully until a second call is made to Bsec2::run().

    Furthermore, to actually get deep sleep working I've had to add back in missing functionality to the API from BSEC 1.0:

    /**
    * @brief Constructor
    */
    Bsec::Bsec()
    {
    nextCall = 0;
    ...

    That provided public access to when the "nextCall" is available. This is missing in both the downloadable and the github version of BSEC 2.0 library so I added a getter for it (in the downloaded version I'm using):

     /**
    * @brief Function to return the time when the algorithm has to be called next in ms
    */
    int64_t Bsec::getNextTime(void)
    {
    return _bsec_bme_settings.next_call / INT64_C(1000000);
    }

    Any help with this issue would be greatly appreciated.

    Thanks in advance.

    4 REPLIES 4

    BSTRobin
    Community Moderator
    Community Moderator

    Hello iamdjango,

    Could you provide you source code to review?

    Hi BSTRobin,

    You can run the basic_config_state.ino example and see the issue I describe. For your convenience I've edited the example and attached it in the context of my setup. Between the following:

    ...
    BSEC next call time: 0ms
    BSEC next call time: 3113ms
    ...

    should be the output from the callback but there is nothing. The first invocation of bsecInst.run() does not invoke the callback thus deep sleeping, without wasting power until the first callback, is not possible as no values will every be returned from the sensor. Instead we have to wait for the LP or ULP interval from ESP_RST_POWERON, ESP_RST_DEEPSLEEP, etc. before we get the first output:

    ...
    BSEC next call time: 3113ms
    bsecInst.run() invocations:1
    BSEC outputs:
    timestamp = 3114
    iaq = 27.09
    iaq accuracy = 0
    static iaq = 28.00
    co2 eq = 512.01
    voc eq = 0.52
    temperature = 24.66
    pressure = 101028.48
    humidity = 42.93
    gas resistance = 69584.13
    compensated temperature = 24.66
    compensated humidity = 38.93

    Thank you again for looking at the issue.

    Hi again,

    I've been doing further testing within bme68x.c and have further insight into my problem:

    Bsec::run() [bsec.cpp] -> bme68x_get_data() [bme68x.c] -> read_field_data() [bme68x.c]

    does not return any results and thus my callback is not called. I can only assume because the sensor is not ready. Looking through the code I can see that read_field_data() tries 5 times waiting 10ms each time before returning to bme68x_get_data() which sets the returned result to BME68X_W_NO_NEW_DATA. If I alter the number of retries to 25:

    /* This internal API is used to read a single data of the sensor */
    static int8_t read_field_data(uint8_t index, struct bme68x_data *data, struct bme68x_dev *dev)
    ...
    uint8_t tries = 25; // Was 5
    ...
    while ((tries) && (rslt == BME68X_OK))
    {
    ...
    if (rslt == BME68X_OK)
    {
    dev->delay_us(BME68X_PERIOD_POLL, dev->intf_ptr); // TODO: Increase period to ~240ms for this function only so less wakeups from light sleep?
    }

    tries--;
    }

    read_field_data() returns with BME68X_NEW_DATA_MSK and we get:

    BSEC outputs:
    timestamp = 114
    iaq = 30.01
    iaq accuracy = 0
    static iaq = 33.45
    co2 eq = 533.80
    voc eq = 0.57
    temperature = 24.58
    pressure = 101232.21
    humidity = 48.54
    gas resistance = 13742.75
    compensated temperature = 24.58
    compensated humidity = 45.68

    The timestamp is now at 114ms after 20 retries or ~240ms of waiting. I can thus get a single reading and go straight back to deep sleep without having to wait for one sample rate period (3/300s). I assume this is the sleep stipulation in the BME688 Integration Guide:

    "Typical durations for the "Sleep until measurement is finished" are 0.190 seconds for LP mode and 2 seconds for ULP mode"

    I think this is a bug in the BME68x-Sensor-API and wasn't account for in the interface before my change to the number of retries. The only problem in making this minor change is that ever subsequent call to read_field_data() also has to retry for ~240ms before getting a reading from the device, while previously no retries were needed if the first call to run() returned nothing. I'm not sure why that is, any ideas? Anyway, the power consumption of waiting can be mitigated by hard coding a period of 240ms in the call to  dev->delay_us().

    I hope others find this post useful as I've wasted a lot of time debugging this issue!

    ilcnet
    Established Member
    Hello BSTRobin

    I have a problem with esp32 deep sleep and Bme688, when the esp32 going to deep sleep unfortunately the esp32 pins are active and for example the Bme688 adafruit product the green light on pcb are active that means Bme688 are active and only esp32 cores are sleep, my question is when esp32 is in sleep mode and there is no computing the Bme688 are working and scanning the gases? And Bme688 use battery power in action mode or Bme688 is in standby mode? Thanks
    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