4. WiFi基础通信:Station模式与AP模式、WiFi连接状态机、重连机制设计

好,咱们进入WiFi通信的核心环节。说实话,很多做嵌入式通信的工程师,一开始都容易在WiFi连接这块栽跟头。我自己也不例外——记得第一次做制氧机项目时,设备在实验室连得好好的,一到客户现场就频繁掉线,搞得我焦头烂额。后来我才明白,WiFi通信的基础没打牢,上层协议再漂亮也是白搭。

4.1 Station模式与AP模式:你得先搞清楚角色

WiFi模组有两种基本工作模式,说白了就是两种身份:

  • Station模式(STA):模组作为客户端,去连接一个已有的WiFi热点。比如你家手机连路由器,手机就是STA。
  • AP模式(Access Point):模组自己变成热点,让其他设备来连它。比如你开手机热点给电脑用,手机就是AP。

在制氧机场景里,我一般这样设计:

  • 默认上电:模组先以STA模式启动,尝试连接上次保存的WiFi。
  • 连接失败:自动切换成AP模式,让用户用手机连上来配网。
  • 配网成功后:切回STA模式,连接目标路由器。

你想想看,如果一开始就固定死在一种模式,用户配网会非常痛苦。我见过有些产品,必须用网线连电脑才能配置WiFi,那体验简直了。

关键点:ESP32这类芯片支持同时开启STA+AP模式,但我不建议在制氧机上这么干。同时开两个模式会占用更多内存和射频资源,对稳定性有影响。老老实实分时切换,更靠谱。

4.2 WiFi连接状态机:别用延时硬等

很多新手写WiFi连接代码,喜欢这样:

WiFi.begin("SSID", "password");
delay(5000);  // 等5秒
if (WiFi.status() == WL_CONNECTED) {
    // 连接成功
}

嗯,这里要注意——这种写法在项目里绝对是大忌。5秒不够怎么办?10秒?20秒?万一路由器重启了,你的设备就永远卡死在delay里了。

我个人的习惯是,用状态机来管理WiFi连接。状态机说白了就是一张表,告诉你当前在干什么、下一步该干什么。

状态 描述 触发条件 下一状态
WIFI_STATE_IDLE 空闲,未开始连接 收到连接指令 WIFI_STATE_CONNECTING
WIFI_STATE_CONNECTING 正在尝试连接 连接成功 WIFI_STATE_CONNECTED
WIFI_STATE_CONNECTING 正在尝试连接 超时/失败 WIFI_STATE_RECONNECT
WIFI_STATE_CONNECTED 已连接,正常工作 断线/心跳超时 WIFI_STATE_RECONNECT
WIFI_STATE_RECONNECT 重连中 重连成功 WIFI_STATE_CONNECTED
WIFI_STATE_RECONNECT 重连中 重连次数超限 WIFI_STATE_AP_MODE
WIFI_STATE_AP_MODE 切换为AP模式 用户配网完成 WIFI_STATE_CONNECTING

你看,有了这个状态机,代码就清晰多了。主循环里只需要不断检查当前状态,然后执行对应的动作。不会阻塞,不会死等。

我的小技巧:在状态机里加一个超时计数器。比如CONNECTING状态持续超过15秒还没连上,就自动进入RECONNECT。这个15秒是我在实际项目中试出来的——太短了路由器还没响应,太长了用户等得着急。

4.3 重连机制设计:别让设备变成"孤儿"

WiFi断连是家常便饭。路由器重启、信号干扰、甚至有人不小心踢了电源线,都会导致断线。重连机制设计得好不好,直接决定了设备的可靠性。

我曾经踩过一个坑:设备断线后,每隔1秒就尝试重连一次。结果呢?路由器还没完全启动,设备已经重连了十几次,把WiFi模组搞得死机了。后来我学乖了,采用指数退避策略:

// 重连间隔:1s, 2s, 4s, 8s, 16s, 30s, 30s...
int reconnect_interval = 1;
int max_interval = 30;

void handle_reconnect() {
    if (WiFi.status() != WL_CONNECTED) {
        WiFi.reconnect();
        delay(reconnect_interval * 1000);
        reconnect_interval = min(reconnect_interval * 2, max_interval);
    } else {
        reconnect_interval = 1;  // 连上了就重置
    }
}

为什么要这样做?你想想看,如果路由器正在重启,你每秒重连一次,除了浪费电和增加射频干扰,没有任何意义。等30秒再试,路由器大概率已经起来了。

另外,我建议在重连机制里加入心跳检测。WiFi状态机里的WL_CONNECTED并不完全可靠——有时候芯片报告已连接,但实际上已经断开了。我的做法是:

  • 每30秒ping一次网关IP
  • 连续3次ping不通,就认为断线了
  • 触发重连流程

注意:不要用WiFi.status()作为唯一判断依据。我在项目中遇到过,WiFi.status()返回WL_CONNECTED,但实际已经无法收发数据了。一定要加上应用层的心跳检测,双重保险。

4.4 实战中的一些细节

最后分享几个我在制氧机项目里积累的经验:

  1. 保存WiFi信息到NVS:配网成功后,把SSID和密码存到非易失性存储里。下次上电直接读取,不用重新配网。
  2. AP模式的超时自动关闭:如果进入AP模式后5分钟内没有设备连接,自动关闭AP并重新尝试连接上次的WiFi。防止AP一直开着浪费功耗。
  3. 连接失败后的降级策略:如果重连10次都失败,不要无限循环。可以进入低功耗模式,每隔5分钟唤醒一次尝试连接。制氧机是医疗设备,不能因为WiFi问题影响正常运行。
  4. 日志输出:在状态切换时打印日志,比如"WiFi: CONNECTING -> CONNECTED"。调试时这些日志能救命。

好了,WiFi基础通信这部分就讲到这里。下一章我们会聊MQTT协议,到时候这些连接状态机和重连机制还会用上。记住一句话:WiFi连接是物联网设备的"命门",设计得再小心都不为过。