You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NodeMCU运行数秒后异常重启问题排查(附错误栈与代码)

NodeMCU重启循环问题排查与修复

问题现象

NodeMCU初始运行正常,数秒后进入重启循环。网页端和串口监视器能正常显示气象数据,但数据输出完成后会卡顿数秒随即重启。

解码后的错误栈

0x4020af5c: operator new (unsigned int) at /home/gonit/.arduino15/packages/esp8266 /hardware/esp8266/3.1.2/cores/esp8266/abi.cpp line 44

8x40208604: AsyncWebServer::on (char const*, unsigned char, std::function) at

/home/gonit/Arduino/libraries/ESPAsyncWebServer/src/WebServer.cpp line 149

0x40214208: std::_Function_handler >::_M_manager(std::_Any_data &, const std::_Any_data &, std::_Manager_operation) at /home/gonit/.arduino15/packages /esp8266/tools/xtensa-lx106-elf-gcc/3.1.0-gcc10.3-e5f9fec/xtensa-1x106-elf/include /c++/10.3.0/bits/std_function.h line 268

8x402011f8: std:: Function_handler >::_M_invoke(const std::_Any_data &, AsyncWebServerRequest *&&) at /home/gonit/.arduino15/packages/esp8266/tools/xtensa- 1x106-elf-gcc/3.1.0-gcc10.3-e5f9fec/xtensa-1x106-elf/include/c++/18.3.0 /bits/std_function.h line 289

0x4020a38d: String::operator= (char const*) at /home/gonit/. arduino15/packages /esp8266/hardware/esp8266/3.1.2/cores/esp8266/WString.cpp line 319

8x482027b2: Loop() at /home/gonit/.arduino15/packages/esp8266/tools/xtensa-lx106- elf-gcc/3.1.0-gcc10.3-e5f9fec/xtensa-lx106-elf/include/c++/10.3.0 /bits/std_function.h line 303

0x402142d4: std:: Function_handler >::_M_manager(std::_Any_data &, const std::_Any_data &, std::_Manager_operation) at /home/gonit/.arduino15/packages /esp8266/tools/xtensa-lx106-elf-gcc/3.1.0-gcc10.3-e5f9fec/xtensa-lx106-elf/include /c++/10.3.0/bits/std_function.h line 268

0x402011a0: std::_Function_handler >::_M_invoke(const std::_Any_data &, AsyncWebServerRequest *&&) at /home/gonit/.arduino15/packages/esp8266/tools/xtensa- 1x106-elf-gcc/3.1.0-gcc10.3-e5f9fec/xtensa-lx106-elf/include/c++/10.3.0 /bits/std_function.h line 289

8x40202a77: ESP8266WiFiAPClass::softAPConfig(IPAddress, IPAddress, IPAddress) at /home/gonit/.arduino15/packages/esp8266/hardware/esp8266/3.1.2/libraries /ESP8266WiFi/src/ESP8266WiFiAP.cpp line 259

8x4820b2f8: Loop_wrapper() at /home/gonit/.arduino15/packages/esp8266/hardware /esp8266/3.1.2/cores/esp8266/core_esp8266_main.cpp line 258

原Arduino代码

// 导入所需库
#include <Arduino.h>
#ifdef ESP32
#include <WiFi.h>
#include <AsyncTCP.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#endif
#include <ESPAsyncWebServer.h>
#include <FS.h>
#include <ArduinoJson.h>

String temp = "";
String pressure = "";
int range;
String rain = "";
float lux;
String light = "";

/* 填写你的SSID和密码 */
const char* ssid = "Weather Station";  // 输入SSID
const char* password = "12345678";  // 输入密码

/* IP地址设置 */
IPAddress local_ip (192,168,1,1);
IPAddress gateway(192,168,1,1);
IPAddress subnet(255,255,255,0);

// 创建端口80的AsyncWebServer对象
AsyncWebServer server(80);

String processor(const String& var){
  //Serial.println(var);
  if(var == "TEMP"){
    return temp;
  }
  else if(var == "PRESSURE"){
    return pressure;
  }
  else if(var == "RAIN"){
    return rain;
  }
    else if(var == "LIGHT"){
    return light;
  }
  return String();
}

void setup() {
  // 初始化串口
  Serial.begin(9600);
  while (!Serial) continue;

  if(SPIFFS.begin()==true) {
    Serial.println("SPIFFS初始化成功");
  }

  WiFi.softAP(ssid, password);
  WiFi.softAPConfig(local_ip, gateway, subnet);
  delay(100);
}

void loop() {
  const size_t capacity = JSON_OBJECT_SIZE(128);
  DynamicJsonDocument doc(capacity);
  
  DeserializationError error = deserializeJson(doc, Serial);
  if (error) {
    Serial.print(F("deserializeJson()失败: "));
    Serial.println(error.c_str());
    return;
  }
  
  //serializeJson(doc, Serial);

  Serial.print("空气温度:  ");
  temp = String(doc["temperature"]);
  Serial.print(temp);
  Serial.println(" *C");
  
  Serial.print("空气压力:  ");
  pressure = String(doc["pressure"]);
  Serial.print(pressure);
  Serial.println(" hPa");

  Serial.print("降雨量:  ");
  range = doc["range"];
    switch (range){
    case 0:
      rain = "下雨";
    break;
    case 1:
      rain = "降雨预警";
    break;
    case 2:
      rain = "无雨";
    break;
  }
  Serial.println(rain);

  Serial.print("光照度:  ");
  lux = doc["lux"];
    if(lux < 100){
    light = "昏暗";
  }
  else if(lux > 100){
    light = "明亮";
  }
  Serial.println(light);
  Serial.println("-----------------------------------------");

  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/index.html", "text/html");
  });

  server.on("/assets/css/foundation.css", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/assets/css/foundation.css", "text/css");
  });

  server.on("/assets/js/vendor.js", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/assets/js/vendor.js", "text/js");
  });

  server.on("/assets/js/foundation.js", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/assets/js/foundation.js", "text/js");
  });
  
  server.on("/temp", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", temp.c_str());
  });
  server.on("/pressure", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", pressure.c_str());
  });
  server.on("/rain", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", rain.c_str());
  });
  server.on("/light", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", light.c_str());
  });

  server.begin();
  //end
}

问题根源与修复

核心问题

所有server.on()路由注册和server.begin()都放在了loop()函数中,每次循环都会重复注册相同路由,持续占用内存,最终导致内存耗尽触发设备重启。

修复代码

将路由注册和服务器启动代码移至setup()函数(仅需执行一次):

// 导入所需库
#include <Arduino.h>
#ifdef ESP32
#include <WiFi.h>
#include <AsyncTCP.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#endif
#include <ESPAsyncWebServer.h>
#include <FS.h>
#include <ArduinoJson.h>

String temp = "";
String pressure = "";
int range;
String rain = "";
float lux;
String light = "";

/* 填写你的SSID和密码 */
const char* ssid = "Weather Station";  // 输入SSID
const char* password = "12345678";  // 输入密码

/* IP地址设置 */
IPAddress local_ip (192,168,1,1);
IPAddress gateway(192,168,1,1);
IPAddress subnet(255,255,255,0);

// 创建端口80的AsyncWebServer对象
AsyncWebServer server(80);

String processor(const String& var){
  //Serial.println(var);
  if(var == "TEMP"){
    return temp;
  }
  else if(var == "PRESSURE"){
    return pressure;
  }
  else if(var == "RAIN"){
    return rain;
  }
    else if(var == "LIGHT"){
    return light;
  }
  return String();
}

void setup() {
  // 初始化串口
  Serial.begin(9600);
  while (!Serial) continue;

  if(SPIFFS.begin()==true) {
    Serial.println("SPIFFS初始化成功");
  }

  WiFi.softAP(ssid, password);
  WiFi.softAPConfig(local_ip, gateway, subnet);
  delay(100);

  // 注册所有路由,仅执行一次
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/index.html", "text/html");
  });

  server.on("/assets/css/foundation.css", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/assets/css/foundation.css", "text/css");
  });

  server.on("/assets/js/vendor.js", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/assets/js/vendor.js", "text/js");
  });

  server.on("/assets/js/foundation.js", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/assets/js/foundation.js", "text/js");
  });
  
  server.on("/temp", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", temp.c_str());
  });
  server.on("/pressure", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", pressure.c_str());
  });
  server.on("/rain", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", rain.c_str());
  });
  server.on("/light", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", light.c_str());
  });

  // 启动服务器,仅执行一次
  server.begin();
}

void loop() {
  const size_t capacity = JSON_OBJECT_SIZE(128);
  DynamicJsonDocument doc(capacity);
  
  DeserializationError error = deserializeJson(doc, Serial);
  if (error) {
    Serial.print(F("deserializeJson()失败: "));
    Serial.println(error.c_str());
    return;
  }
  
  //serializeJson(doc, Serial);

  Serial.print("空气温度:  ");
  temp = String(doc["temperature"]);
  Serial.print(temp);
  Serial.println(" *C");
  
  Serial.print("空气压力:  ");
  pressure = String(doc["pressure"]);
  Serial.print(pressure);
  Serial.println(" hPa");

  Serial.print("降雨量:  ");
  range = doc["range"];
    switch (range){
    case 0:
      rain = "下雨";
    break;
    case 1:
      rain = "降雨预警";
    break;
    case 2:
      rain = "无雨";
    break;
  }
  Serial.println(rain);

  Serial.print("光照度:  ");
  lux = doc["lux"];
    if(lux < 100){
    light = "昏暗";
  }
  else if(lux > 100){
    light = "明亮";
  }
  Serial.println(light);
  Serial.println("-----------------------------------------");
}

额外优化建议

  • 将DynamicJsonDocument声明为全局变量或使用StaticJsonDocument,减少loop()中的内存分配,降低碎片化风险。
  • 所有串口打印字符串用F()宏包裹,将字符串存储在Flash而非RAM中,节省内存。

内容的提问来源于stack exchange,提问作者Bimo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 05:55:54