Por qué tu estación meteorológica con ESP32 se cuelga a las 24 horas (y cómo solucionarlo)

Los proyectos escolares de IoT con ESP32 rara vez fallan por problemas del silicio. Se bloquean debido a la fragmentación de la memoria dinámica (heap), bucles bloqueantes de reconexión wifi y temporizadores watchdog por hardware no gestionados.
Si la estación meteorológica con ESP32 de tu clase funciona a la perfección en la mesa del laboratorio durante la cuarta hora, pero a la mañana siguiente está completamente apagada, el silicio no es defectuoso. Los microcontroladores no se degradan en veinticuatro horas. En su lugar, el software embebido de larga ejecución casi siempre falla por dos problemas acumulativos y silenciosos: la fragmentación de la memoria dinámica (heap) debida a operaciones de texto dinámicas y las caídas de red no gestionadas que atrapan al procesador en un bucle bloqueante infinito.
Resolver estos problemas requiere dejar atrás los atajos de los prototipos rápidos y adoptar prácticas estándar de ingeniería de sistemas embebidos: búferes de memoria de tamaño fijo, máquinas de estados de red no bloqueantes y un temporizador watchdog por hardware.
Culpable 1: Cadenas dinámicas y fragmentación del heap
El ESP32 cuenta con aproximadamente 320 KB de SRAM interna utilizable. En una estación meteorológica que consulta los sensores cada diez segundos, el código escrito con la clase estándar String de Arduino asigna, redimensiona y libera pequeños bloques de memoria miles de veces al día:
// El patrón que rompe silenciosamente tu proyecto:
String payload = "{\"temp\": ";
payload += String(temperature);
payload += ", \"humidity\": ";
payload += String(humidity);
payload += "}";
http.POST(payload);Cada vez que se crean y concatenan cadenas dinámicas dentro de loop(), el entorno de ejecución de C++ asigna espacio en el heap. Dado que otras tareas del sistema en segundo plano (como las pilas de Wi-Fi y Bluetooth) asignan memoria al mismo tiempo, esta constante asignación y liberación convierte el heap en un queso suizo. La memoria libre total aún podría indicar 150 KB, pero el bloque libre contiguo más grande se reduce a unos pocos cientos de bytes. Cuando la pila Wi-Fi o el serializador JSON solicitan repentinamente un bloque continuo de 2 KB para un paquete TCP, la asignación falla y devuelve un puntero nulo que provoca un kernel panic silencioso o un cuelgue no controlado.
La solución: Utiliza búferes de pila (stack) de tamaño fijo y snprintf. El firmware de un microcontrolador debe asignar búferes estáticos o basados en la pila cuyo tamaño se conozca en tiempo de compilación.
// Alternativa robusta sin asignación en el heap:
char payload[128];
snprintf(payload, sizeof(payload),
"{\"temp\":%.2f,\"humidity\":%.2f}",
temperature, humidity);
http.POST((uint8_t*)payload, strlen(payload));Culpable 2: El bucle de reconexión al wifi escolar
En los entornos educativos, la conexión wifi rara vez es estática. Los puntos de acceso renuevan las claves de seguridad, las concesiones DHCP caducan y los cortes de suministro eléctrico locales o las transiciones de cortes programados (load-shedding) desconectan brevemente los routers principales, incluso si la estación IoT funciona con batería. Muchos tutoriales de iniciación sugieren reconectarse al wifi de esta manera:
if (WiFi.status() != WL_CONNECTED) {
WiFi.reconnect();
while (WiFi.status() != WL_CONNECTED) {
delay(500); // Fatal: bloquea el procesador indefinidamente
}
}Si el router se reinicia y tarda dos minutos en levantar la subred local, este bucle while congela la ejecución. Dado que FreeRTOS ejecuta la pila wifi y las tareas de gestión del sistema en los dos núcleos, detener el bucle principal puede privar de recursos a las tareas del watchdog en segundo plano, lo que provoca un reinicio por hardware inmediato o un bloqueo permanente de tareas.
La solución: Tratar la conectividad como una máquina de estados no bloqueante. Nunca detengas la ejecución esperando una conexión. Si el wifi se cae, registra los datos localmente en la memoria flash o en una tarjeta SD y reintenta la conexión a intervalos programados sin interrumpir la lectura de los sensores.
Culpable 3: Falta de temporizadores watchdog
Por muy limpio que sea el código, los sensores de exterior, los picos de tensión de compresores cercanos o las líneas del bus I2C que no responden (especialmente en los omnipresentes sensores BME280 o DHT22) pueden llevar al ESP32 a un bloqueo por hardware (deadlock). Si un sensor no libera la línea de reloj I2C, la librería estándar Wire puede quedarse colgada para siempre.
Un temporizador watchdog de tareas (TWDT, por sus siglas en inglés) supervisa los bucles críticos. Si el bucle principal no consigue «alimentar» o reiniciar el watchdog dentro de un intervalo definido (p. ej., 8 segundos), el ESP32 activa automáticamente un reinicio por hardware y se recupera de forma autónoma.
#include <esp_task_wdt.h>
#define WDT_TIMEOUT_SECONDS 8
void setup() {
// Inicializar el watchdog con un tiempo de espera de 8 segundos
esp_task_wdt_init(WDT_TIMEOUT_SECONDS, true);
esp_task_wdt_add(NULL); // Suscribir el hilo actual
}
void loop() {
// Reiniciar el temporizador watchdog en cada ciclo
esp_task_wdt_reset();
readSensors();
sendTelemetry();
// Evitar delay() prolongados; utilizar comprobaciones no bloqueantes con millis()
}Una nota sobre la estabilidad de la alimentación
Antes de asumir que un error es puramente de software, inspecciona la línea de alimentación de hardware. Un ESP32 consume breves pulsos de corriente de hasta 350–500 mA durante las ráfagas de transmisión wifi (calibración de RF y envío de paquetes). Si la placa se alimenta mediante un cable USB fino conectado a un portátil o a un adaptador de pared de 5V de bajo coste, las caídas de tensión por debajo del umbral de apagado por subtensión (brownout) de 2,7V hacen que el detector interno de brownout provoque un reinicio abrupto.
- Coloca un condensador electrolítico de 100 µF a 470 µF entre los pines
VINyGNDpara absorber los picos transitorios de corriente. - Asegúrate de que el detector de caídas de tensión (brownout) esté habilitado en tu entorno de desarrollo en lugar de desactivado, ya que la subtensión daña la memoria flash interna.
Si estás construyendo estaciones de monitorización preparadas para su uso en el terreno para ciencias ambientales o en el recinto escolar, nuestra ingeniería curricular en Sheen IoT ofrece marcos de hardware modulares y patrones de firmware listos para producción que evitan estos errores clásicos de las aulas.



