跳转到内容

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子系统在两种主要模式下运行:

  • Station(STA)模式:ESP32连接到现有的Wi-Fi接入点(路由器)。这是物联网设备最常见的模式。
  • Access Point(AP)模式:ESP32创建自己的Wi-Fi网络,其他设备可以加入。用于设备配置或直接连接。
  • STA+AP模式:同时运行两种模式。ESP32在连接到网络的同时也托管自己的AP。

本节重点介绍 Station模式,它用于所有课程项目。

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_NO_SHIELD255Wi-Fi模块不存在
WL_IDLE_STATUS0Wi-Fi模块空闲
WL_NO_SSID_AVAIL1未找到SSID
WL_SCAN_COMPLETED2网络扫描完成
WL_CONNECTED3成功连接
WL_CONNECT_FAILED4连接失败(密码错误)
WL_CONNECTION_LOST5连接后丢失连接
WL_DISCONNECTED6模块已断开

最简单的连接代码:

#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 循环会阻塞执行直到连接建立。对于生产代码,推荐使用非阻塞方法(第二步)。

一个健壮的连接例程应该超时并重试,而不是无限期阻塞:

#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);
}

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);
}

在草图中硬编码凭证对开发没问题,但生产环境不安全。替代方法:

选项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)中,在重启后持续存在。

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)

原因

  • SSID或密码错误
  • 路由器未广播SSID(隐藏网络)
  • 路由器在不同频段(ESP32仅支持2.4 GHz)

解决方案

  1. 仔细检查SSID和密码(区分大小写)
  2. 确保路由器正在广播SSID
  3. 验证路由器使用2.4 GHz(ESP32不支持5 GHz Wi-Fi)
  4. 如果使用隐藏SSID,添加:WiFi.begin(ssid, password, 0, bssid) 并使用BSSID

原因

  • Wi-Fi信道干扰
  • ESP32离路由器太远
  • 电源供应不稳定

解决方案

  1. 将ESP32靠近路由器
  2. 使用更长的USB线或外部电源
  3. 添加 WiFi.setSleep(false) 禁用省电模式(提高稳定性)
  4. 使用指数退避实现重连逻辑

原因

  • ESP32 Wi-Fi天线问题
  • 只有5 GHz网络可用
  • ESP32硬件故障

解决方案

  1. 扫描网络:创建一个调用 WiFi.scanNetworks() 的草图
  2. 如果列表为空但其他设备能看到网络,ESP32可能有故障
  3. 尝试外部天线(如果开发板有连接器)
  • 使用基于事件的Wi-Fi处理WiFi.onEvent()):比在 loop() 中轮询 WiFi.status() 更健壮且非阻塞
  • 实现连接超时:永远不要无限等待连接——使用计数器限制尝试次数
  • 启用自动重连WiFi.setAutoReconnect(true) 减少手动重连代码
  • 将凭证与代码分离:使用 credentials.h 或WiFiManager避免在源码中暴露密码
  • 监控RSSI:如果信号低于-80 dBm,连接将不稳定
  • 在单独文件中处理Wi-Fi:创建 wifi_manager.h/.cpp 以获得整洁的项目结构
  1. ESP32通过Station模式下的 WiFi.begin(ssid, password) 连接Wi-Fi
  2. 带超时的非阻塞连接防止无限阻塞
  3. 基于事件的处理(WiFi.onEvent)是最健壮的方法
  4. 凭证应与主代码分开存储(头文件或WiFiManager)
  5. RSSI监控有助于诊断连接质量
  6. ESP32仅支持2.4 GHz Wi-Fi——这是一个常见的混淆来源