ESP32C3 does not store variable value in RTC_DATA_ATTR

Hello, I hope for your help since I can’t solve the problem myself.

I need to store the variable value 1 or 0 when entering deep sleep mode
I post the variable

RTC_DATA_ATTR int shouldWakeUp = 0;

Next, when the device calls the method to go to sleep, I change

shouldWakeUp = 1;
startDeepSleep();

Next the method is called

void startDeepSleep() {
esp_sleep_enable_timer_wakeup(10 * 1000000);
Serial.print("startDeepSleep() RTC_DATA_ATTR shouldWakeUp = ");
Serial.println(shouldWakeUp);
Serial.println(“SLEEP for 1 min”);
delay(1000);
esp_deep_sleep_start();
}

Now, according to the idea, when ESP starts, the shouldWakeUp variable should be 1

But she’s 0 again

What am I doing wrong? Please take a look at the whole code:

#include <NimBLEDevice.h>
#include "Wire.h"
#include <MPU6050_light.h>
#include <DFRobot_QMC5883.h>

DFRobot_QMC5883 compass(&Wire, /*I2C addr*/ QMC5883_ADDRESS);
MPU6050 mpu(Wire);

// Structure to hold sensor data
struct SensorData {
  int16_t ax;
  int16_t ay;
  int16_t az;
  int16_t h;
  int16_t v;
};

BLEServer *pServer = NULL;
BLECharacteristic *Ch_SendData;
bool deviceConnected = false;
RTC_DATA_ATTR int shouldWakeUp = 0;
unsigned long sleepTimer = 0;
const unsigned long AFTER_SLEEP_TIMER = 5000;           // 5 seconds
const unsigned long SLEEP_TIMEOUT_CONNECTED = 30000;    // 30 seconds
const unsigned long SLEEP_TIMEOUT_DISCONNECTED = 30000; // 30 seconds

#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9A"
#define UUID_Reboot "6E400002-B5A3-F393-E0A9-E50E24DCCA9B"
#define UUID_SendData "6E400003-B5A3-F393-E0A9-E50E24DCCA9C"

// Placeholder method for handling movement after waking up from sleep
void startMoving() {
  // Implementation to be added
}

// Function to initiate deep sleep
void startDeepSleep() {
  // Disable BLE
  BLEDevice::deinit(true);
  // Set sleep timer for 10 seconds
  esp_sleep_enable_timer_wakeup(10 * 1000000);
  Serial.print("startDeepSleep() RTC_DATA_ATTR shouldWakeUp = ");
  Serial.println(shouldWakeUp);
  Serial.println("SLEEP for 1 min");
  delay(1000);
  // Enter deep sleep
  esp_deep_sleep_start();
}

// Function to check for movement based on gyro data
void motionTracking(float tx, float ty, float tz) {
  if (abs(tx) > 40 || abs(ty) > 40 || abs(tz) > 40) {
    // If movement is detected
    Serial.println("MOVING");
    sleepTimer = millis();
  }
}

// Function to handle actions after waking up from sleep
void wakeUp() {
  Serial.println("Restart 70");
  mpu.update();
  float tx = mpu.getGyroX();
  float ty = mpu.getGyroY();
  float tz = mpu.getGyroZ();
  motionTracking(tx, ty, tz);
  if (millis() - sleepTimer > AFTER_SLEEP_TIMER) {
    shouldWakeUp = 0;
    Serial.println("Time elapsed after wakeup, performing additional actions");
  } else {
    Serial.println("TRYDEEPSLEEP");
    startDeepSleep();
  }
}

// Placeholder for BLE initialization (to be implemented)
void startBLE() {
  // Add BLE initialization code here
}

void setup() {
  Serial.begin(115200);
  Wire.begin(6, 7);
  while (!compass.begin()) {
    Serial.println("Could not find a valid 5883 sensor, check wiring!");
    delay(500);
  }
  byte status = mpu.begin();
  startBLE();
}

void loop() {
  if (deviceConnected) {
    uint32_t Vbatt = 0;
    for (int i = 0; i < 16; i++) {
      Vbatt = Vbatt + analogReadMilliVolts(A0); // ADC with correction
    }
    float Vbattf = 2 * Vbatt / 16 / 1000.0; // Attenuation ratio 1/2, mV --> V

    SensorData sensorData;
    mpu.update();

    float declinationAngle = (4.0 + (26.0 / 60.0)) / (180 / PI);
    compass.setDeclinationAngle(declinationAngle);
    sVector_t mag = compass.readRaw();
    compass.getHeadingDegrees();

    int16_t ax = mpu.getAngleX();
    int16_t ay = mpu.getAngleY();
    int16_t az = mpu.getAngleZ();
    int16_t headingInt = mag.HeadingDegress;
    float tx = mpu.getGyroX();
    float ty = mpu.getGyroY();
    float tz = mpu.getGyroZ();
    sensorData.ax = ax;
    sensorData.ay = ay;
    sensorData.az = az;
    sensorData.h = headingInt;
    sensorData.v = static_cast<int16_t>(round(Vbattf * 100));
    Serial.println(Vbattf, 3);

    Ch_SendData->setValue((uint8_t *)&sensorData, sizeof(sensorData));
    Ch_SendData->notify();
    // Monitoring for movement
    motionTracking(tx, ty, tz);
    if (millis() - sleepTimer > SLEEP_TIMEOUT_CONNECTED) {
      // If no movement within SLEEP_TIMEOUT_CONNECTED seconds, enter deep sleep
      Serial.println("SLEEP-With BLE");
      shouldWakeUp = 1;
      startDeepSleep();
    }
    delay(200);
  } else {
    Serial.println("Start");
    Serial.print("setup(): RTC_DATA_ATTR shouldWakeUp = ");
    Serial.println(shouldWakeUp);
    if (shouldWakeUp == 1) {
      Serial.println("shouldWakeUp == 1");
      wakeUp();
    }
    mpu.update();
    float tx = mpu.getGyroX();
    float ty = mpu.getGyroY();
    float tz = mpu.getGyroZ();
    motionTracking(tx, ty, tz);
    if (millis() - sleepTimer > SLEEP_TIMEOUT_DISCONNECTED) {
      // If no movement within SLEEP_TIMEOUT_DISCONNECTED - 10 seconds, enter deep sleep
      Serial.println("SLEEP-With BLE ");
      shouldWakeUp = 1;
      startDeepSleep();
    }
  }
  delay(1000);
}

Hi,
Did you find the reason for this issue? I have the same issue.
it was working and then stoped working. cant see why

Yes! The fact is that as long as the ESP is connected via USB and the Serial Port is open, the variable is not stored. You need to close the Serial Port and then the RTC memory remembers the variable after waking up from sleep

Thank you very much for this info, I was confused why my vars were not holding value!!! This is even more frustrating when Seeed’s example even shows Serial.print and does not even mention this shortcoming.

Hi there,
You can also declare it a “Volatile” variable as well.
or write it to the flash memeory.
HTH
GL :slight_smile: PJ :v:

@PJ_Glasso from what I understand volatile is not a drop in replacement for RTC_DATA_ATTR variables, volatile are variables that the compiler should not optimize and for use with interrupts, while RTC_DATA_ATTR are variables that are Real Time Clock memory variables which are preserved in deep sleep.

Again, from what I understand, while flash memory could accomplish data being preserved, it is slower than using RTC_DATA_ATTR and has more overhead associated with it, so flash might not be appropriate for a situation where a program goes to sleep quite often.

1 Like

Hi there,
Ah’ I see that now, I stopped comprehending after “does not store variable” Snap!
low hanging fruit first :grinning:
I have sleep code w/ wake button included in the Grove Expansion Flash Upgrade Demo on here. One is for Nrf52840 and the other is for Xiao ESP32C3 with that boot count code working, I don’t recall same issues, it’s battery and USB, works both ways.
May be off your mark slightly but good info just the same.
HTH
GL :slight_smile: PJ :v:

swing and a miss,
I found this one , It’s the preferences LIB, Works and saved across resets.

Hi there,
So I did have it working here, well.

Sleeps as long as you don’t wake it :grinning:, Keeps a good boot count. :+1:
HTH
GL :slight_smile: PJ :v: