故障定位与升级 / 供电诊断实验方法发布 内容更新

ESP32 一联网就重启?从 Brownout 日志查供电

用固定版本诊断程序保存复位分类与联网时刻,做USB线材、负载和板端电压对照。给出测量模板与恢复流程,不靠关闭欠压检测掩盖问题。

读完能做什么
形成有固件版本、完整日志、供电条件和仪表记录的故障报告,判断下一步查供电还是软件。
开始之前
完成首次上传、模块核对与N01联网程序;能正确使用万用表直流电压挡。有示波器时另记录其设置。
所需器材
DevKitC-1 v1.1 N8R8、两条可传数据的USB线、同一电脑端口、万用表;示波器可选、有权限使用的2.4GHz接入点
版本组合
工具链:Arduino CLI1.5.1 / Arduino-ESP32 3.3.12SDK复位定义:ESP-IDF v5.5.5板型:DevKitC-1 v1.1 / N8R8
适用范围

官方ESP32-S3-DevKitC-1 v1.1 / WROOM-1-N8R8,Arduino3.3.12/IDF5.5.5,仅USB-to-UART单路供电。当前是完整实验方法,无本站欠压波形或线材故障结论。

这篇验证到了哪一步

资料核对已通过
docs/esp32-evidence/maintenance.md#r01;IDF5.5.5 Brownout与esp_system.h、指定板供电路径核对。验证日期:
构建 / 配置已通过
docs/esp32-evidence/r01-build.json;实际Exit0,当前源SHA匹配,原日志r01-build.log。对象:ESP32-S3 / N8R8版本:CLI1.5.1 / core3.3.12验证日期:
仿真不适用
欠压、USB供电与测量链路不能用主机逻辑测试证明。
本站实板待验证
本站无波形、线材对照或联网复位实验;CSV保持空白。

构建通过只说明指定环境中的代码或配置通过检查;实物功能、功耗和稳定性以对应的实板记录为准。

01 / 供电诊断实验方法

先记录哪一次重启,再谈供电原因

“开Wi-Fi就重启”把触发时刻和原因混在了一起。先保存完整启动头、异常文本、程序版本和上电方式,判断是真的重新执行应用,还是串口桥从电脑消失了。uptime重新从小值开始是重启线索,还要结合新的启动头与复位分类。

在匹配IDF版本中,Brownout检测默认启用,检测到不安全的供电下降后可能复位。掉电很快时串口消息可能只输出一部分。因此看到Brownout应检查供电,但没看到那一行也不能证明供电稳定。

做到这里,你应该看到
保留了未经删减的启动上下文,不用一句“串口断了”替代故障记录。

参考:[1] ESP-IDF v5.5.5 S3 Fatal Errors:Brownout及其他复位线索[2] ESP-IDF v5.5.5 esp_system.h:复位枚举与查询函数

02 / 供电诊断实验方法

把错误分类与故障器件分开

BROWNOUT是SDK对上次复位的分类,不会告诉你是USB线、电源、接口接触、板上稳压还是外设负载出了问题。PANIC和看门狗应保留回溯、阻塞与内存上下文,走对应软件诊断。只有断连声而没有应用日志时,先检查串口和USB枚举。

换线后一次不再重启是可复验线索,不是永久修复证明。后面的实验每次只变一个条件,将分类、波形或电压、反复对照放在一起,再把结论限定到所测板和负载。

观察优先保留下一步
BROWNOUT分类完整启动及供电条件板端电压与单变量供电对照
PANIC/看门狗完整回溯与匹配固件软件故障定位
只有USB消失主机枚举与端口变化检查线材、端口和桥接;继续收集CPU证据

参考:[1] ESP-IDF v5.5.5 S3 Fatal Errors:Brownout及其他复位线索[2] ESP-IDF v5.5.5 esp_system.h:复位枚举与查询函数

03 / 供电诊断实验方法

先关无线留基线,再手动启动一次连接

下载包的config.h只含SSID与密码占位值。先编译;有权限连接自己的接入点时,再在本机填写,不能将真实配置发布。程序不打印这些值,读取复位枚举、uptime与内存上下文,并提供w开启Wi-Fi、o关闭的串口指令。

通过USB-to-UART上传与115200监视,CDC关闭,Flash8MB/QIO、OPI PSRAM与8M with spiffs。RESET后先保存至少10秒无线关闭记录,再发w,并保存前后日志;要重做时先o再w。驱动可能有内部重试,不能把一次w称为一次射频发射或以日志周期估算功耗。

本例没有电压传感器。free_heap/min_heap用于保留软件条件,既不是电流,也不是电压。程序不写brownout控制寄存器,不把关闭保护作为“修好”。安装、完整FQBN与命令见包内README。

代码 / 配置
// SPDX-License-Identifier: MIT
#include <Arduino.h>
#include <WiFi.h>
#include <esp_system.h>
#include "config.h"
uint32_t reportedAt = 0;
bool wifiStarted = false;
const char* resetName(esp_reset_reason_t reason) {
  switch (reason) {
    case ESP_RST_POWERON: return "POWERON";
    case ESP_RST_SW: return "SOFTWARE";
    case ESP_RST_PANIC: return "PANIC";
    case ESP_RST_INT_WDT: return "INT_WATCHDOG";
    case ESP_RST_TASK_WDT: return "TASK_WATCHDOG";
    case ESP_RST_WDT: return "OTHER_WATCHDOG";
    case ESP_RST_DEEPSLEEP: return "DEEP_SLEEP";
    case ESP_RST_BROWNOUT: return "BROWNOUT";
    default: return "OTHER_OR_UNKNOWN";
  }
}
void setup() {
  Serial.begin(115200);
  delay(300);
  const auto reason = esp_reset_reason();
  Serial.printf("R01 core=3.3.12 reset=%d label=%s\n", int(reason), resetName(reason));
  WiFi.persistent(false);
  WiFi.setAutoReconnect(false);
  WiFi.mode(WIFI_OFF);
  Serial.println("Commands: w=start Wi-Fi (configure config.h first); o=Wi-Fi off");
  Serial.println("No voltage sensor in this example. Heap/RSSI are not voltage readings.");
}
void loop() {
  if (Serial.available()) {
    const char command = Serial.read();
    if (command == 'w' && !wifiStarted) {
      Serial.printf("ACTION=start_wifi uptime_ms=%lu\n", (unsigned long)millis());
      WiFi.mode(WIFI_STA);
      WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
      wifiStarted = true;
    } else if (command == 'o') {
      Serial.printf("ACTION=wifi_off uptime_ms=%lu\n", (unsigned long)millis());
      WiFi.mode(WIFI_OFF);
      wifiStarted = false;
    }
  }
  const uint32_t now = millis();
  if (uint32_t(now - reportedAt) >= 1000) {
    reportedAt = now;
    Serial.printf("uptime_ms=%lu wifi_requested=%u wifi_status=%d free_heap=%lu min_heap=%lu\n",
      (unsigned long)now, wifiStarted, int(WiFi.status()),
      (unsigned long)ESP.getFreeHeap(), (unsigned long)ESP.getMinFreeHeap());
  }
  delay(1);
}
做到这里,你应该看到
日志显示实际固件版本、复位分类和动作时刻;凭据没有出现在公开日志。

参考:[2] ESP-IDF v5.5.5 esp_system.h:复位枚举与查询函数[5] Arduino-ESP32 3.3.12:STA初始化和连接实现

04 / 供电诊断实验方法

用两条数据线做可复验的对照

先拔外设,只留下开发板和USB-to-UART数据线。选同一台电脑同一个端口、同一固件与接入点,每种条件重复三次,从RESET、关闭无线基线到w的操作保持相同。三次是本实验的重复约定,不代表长时间可靠性。

先用A线记录,再只换B线记录。若现象变化,再换回A复验,避免把偶然的网络时序或系统负载当作线材结果。确认最小系统稳定后,才按原工程每个模块的供电额定逐个恢复负载,不一次接回屏幕、功放和电机。

在power-observations.csv写入日期、板修订、固件SHA、线/端口/电源、负载、复位分类与次数、仪表和原始数据路径。没有条件测量的栏保持未测,不能把本文的例子填成自己的结果。

  1. A线/同一端口/最小系统,记录三次关闭→开启无线。
  2. 只换B线,重复同一时序。
  3. 若有差异,换回A复查;记录未能重复的现象。
  4. 按供电要求一次恢复一个外设,分别保存结果。
做到这里,你应该看到
每一行记录只比上一条件改变了一个可说明的变量。

参考:[3] DevKitC-1 v1.1 固定文档:供电方式和排针[4] ESP32-S3 数据手册 v2.2:供电与外设电气边界

05 / 供电诊断实验方法

先量3V3对地,快速下陷需要另外的证据

断电固定表笔后,用万用表直流电压挡并联量板端3V3与GND,记录无线关闭和开启阶段。表笔不能在电流挡跨电源,也不向3V3排针另送电。只用选定的一条USB供电,避免第二路电源改变测试对象。

万用表更新速度有限,显示正常均值不排除短时供电下陷。使用示波器时先确认探头接地与板GND兼容,断电固定短接地附件,不会确认接地者停在仪表和对照记录。保存倍率、耦合、时基、采样率、带宽限制、触发条件、最小值和原始数据。

触发阈值按所选板和电源规格及观察目标设置,不能将它写成统一brownout阈值;软件串口时刻和示波器时刻也不自动同步。用动作前后时间上下文说明相关性,避免从一张不知条件的截图判断因果。

做到这里,你应该看到
电压记录有测点与量程;波形记录有完整设置,缺测就明示缺测。

参考:[3] DevKitC-1 v1.1 固定文档:供电方式和排针[4] ESP32-S3 数据手册 v2.2:供电与外设电气边界

06 / 供电诊断实验方法

修复后重复原条件,保留结论的边界

将Brownout分类、板端供电变化和线材/负载对照一起看,证据一致才把供电链路列为较强原因线索。相同PANIC或回溯持续出现时,继续查软件,不因为“联网前后”就跳过其他分支。

恢复到仅开发板和已知合格数据线,必要时重新烧入本例或首次上传程序。断电再修接线。不要故意把供电调出规格来制造Brownout,也不要没有依据就往板上堆电容;出现短路或异常发热时保持断电核查。

本站尚无本实验的波形、线材结论或重启率数字。本文提供完整程序、记录模板与方法,实际编译和硬件结果在四维状态分别呈现。通过后也只对本板、本电源、本负载和观察时长成立,不能推断所有S3或整机都稳定。

参考:[1] ESP-IDF v5.5.5 S3 Fatal Errors:Brownout及其他复位线索[2] ESP-IDF v5.5.5 esp_system.h:复位枚举与查询函数[3] DevKitC-1 v1.1 固定文档:供电方式和排针

BACK TO THE SOURCE

资料来源与版本说明

Brownout说明来自匹配IDF版本,测点按指定板修订核对。仪表与线材结果必须由实际实验填写。资料核对日期:。资料核对、程序构建与实板测试分别记录,不互相替代。

  1. ESP-IDF v5.5.5 S3 Fatal Errors:Brownout及其他复位线索
  2. ESP-IDF v5.5.5 esp_system.h:复位枚举与查询函数
  3. DevKitC-1 v1.1 固定文档:供电方式和排针
  4. ESP32-S3 数据手册 v2.2:供电与外设电气边界
  5. Arduino-ESP32 3.3.12:STA初始化和连接实现