ESP32-S3 MQTT 节点调试总结

项目:esp32-mqtt-node
硬件:ESP32-S3-DevKitC-1 N8(8MB Flash,无可用 PSRAM),WS2812 GPIO48,串口 COM6
Broker:OpenWrt Pi 上的 Mosquitto
文档日期:2026-06-17


一、目标与最终成果

目标

  • ESP32-S3 连接 WiFi,通过 MQTT 连接 OpenWrt Pi 上的 Mosquitto
  • 支持 LED 控制(led/set)与遥测上报(RSSI、uptime、online 状态)
  • Topic 前缀:node/esp32-01/

最终可用配置

项目
WiFi SSID TP-LINK_02FC
WiFi 密码 12345678
ESP32 IP 192.168.0.199(DHCP,建议在 TP-Link 静态绑定)
MQTT Broker mqtt://192.168.0.102:1883
Pi WiFi(wan) 192.168.0.102(phy0-sta0,连 TP-Link)
Pi 有线(lan) 192.168.50.1(br-lan,PC 网线 SSH 用)
Pi 上网(wan 原路径) 192.168.1.113(曾连 South 305,后改为 TP-Link STA)
掩码覆盖 关闭/24,不用 /16

验证成功的现象

  • 串口出现:MQTT connected
  • Pi 上执行:
mosquitto_sub -h 127.0.0.1 -t 'node/esp32-01/#' -v

可收到:

node/esp32-01/status/online 1
node/esp32-01/led/state 0
node/esp32-01/telemetry/rssi -40
node/esp32-01/telemetry/uptime ...

二、网络拓扑演进

2.1 最终拓扑

                    [South 305 / 上级路由]
                              │
                    TP-Link WAN(可选上级)
                              │
                    TP-Link  192.168.0.1
                    DHCP: 0.100 ~ 0.200
                         │
         ┌───────────────┼───────────────┐
         │               │               │
    [ESP32 WiFi]    [Pi phy0-sta0]   [PC WiFi 0.x]
    192.168.0.199   192.168.0.102     (Broker 客户端)

[PC 以太网 192.168.50.166] ──网线── [Pi eth0 / br-lan 192.168.50.1]
                                      (SSH / 调试,与 MQTT 主路径分离)

2.2 关键认知

  1. MQTT 是 TCP 双向通信:不仅 ESP 要能发到 Pi,Pi 回包也必须能到 ESP。
  2. PC 能 ping 通 ≠ ESP 能连 MQTT:PC 曾同时有网线 50.x 和 WiFi 0.x 两条路径,ESP 只有 WiFi 0.x
  3. Broker 放在 192.168.50.1 本身没问题,但 ESP 在 0.x 时必须存在 L3 路由同网段,否则 esp-tls: select() timeout
  4. OpenWrt 的 lan 与 wan 必须不同网段(例如 50.x + 1.x,或 50.x + 0.x),否则会出现 udhcpc: no lease, failing 等冲突。

三、问题与解决方案

3.1 WiFi 连接失败(reason 2 / 205)

现象

W mqtt_node: WiFi disconnect reason=2 AUTH_EXPIRE(2)
W mqtt_node: WiFi disconnect reason=205 CONN_FAIL(205)

同一板子、同一路由器上 stationtest 能连,mqtt_node 不能。

根因(按影响排序)

优先级 问题 stationtest mqtt_node(改前)
pmf_cfg.capable false true
WiFi 存储 WIFI_STORAGE_RAM + clear_fast_connect
射频兼容 wifi_apply_rf_compat()(CN/HT20/关省电)
连接触发 / 重试间隔 STA_START 触发 + 2s 延迟 手动 connect、无延迟

解决

  • mqtt_node 的 WiFi 初始化对齐 stationtest(PMF、RAM 存储、RF 兼容、事件处理等)
  • 确认 sdkconfig 中 SSID/密码与路由器一致

3.2 MQTT 超时(WiFi 已连上)

现象

E esp-tls: [sock=54] select() timeout
E mqtt_client: Error transport connect

根因

  • ESP 在 192.168.0.x,Broker 配置为 192.168.50.1
  • mini/TP-Link 的 0.x 与 Pi 的 50.x 无路由
  • Pi ip route 中没有 192.168.0.0/24,Pi 也 ping 不通 ESP

尝试过的方案

方案 结果
改 ESP 掩码为 /16 有时能通,但不稳定;且曾引发代码 bug(见 3.3)
TP-Link 静态路由 + WAN 接 South 305 WAN 接不到 Pi,Pi 在 50.x 孤立
PC 网线代接 WAN→Pi PC 未开 IP 转发,不能代替路由器
Pi WiFi STA 连 TP-Link,Broker 用 0.102 最终可行

3.3 掩码覆盖(/16)相关 Bug

现象 A

netmask override failed: ESP_ERR_ESP_NETIF_DHCP_NOT_STOPPED

解决:改掩码前先 esp_netif_dhcpc_stop()

现象 B

netmask override -> 255.255.0.0   (刷屏数十次)

根因esp_netif_set_ip_info() 再次触发 GOT_IP,形成死循环,MQTT 无法连接。

解决:仅首次改掩码,改完 return,等第二次 GOT_IP 再置 WIFI_CONNECTED_BIT

最终决策:关闭 CONFIG_WIFI_NETMASK_OVERRIDE,ESP 使用 /24,与 TP-Link 同网段访问 Pi 0.102


3.4 Pi OpenWrt 连不上 TP-Link WiFi

现象

iw dev phy0-sta0 link
Not connected.
phy0-sta0: state DOWN

踩坑记录

错误配置 日志 / 现象 正确写法
band='5g' 扫不到 2.4G 的 SSID band='2g'
band='2.4g' band: 2.4g has to be one of [ "2g", "5g", ... ],radio Died band='2g'
htmode='VHT80' on 2.4G Not supported (-95) htmode='HT20'
密码 123456789 认证失败 12345678(与 TP-Link/ESP 一致)

正确 wireless 片段

uci set wireless.radio0.band='2g'
uci set wireless.radio0.channel='6'
uci set wireless.radio0.htmode='HT20'
uci set wireless.sta.ssid='TP-LINK_02FC'
uci set wireless.sta.key='12345678'
uci set wireless.sta.network='wan'
uci commit wireless
wifi reload

若仍 Failed to initiate sched scan(可选)

echo 'options brcmfmac feature_disable=0x82000' > /etc/modprobe.d/brcmfmac.conf
reboot

3.5 早期硬件 / 工程问题(已解决)

问题 解决
目标芯片误设为 esp32 改为 esp32s3
开启 PSRAM 但板子无 PSRAM sdkconfig 关闭 SPIRAM
GCC ICE(esp_lcd) 根目录 MINIMAL_BUILD ON
USB 线/ hub 供电不稳 直连 USB,改善 WiFi 异常

四、代码与配置改动摘要

4.1 main/mqtt_node.c

  • WiFi 初始化对齐 stationtest(PMF、RAM 存储、RF 兼容、事件重试)
  • 可选掩码覆盖(默认关闭):CONFIG_WIFI_NETMASK_OVERRIDE
  • WiFi 未连接时不启动 MQTT
  • MQTT 连上后发布 online、订阅 led/set、周期上报 RSSI/uptime

4.2 main/Kconfig.projbuild

  • WIFI_NETMASK_OVERRIDE(默认 n
  • WIFI_NETMASK
  • MQTT_BROKER_URINODE_ID、WS2812 等

4.3 sdkconfig(当前推荐)

CONFIG_WIFI_SSID="TP-LINK_02FC"
CONFIG_WIFI_PASSWORD="12345678"
# CONFIG_WIFI_NETMASK_OVERRIDE is not set
CONFIG_MQTT_BROKER_URI="mqtt://192.168.0.102:1883"
CONFIG_NODE_ID="esp32-01"
CONFIG_ESP32S3_DEVKITC_LED_WS2812=y
CONFIG_LED_GPIO=48

4.4 Pi Mosquitto

listener 1883
allow_anonymous true

防火墙规则(示例名称):

  • Allow-MQTT-ESP
  • Allow-MQTT-wan

五、MQTT Topic 与测试命令

Topic 列表

Topic 方向 说明
node/esp32-01/status/online ESP → Broker 在线状态,遗嘱 0
node/esp32-01/telemetry/rssi ESP → Broker 约每 10s
node/esp32-01/telemetry/uptime ESP → Broker 约每 10s
node/esp32-01/led/state ESP → Broker LED 状态反馈
node/esp32-01/led/set Broker → ESP 1 开 / 0

常用命令

Pi 上订阅

mosquitto_sub -h 127.0.0.1 -t 'node/esp32-01/#' -v

PC PowerShell 测端口

Test-NetConnection 192.168.0.102 -Port 1883

控制 LED

mosquitto_pub -h 192.168.0.102 -t "node/esp32-01/led/set" -m "1"
mosquitto_pub -h 192.168.0.102 -t "node/esp32-01/led/set" -m "0"

六、运维建议

6.1 TP-Link 静态地址保留

DHCP 服务器 → 静态地址保留 → 添加新条目

设备 MAC IP
Pi WiFi 2C:CF:67:41:99:62 192.168.0.102
ESP32 28:37:2F:E5:73:18 192.168.0.199

绑完后 使所有条目生效。若 Pi IP 变更,需同步修改 CONFIG_MQTT_BROKER_URI 并重新 Flash ESP。

6.2 烧录注意

  • 修改 sdkconfig 或代码后必须 Build + Flash,不能仅 Monitor 旧固件
  • 串口确认:Compile time 更新、无 netmask override 刷屏、有 MQTT connected

6.3 SSH 路径

方式 地址
PC 网线 → Pi eth0 ssh root@192.168.50.1
PC/手机 WiFi → Pi STA ssh root@192.168.0.102

七、排查速查表

症状 优先检查
WiFi reason 2/205 PMF、SSID/密码、是否 Flash 新固件
WiFi OK,MQTT timeout ESP 与 Broker 是否同网段;Pi 防火墙 1883
netmask override 刷屏 升级固件(死循环已修)或关闭 OVERRIDE
Pi WiFi Not connected band=2g(非 2.4g/5g)、HT20、密码
Pi radio0 Died uci 里 band 必须是 2g / 5g,不能写 2.4g
Pi 收不到 ESP 消息 mosquitto_sub 本地测;Broker URI 是否指向 Pi 当前 0.x IP

八、经验结论

  1. 先打通 WiFi,再查 MQTT;MQTT 失败多数是 IP 路由,不是 Mosquitto 配置本身。
  2. stationtest 能连而 mqtt_node 不能 时,优先对比 wifi_config_t 与初始化序列(PMF 一字之差即可 reason 2)。
  3. Broker 地址不必固定为 50.1;应使用 ESP 能路由到的 Pi 地址(本次为 192.168.0.102)。
  4. OpenWrt 双接口:lan/wan 不同网段是硬性要求;Pi 用 WiFi 作 wan 连 TP-Link 是本次最简可行方案。
  5. 文档与 lab 环境强相关:换路由器、换 Pi 接线或改 DHCP 后,应重新核对 Broker URI 与静态绑定。

九、后续可选工作

  • TP-Link 完成 Pi / ESP 静态 IP 绑定
  • 测试 led/setled/state 闭环
  • Mosquitto 关闭 allow_anonymous,配置账号密码
  • OpenWrt / 上位机订阅 node/esp32-01/# 做展示或自动化
  • 多节点:修改 CONFIG_NODE_ID 烧录第二块板
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐