boschsensortec / Bosch-BSEC2-Library

Arduino library to simplify using Bosch Sensortec's BSEC2 library
Other
77 stars 31 forks source link

ESP32-S3 Deepsleep implementation #31

Open maxdd opened 1 year ago

maxdd commented 1 year ago

Hello, I would like to use a BME680 sensor with BSEC2 library in a ESP32-S3 with battery. Can you provide the constraints on using it together with deepsleep? BSEC library is quite picky in terms of timings. How does the BSEC2 behave?

Deepak-Mvk commented 1 year ago

Hi @maxdd, The BME680 sensor is supported by the BSEC2 library for IAQ outputs. Please note that the BSEC library always expects an incrementing timestamp to calculate the outputs, so ensure that the time continues to tick during the deepsleep. Currently there is no warning code in BSEC to report if there is any mismatch in the input time.

maxdd commented 1 year ago

Hello @Deepak-Mvk, WIth IAQ outputs do you mean it doesn't not support other features? If so can you refer to a specification mentioning this? In BSEC the esp32 deep sleep implementation was using

RTC_DATA_ATTR uint8_t sensor_state[BSEC_MAX_STATE_BLOB_SIZE] = {0};
RTC_DATA_ATTR int64_t sensor_state_time = 0;

Is this the intended way? Are you planning to update the source file here https://github.com/boschsensortec/BSEC-Arduino-library/blob/master/examples/esp32DeepSleep/esp32DeepSleep.ino

with BSEC2?

Regards,

TCB13 commented 4 months ago

Is this the intended way? Are you planning to update the source file here https://github.com/boschsensortec/BSEC-Arduino-library/blob/master/examples/esp32DeepSleep/esp32DeepSleep.ino

Question: did that code ever work? The library seems to use the millis() function and that get's reset every time the device goes into sleeping...

https://community.bosch-sensortec.com/t5/MEMS-sensors-forum/Supporting-BME680-with-BSEC-on-ESP32-using-deep-sleep/m-p/10644/highlight/true#M1950

maxdd commented 4 months ago

If I remember correctly I had to use a gettimestamp function after waking from sleep and connecting to the internet. As far as I know you need to have the absolute time for the algo to work

#include <sys/time.h>

int64_t GetTimestamp() {
  struct timeval tv;
  gettimeofday(&tv, NULL);
  return (tv.tv_sec * 1000LL + (tv.tv_usec / 1000LL));
}
#define BOOT_TIME 74000
void loop() {
  int64_t calltime = GetTimestamp();
  int64_t since_start = esp_timer_get_time();
  if (sensor.run(calltime)) { // <-- when we reach here the time sensor.nextCall of the previous iteration must be equal to the absolute time here.
    sensor_state_time = GetTimestamp(); //not really sure if needed
    sensor.getState(sensor_state);

    uint64_t time_us = ((sensor.nextCall - GetTimestamp()) * 1000) - since_start - BOOT_TIME;
    esp_sleep_enable_timer_wakeup(time_us);
    esp_deep_sleep_start();
  }
}

Not sure if it is right, it was a long time ago. "BOOT_TIME" and "since_start" are used to compensate how much it will take to boot and reach the following sensor.run call (you can measure the BOOT_TIME by putting logs in the setup and right before entering sleep, in my case wifi connection has an impact). The assumption ofc is that the next iteration will be somewhat similar to the one being executed.

Theoretically you only need to update the RTC time once if you don't fully remove power so the code can be improved with a persistent variable to skip wifi connection.

My understanding is that "nextCall" is the time for the "next" sensor.run() call with "calltime" being the current absolute posix time (needed by the algo logic).

TCB13 commented 4 months ago

Thanks for the ideas.

So at some point you did changed this line here https://github.com/BoschSensortec/BSEC-Arduino-library/blob/master/src/bsec.cpp#L457 didn't you?

Because if you didn't then the library will have the wrong time and will mess up the readings...

maxdd commented 4 months ago

I believe BSEC has been aligned to BSEC2 api call so that code might not be valid anymore. I wouldn't be surprised if they changed and fixed this internally although i ignore how since as you said millis() is getting reset, What i remember is that if you have time problem, the sensor never go into the proper state after an hour or so of stabilization

TCB13 commented 4 months ago

I believe BSEC has been aligned to BSEC2 api call so that code might not be valid anymore.

https://github.com/boschsensortec/Bosch-BSEC2-Library/blob/master/src/bsec2.cpp#L254

The BSEC2 code also calls millis()...

What i remember is that if you have time problem, the sensor never go into the proper state after an hour or so of stabilization

Definitely but from my understanding those time problems come from millis() being reset.

maxdd commented 4 months ago

This change reports that compensation is not supported

To overcome this the sleep duration can be added to the millis and passed to bsec from the example code. Changes in bsec.c is also needed for this to work.

@kegov is there a chance to see a fix here?

I guess bsec.c needs to be somehow reverted to something similar to

https://github.com/boschsensortec/BSEC-Arduino-library/commit/2dd977fd57167bdfbf7753f2c9fadb31ebb9704f#diff-61d5bff668b4530537b21e88250797087f2bad8ccb4aa261551665b293aafb62R182