// Sketch to test button GPIO deep sleep wakeup alongside library based button event handling
#include "Button2.h" // https://github.com/LennartHennigs/Button2
#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"
#include <esp_sleep.h>
/***********/
/* DEFINES */
/***********/
#define uS_TO_mS_FACTOR 1000 // Conversion factor for micro seconds to miliseconds
#define SERIAL_BAUD 115200
#define BUTTON_PIN GPIO_NUM_5 // (D3 )Hardware pin for main button
#define POWER_LED_PIN GPIO_NUM_8 // (D8) Pin for soft power LED
#define SLEEP_MODE ESP_GPIO_WAKEUP_GPIO_LOW // LOW = 0, HIGH = 1
#define DEBUG_LEVEL 2
/*************/
/* VARIABLES */
/*************/
const char *APP_NAME = "--- Smart Bead 0.1 ---"; // Program String Identifier
RTC_DATA_ATTR int bootCount = 0; // Saves number of boots since last power-on reset level reset.
RTC_DATA_ATTR int secondsCounted = 0;
RTC_DATA_ATTR int wakeupNumber = 0;
RTC_DATA_ATTR int countingState = 0;
static unsigned long lastCountMillis = 0; // Holds the counter start millis
Button2 button; // Creates event driven button library instance
// Method to print the reason by which ESP32 has been awaken from sleep
void print_wakeup_reason()
{
if (DEBUG_LEVEL <= 1)
{
return;
}
Serial.println("--- 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("--- (2) ESP_SLEEP_WAKEUP_EXT0 - Wakeup caused by external signal using RTC_IO");
break;
case ESP_SLEEP_WAKEUP_EXT1:
Serial.println("--- (3) ESP_SLEEP_WAKEUP_EXT1 - Wakeup caused by external signal using RTC_CNTL");
break;
case ESP_SLEEP_WAKEUP_TIMER:
Serial.println("--- (4) ESP_SLEEP_WAKEUP_TIMER - Wakeup caused by timer");
break;
case ESP_SLEEP_WAKEUP_TOUCHPAD:
Serial.println("--- (5) ESP_SLEEP_WAKEUP_TOUCHPAD - Wakeup caused by touchpad");
break;
case ESP_SLEEP_WAKEUP_ULP:
Serial.println("--- (6) ESP_SLEEP_WAKEUP_ULP - Wakeup caused by ULP program");
break;
case ESP_SLEEP_WAKEUP_GPIO:
Serial.println("--- (7) ESP_SLEEP_WAKEUP_GPIO - Wakeup caused by GPIO signal");
break;
default:
Serial.printf("--- Wakeup was not caused by deep sleep: %d\n", wakeup_reason);
break;
}
}
void hmiButtonSetup()
{
Serial.println("--- hmiButtonSetup()");
/*
First we configure the wake up source. We set our ESP32 to wake up for an external trigger. for ESP32, ext0 and ext1.
ext0 uses RTC_IO to wakeup thus requires RTC peripherals to be on while ext1 uses RTC Controller so doesnt need peripherals
to be powered on. Note that using internal pullups/pulldowns also requires RTC peripherals to be turned on.
*/
pinMode(BUTTON_PIN, INPUT);
esp_deep_sleep_enable_gpio_wakeup(1 << BUTTON_PIN, SLEEP_MODE); // 1 = High, 0 = Low
gpio_set_direction((gpio_num_t)BUTTON_PIN, GPIO_MODE_INPUT);
}
void hmiPowerLEDsetup()
{
Serial.println("--- hmiPowerLEDsetup()");
pinMode(POWER_LED_PIN, OUTPUT); // Setup output LED pin as output
digitalWrite(POWER_LED_PIN, 1); // Turn on LED initially
}
void powerSetup()
{
Serial.println("--- powerSetup()");
CLEAR_PERI_REG_MASK(RTC_CNTL_BROWN_OUT_REG, RTC_CNTL_BROWN_OUT_RST_ENA); // Disable brownout detection for deep sleep operation
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // disable brownout detector
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
// If you were to use ext1, you would use it like
// esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK,ESP_EXT1_WAKEUP_ANY_HIGH);
}
void handleWakeupReset()
{
digitalWrite(POWER_LED_PIN, 1);
Serial.println("--- handleWakeupReset()");
esp_reset_reason_t esp_reason = esp_reset_reason();
printf("--- ESP reset reason: %i\n", esp_reason);
esp_sleep_source_t wakeup_respon = esp_sleep_get_wakeup_cause();
printf("--- Wakeup reason: %i\n", wakeup_respon);
secondsCounted = secondsCounted + millis();
Serial.println("--- Boot number: " + String(bootCount));
Serial.println("--- Wakeup millis: " + String(millis()));
Serial.println("--- wakeupNumber: " + String(wakeupNumber));
Serial.println("--- countingState: " + String(countingState));
Serial.println("--- secondsCounted: " + String(secondsCounted));
wakeupNumber++;
struct timeval current_time;
gettimeofday(¤t_time, NULL);
Serial.printf("--- Seconds : %ld\n--- micro seconds : %ld\n",
current_time.tv_sec, current_time.tv_usec);
delay(250);
}
void programSetup()
{
Serial.begin(SERIAL_BAUD);
Serial.println(APP_NAME);
Serial.println("--- Boot number: " + String(bootCount));
++bootCount; // Increment wakeup bootcount until hard reset
Serial.println("--- Boot millis: " + String(millis()));
}
void handleDoubleClick(Button2 &b)
{
Serial.println("--- handleDoubleClick");
Serial.println("--- Going to sleep now");
Serial.flush();
lastCountMillis = millis();
Serial.println("--- Going to sleep at: " + String(lastCountMillis));
// esp_deep_sleep_start(); //Enter deep sleep with the configured wakeup options
Serial.println("This will never be printed");
}
void setup()
{
programSetup();
handleWakeupReset();
hmiButtonSetup();
button.setDoubleClickHandler(handleDoubleClick);
hmiPowerLEDsetup();
powerSetup();
// Print the wakeup reason for ESP32
lastCountMillis = millis();
print_wakeup_reason();
delay(250); // Take some time to open up the Serial Monitor
Serial.println("--- Going to sleep from setup() at: " + String(lastCountMillis));
// Serial.println("Going to sleep now");
// Serial.flush();
// esp_deep_sleep_start(); //Enter deep sleep with the configured wakeup options
secondsCounted = secondsCounted + millis();
esp_deep_sleep(10000 * uS_TO_mS_FACTOR);
}
void loop()
{
button.loop();
}