ESP32运行一周后无响应,看门狗及每日重启方案失效求助
问题分析与解决方案
失效原因拆解
1. 每日重启逻辑完全无效
你当前的重启代码存在逻辑错误:
unsigned long current_millis = millis(); if (current_millis > 24 * 60 * 60 * 1000) { esp_restart(); }
- 设备首次运行24小时后会触发重启,但重启后
millis()会重置为0,之后current_millis永远小于86400000,不会再触发重启。 - 你只实现了一次重启,而非每日自动重启,自然无法解决一周后的累积问题。
2. 看门狗未覆盖关键场景
你仅将当前APP任务(loop()所在任务)加入看门狗监控,但ESP32系统运行依赖多个核心任务:
- 如果WiFi栈、mDNS服务或WebServer连接池崩溃,APP任务可能仍在正常执行
esp_task_wdt_reset(),看门狗不会触发复位。 - 若
loop()中存在隐性阻塞(比如传感器读取时的未处理超时、delay()调用),但阻塞时间未超过240秒,看门狗也不会干预。
3. 核心稳定性隐患(一周失效的根源)
大概率是以下累积性问题导致系统无响应:
- 内存泄漏:Web请求处理、传感器数据解析时动态分配内存未释放,或
String操作产生内存碎片,一周后内存耗尽,系统无法处理新请求。 - WebServer连接耗尽:客户端异常断开后未释放连接资源,连接池被占满,无法接受新的访问请求。
- WiFi/mDNS服务崩溃:长时间运行后WiFi连接异常断开且无重连逻辑,mDNS服务未随WiFi重连重启,导致两种访问方式均失效。
- 系统任务死锁:部分ESP32 Arduino Core版本存在任务调度bug,长时间运行后核心任务死锁,仅APP任务存活。
针对性修复方案
1. 修复每日重启逻辑
使用时间差比较(自动处理millis()溢出问题),确保每日触发重启:
// 全局变量 unsigned long last_restart_timestamp = millis(); const unsigned long DAILY_RESTART_INTERVAL = 24UL * 60 * 60 * 1000; void loop() { unsigned long current_millis = millis(); // 时间差比较,不受millis溢出影响 if (current_millis - last_restart_timestamp >= DAILY_RESTART_INTERVAL) { esp_restart(); } // 原有业务代码 server.handleClient(); esp_task_wdt_reset(); }
2. 优化看门狗配置
- 监控更多关键任务:除APP任务外,将WiFi任务、TCP/IP任务加入看门狗(需通过ESP-IDF API获取任务句柄)。
- 替换为硬件看门狗:若软件看门狗无法覆盖场景,可使用ESP32的硬件看门狗(
esp_hw_wdt.h),配置更长超时时间,确保系统彻底复位。
3. 解决核心稳定性问题
- 排查内存泄漏:定期打印剩余内存,定位泄漏点:
若内存持续下降,检查动态内存分配(// 每隔一段时间打印一次 Serial.print("Free internal RAM: "); Serial.println(heap_caps_get_free_size(MALLOC_CAP_INTERNAL));new/malloc)是否未释放,或改用静态字符串替代String类。 - 优化WebServer稳定性:
- 设置连接超时:
server.setTimeout(30000);(30秒超时释放连接)。 - 替换为
AsyncWebServer:非阻塞架构,比官方WebServer更稳定,避免连接池耗尽问题。
- 设置连接超时:
- 添加WiFi重连与mDNS重启逻辑:
void loop() { // 检查WiFi连接,断开则重连 if (WiFi.status() != WL_CONNECTED) { WiFi.disconnect(); WiFi.reconnect(); delay(2000); // 重连后重启mDNS MDNS.end(); MDNS.begin("esp32-temp"); } // 原有代码... } - 更新固件依赖:升级Arduino ESP32 Core到最新稳定版本,修复已知的任务调度、内存泄漏bug。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

