CCS811 icon indicating copy to clipboard operation
CCS811 copied to clipboard

CCS811 & Deep Sleep

Open lloydrichards opened this issue 4 years ago • 14 comments

Greetings,

So I've been doing some experimenting with using the CCS811 with a deep sleep functionality and have been getting some odd results. Perhaps someone also has some experience and can help me out. So the code looks something like this:

const SleepTimer = 15 //in min
void setup(){
esp_sleep_wakeup_cause_t wakeup_reason;
  wakeup_reason = esp_sleep_get_wakeup_cause();

switch (wakeup_reason)
  {
  case ESP_SLEEP_WAKEUP_UNDEFINED:
     ccs811.begin();
  break;

   case ESP_SLEEP_WAKEUP_TIMER:
      uint16_t eco2, etvoc, errstat, raw;

      ccs811.read(&eco2, &etvoc, &errstat, &raw);
      Serial.println(eco2);
      Serial.println(etvoc);
   break;
   };

   esp_sleep_enable_timer_wakeup(SleepTimer * 1000000LL);
   delay(100);
   esp_deep_sleep_start();
}

While this works and I get readings every 15 min and they even seem to be quite accurate for the first hour or two. The problem is that after that first hour the VOC steadily increases resulting in an increased eCO2. I have several CCS811 sensors so I've compared the deep sleep version with one that runs in the loop and there is odd behaviour going on while it's asleep.

I have several theories, including that while the sensor is not being read it slowly builds VOC in the sensor resulting in increased readings, but I have no way to verify this. If anyone has any ideas, it would be much appreciated!

lloydrichards avatar May 04 '20 15:05 lloydrichards

Hi, if the sensor is set to 1s or 60s interval time and not being switched off during ESP deep sleep I do not see why the overall sensor behavior should be different from a sensor which is read more frequently. The other sensor has the same history and is well run-in? CCS811 has a faster baseline correction during the very first days of operation which might cause some delta between the two sensor outputs. It is important not to power off CCS811 or switching to sensor sleep mode without using the baseline save and restore features. MOX sensors are power hungry but long power-off times will result in reduced sensor performance.

nordicp avatar May 07 '20 09:05 nordicp

img_20200507_124105

The sensor on the left is running at 15min deep sleep interval with the 60sec mode and the one on the right is running 15min deep sleep interval with 1sec mode. The right sensor seems to be about right and but the left is all over the place. As far as I know, the baseline is updating automatically but maybe I should try saving and setting it before and after deep sleep? Alternatively, I'm going to try waking up the device more frequently to just read the sensor and see if that helps?

lloydrichards avatar May 07 '20 10:05 lloydrichards

Hi Lloyd,

That is a nice looking board you have there! I guess ESP with e-ink? Did you make it yourself or is this a standard product.

Just to check, the left and right board both have a CCS811, both have the same firmware version (which one?), both have about the same purchase date and the same operation time. And both have been powered on at the same time and have been side-by-side during continuously since they were powered on. And you did not do any baseline restore.

The difference is that the left runs the CCS811 in 60s mode and the right runs the CCS811 in 1s mode. In both boards, the CCS811 is always powered and running, it is only the ESP that sleeps 15 min.

maarten-pennings avatar May 10 '20 18:05 maarten-pennings

The ESP32 and the E-Ink are part of the TTGO T5 2.3V package, which I'm using mostly to debug while not attached to Serial ports. The round shield underneath is what I've designed. Its mostly a sensor matrix with a few LED's and breakout pins for testings. The CCS811 is on the shield and wired exactly the same as the Sparkfun CCS811 breakout unit.

Both Units were started at the same time, with similar battery systems using the same code except for the CCS811 Mode. Everything has been bought in the last month so should all be up to date with firmware and specks. Have been running these now for about three days and still getting a bit of discrepancy when they take readings. But until I've gotten a nanometer and can see how much power each mode is drawing I'm just going to have to deal with having them all on one mode for now and dealing with it later.

Additionally, I'm working on the legal bits and pieces to release the shield as an Open Source Hardware module with the library and schematics I've done. For those looking for a bit of an all-rounder indoor sensor (light, UV, heat, temp, pressure, eCo2, VOC). When I'm sorted, I'll send you the details if you're interested :)

lloydrichards avatar May 10 '20 21:05 lloydrichards

Hi Lloyd, Hi Maarten,

I have a similar but way more simplified setup and I was testing the TTGO T8 (ESP32) and the WEMOS D1 mini (ESP8266) next to each other to test the battery life (2900mAh samsung battery) with the CCS811 with integrated HDC1080 temperature and humidity sensor.

IMG_20201021_153829428

I'm interested in the results of your test on the 1sec / 60sec intervals. Mine are on the 60sec intervals.

I have two questions about this:

  1. it is consuming 0,4mA in deep sleep (for 15 minutes), and 94mA when awake and sending data (for about 1sec). So it should survive on battery about 100-200 days. It only last 6 with the WEMOS D1 and 4 with the TTGO T8 board.. I don't understand what happens... any Idea?
  2. I cannot use the protected (seems logical) functions wake_up and wake_down.. will it automatically go to sleep and wake up if the pin is defined (mine is on D3)

@Maarten: thanx a lot for the library and the extended explanations.

DeKasClimber avatar Oct 21 '20 14:10 DeKasClimber

Could you explain in more detail the power cycle.

It sounds like the ESP is sleeping for 15min and awake for 1sec. This seems to consume 0.4mA. But what is the CCS811 doing? Is it always running in 60sec mode? This means that once in a while (is that 1 sec per 60 sec??) the heater is on using ~40mA.

Yes, if the wake pin is defined it should go to sleep. Can you measure this?

maarten-pennings avatar Oct 21 '20 15:10 maarten-pennings

Thank you for the quick response. You have the power cycle correct. You can read it in the code snippets below.

And I hoped the sensor was put to sleep when connected to the wake pin. I measured the power for a couple of cycles and it is a steady 0,4 mA in deep sleep.

DEEP_SLEEP_TIME = 15

setup cycle

void setup() {
    Serial.begin(115200);
    Serial.println("sensor station started.");

    connectWiFi();

    initializeSensors();

    runSensors();

    Serial.println("going to sleep now!");
    
    //sleep 15 minutes
    ESP.deepSleep(DEEP_SLEEP_TIME * 60L * 1000000L); 

}

initializeSensors code

void initializeSensors(){
    
  Serial.println("now starting sensors…");

  //This begins the HDC sensor 
  Serial.println("HDC1080: setup begins.");
  myHDC1080.begin(0x40);
  Serial.println("HDC1080: setup done.");

  Wire.begin();
  ccs811.set_i2cdelay(50); // Needed for ESP8266 because it doesn't handle I2C clock stretch correctly

  int REASON_DEEP_SLEEP_AWAKE = 5;
  rst_info * rstinfo = ESP.getResetInfoPtr(); // get reason why awake ESP8266
  Serial.println(rstinfo->reason);
  
  // when NOT coming out of deepsleep:
  if (rstinfo->reason != REASON_DEEP_SLEEP_AWAKE){ //ESP8266

    Serial.println("CCS811: setup begins.");
    bool ok= ccs811.begin();
    if( !ok ) Serial.println("setup: CCS811 begin FAILED");
    ok= ccs811.start(CCS811_MODE_60SEC);
    if( !ok ){
        // start failed!
        Serial.println("setup: CCS811 start FAILED");
    }
    
    } else {
      // we come out of deep sleep and ccs811 is in known state.
      Serial.println("CCS811: setup already done.");
  }

}

running the sensors:

void runSensors(){
    
    //read HDC1080 sensor
    float sensorTempC = myHDC1080.readTemperature();
    float sensorHumid = myHDC1080.readHumidity();

    submitSensorData(apiKeyValue,"Temperature",sensorTempC);
    submitSensorData(apiKeyValue,"Humidity",sensorHumid);

    //compensating the CCS811 with humidity and temperature readings from the HDC1080
    ccs811.set_envdata(myHDC1080.readHumidity(), myHDC1080.readTemperature()); 
    
    //read CCS811 sensor
    uint16_t eco2, etvoc, errstat, raw;
      ccs811.read(&eco2,&etvoc,&errstat,&raw);
      // Print measurement results based on status
      if( errstat==CCS811_ERRSTAT_OK ) {
          // everything is fine, we have new data
        submitSensorData(apiKeyValue,"eCO2",eco2);
        submitSensorData(apiKeyValue,"TVOC",etvoc);
      } else if( errstat==CCS811_ERRSTAT_OK_NODATA ) {
          // everything is fine, but there is no new data yet.)
        Serial.println("CCS811: waiting for (new) data");
      } else if( errstat & CCS811_ERRSTAT_I2CFAIL ) {
          // I2C Connection failed
        Serial.println("CCS811: I2C error");
      } else {
          // other error
        Serial.print("CCS811: errstat="); Serial.print(errstat,HEX);
        Serial.print("="); Serial.println( ccs811.errstat_str(errstat) );
      }  
}

DeKasClimber avatar Oct 21 '20 15:10 DeKasClimber

Each time the ESP comes out of deep sleep, it executes setup() and thus initializeSensors() and thus ccs811.begin(). This resets the CCS811. This is not what you want, is it? The CCS811 is supposed to keep on running in 60sec mode, and you just want to read it, not?

maarten-pennings avatar Oct 21 '20 16:10 maarten-pennings

First I check the wake-up reason. If it is different from awakening from deep sleep, I do the setup, otherwise I don't do the setup.

simplified code: if (rstinfo->reason != REASON_DEEP_SLEEP_AWAKE) { ccs811.begin() } else { println( "CCS811: setup already done.") }

Preferably the CCS811 goes to sleep (or low power mode - 0) for 15 minutes. wakes up when the WEMOS is awake, and reads one time CO2 and TVOC and goes to low power mode again.

DeKasClimber avatar Oct 21 '20 17:10 DeKasClimber

Sorry; missed the `if``.

Other question; is this correct?

ccs811.set_envdata(myHDC1080.readHumidity()...)

The set_envdata wants ccs811 internal format

maarten-pennings avatar Oct 21 '20 18:10 maarten-pennings

The set_envdata wants ccs811 internal format: I read about the format. I just took the risk. It seams to work. No errors, and results seam ok, but I don't know if I have to expect an error or very different values. I have one setup running without the environmental data, and one with.. it is slightly different, but fluctuations on CO2 are always big..

DeKasClimber avatar Oct 21 '20 18:10 DeKasClimber

You will not get errors; just the internal algorithm uses wrong t/h values. Assuming HDC1080.readHumidity() returns the value in % you need to multiply it by 512; datasheet says "Humidity is stored as an unsigned 16 bits in 1/512%RH". Temperature is harder: you have to add 25 then multiply by 512, assuming the hdc reports in celsius.

Now back to power ;-)

maarten-pennings avatar Oct 21 '20 18:10 maarten-pennings

yep, you got it right. I'm sending the wrong data. I'll adapt the code, because correct data is essential..

But the power is indeed the main issue..

DeKasClimber avatar Oct 21 '20 19:10 DeKasClimber

@lloydrichards: did you find a solution for the increasing values yet? since my soldered version is running for a couple of weeks now (which is better than before) I was wandering what data came out (was busy with work - forgot about checking the data) and both TVOC and CO2 values are very high.. with nearly nobody around.

With the basic sketch I have normal CO2 values varying from 410-550 ppm, both with version 1.0.1 as with version 2.0.1 (yes I flashed the sensors firmware successfully - for the record - WEMOS D1 mini ESP8266 with the CCS811 HDC1080 sensor - thanks Maarten) but in deep sleep values are increasing way beyond healthy levels..

Deep sleep every 15 mins afbeelding

On power with basic sketch afbeelding

DeKasClimber avatar Nov 18 '20 21:11 DeKasClimber