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);
}