I'm new to the ESP32 and am trying to get some code to work which I'd like to use in a larger project.
Basically I want the chip to enter Deep Sleep mode at the push of a button (GPIO 0), and also wake from Deep Sleep with the push of the same button.
I've set up an interrupt service routine which waits for GPIO0 to be pulled low, then runs the deep sleep code, and then once in deep sleep, pushing the same button also wakes the ESP up.
The problem is, this only works once, and afterwards there's no response from pushing the button at GPIO0 unless I reboot the ESP and start from scratch. I'm a bit confused as to why this is, especially since I'm running esp_restart() in the Wake Stub code, which I would assume mimics a hard reboot.
Would anyone have a clue as to why it's only working once?
Thanks!
Here's my full code:
Code: Select all
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "esp_deep_sleep.h"
#include "sdkconfig.h"
#include "sys/time.h"
#include "driver/gpio.h"
#include "freertos/semphr.h"
#include "driver/rtc_io.h"
#include "soc/rtc_cntl_reg.h"
#define GPIO_INPUT_IO_TRIGGER 0 // GPIO 0 Pushbutton
#define BUTTON_PIN 0
#define ESP_INTR_FLAG_DEFAULT 0
#define INFINITE_LOOP 1
#define LOW 0
SemaphoreHandle_t xSemaphore = NULL;
// Function Prototypes
void IRAM_ATTR button_isr_handler(void* arg);
void deep_sleep(void);
void init_button_intr(void);
void button_task(void* arg);
void RTC_IRAM_ATTR esp_wake_deep_sleep(void);
void IRAM_ATTR button_isr_handler(void* arg){
// Notify the button task
xSemaphoreGiveFromISR(xSemaphore, NULL);
}
void deep_sleep(void){
esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_AUTO);
gpio_pullup_en(GPIO_INPUT_IO_TRIGGER);
gpio_pulldown_dis(GPIO_INPUT_IO_TRIGGER);
esp_deep_sleep_enable_ext0_wakeup(GPIO_INPUT_IO_TRIGGER, LOW);
printf("Going into deep sleep\n");
esp_deep_sleep_start();
}
void init_button_intr(void){
gpio_pullup_en(GPIO_INPUT_IO_TRIGGER);
gpio_pulldown_dis(GPIO_INPUT_IO_TRIGGER);
// Create binary semaphore
xSemaphore = xSemaphoreCreateBinary();
// Configure Pushbutton GPIO pin
gpio_pad_select_gpio(BUTTON_PIN);
// Configure GPIO Direction
gpio_set_direction(BUTTON_PIN, GPIO_MODE_INPUT);
// Enable interrupt on falling edge
gpio_set_intr_type(BUTTON_PIN, GPIO_INTR_NEGEDGE);
// Start Task that will handle the Pushbutton
xTaskCreate(button_task, "button task", 2048, NULL, 10, NULL);
// Install ISR service with default configuration
gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
// Attach the interrupt service routine
gpio_isr_handler_add(BUTTON_PIN, button_isr_handler, NULL);
}
void button_task(void* arg){
while (INFINITE_LOOP){
if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE){
//printf("Button Pressed\n");
vTaskDelay(500 / portTICK_PERIOD_MS);
deep_sleep();
}
}
}
// Wake Stub code
void RTC_IRAM_ATTR esp_wake_deep_sleep(void){
esp_default_wake_deep_sleep();
vTaskDelay(500 / portTICK_PERIOD_MS);
esp_restart();
REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_WAK, 4);
REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_SLP, 4);
init_button_intr();
}
// MAIN FUNCTION
void app_main()
{
printf("TEST\n");
init_button_intr();
}