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 实战中的一些细节
最后分享几个我在制氧机项目里积累的经验:
- 保存WiFi信息到NVS:配网成功后,把SSID和密码存到非易失性存储里。下次上电直接读取,不用重新配网。
- AP模式的超时自动关闭:如果进入AP模式后5分钟内没有设备连接,自动关闭AP并重新尝试连接上次的WiFi。防止AP一直开着浪费功耗。
- 连接失败后的降级策略:如果重连10次都失败,不要无限循环。可以进入低功耗模式,每隔5分钟唤醒一次尝试连接。制氧机是医疗设备,不能因为WiFi问题影响正常运行。
- 日志输出:在状态切换时打印日志,比如"WiFi: CONNECTING -> CONNECTED"。调试时这些日志能救命。
好了,WiFi基础通信这部分就讲到这里。下一章我们会聊MQTT协议,到时候这些连接状态机和重连机制还会用上。记住一句话:WiFi连接是物联网设备的"命门",设计得再小心都不为过。