GPIO0 Pushbutton to Enter AND Wake from Deep Sleep - Only works once!

reb810
Posts: 2
Joined: Mon Sep 11, 2017 12:17 pm

GPIO0 Pushbutton to Enter AND Wake from Deep Sleep - Only works once!

Postby reb810 » Mon Sep 11, 2017 12:32 pm

Hi guys,

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

}

ESP_igrr
Posts: 2072
Joined: Tue Dec 01, 2015 8:37 am

Re: GPIO0 Pushbutton to Enter AND Wake from Deep Sleep - Only works once!

Postby ESP_igrr » Mon Sep 11, 2017 1:01 pm

1. You can not use FreeRTOS functions and drivers (such as GPIO drivers in deep sleep stub. Only functions marked with RTC_IRAM_ATTR can be called. See http://esp-idf.readthedocs.io/en/latest ... wake-stubs. You are calling vTaskDelay(500 / portTICK_PERIOD_MS), esp_restart(), and init_button_intr, none of which are RTC_IRAM_ATTR functions.

2. When you select an IO to be used for deep sleep wakeup, it is configured as an RTC IO. To use it again as a digital IO, you need to call appropriate function. See orange warning box in this section: http://esp-idf.readthedocs.io/en/latest ... akeup-ext0.

reb810
Posts: 2
Joined: Mon Sep 11, 2017 12:17 pm

Re: GPIO0 Pushbutton to Enter AND Wake from Deep Sleep - Only works once!

Postby reb810 » Tue Sep 12, 2017 9:44 am

ESP_igrr wrote:1. You can not use FreeRTOS functions and drivers (such as GPIO drivers in deep sleep stub. Only functions marked with RTC_IRAM_ATTR can be called. See http://esp-idf.readthedocs.io/en/latest ... wake-stubs. You are calling vTaskDelay(500 / portTICK_PERIOD_MS), esp_restart(), and init_button_intr, none of which are RTC_IRAM_ATTR functions.

2. When you select an IO to be used for deep sleep wakeup, it is configured as an RTC IO. To use it again as a digital IO, you need to call appropriate function. See orange warning box in this section: http://esp-idf.readthedocs.io/en/latest ... akeup-ext0.

Thanks for that, I'll see how I go

Who is online

Users browsing this forum: No registered users and 104 guests