AIGC标识 ESP32 工程实践:为 Wi-Fi 断线重连加入超时与指数退避

很多入门程序在 setup() 里一直等待 WL_CONNECTED。路由器关机或密码错误时,设备就停在启动阶段,屏幕、按键和本地采集也无法继续。本篇实现有连接时限的重连流程,让设备离线时仍能执行本地任务。

示例使用 Arduino-ESP32 3.x 的 WiFi API,未完成实机验证。它只解决接入点连接和获取网络状态,不包含 MQTT、DNS 与业务服务器的健康检查。

先定义重试规则

每次连接最多等待 15 秒。失败后从约 1 秒开始等待,逐次增加到最多 60 秒,并加入少量随机抖动,减少多设备同时重连的拥塞。连接成功后恢复初始退避。

本例关闭自动重连,由一个状态机控制尝试节奏。不要再在其他任务里反复调用 WiFi.begin()。

最小示例

将网络名称和密码替换为自己的测试网络,发布代码时不要包含真实凭据。

#include <Arduino.h>
#include <WiFi.h>
#include <esp_system.h>

const char* SSID = "YOUR_SSID";
const char* PASS = "YOUR_PASSWORD";
constexpr uint32_t CONNECT_TIMEOUT = 15000;
bool attempting = false;
bool wasConnected = false;
uint32_t attemptAt = 0;
uint32_t waitAt = 0;
uint32_t waitMs = 0;
uint32_t backoffMs = 1000;

void scheduleRetry(uint32_t now) {
  WiFi.disconnect(false, false); // 不关闭无线电,不擦除配置。
  attempting = false;
  waitAt = now;
  waitMs = backoffMs + esp_random() % 501;
  if (waitMs > 60000) waitMs = 60000;
  backoffMs = backoffMs >= 30000 ? 60000 : backoffMs * 2;
  Serial.printf("retry in %lu ms\n", (unsigned long)waitMs);
}

void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.setAutoReconnect(false);
  waitAt = millis();
}

void loop() {
  const uint32_t now = millis();
  if (WiFi.status() == WL_CONNECTED) {
    if (!wasConnected) {
      Serial.print("IP: ");
      Serial.println(WiFi.localIP());
    }
    wasConnected = true;
    attempting = false;
    backoffMs = 1000;
  } else {
    if (wasConnected) {
      wasConnected = false;
      scheduleRetry(now);
    }
    if (attempting) {
      if (uint32_t(now - attemptAt) >= CONNECT_TIMEOUT) {
        scheduleRetry(now);
      }
    } else if (uint32_t(now - waitAt) >= waitMs) {
      Serial.println("connecting...");
      WiFi.begin(SSID, PASS);
      attempting = true;
      attemptAt = now;
    }
  }
  // 在这里推进按键、采集或显示任务;避免长时间阻塞。
  delay(10);
}

这段代码采用轮询,追求流程易读。事件驱动版本可以记录断连原因,但网络事件回调可能运行在其他任务中,回调宜只更新同步状态或发送队列消息,不执行耗时业务。

连接成功不等于业务恢复

WL_CONNECTED 不能证明互联网、DNS、TLS 和 MQTT 服务全部可用。业务层应有独立的超时与重连状态,连接恢复后重新建立会话,并根据需要重新订阅。

离线采样也应设置缓存上限。恢复连接后分批补传,使用消息序号或幂等键处理重发,避免一次性补传占满内存。

建议的验证步骤

先正常连接,再关闭接入点,确认本地任务仍运行且串口重试间隔逐步增加。重新打开接入点,检查设备能否在后续尝试中恢复。然后用错误密码测试,确认程序持续工作且不会打印密码。

如长期连接不上,先核对芯片支持的频段、接入点认证方式、信号和 DHCP;经典 ESP32 仅支持 2.4 GHz Wi-Fi,不能直接连接仅启用 5 GHz 的网络。不同 ESP32 系列能力请查对应数据手册。

参考资料

posted on 2026-11-02 22:01  潇洒石头  阅读(2)  评论(0)    收藏  举报

导航