Tutorial del Internet de las Cosas y Bluetooth con el ESP32
Juan Antonio Villalpando
Volver al índice del tutorial
____________________________
234.- Wemos D1 R32 ESP32. Deep Sleep. Sueño profundo. Light Sleep. Sueño ligero.
- https://github.com/espressif/esp-idf/blob/master/docs/en/api-reference/system/sleep_modes.rst
- El ESP32 tiene un bloque llamado RTC, en él se encuentra un ULP (Ultra Low Power), un
PMU (Phasor Measurement Unit)
y una memoria (8 KB), todo esto forma una etapa procesadora que funciona con muy poca energía.
- Podemos establecer que, mientras el ESP32 no esté realizando operaciones de WiFi, Bluetooth,..., se deshabiliten los procesadores principales del Dual Core y actúe el RTC. También se desactiva la memoria principal, por lo cual la información que tenemos se perderá. [Debemos tener un método para no perder la información de las variables]. Para que los datos de la memoria no se pierdan, los guardamos en la memoria del RTC "Recovery memory". Cuando volvamos al estado Despierto, Recuperaremos esos datos.
- Esto hará que se consuma muy poca energía, una corriente de unos 0,015 mA, pero...
- ... los 0,015 mA se refiere al Chip ESP32, no a la placa completa. Según el diseño del fabricante de la placa puede consumir más o menos en sueño profundo, unas cantidades típicas son 66 mA en funcionamiento con las CPU y unos 19 mA en Deep Sleep.

Hay varias formas de despertar el chip. Podemos usar un temporizador, un pin RTC_GPIO de nivel, un pin GPIO de toque o el coprocesador.
esp_deep_sleep_enable_timer_wakeup(3000000) // Temporizador. Despierta a los 3 segundos.
esp_deep_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int nivel) // RTC_GPIO. Estos terminales:
0,2,4,12-15,25-27,32-39. El nivel puede ser a 0 o a 1
esp_sleep_enable_touchpad_wakeup(); // Mediante tecla de contacto.
// Inicio del modo sleep
esp_deep_sleep_start (); // A partir de este momento el chip está desactivado, solo funciona la parte del RTC.
// Indica la causa de la activación a despierto
esp_sleep_get_wakeup_cause ();
// Si lo hacemos con sensores de toque, esto nos dirá que pin lo despertó:
esp_sleep_get_touchpad_wakeup_status ();
- En este enlace tenemos tres ejemplos de Deep Sleep (Despierta por señal externa, por temporizador y por toque.):
https://github.com/espressif/arduino-esp32/tree/master/libraries/ESP32/examples/DeepSleep
________________________________
1.- Toca IO14 y duerme. Toca IO12 y despierta. Teclas de contacto.
- Conectamos un cable en IO12 y otro en IO14.
- Despertamos y dormimos por sensor de toque.

|
// Juan Antonio Villalpando.
// kio4.com
#define Dormir T6 // Es el IO14 de la placa de ESP32
#define Despertar T5 // Es el IO12 de la placa de ESP32
int umbral = 100;
void setup()
{
Serial.begin(115200);
print_wakeup_touchpad();
// Cuando toque el IO12 (T5) y el umbral sea mayor de 50 despertará.
touchAttachInterrupt(Despertar, ve_despierto, 50);
}
void ve_despierto(){
Serial.println("Estoy despierto.");
}
void loop()
{
umbral = touchRead(Dormir); // Tocado el T6 (IO14)
Serial.println(umbral); // Imprime el valor umbral de toque.
if (umbral < 50) // Si es menor de 50 dormirá.
{
Serial.println("Me voy a dormir.");
delay(500);
esp_sleep_enable_touchpad_wakeup();
esp_deep_sleep_start();
}
else
{
// Si está despierto y es mayor de 50.
Serial.println("Mayor de 50.");
}
delay(200);
}
void print_wakeup_touchpad(){
Serial.println("Despertando.");
}
|
- Si tocamos el IO14, el umbral será menor de 50 y dormirá.
- Si no tocamos el IO14, el umbral será mayor de 50 e imprimirá el valor del umbral.
------------------------------------------------
- Establecemos la IO12 como interrupción. Si está dormido y tocamos el IO12, despertará e informará que "Estoy despierto".
________________________________
2.- Duerme y despierta por Temporizador.
- La primera vez que se activa el código, se enciende el LED14 y la variable cuenta suma 1.
- Para entrar en el modo DeepSleep, ponemos:
esp_sleep_enable_timer_wakeup(3000000); // En Microsegundos.
esp_deep_sleep_start();
- Dormirá 3 segundos y despertará.
- Al despetar comenzará a realizar el código desde el setup.
- Debido a que la variable cuenta está en la memoria RTC RTC_DATA_ATTR int cuenta = 0;
- las siguentes veces que realice el código no se encenderá el LED14, ya que la cuenta no es 0.
- Así que si guardamos algo en la memoria RTC, no se perderá ese valor cuando despierte.
deepsleep_temporizado.ino
|
RTC_DATA_ATTR int cuenta = 0; // Memoria RTC
int LED2 = 2;
int LED14 = 14;
void setup(){
pinMode(LED2,OUTPUT);
pinMode(LED14,OUTPUT);
delay(500);
if(cuenta == 0) // Run this only the first time
{
digitalWrite(LED14,HIGH);
cuenta = cuenta + 1;
} else
{
digitalWrite(LED2,HIGH);
}
delay(3000);
digitalWrite(LED2,LOW);
digitalWrite(LED14,LOW);
esp_sleep_enable_timer_wakeup(3000000); // En Microsegundos.
esp_deep_sleep_start();
}
void loop(){
}
|
https://github.com/espressif/arduino-esp32/blob/master/libraries/ESP32/examples/DeepSleep/TimerWakeUp/TimerWakeUp.ino
________________________________
3.- Duerme y despierta por sensor de contacto.
- Podemos hacer que al tocar un pin se duerma y al tocar otro se despierte.
- Estos GPIO se pueden utilizar como sensores de contacto.
T0: IO4
T1: IO0
T2: IO2
T3: IO15
T4: IO13
T5: IO12
T6: IO14
T7: IO27
T8: IO33
T9: IO32
|
TaskHandle_t Task1;
TaskHandle_t Task2;
// LED pins
const int led2 = 2;
const int led14 = 14;
void setup() {
Serial.begin(115200);
pinMode(led2, OUTPUT);
pinMode(led14, OUTPUT);
//create a task that will be executed in the Task1code() function, with priority 1 and executed on core 0
xTaskCreatePinnedToCore(
Task1code, /* Task function. */
"Task1", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
&Task1, /* Task handle to keep track of created task */
0); /* Núcleo 0 */
delay(500);
//create a task that will be executed in the Task2code() function, with priority 1 and executed on core 1
xTaskCreatePinnedToCore(
Task2code, /* Task function. */
"Task2", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
&Task2, /* Task handle to keep track of created task */
1); /* Núcleo 1 */
delay(500);
}
//Task1code: blinks an LED every 1000 ms
void Task1code( void * pvParameters ){
Serial.print("Task1 running on core ");
Serial.println(xPortGetCoreID());
for(;;){
digitalWrite(led2, HIGH);
delay(1000);
digitalWrite(led2, LOW);
delay(1000);
}
}
//Task2code: blinks an LED every 700 ms
void Task2code( void * pvParameters ){
Serial.print("Task2 running on core ");
Serial.println(xPortGetCoreID());
for(;;){
digitalWrite(led14, HIGH);
delay(700);
digitalWrite(led14, LOW);
delay(700);
}
}
void loop() {
// Esto trabaja en el Núcleo 1
}
|
________________________________
4.- Duerme y despierta por nivel en RTCIO.
- Estos GPIO se pueden utilizar como RTC.
- RTC_GPIO0 (GPIO36)
- RTC_GPIO3 (GPIO39)
- RTC_GPIO4 (GPIO34)
- RTC_GPIO5 (GPIO35)
- RTC_GPIO6 (GPIO25)
- RTC_GPIO7 (GPIO26)
- RTC_GPIO8 (GPIO33)
- RTC_GPIO9 (GPIO32)
- RTC_GPIO10 (GPIO4)
- RTC_GPIO11 (GPIO0)
- RTC_GPIO12 (GPIO2)
- RTC_GPIO13 (GPIO15)
- RTC_GPIO14 (GPIO13)
- RTC_GPIO15 (GPIO12)
- RTC_GPIO16 (GPIO14)
- RTC_GPIO17 (GPIO27)
- En estos tutoriales está bien explicado:
https://randomnerdtutorials.com/esp32-deep-sleep-arduino-ide-wake-up-sources/
https://randomnerdtutorials.com/esp32-external-wake-up-deep-sleep/
- Lo comento ligeramente. Hay dos métodos para despertar al ESP32 mediante una señal externa, se denominan ext0 y ext1.
- El ext0 se utiliza cuando solo necesitamos despertarlo desde un puesto.
-
El ext1 cuando lo queramos despertar desde varios puestos, en este método es necesario convertir un número en máscara.
- Los pines RTCIO son: 0,2,4,12-15,25-27,32-39.
- Vamos a utilizar el pin GPIO26.

- Observa el siguiente código.
- Si quieres hacerlo con el método ext0, utiliza la línea:
esp_sleep_enable_ext0_wakeup(GPIO_NUM_26,1); //1 = High, 0 = Low
- Si quieres hacerlo con el método ext1, utiliza las líneas:
#define BUTTON_PIN_BITMASK 0x4000000 // 2^26 in hex. Esto es para el método ext1
esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK,ESP_EXT1_WAKEUP_ANY_HIGH);
- La máscara la utilizamos solo en el método ext1.
- Queremos utilizar el método ext1 con el GPIO26. Con una calculadora calculamos 2^26 = 67108864
- Ahora vamos a: https://www.rapidtables.com/convert/number/decimal-to-hex.html
- Ponemos el número decimal 67108864 y obtenemos el número hexadecimal: 4000000
|
#define BUTTON_PIN_BITMASK 0x4000000 // 2^26 in hex. Esto es para el método ext1
RTC_DATA_ATTR int bootCount = 0;
void setup(){
Serial.begin(115200);
delay(1000);
// Incrementa el número de reinicios.
++bootCount;
Serial.println("Numero de reinicios: " + String(bootCount));
// Esto es para el método ext0.
esp_sleep_enable_ext0_wakeup(GPIO_NUM_26,1); //1 = High, 0 = Low
// Esto es para el método ext1
// esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK,ESP_EXT1_WAKEUP_ANY_HIGH);
Serial.println("Ahora va a dormir. Modo Sleep.");
delay(1000);
esp_deep_sleep_start();
Serial.println("Esta linea no se imprimira porque esta dormido.");
}
void loop(){
// This is not going to be called
}
|
- En el método ext1 si quisieras utilizar dos pulsadores, uno en GPIO25 y otro en GPIO26, debes utilizar esta máscara:
2^25 + 2^26 = 33554432 + 67108864 = 100663296 que en hexadecimal es 6000000
- Mediante este código podemos obtener el pin que ha provocado el despertar:
int GPIO_reason = esp_sleep_get_ext1_wakeup_status () ;
Serial.print ("GPIO that triggered the wake up: GPIO ") ;
Serial.println ( (log(GPIO_reason)) / log (2),0) ;
________________________________
- Comentarios.
-
_______________________________
|