WiFi连接实现
WiFi连接实现
Section titled “WiFi连接实现”本节介绍如何将ESP32连接到Wi-Fi网络。通过本节学习,你将能够:
- 编写连接Wi-Fi网络的ESP32草图
- 实现连接超时和重连逻辑
- 连接后显示ESP32的IP地址
- 优雅处理Wi-Fi断开事件
- 使用Arduino IDE(01-04)或PlatformIO(01-05)设置好ESP32开发板
- 一个已知SSID和密码的Wi-Fi网络
ESP32 Wi-Fi架构
Section titled “ESP32 Wi-Fi架构”ESP32 Wi-Fi子系统在两种主要模式下运行:
- Station(STA)模式:ESP32连接到现有的Wi-Fi接入点(路由器)。这是物联网设备最常见的模式。
- Access Point(AP)模式:ESP32创建自己的Wi-Fi网络,其他设备可以加入。用于设备配置或直接连接。
- STA+AP模式:同时运行两种模式。ESP32在连接到网络的同时也托管自己的AP。
本节重点介绍 Station模式,它用于所有课程项目。
Wi-Fi库
Section titled “Wi-Fi库”ESP32使用内置的 WiFi.h 库,该库包含在ESP32 Arduino Core中。关键函数如下:
| 函数 | 描述 |
|---|---|
WiFi.begin(ssid, password) | 开始连接Wi-Fi |
WiFi.status() | 返回当前连接状态 |
WiFi.localIP() | 获取分配的IP地址 |
WiFi.disconnect() | 断开Wi-Fi连接 |
WiFi.reconnect() | 强制重新连接 |
WiFi.mode(mode) | 设置Wi-Fi模式(STA/AP/AP_STA) |
WiFi.setAutoReconnect(true) | 启用自动重新连接 |
连接状态(wl_status_t)
Section titled “连接状态(wl_status_t)”| 状态 | 值 | 含义 |
|---|---|---|
WL_NO_SHIELD | 255 | Wi-Fi模块不存在 |
WL_IDLE_STATUS | 0 | Wi-Fi模块空闲 |
WL_NO_SSID_AVAIL | 1 | 未找到SSID |
WL_SCAN_COMPLETED | 2 | 网络扫描完成 |
WL_CONNECTED | 3 | 成功连接 |
WL_CONNECT_FAILED | 4 | 连接失败(密码错误) |
WL_CONNECTION_LOST | 5 | 连接后丢失连接 |
WL_DISCONNECTED | 6 | 模块已断开 |
第一步:基础Wi-Fi连接
Section titled “第一步:基础Wi-Fi连接”最简单的连接代码:
#include <WiFi.h>
const char* ssid = "YourWiFiSSID";const char* password = "YourWiFiPassword";
void setup() { Serial.begin(115200); delay(1000);
Serial.println(); Serial.print("Connecting to "); Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.println(); Serial.println("Wi-Fi connected!"); Serial.print("IP address: "); Serial.println(WiFi.localIP());}
void loop() { // 你的主代码在这里 delay(10000);}重要:while 循环会阻塞执行直到连接建立。对于生产代码,推荐使用非阻塞方法(第二步)。
第二步:带超时的非阻塞连接
Section titled “第二步:带超时的非阻塞连接”一个健壮的连接例程应该超时并重试,而不是无限期阻塞:
#include <WiFi.h>
const char* ssid = "YourWiFiSSID";const char* password = "YourWiFiPassword";const int MAX_CONNECTION_ATTEMPTS = 40; // ~20秒(40 * 500ms)
void setup() { Serial.begin(115200); delay(1000);
connectToWiFi();}
void connectToWiFi() { Serial.print("Connecting to Wi-Fi"); WiFi.begin(ssid, password);
int attempts = 0; while (WiFi.status() != WL_CONNECTED && attempts < MAX_CONNECTION_ATTEMPTS) { delay(500); Serial.print("."); attempts++; }
if (WiFi.status() == WL_CONNECTED) { Serial.println(); Serial.println("Wi-Fi connected!"); Serial.print("IP address: "); Serial.println(WiFi.localIP()); } else { Serial.println(); Serial.println("Wi-Fi connection failed!"); Serial.println("Restarting ESP32..."); delay(2000); ESP.restart(); // 重启并重试 }}
void loop() { // 定期检查连接状态 if (WiFi.status() != WL_CONNECTED) { Serial.println("Wi-Fi disconnected! Reconnecting..."); connectToWiFi(); }
delay(10000);}第三步:使用Wi-Fi事件(推荐)
Section titled “第三步:使用Wi-Fi事件(推荐)”ESP32 Arduino Core提供Wi-Fi事件处理,比轮询更健壮:
#include <WiFi.h>
const char* ssid = "YourWiFiSSID";const char* password = "YourWiFiPassword";
// 事件处理函数void WiFiEvent(WiFiEvent_t event) { switch (event) { case ARDUINO_EVENT_WIFI_STA_START: Serial.println("Wi-Fi started"); break;
case ARDUINO_EVENT_WIFI_STA_CONNECTED: Serial.println("Wi-Fi connected to AP"); break;
case ARDUINO_EVENT_WIFI_STA_GOT_IP: Serial.print("IP address obtained: "); Serial.println(WiFi.localIP()); break;
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: Serial.println("Wi-Fi disconnected! Attempting to reconnect..."); WiFi.reconnect(); // 自动重连 break;
case ARDUINO_EVENT_WIFI_STA_STOP: Serial.println("Wi-Fi stopped"); break;
default: break; }}
void setup() { Serial.begin(115200); delay(1000);
// 注册事件处理函数 WiFi.onEvent(WiFiEvent);
// 启用自动重连(ESP32内置功能) WiFi.setAutoReconnect(true);
// 开始连接 WiFi.begin(ssid, password);
Serial.print("Connecting to "); Serial.println(ssid);}
void loop() { // 你的主代码在这里运行 // Wi-Fi重连由事件自动处理 delay(10000);}第四步:安全存储凭证
Section titled “第四步:安全存储凭证”在草图中硬编码凭证对开发没问题,但生产环境不安全。替代方法:
选项1:单独的头文件(开发环境推荐)
创建 credentials.h:
#ifndef CREDENTIALS_H#define CREDENTIALS_H
const char* ssid = "YourWiFiSSID";const char* password = "YourWiFiPassword";
#endif在 main.cpp 中:
#include "credentials.h"将 credentials.h 添加到 .gitignore:
credentials.h选项2:WiFiManager库(生产环境)
WiFiManager库在首次启动时创建一个配置门户,允许用户通过Web浏览器配置Wi-Fi凭证。
#include <WiFiManager.h>
void setup() { Serial.begin(115200);
WiFiManager wm;
// 使用保存的凭证自动连接,或启动配置门户 if (!wm.autoConnect("ESP32-Config")) { Serial.println("Failed to connect!"); ESP.restart(); }
Serial.println("Wi-Fi connected!"); Serial.print("IP: "); Serial.println(WiFi.localIP());}
void loop() { delay(10000);}凭证存储在ESP32的非易失性存储(NVS)中,在重启后持续存在。
第五步:信号强度监控
Section titled “第五步:信号强度监控”void printSignalStrength() { long rssi = WiFi.RSSI(); Serial.print("Signal strength (RSSI): "); Serial.print(rssi); Serial.print(" dBm (");
// 定性评估 if (rssi > -50) { Serial.print("Excellent"); } else if (rssi > -60) { Serial.print("Good"); } else if (rssi > -70) { Serial.print("Fair"); } else if (rssi > -80) { Serial.print("Weak"); } else { Serial.print("Very weak"); } Serial.println(")");}- ESP32连接到Wi-Fi网络并获取IP地址
- 串行监视器显示”Wi-Fi connected”及正确的IP
- 断开路由器连接导致ESP32尝试重连
- 重新连接路由器后恢复Wi-Fi连接
- 基于事件的方法处理断开连接而不阻塞
loop() - RSSI读数合理(稳定运行需要>-70 dBm)
”No such host”或连接超时
Section titled “”No such host”或连接超时”原因:
- SSID或密码错误
- 路由器未广播SSID(隐藏网络)
- 路由器在不同频段(ESP32仅支持2.4 GHz)
解决方案:
- 仔细检查SSID和密码(区分大小写)
- 确保路由器正在广播SSID
- 验证路由器使用2.4 GHz(ESP32不支持5 GHz Wi-Fi)
- 如果使用隐藏SSID,添加:
WiFi.begin(ssid, password, 0, bssid)并使用BSSID
反复断开连接
Section titled “反复断开连接”原因:
- Wi-Fi信道干扰
- ESP32离路由器太远
- 电源供应不稳定
解决方案:
- 将ESP32靠近路由器
- 使用更长的USB线或外部电源
- 添加
WiFi.setSleep(false)禁用省电模式(提高稳定性) - 使用指数退避实现重连逻辑
ESP32找不到任何网络
Section titled “ESP32找不到任何网络”原因:
- ESP32 Wi-Fi天线问题
- 只有5 GHz网络可用
- ESP32硬件故障
解决方案:
- 扫描网络:创建一个调用
WiFi.scanNetworks()的草图 - 如果列表为空但其他设备能看到网络,ESP32可能有故障
- 尝试外部天线(如果开发板有连接器)
- 使用基于事件的Wi-Fi处理(
WiFi.onEvent()):比在loop()中轮询WiFi.status()更健壮且非阻塞 - 实现连接超时:永远不要无限等待连接——使用计数器限制尝试次数
- 启用自动重连:
WiFi.setAutoReconnect(true)减少手动重连代码 - 将凭证与代码分离:使用
credentials.h或WiFiManager避免在源码中暴露密码 - 监控RSSI:如果信号低于-80 dBm,连接将不稳定
- 在单独文件中处理Wi-Fi:创建
wifi_manager.h/.cpp以获得整洁的项目结构
- ESP32通过Station模式下的
WiFi.begin(ssid, password)连接Wi-Fi - 带超时的非阻塞连接防止无限阻塞
- 基于事件的处理(
WiFi.onEvent)是最健壮的方法 - 凭证应与主代码分开存储(头文件或WiFiManager)
- RSSI监控有助于诊断连接质量
- ESP32仅支持2.4 GHz Wi-Fi——这是一个常见的混淆来源