In this tutorial, we will learn to use ESP32 touch pins as a wake-up source from a deep sleep. First, we will put ESP32 into deep sleep mode and then see how to wake it up using touch sensor pins. When the ESP32 is in deep sleep, it consumes very low power, making it an ideal choice for battery-powered applications that need to wake up periodically to perform some task. The touch wake up feature allows the ESP32 to wake up from deep sleep when a capacitive touch sensor is triggered, providing a low-power way to wake up the device.
To wake up the ESP32 from deep sleep using touch, we will use the esp_sleep_enable_touchpad_wakeup() function in the Arduino IDE.
esp_sleep_enable_touchpad_wakeup()
ESP32 Touch Wake Up
ESP32 provides 10 capacitive touch GPIO pins which can be used for touch sensing. These are capacitive touch pins that detect changes in capacitance when a conductive object, such as a finger, comes into contact with the sensor. The touch sensing mechanism is based on the capacitance variation principle, where the capacitance of a capacitive sensor is affected by changes in the dielectric constant of the surrounding environment.
The ESP32 uses a capacitive sensing module to measure the capacitance of the touch pins. When a touch is detected, the capacitance of the corresponding touch pin changes, and the capacitive sensing module generates an interrupt to wake up the ESP32 from a deep sleep. The touch pins can also be used as regular GPIO pins when touch sensing is not required.
Touch sensor pins of Devkit
The touch pins on the ESP32 are numbered T0 to T9 and their respective GPIO numbers are shown below:
- TOUCH0 – GPIO4
- TOUCH1 – GPIO0
- TOUCH2 – GPIO2
- TOUCH3 – GPIO15
- TOUCH4 – GPIO13
- TOUCH5 – GPIO12
- TOUCH6 – GPIO14
- TOUCH7 – GPIO27
- TOUCH8 – GPIO33
- TOUCH9 – GPIO32
Attach a connecting wire to your ESP32 module as shown below. In this case, we are using GPIO15 (Touch 3) because that is the touch pin used in the example code. You can use any suitable touch pin.
How to Write Deep Sleep Code for ESP32?
To program ESP32 deep sleep mode and set up a wake-up resource, follow these steps:
- Start by configuring the wake up source. In other words, define what source will wake up ESP32 from a deep sleep. As you may know that ESP32 supports multiple sources such as timer, external interrupt, and touch pins. We can use any one of them or a combination of these. We will use the touch pins of ESP32 as a wake up source in this tutorial
- Next, we need to decide which peripheral’s power should be cut off. By default, ESP32 shut down power for all peripherals that are not required by a selected wake up source.
- In the end, use esp_deep_sleep_start() function to put ESP32 into deep sleep mode.
We will be using the Arduino IDE to program ESP32. If you have not used ESP32 with the Arduino IDE before, you need to install an ESP32 library in Arduino by following this guide.
ESP32 Touch Pins Wake Up from Deep Sleep Example
Let’s have a look at a simple example demonstrating a touch wake up using the example from the library. We are going to show you a simple demonstration of how to use the touch pins to wake up. The ESP32 will remain in active mode whenever the user will touch the wire which is connected to the touch pin otherwise it will be in deep sleep mode.
Open your Arduino IDE and go to File > Examples > ESP32 > Deep Sleep > TouchWakeUp. The following sketch will open up.
/*
Deep Sleep with Touch Wake Up
=====================================
This code displays how to use deep sleep with
a touch as a wake up source and how to store data in
RTC memory to use it over reboots
This code is under Public Domain License.
Author:
Pranav Cherukupalli <cherukupallip@gmail.com>
*/
#define Threshold 40 /* Greater the value, more the sensitivity */
RTC_DATA_ATTR int bootCount = 0;
touch_pad_t touchPin;
/*
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;
}
}
/*
Method to print the touchpad by which ESP32
has been awaken from sleep
*/
void print_wakeup_touchpad(){
touchPin = esp_sleep_get_touchpad_wakeup_status();
switch(touchPin)
{
case 0 : Serial.println("Touch detected on GPIO 4"); break;
case 1 : Serial.println("Touch detected on GPIO 0"); break;
case 2 : Serial.println("Touch detected on GPIO 2"); break;
case 3 : Serial.println("Touch detected on GPIO 15"); break;
case 4 : Serial.println("Touch detected on GPIO 13"); break;
case 5 : Serial.println("Touch detected on GPIO 12"); break;
case 6 : Serial.println("Touch detected on GPIO 14"); break;
case 7 : Serial.println("Touch detected on GPIO 27"); break;
case 8 : Serial.println("Touch detected on GPIO 33"); break;
case 9 : Serial.println("Touch detected on GPIO 32"); break;
default : Serial.println("Wakeup not by touchpad"); break;
}
}
void callback(){
//placeholder callback function
}
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 and touchpad too
print_wakeup_reason();
print_wakeup_touchpad();
//Setup interrupt on Touch Pad 3 (GPIO15)
touchAttachInterrupt(T3, callback, Threshold);
//Configure Touchpad as wakeup source
esp_sleep_enable_touchpad_wakeup();
//Go to sleep now
Serial.println("Going to sleep now");
esp_deep_sleep_start();
Serial.println("This will never be printed");
}
void loop(){
//This will never be reached
}
How does the Code Work?
In this section, we will explain different parts of code to give you a better understanding.
Define Touch Pins Threshold
As we have to use the touch pins to awaken the ESP32 board from deep sleep thus, we will have to set a threshold value. This threshold value will be compared with the value read by the sensor when the user will touch the touch pin. If the read value is lower than the threshold which is 40 in this case then the ESP32 board will wake up. One thing to mention here is that, whenever the user touches the wire connected with the touch pin, the value read by the sensor will decrease.
#define Threshold 40
Saving Boot Count in RTC Memory
ESP32 has an 8kb SRAM for the RTC controller which is also known as RTC fast memory and this memory can be used to save data. The data stored on this memory will remain saved during deep sleep but it will be erased during boot-up. Hence, we can use this memory to save data before putting ESP32 into deep sleep mode.
Now we will save the number of times our ESP32 board woke up from deep sleep inside the variable ‘bootCount.’
This will be saved in the RTC Memory of the development board by using ‘RTC_DATA_ATTR’ before defining the bootCount variable.
RTC_DATA_ATTR int bootCount = 0;
ESP32 Wake Up Reason
This print_wakeup_reason() function prints the reason for the ESP32 waking up from deep sleep. The method gets the wakeup reason using the function esp_sleep_get_wakeup_cause() and prints the corresponding message using a switch-case statement. The possible wakeup reasons include external signals using RTC_IO or RTC_CNTL pins, a timer, touchpad, or ULP program. If the wakeup reason is not caused by deep sleep, a message with the wakeup reason code is printed.
/*
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;
}
}
This print_wakeup_touchpad function defines print the touchpad by which the ESP32 was awakened from a deep sleep. The esp_sleep_get_touchpad_wakeup_status()
function is called to retrieve the touchpad number from the RTC memory, which is stored during the sleep cycle. A switch-case statement is used to print the corresponding GPIO pin number of the touchpad. If the wake up was not caused by a touchpad, the function prints “Wakeup not by touchpad”.
/*
Method to print the touchpad by which ESP32
has been awaken from sleep
*/
void print_wakeup_touchpad(){
touchPin = esp_sleep_get_touchpad_wakeup_status();
switch(touchPin)
{
case 0 : Serial.println("Touch detected on GPIO 4"); break;
case 1 : Serial.println("Touch detected on GPIO 0"); break;
case 2 : Serial.println("Touch detected on GPIO 2"); break;
case 3 : Serial.println("Touch detected on GPIO 15"); break;
case 4 : Serial.println("Touch detected on GPIO 13"); break;
case 5 : Serial.println("Touch detected on GPIO 12"); break;
case 6 : Serial.println("Touch detected on GPIO 14"); break;
case 7 : Serial.println("Touch detected on GPIO 27"); break;
case 8 : Serial.println("Touch detected on GPIO 33"); break;
case 9 : Serial.println("Touch detected on GPIO 32"); break;
default : Serial.println("Wakeup not by touchpad"); break;
}
}
Interrupt
Another important part in the program code for the touch wake up is including an interrupt for the respective touch pin. We will define the interrupt in the following line:
//Setup interrupt on Touch Pad 3 (GPIO15)
touchAttachInterrupt(T3, callback, Threshold);
The touchAttachInterrupt() function takes in three parameters. the first is the touch pin, the second is the callback function and the third is the threshold variable which we previously defined. Notice, that we are using GPIO15 (Touch3) as the touch pin thus we have used T3 as a parameter inside the function. For your particular touch pin specify the parameter accordingly e.g. T2 if using GPIO2. When the user will touch the touch pin (T3), the value on that particular pin will be lower than the threshold value, the ESP32 board wakes up. As a result, the callback function will be called then.
The callback function will only be called when the ESP32 module has woken up from deep sleep. This function is empty.
void callback(){
//placeholder callback function
}
The following line of code will enable the touch wake up as the source of wake up for the module.
//Configure Touchpad as wakeup source
esp_sleep_enable_touchpad_wakeup()
Demonstration
Attach a connecting wire to GPIO15 of your ESP32 module. After uploading the code to your module, press its ENABLE button. Now open the serial monitor in your Arduino IDE. Touch the connecting wire attached T3 and the module will wake up. In the serial monitor, you will be able to view the boot count, the reason for wakeup, the GPIO pin which was touched and a message displaying that the board is going back to sleep.
In summary:
In this tutorial, we have learned how to use the ESP32’s deep sleep mode with touch wake-up, and how to store data in RTC memory. When the ESP32 wakes up from deep sleep, it prints the reason for wakeup and the touchpad that caused it to the serial monitor, attaches an interrupt to touchpad T3, configures the touch pin as a wakeup source, and puts the ESP32 into deep sleep mode.
You may also like to read: