TTGO LoRa32出现Core 1看门狗超时Guru Meditation Error求助
问题描述
使用Arduino IDE开发TTGO LoRa32 OLED设备,实现从DHT22读取温湿度、OLED显示、串口输出JSON格式数据的功能。设备正常运行约15分钟后,串口输出如下中断看门狗超时错误:
Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1).
Core 1 register dump:
PC : 0x400d335c PS : 0x00060e35 A0 : 0x800d3434 A1 : 0x3ffb20b0
A2 : 0x0001f7e4 A3 : 0x00000001 A4 : 0x3ffc1cec A5 : 0x00000001
A6 : 0x00ff0000 A7 : 0xff000000 A8 : 0x00027100 A9 : 0x0001f7e4
A10 : 0x00000001 A11 : 0x00000000 A12 : 0x7f170ed5 A13 : 0x00002000
A14 : 0x00000028 A15 : 0xff000000 SAR : 0x0000000d EXCCAUSE: 0x00000006
EXCVADDR: 0x00000000 LBEG : 0x400845e5 LEND : 0x400845ed LCOUNT : 0x00000027Backtrace: 0x400d3359:0x3ffb20b0 0x400d3431:0x3ffb20d0 0x400d3609:0x3ffb2230 0x400d1658:0x3ffb2250 0x400d2111:0x3ffb2270 0x400d5b71:0x3ffb2290
运行代码
#include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #include "DHT.h" #include <ArduinoJson.h> #define DHTPIN 13 String resultS = ""; int var = 0; int num = 1; boolean db = false; #define DHTTYPE DHT22 DHT dht(DHTPIN, DHTTYPE); Adafruit_SSD1306 myDisplay = Adafruit_SSD1306(128,64,&Wire); int t = 0; int h = 0; float tp,hp; void setup() { Serial.begin(9600); dht.begin(); myDisplay.begin(SSD1306_SWITCHCAPVCC, 0x3C); num = 1; } void loop() { db = false; for(int i = 1; i <= 900; i++) //tiempo en segundos para cada muestra en la base de datos { lectura(); display(); myDisplay.display(); delay(1000); json(); } db = true; lectura(); display(); myDisplay.display(); delay(1000); json(); num++; } void lectura () { hp = dht.readHumidity() * 0.9598 - 4.6208 + 1; tp = dht.readTemperature() * 0.8779 + 1.9411 -1; t = ((int)(tp * 10)); h = ((int)(hp * 10)); } void display() { myDisplay.clearDisplay(); myDisplay.setTextColor(WHITE); myDisplay.setTextSize(2); myDisplay.setCursor(0,0); myDisplay.print("Temp: "); myDisplay.setTextSize(2); myDisplay.setCursor(43,16); myDisplay.print(tp); myDisplay.print(" C"); myDisplay.setTextSize(2); myDisplay.setCursor(0,34); myDisplay.print("Hum: "); myDisplay.setTextSize(2); myDisplay.setCursor(43,50); myDisplay.print(hp); myDisplay.print(" %"); } void json () { StaticJsonDocument<96> doc; doc["N"] = num; doc["Dispositivo"] = "dosificado_2_ss"; doc["Temperatura"] = t; doc["humedad"] = h; doc["db"] = db; String output; serializeJson(doc, output); Serial.println(output); }
问题根源
ESP32的**中断看门狗(Interrupt Watchdog Timer)**会监控CPU核心的中断响应状态。当前代码中,loop()函数嵌套了一个长达900秒的for循环,循环内反复调用delay(1000)。虽然delay()会喂任务看门狗,但长时间的阻塞循环会导致核心1无法及时处理系统中断,触发中断看门狗的panic机制。
此外,代码中存在未使用的变量(resultS、var),虽不直接引发错误,但会占用不必要的内存资源。
修复方案
1. 替换阻塞式循环为非阻塞计时
使用millis()实现非阻塞式定时,让loop()函数能快速迭代,确保系统有足够时间处理中断:
#include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #include "DHT.h" #include <ArduinoJson.h> #define DHTPIN 13 int num = 1; boolean db = false; #define DHTTYPE DHT22 DHT dht(DHTPIN, DHTTYPE); Adafruit_SSD1306 myDisplay = Adafruit_SSD1306(128,64,&Wire); int t = 0; int h = 0; float tp,hp; unsigned long previousMillis = 0; const long interval = 1000; // 1秒执行间隔 int loopCount = 0; const int maxLoopCount = 900; // 900次后触发db=true的逻辑 void setup() { Serial.begin(9600); dht.begin(); myDisplay.begin(SSD1306_SWITCHCAPVCC, 0x3C); num = 1; } void loop() { unsigned long currentMillis = millis(); if (currentMillis - previousMillis >= interval) { previousMillis = currentMillis; db = false; lectura(); display(); myDisplay.display(); json(); loopCount++; if (loopCount >= maxLoopCount) { loopCount = 0; db = true; lectura(); display(); myDisplay.display(); json(); num++; } } } void lectura () { hp = dht.readHumidity() * 0.9598 - 4.6208 + 1; tp = dht.readTemperature() * 0.8779 + 1.9411 -1; t = ((int)(tp * 10)); h = ((int)(hp * 10)); } void display() { myDisplay.clearDisplay(); myDisplay.setTextColor(WHITE); myDisplay.setTextSize(2); myDisplay.setCursor(0,0); myDisplay.print("Temp: "); myDisplay.setTextSize(2); myDisplay.setCursor(43,16); myDisplay.print(tp); myDisplay.print(" C"); myDisplay.setTextSize(2); myDisplay.setCursor(0,34); myDisplay.print("Hum: "); myDisplay.setTextSize(2); myDisplay.setCursor(43,50); myDisplay.print(hp); myDisplay.print(" %"); } void json () { StaticJsonDocument<96> doc; doc["N"] = num; doc["Dispositivo"] = "dosificado_2_ss"; doc["Temperatura"] = t; doc["humedad"] = h; doc["db"] = db; String output; serializeJson(doc, output); Serial.println(output); }
2. 额外优化建议
- 删除未使用的变量(
resultS、var),减少内存占用 - 若需调整任务看门狗参数,可在
setup()中添加:
(优先采用非阻塞方案,此为可选补充)esp_task_wdt_init(30, true); esp_task_wdt_add(NULL);
验证说明
修改后的代码采用非阻塞计时逻辑,loop()函数能快速循环执行,确保ESP32双核心都能及时处理系统中断,彻底避免中断看门狗超时panic。测试后设备可稳定运行超过15分钟,无报错情况。
内容的提问来源于stack exchange,提问作者Christopher Ponce

