Arrays and RTC_DATA_ATTR with DeepSleep (ESP32C6)

owainsutton
Posts: 1
Joined: Wed Aug 27, 2025 3:51 pm

Arrays and RTC_DATA_ATTR with DeepSleep (ESP32C6)

Postby owainsutton » Wed Aug 27, 2025 3:56 pm

I'm making a low-power CO2 monitor, with an eink display, using Deep Sleep to keep the battery consumption minimal with solar charging (using a DFRobot Firebeetle 2 ESP32-C6).

It's working fine for wakeup each 60 seconds, and with retaining the value of bootCount declared with RTC_DATA_ATTR.

I want to use two arrays, also with RTC_DATA_ATTR, to populate with previous readings from which ten-minute and one-hour averages can be calculated. But these are not being retained, on wakeup they are being filled with zeroes. (Or, if I remove the value from the declaration, they contain random data, as would be expected from a newly-declared variable.)

Is the issue that arrays cannot be placed in RTC memory in this way - and if so, is there another way to retain this data through deep sleep? Or is it another problem entirely?

Code: Select all

#include <GxEPD2_BW.h>
#include <DFRobot_SCD4X.h>
#include <Fonts/FreeSansBold24pt7b.h>
#include <Fonts/FreeSansBold12pt7b.h>

#define BATT_V_PIN    0

#define uS_TO_S_FACTOR 1000000ULL  /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP  60        /* Time ESP32 will go to sleep (in seconds) */
#define TEN_MINUTE_READINGS 10      // Adjust these to match TIME_TO_SLEEP
#define ONE_HOUR_READINGS 60    //      "        "      "       "

GxEPD2_BW<GxEPD2_420_GDEY042T81, GxEPD2_420_GDEY042T81::HEIGHT> display(GxEPD2_420_GDEY042T81(14, 8, 16, 17)); // 400x300, SSD1683

DFRobot_SCD4X SCD4X(&Wire, SCD4X_I2C_ADDR);
DFRobot_SCD4X::sSensorMeasurement_t data;

char displayText[12];

struct readings {
  uint16_t CO2;
  float temp;
  float humid;
  int tempInt;
  int humidInt;
  float battery;
};

readings current;

RTC_DATA_ATTR int CO2_ten_minutes[TEN_MINUTE_READINGS] = {0};
RTC_DATA_ATTR int CO2_one_hour[ONE_HOUR_READINGS] = {0};

int CO2_ten_minute_average = 0;
int CO2_one_hour_average = 0;
RTC_DATA_ATTR int bootCount = 0;
int i;

void setup() {
  Serial.begin(115200);

  pinMode(BATT_V_PIN, INPUT);

  while( !SCD4X.begin() ){
    Serial.println("Communication with device failed, please check connection");
    delay(3000);
  }
  Serial.println("SCD4X initialised OK");

  bootCount++;
  Serial.println("Boot count: " + String(bootCount));

  SCD4X.enablePeriodMeasure(SCD4X_STOP_PERIODIC_MEASURE);

  display.init(115200,true,50,false);
  
  Serial.println("Display init OK");
  display.setTextColor(GxEPD_BLACK);

}

void loop() {

  display.fillScreen(GxEPD_WHITE);

  SCD4X.measureSingleShot(SCD4X_MEASURE_SINGLE_SHOT);
  Serial.print("Waiting for readings to be available...");
  while (!SCD4X.getDataReadyStatus()) 
  {
    Serial.print(F("."));
    delay(500);
  }
  Serial.println("taking readings now.");
  
  // Discard the first set of data, because the chip datasheet indicates the first reading obtained after waking up is invalid
  SCD4X.measureSingleShot(SCD4X_MEASURE_SINGLE_SHOT);
  while(!SCD4X.getDataReadyStatus()) {
    delay(100);
  }
  SCD4X.readMeasurement(&data);

  current.CO2 = data.CO2ppm;
  current.temp = data.temp;
  current.humid = data.humidity;
  current.tempInt = rint(data.temp);
  current.humidInt = rint(data.humidity);

  Serial.print("Carbon dioxide concentration : ");
  Serial.print(current.CO2);
  Serial.println(" ppm");

  for (i = 0; i++; i < (TEN_MINUTE_READINGS - 1) ) {
    CO2_ten_minutes[i] = CO2_ten_minutes[i+1];
    CO2_ten_minute_average += CO2_ten_minutes[i];
  }
  CO2_ten_minutes[i] = current.CO2;
  CO2_ten_minute_average += CO2_ten_minutes[i];
  CO2_ten_minute_average /= TEN_MINUTE_READINGS;

  if ( bootCount >= TEN_MINUTE_READINGS ) {
    Serial.print("Ten minutes CO2 average: ");
    Serial.println(CO2_ten_minute_average);
  }
  else {
    Serial.println("Awaiting ten-minute average");
  }

  for (i = 0; i++; i < (ONE_HOUR_READINGS - 1) ) {
    CO2_one_hour[i] = CO2_one_hour[i+1];
    CO2_one_hour_average += CO2_one_hour[i];
  }
  CO2_one_hour[i] = current.CO2;
  CO2_one_hour_average += CO2_one_hour[i];
  CO2_one_hour_average /= ONE_HOUR_READINGS;

  if ( bootCount >= ONE_HOUR_READINGS ) {
    Serial.print("One hour CO2 average: ");
    Serial.println(CO2_one_hour_average);
  }
  else {
    Serial.println("Awaiting one-hour average");
  }  

  Serial.print("Environment temperature : ");
  Serial.print(current.temp);
  Serial.println(" C");

  Serial.print("Relative humidity : ");
  Serial.print(current.humid);
  Serial.println("%");

  display.setFont(&FreeSansBold24pt7b);
  display.setTextSize(2);
  sprintf(displayText, "%d", current.CO2);
  drawCentreString(displayText, 200, 100);
  
  display.setTextSize(1);
  sprintf(displayText, "%dC", current.tempInt);
  drawCentreString(displayText, 100, 200);

  sprintf(displayText, "%d%%", current.humidInt);
  drawCentreString(displayText, 300, 200);

  display.setFont(&FreeSansBold12pt7b);
  display.setTextSize(1);
  current.battery = (analogReadMilliVolts(BATT_V_PIN)*0.002);
  Serial.print("Battery reading via ADC on pin 0: ");
  Serial.print(current.battery, 2);
  Serial.println("V");
  sprintf(displayText, "Battery: %.2fV", current.battery);
  drawCentreString(displayText, 200, 260);

  display.nextPage();

  Serial.println();

  display.hibernate();
  SCD4X.setSleepMode(SCD4X_POWER_DOWN);
  esp_sleep_enable_timer_wakeup( ( TIME_TO_SLEEP - millis()/1000 ) * uS_TO_S_FACTOR);
  Serial.println("Setup ESP32 to sleep for " + String(TIME_TO_SLEEP) +
  " Seconds");  
  Serial.println("Going to sleep now");
  Serial.flush(); 
  esp_deep_sleep_start();
  Serial.println("This will never be printed");  
}

void drawCentreString(const char *buf, int x, int y)
{
    int16_t x1, y1;
    uint16_t w, h;
    display.getTextBounds(buf, x, y, &x1, &y1, &w, &h);
    display.setCursor(x - w / 2, y);
    display.print(buf);
}

MicroController
Posts: 2663
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: Arrays and RTC_DATA_ATTR with DeepSleep (ESP32C6)

Postby MicroController » Thu Aug 28, 2025 9:32 am

(Or, if I remove the value from the declaration, they contain random data, as would be expected from a newly-declared variable.)
So you fill the arrays with valid data, then go to deep sleep, and the valid data is gone after wakeup?

Who is online

Users browsing this forum: ChatGPT-User, Qwantbot, Semrush [Bot] and 3 guests