How to keep ESP32 from resetting on wakeup from deep_sleep

DanielPLongo
Posts: 11
Joined: Fri Apr 08, 2022 6:02 pm

How to keep ESP32 from resetting on wakeup from deep_sleep

Postby DanielPLongo » Mon Aug 29, 2022 1:14 pm

I am using ulp_start() in the code below to hold a PWM signal while the ESP32-WROOM-32UE is in deep sleep. However, when the program exits deep sleep via the timer, it resets the module. I need the program to stay in the loop and increment the PWM duty cycle at each iteration and NOT reset completely. Can you direct me on how to do this?

Code: Select all

#include <Arduino.h>
#include "esp32/ulp.h"
#include "driver/rtc_io.h"

//const int dutyMeter = 100; // (0-255)

//Time-to-Sleep
#define uS_TO_S_FACTOR 1000000ULL  /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP  1        /* Time ESP32 will go to sleep (in microseconds); multiplied by above conversion to achieve seconds*/

RTC_DATA_ATTR int bootCount = 0;

/*
Method to print the reason by which ESP32
has been awaken from sleep
*/
void print_wakeup_reason(){
  esp_sleep_wakeup_cause_t wakeup_reason;

  wakeup_reason = esp_sleep_get_wakeup_cause();

  switch(wakeup_reason)
  {
    case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
    case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
    case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
    default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
  }
}

void ulp_start(int dutyMeter) {
// Slow memory initialization
memset(RTC_SLOW_MEM, 0, 8192);
// if LED is connected to GPIO2 (specify by +14)
const gpio_num_t MeterPWMPin = GPIO_NUM_2;
const int MeterPWMBit = RTCIO_GPIO2_CHANNEL + 14;
// GPIOx initialization (set to output and initial value is 0)
rtc_gpio_init(MeterPWMPin);
rtc_gpio_set_direction(MeterPWMPin, RTC_GPIO_MODE_OUTPUT_ONLY);
rtc_gpio_set_level(MeterPWMPin, 0);
// Define ULP program
const ulp_insn_t ulp_prog[] = {
M_LABEL(1),
I_WR_REG(RTC_GPIO_OUT_REG, MeterPWMBit, MeterPWMBit, 1), // on
I_DELAY(dutyMeter * 100),
I_WR_REG(RTC_GPIO_OUT_REG, MeterPWMBit, MeterPWMBit, 0), // off
I_DELAY(25500 - dutyMeter * 100),
M_BX(1),
};
// Run ULP program
size_t size = sizeof(ulp_prog) / sizeof(ulp_insn_t);
ulp_process_macros_and_load(0, ulp_prog, &size);
ulp_run(0);
}

void setup() {
Serial.begin(115200);
  delay(1000); //Take some time to open up the Serial Monitor

  //Increment boot number and print it every reboot
  ++bootCount;
  Serial.println("Boot number: " + String(bootCount));

  //Print the wakeup reason for ESP32
  print_wakeup_reason();
Serial.println("Setup");


//GPIO Outputs

pinMode(32, OUTPUT);   //8
digitalWrite(32, LOW); 
pinMode(33, OUTPUT);   //9
digitalWrite(33, LOW); 
pinMode(25, OUTPUT);   //10
digitalWrite(25, LOW); 
pinMode(26, OUTPUT);   //11
digitalWrite(26, LOW); 
pinMode(27, OUTPUT);   //12
digitalWrite(27, LOW); 
pinMode(14, OUTPUT);   //13
digitalWrite(14, LOW); 
pinMode(12, OUTPUT);   //14
digitalWrite(12, LOW); 
pinMode(13, OUTPUT);   //16
digitalWrite(13, LOW); 
pinMode(15, OUTPUT);   //23
digitalWrite(15, LOW); 
//pinMode(2, OUTPUT);   //24
//digitalWrite(2, LOW); 
pinMode(0, OUTPUT);   //25
digitalWrite(0, LOW); 
pinMode(4, OUTPUT);   //26
digitalWrite(4, LOW); 
pinMode(16, OUTPUT);   //27
digitalWrite(16, LOW); 
pinMode(17, OUTPUT);   //28
digitalWrite(17, LOW); 
pinMode(5, OUTPUT);   //29
digitalWrite(5, LOW); 
pinMode(18, OUTPUT);   //30
digitalWrite(18, LOW); 
pinMode(19, OUTPUT);   //31
digitalWrite(19, LOW); 
pinMode(21, OUTPUT);   //33   //Switch Input
digitalWrite(21, LOW);
/*
pinMode(3, OUTPUT);   //34    //RX
digitalWrite(3, LOW);  
pinMode(1, OUTPUT);   //35    //TX
digitalWrite(1, LOW); 
*/
pinMode(22, OUTPUT);   //36   //LinveVADC Input
digitalWrite(22, LOW); 
pinMode(23, OUTPUT);   //37
digitalWrite(23, LOW); 
}

void loop() {
  
  while(1){
    
    int d=0;
    int i=0;
    for(i=0;i<255;i++){
        
        d=d+10;
    
        ulp_start(d);

        Serial.println("Deep Sleep");
        

        esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR); // time set with variable above
        esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
        
        esp_deep_sleep_start();
        
        Serial.println("I'm Awake");
       
    }
  }
}

martinius96
Posts: 33
Joined: Thu Dec 13, 2018 1:39 am

Re: How to keep ESP32 from resetting on wakeup from deep_sleep

Postby martinius96 » Thu Sep 08, 2022 9:29 am

Sure, timer resets ESP32 main chip that is sleeping. So it will start properly from reset.
There is no other option than reset main chip to wake it, because it will sleep forever without reset.
You can just use other options for wakeup that will cause reset, like button a.k.a. external interrupt, timer or touch wakeup.
Also there is possible to use group of GPIOs and if all of them are in some state LOW or HIGH it will wakeup ESP using reset.
If you are using ESP-IDF and low-level programming, you can use also UART as wakeup source, where you can set number of bytes received until u react on that with reset. Also co-processor can be used for reset of ESP32 main chip.

chegewara
Posts: 2306
Joined: Wed Jun 14, 2017 9:00 pm

Re: How to keep ESP32 from resetting on wakeup from deep_sleep

Postby chegewara » Sat Sep 10, 2022 10:04 am

Wake up from deep sleep is almost the same as the power on reset, with few small exceptions.

JovazOr
Posts: 1
Joined: Mon Dec 19, 2022 5:38 am

Re: How to keep ESP32 from resetting on wakeup from deep_sleep

Postby JovazOr » Mon Dec 19, 2022 5:46 am

I had similair observatoins. In deep sleep the main memory is powered down, so any variables inside are lost. Since the RTC memory is powered on in deep sleep you normaly save variables in there so you can e.g. increment when coming out of deep sleep.

However, the ULP start code you got from viewtopic.php?t=19685 wipes out any variables you declared in the RTC memory. It's one of those solutions that gives a new problem. For me it was not a big deal so I never put to much energy in finding a solution, but maybe it's helpful for others.

DanielPLongo
Posts: 11
Joined: Fri Apr 08, 2022 6:02 pm

Re: How to keep ESP32 from resetting on wakeup from deep_sleep

Postby DanielPLongo » Thu Apr 13, 2023 1:34 pm

I can successfully save variable data in RTC memory by initializing it as follows:

(My examples)
//ULP Variables
RTC_DATA_ATTR int dutyMeter = 0;
RTC_DATA_ATTR int ulpStarted = 0;

I use the ulpStarted flag and test in the main loop with an if statement to continue with the program if the normal startup procedures have already executed and it is just 'waking up'. This is working for me.

Who is online

Users browsing this forum: Fusion and 42 guests