Optimización de Bajo Consumo en Modos de Sueño Profundo del ESP32
Modos de Energía - Modo de sueño de módem, sueño profundo, periféricos de bajo consumo y más. Optimiza tu ESP32 para Ultra Bajo Consumo con estrategias y ejemplos del mundo real.
Una de las consideraciones más críticas en los proyectos de IoT, especialmente aquellos que involucran aplicaciones alimentadas por batería, es el consumo de energía.
En esta publicación del blog, nos sumergiremos en el mundo de la optimización de ultra bajo consumo en las placas de desarrollo ESP32. Entender e implementar técnicas de ahorro de energía es crucial para extender la vida útil de la batería y mejorar la eficiencia general de tus proyectos.
Partes Funcionales del Sistema en un Chip (SoC) del ESP32 #
El Sistema en un Chip (SoC) del ESP32 integra varios componentes, incluyendo una CPU de doble núcleo, conectividad Wi-Fi y Bluetooth, numerosos periféricos (e.g., GPIO, ADC, PWM), y un Coprocesador de Ultra Bajo Consumo (ULP). También cuenta con componentes de seguridad como el arranque seguro y el cifrado de flash. Las partes internas se pueden separar en varias categorías:
- ESP32 Núcleo de CPU y Memoria: El procesador principal del chip, junto con la memoria. Los componentes clave en esta parte son Microprocesador, Caché, SRAM, JTAG y ROM.
- Radio: Esta parte incluye los componentes necesarios para las comunicaciones de Radio Frecuencia (RF). Incluye receptor y transmisor de 2.4 GHz, Balun + Switch de 2.4 GHz, sintetizador RF, reloj principal externo, oscilador RC rápido y bucle de fase. También incluimos Circuitos Inalámbricos en esta parte, que incluye componentes específicos de WiFi y Bluetooth, como WiFi MAC, WiFi Baseband, controlador de enlace Bluetooth LE y base de banda Bluetooth LE.
- Coprocesador de Ultra Bajo Consumo: El coprocesador de Ultra Bajo Consumo es un núcleo de microcontrolador especializado diseñado para manejar eficientemente tareas de bajo consumo y operaciones de sensores mientras los núcleos principales de la CPU están en un estado de sueño profundo. Consiste en varios componentes clave, como núcleo de CPU ULP, memoria, interfaz de sensores, temporizadores, capacidades de despertar y más.
- RTC: El Reloj de Tiempo Real proporciona funciones precisas de cronometraje y relacionadas con el tiempo. Se utiliza para llevar la cuenta del tiempo, realizar operaciones basadas en el tiempo y programar eventos de despertar. Consiste en componentes clave, como memoria RTC, Unidad de Gestión de Energía (PMU) y detector de caída de tensión.
- Periféricos: varios componentes de hardware y características integradas en el chip. Estos periféricos mejoran las capacidades del chip y permiten que interfiera con sensores, dispositivos externos y más. Algunos de los principales periféricos son UART, USB OTG, RMT, temporizador del sistema, contador de pulsos, LED PWM, interfaz LCD, I2S, I2C, interfaz de cámara, GPIO, USB Serial/JTAG y más.
- Periféricos de Bajo Consumo: podrías llamar a esto una extensión de los periféricos, pero estos están diseñados para funcionar en modo de sueño profundo, consumiendo cantidades mínimas de energía. Los componentes clave a menudo incluyen RTC GPIO, RTC ADC, controlador eFuse, temporizador de vigilancia RTC, super vigilancia, sensor táctil, sensor de temperatura, etc.
Comprendiendo los Modos de Energía del ESP32 #
Las placas de desarrollo ESP32 ofrecen múltiples modos de energía, cada uno con sus propias características e implicaciones en el consumo de energía. Para lograr una operación de ultra bajo consumo, es crucial entender estos modos a fondo.
- Modo Activo
Este es el modo de operación estándar cuando el ESP32 está ejecutando código activamente. Aunque proporciona la mayor potencia de procesamiento, también consume la mayor cantidad de energía.
Todos los componentes del SoC del ESP32 están activos en este modo. Para optimizar la energía en este modo, considera usar algoritmos eficientes y minimizar los cálculos innecesarios.
- Modo de Sueño de Módem (Sueño Ligero ESP 32)
El sueño ligero del ESP32, o a veces llamado Sueño de Módem, es ideal cuando no necesitas utilizar las comunicaciones por radio o necesitas conservar energía mientras esperas eventos externos, como entradas de sensores.
En el modo de Sueño Ligero del ESP32, la radio se apaga, lo que significa que no hay capacidades de RF en este modo. La mayoría de los periféricos también están apagados, excluyendo los periféricos de bajo consumo. Al configurar inteligentemente las fuentes de activación, puedes reducir significativamente el consumo de energía.
- Sueño Profundo
Entre los modos más eficientes en cuanto a energía del ESP32, el sueño profundo apaga el núcleo principal del ESP32, que incluye la potencia de procesamiento principal y la memoria, lo que resulta en un consumo mínimo de energía.
Mientras el núcleo del ESP32 está apagado, el coprocesador ULP permanece activo y espera un disparador externo o un temporizador para despertarse del sueño profundo. Configurar correctamente el sueño profundo es crucial para maximizar el ahorro de energía, especialmente en escenarios donde el ESP32 está recopilando datos periódicamente o enviando actualizaciones intermitentes.
- Hibernación
Este es el modo más conservador de energía. Es útil para aplicaciones de ultra bajo consumo con períodos de sueño prolongados, como nodos de sensores remotos que funcionan con baterías.
En este modo, casi todos los circuitos internos, excepto el RTC (Reloj de Tiempo Real), están apagados, lo que significa que no hay suficiente espacio para procesar nada, pero aún maneja los temporizadores o disparadores de activación.
Resumen de Modos de Energía del ESP32 #
Al elegir el modo de energía adecuado y optimizar la ejecución del código, puedes encontrar el equilibrio adecuado entre rendimiento y eficiencia energética para tus proyectos ESP32. En las siguientes secciones, exploraremos técnicas específicas de optimización de energía para aprovechar al máximo cada modo de energía.
Técnicas de Optimización de Energía: Mejorando la Eficiencia Energética #
Para lograr un consumo óptimo de energía en las placas de desarrollo ESP32, se puede emplear una combinación de técnicas de software y hardware. Vamos a explorar algunas estrategias efectivas de optimización de energía:
Períodos y Modos de Sueño Eficientes: Ajusta los períodos de sueño según los requisitos de la aplicación. Minimiza los despertares y maximiza los tiempos de sueño para encontrar el equilibrio adecuado entre capacidad de respuesta y conservación de energía. Elige las fuentes de activación adecuadas para cada modo de energía. Selecciona sensores y disparadores que consuman mínima energía mientras proporcionan la funcionalidad necesaria. Asegúrate de apagar tantos componentes no utilizados como sea posible.
Gestión del Reloj y Escalado Dinámico de Frecuencia: Ajustar la frecuencia del reloj del sistema puede afectar significativamente el uso de energía. Reducir el reloj de la CPU durante períodos de baja actividad reduce el consumo de energía mientras se mantiene la funcionalidad. Ten cuidado al ajustar las velocidades del reloj, ya que podría afectar la precisión temporal de las operaciones sensibles al tiempo.
Periféricos de Bajo Consumo: Utiliza versiones de bajo consumo de los periféricos del ESP32 siempre que sea posible. Por ejemplo, el ESP32 ofrece un coprocesador ULP (Ultra-Low Power) que puede manejar tareas específicas sin despertar la CPU principal, conservando energía durante los modos de sueño ligero y sueño profundo.
Programación de Tareas: Organiza las tareas de manera efectiva y evita procesos de fondo innecesarios durante los modos de sueño. Gestiona correctamente el programador de tareas para asegurar que las tareas se ejecuten solo cuando sea necesario, minimizando el consumo de energía.
Consideraciones de Suministro de Energía: Elige componentes y diseños de circuitos de suministro de energía eficientes para minimizar las pérdidas de energía. Usa reguladores de bajo dropout y características de ahorro de energía en los reguladores de voltaje cuando estén disponibles.
Al implementar estas técnicas de optimización de energía con cuidado, puedes transformar tus proyectos ESP32 en soluciones altamente eficientes en energía, ideales para aplicaciones alimentadas por batería y conscientes de la energía. En la siguiente sección, revisaremos estas técnicas en ejemplos prácticos y estudios de caso para ilustrar los beneficios de la optimización de ultra bajo consumo en las placas de desarrollo ESP32.
Implementación: Guía Práctica para la Optimización de Ultra Bajo Consumo #
Ahora que sabemos bastante sobre la optimización del consumo de energía en los chips ESP32, pongámoslo en práctica. Revisaremos diferentes técnicas en ejemplos separados. Ten en cuenta que todas las técnicas proporcionadas se pueden combinar en una aplicación eficiente de ultra bajo consumo.
- Desactivar WiFi y Bluetooth en ESP32
El caso de uso más común para ahorrar energía en ESP32 es desactivar el WiFi o Bluetooth, si no se están utilizando. Aunque si el WiFi o Bluetooth no están inicializados, están apagados por defecto. Sin embargo, es posible que desees desactivar/activar WiFi y Bluetooth en ESP32 periódicamente en tu programa.
#include "WiFi.h"
#define WIFI_SSID "your-ssid"
#define WIFI_PW "your-pass"
void setup() {
Serial.begin(115200);
// --- Enable / disable Bluetooth ---
// Start Bluetooth
Serial.println("Starting Bluetooth");
btStart();
delay(5000);
// Stop Bluetooth
Serial.println("Stopping Bluetooth");
btStop();
delay(5000);
// --- ---
// --- Enable / disable WiFi ---
// Start WiFi in Station (STA) Mode
Serial.println("Starting WiFi in Station Mode");
WiFi.begin(WIFI_SSID, WIFI_PW);
delay(5000);
// Disable WiFi
Serial.println("Stopping WiFi");
WiFi.mode(WIFI_OFF);
delay(5000);
// --- ---
// --- Enable / Disable Both WiFi and Bluetooth
// Enable WiFi and Bluetooth
Serial.println("Starting Both WiFi and Bluetooth");
btStart();
WiFi.begin(WIFI_SSID, WIFI_PW);
delay(5000);
// Disable WiFi and Bluetooth
Serial.println("Stopping Both WiFi and Bluetooth");
WiFi.mode(WIFI_OFF);
btStop();
delay(5000);
// --- ---
}
void loop() {
}
En el ejemplo anterior, cuando enciendes el ESP32, habilitará Bluetooth y lo deshabilitará después de 5 segundos. Luego habilitará y conectará a WiFi y deshabilitará el WiFi después de 5 segundos. Finalmente, habilitará Bluetooth y WiFi nuevamente, y después de un retraso de 5 segundos, deshabilitará el WiFi y Bluetooth del ESP32.
- Configuración de Modos de Energía y Fuentes de Despertar A continuación, veremos cómo utilizar diferentes modos de energía (sueño ligero, sueño profundo e hibernación). Para poder continuar la operación del ESP32 en modo normal después de un sueño, necesitamos configurar una fuente de activación.
Hay múltiples opciones diferentes para usar como fuente de activación, la más fácil es un temporizador, que simplemente despierta después de una cantidad de tiempo especificada. Sin embargo, eso podría no ser siempre adecuado para aplicaciones específicas. Echemos un vistazo primero a otras fuentes de activación:
- Despertar con Sensor Táctil: Algunos módulos ESP32 incluyen sensores táctiles que se pueden utilizar para despertar el dispositivo cuando se tocan o cuando se detecta un cambio en la capacitancia.
- Despertar Externo: el ESP32 puede ser despertado del sueño profundo por una señal externa en un pin RTC GPIO designado.
- Despertar con Coprocesador ULP: El coprocesador ULP puede despertar el ESP32 cuando se cumplen ciertas condiciones, como que se cruce un umbral de sensor.
- Despertar con GPIO (Solo desde Modo de Sueño Ligero): Los pines GPIO se pueden configurar para activar un despertar cuando cambia su estado, como una pulsación de botón.
- Despertar con UART (Solo desde Modo de Sueño Ligero): El despertar con UART es similar al despertar con GPIO, pero específico para la comunicación UART.
Para la simplicidad de los ejemplos, mostraremos cómo usar diferentes Modos de Sueño en ESP32, utilizando la fuente de activación de temporizador.
const uint32_t SLEEP_DURATION = 5 * 1000000; // µs
// ESP32 boot count
RTC_DATA_ATTR int bootCount = 0;
void printWakeUpReason() {
esp_sleep_wakeup_cause_t wakeupReason = esp_sleep_get_wakeup_cause();
switch (wakeupReason) {
case ESP_SLEEP_WAKEUP_EXT0:
Serial.println("The device was awakened by an external signal using RTC_IO.");
break;
case ESP_SLEEP_WAKEUP_EXT1:
Serial.println("The device was awakened by an external signal using RTC_CNTL.");
break;
case ESP_SLEEP_WAKEUP_TIMER:
Serial.println("The device was awakened by a timer event.");
break;
case ESP_SLEEP_WAKEUP_TOUCHPAD:
Serial.println("The device was awakened by a touchpad interaction.");
break;
case ESP_SLEEP_WAKEUP_ULP:
Serial.println("The device was awakened by a ULP (Ultra-Low-Power) program.");
break;
default:
Serial.printf("The device woke up for an unknown reason: %d\n", wakeupReason);
break;
}
}
void setup() {
Serial.begin(115200);
delay(1000); // Wait a bit to make sure Serial starts
// Print boot counter every boot
++bootCount;
Serial.println("Boot number: " + String(bootCount));
// Print wake up reason
printWakeUpReason();
}
// Enter Light Sleep with Timer Wake-up source
void lightSleep() {
esp_sleep_enable_timer_wakeup(SLEEP_DURATION);
esp_light_sleep_start();
}
// Enter Deep Sleep with Timer Wake-up source
void deepSleep() {
esp_sleep_enable_timer_wakeup(SLEEP_DURATION);
esp_deep_sleep_start();
}
// Enter Hibernation mode with Timer Wake-up source
void hibernate() {
// Shut down RTC (Low Power) Peripherals
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF);
// Shut down RTC Slow Memory
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_OFF);
// Shut down RTC Fast Memory
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_OFF);
// Shut down Crystal Oscillator XTAL
esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_OFF);
// Enter Deep Sleep
deepSleep();
}
void loop() {
Serial.println("Entering Light Sleep mode...");
delay(1000);
lightSleep();
Serial.println("Entering Deep Sleep mode...");
delay(1000);
deepSleep();
Serial.println("Entering Hibernation mode...");
delay(1000);
hibernate();
}
Esta aplicación debería imprimir el conteo de arranque incrementado, indicar la razón del despertar, escribir el modo en que el ESP32 entrará a continuación en el Monitor Serial y entrar en modo de Sueño Profundo / Sueño Ligero o Hibernación. Usa esta plantilla en tu aplicación para utilizar los diferentes modos de energía que proporciona el ESP32.
- Estableciendo la Frecuencia de la CPU
En el ESP32, puedes establecer la frecuencia de la CPU en tiempo de ejecución fácilmente. Puedes hacerlo para reducir el consumo de energía en las partes de la aplicación que no necesitan mucha potencia de procesamiento.
Las frecuencias de CPU compatibles son 240 MHz, 160 MHz y 80 MHz. Si la frecuencia del XTAL (oscilador de cristal) es inferior a 40 MHz, se admiten frecuencias adicionales de 40 MHz y 20 MHz.
void setup() {
Serial.begin(115200);
Serial.printf("XTAL Frequency: %i MHz", getXtalFrequencyMhz());
Serial.printf("APB Frequency: %i MHz", getApbFrequency());
}
void loop() {
Serial.printf("CPU Frequency: %i MHz", getCpuFrequencyMhz());
setCpuFrequencyMhz(160);
delay(2000);
Serial.printf("CPU Frequency: %i MHz", getCpuFrequencyMhz());
setCpuFrequencyMhz(80);
delay(2000);
}
El código anterior imprimirá las frecuencias XTAL y APB al arrancar. Primero, imprimirá la frecuencia actual de la CPU. Luego, establecerá la frecuencia de la CPU a 160 MHz, esperará 2 segundos e imprimirá la frecuencia actual de la CPU, que debería ser 160 MHz ahora. Finalmente, establecerá la frecuencia de la CPU a 80 MHz y la imprimirá después de 2 segundos y se repetirá indefinidamente.
- Periféricos de Bajo Consumo del ESP32: Utiliza el coprocesador ULP para tareas específicas sin despertar la CPU principal.
El microcontrolador ESP32 proporciona soporte RTC GPIO, lo que permite el uso de pines GPIO específicos en el subsistema de bajo consumo RTC durante el sueño profundo. Estos GPIO RTC designados sirven como fuentes de activación, permitiendo que el ESP32 se despierte del sueño profundo, especialmente cuando el coprocesador de Ultra Bajo Consumo (ULP) está activo. Estos pines GPIO se pueden configurar para activar el proceso
#include <Arduino.h>
#include <esp_sleep.h>
void mainTask() {
// Mock Main Task code
delay(500);
}
void secondaryTask() {
// Mock Secondary Task code
delay(1000);
}
void setup() {
// Add your setup code here
}
void loop() {
// Calculate the time until the next scheduled task or event
unsigned long nextMainTaskTime = millis() + 500;
unsigned long nextSecondaryTaskTime = millis() + 1000;
// Determine the minimum time until the next task
unsigned long nextTaskTime = min(nextMainTaskTime, nextSecondaryTaskTime);
// Enter deep sleep to save power until the next task is scheduled
esp_sleep_enable_timer_wakeup(nextTaskTime * 1000); // Convert to microseconds
esp_deep_sleep_start();
}
Este código Arduino define dos tareas simuladas con retrasos específicos, calcula el tiempo hasta que se programe la próxima tarea y entra en modo de sueño profundo en un ESP32 para ahorrar energía hasta ese momento. Espera efectivamente la primera de las dos tareas y minimiza el consumo de energía durante el período inactivo.
- Gestión de la Batería: Implementa técnicas para monitorear los niveles de la batería y extender la vida útil de la batería.
#include <Arduino.h>
// Analog pin used for reading battery voltage
const int BATTERY_PIN = A0;
// Function to read battery voltage
float readBatteryVoltage() {
int rawValue = analogRead(BATTERY_PIN);
float voltage = rawValue * (3.3 / 1023.0); // Convert ADC reading to voltage
return voltage;
}
void setup() {
// Add your setup code here
}
void loop() {
// Read the current battery voltage
float batteryVoltage = readBatteryVoltage();
// Implement battery management logic based on batteryVoltage
if (batteryVoltage < 3.0) {
// Take actions to extend battery life, such as reducing power-hungry operations
// Implement deep sleep, adjust performance, or send a low battery alert
}
// Your main code for regular operation here
}
Este código de Arduino lee el voltaje de una batería conectada a un pin analógico y realiza la gestión de la batería en función del nivel de voltaje. Convierte la lectura analógica a voltaje y verifica si el voltaje de la batería está por debajo de 3.0 voltios. Si es bajo, sugiere tomar medidas para preservar la vida útil de la batería, como entrar en modo de sueño profundo, ajustar el rendimiento o enviar una alerta de batería baja. Este código es esencial para gestionar los recursos de energía al ejecutar aplicaciones en dispositivos alimentados por batería.
Estudios de Caso: Implementación de Ultra Bajo Consumo en Placas de Desarrollo ESP32 #
Vamos a explorar algunos ejemplos del mundo real de cómo se puede aplicar la optimización de ultra bajo consumo a proyectos con ESP32:
Red de Sensores Inalámbricos (WSN): Imagina que estás diseñando una red de sensores inalámbricos para monitorear condiciones ambientales en una ubicación remota. Al implementar técnicas adecuadas de gestión de energía, puedes asegurar que los nodos ESP32 duerman la mayor parte del tiempo, despertando periódicamente para recopilar y transmitir datos. Utilizar el modo de sueño profundo junto con disparadores de activación eficientes, como intervalos de tiempo o eventos externos, puede llevar a una vida prolongada de la batería, permitiendo una operación autónoma a largo plazo.
Dispositivo IoT Alimentado por Batería: Considera un dispositivo IoT alimentado por batería, como un sensor de puerta inteligente o un rastreador de fitness portátil, donde la eficiencia energética es crucial para un uso prolongado. Al optimizar los modos de energía del ESP32 y ajustar finamente las duraciones de sueño, puedes encontrar un equilibrio entre capacidad de respuesta y consumo de energía. Por ejemplo, usar el modo de sueño ligero con capacidades de activación por sensor puede mantener actualizaciones oportunas de datos mientras se conserva la energía durante los períodos de inactividad.
Estación de Monitoreo Remoto: En aplicaciones donde las fuentes de energía son escasas o inaccesibles, como estaciones de monitoreo meteorológico remoto o dispositivos de rastreo de vida silvestre, el modo de hibernación puede ser un cambio de juego. Al apagar componentes no esenciales y confiar en el RTC para despertar el ESP32 en intervalos específicos, puedes lograr una operación de ultra bajo consumo durante meses o incluso años sin reemplazos de batería.
Estos estudios de caso demuestran los beneficios reales de optimizar el consumo de energía en las placas de desarrollo ESP32. Dependiendo de los requisitos específicos de tu proyecto, puedes elegir entre una variedad de modos de energía y técnicas para lograr soluciones energéticamente eficientes y sostenibles.
Conclusión: Desbloqueando la Eficiencia Energética con ESP32 #
En esta publicación del blog, hemos explorado el SoC ESP32 en más detalle, observando las diferentes partes que componen el chip. Luego hemos explorado los diferentes modos de energía del ESP32 y aprendido qué partes se apagan en diferentes modos.
Luego hemos explorado más a fondo por qué deberíamos considerar el consumo de energía en proyectos de microcontroladores y qué otras estrategias podemos utilizar, aparte de los diferentes modos de energía, para ahorrar energía.
Finalmente, hemos utilizado las diferentes estrategias de ahorro de energía con ejemplos de código, que se pueden utilizar en tus proyectos como plantilla.