ESP-NOW接收数据后无法连接Wi-Fi网络问题求助
ESP-NOW接收数据后WiFi状态始终为6无法连接的解决方法
问题描述
我使用ESP-NOW接收另一台ESP设备的信息,之后需连接Wi-Fi网络将数据上传至数据库,但接收数据后Wi-Fi状态始终为6,无法成功连接。已确认SSID、密码无误,且不存在硬件问题。
原代码
setup函数
void setup() { Serial.begin(115200); configDeviceAP(); InitESPNow(); esp_now_register_recv_cb(OnDataRecv); }
配置SoftAP函数
void configDeviceAP() { const char *SSID = "Slave_1"; bool result = WiFi.softAP(SSID, "Slave_1_Password", CHANNEL, 0); if (!result) { Serial.println("AP Config failed."); } else { Serial.println("AP Config Success. Broadcasting with AP: " + String(SSID)); Serial.print("AP CHANNEL "); Serial.println(WiFi.channel()); } }
切换到客户端模式函数
void resetToClientMode() { WiFi.disconnect(true); WiFi.persistent(false); WiFi.mode(WIFI_STA); Serial.println(WiFi.status()); Serial.println(WIFI_SSID); Serial.println(WIFI_PASSWORD); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); Serial.print("Connecting to WiFi .."); while (WiFi.status() != WL_CONNECTED) { Serial.print('.'); delay(1000); } Serial.println(WiFi.localIP()); Serial.println("Connected to WiFi."); }
ESP-NOW数据接收回调
void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len) { DataStruct receivedData; memcpy(&receivedData, data, sizeof(DataStruct)); Serial.print("Valeur humidité : "); Serial.println(receivedData.h); Serial.print("Valeur température : "); Serial.println(receivedData.t); Serial.println(""); // Connect to WiFi and Firebase resetToClientMode(); Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH); Firebase.reconnectWiFi(true); // Enregistrez les données reçues dans la base de données Firebase Firebase.setInt(fbdo, "/Rooms/Room01/Temp", receivedData.t); Firebase.setInt(fbdo, "/Rooms/Room01/Humidity", receivedData.h); // Déconnectez-vous du réseau WiFi WiFi.disconnect(true); WiFi.persistent(false); WiFi.mode(WIFI_OFF); } void loop() { // Chill }
问题分析
- ESP-NOW与WiFi模式切换的资源冲突:ESP-NOW运行时会占用WiFi模块的底层资源,直接从SoftAP+ESP-NOW模式切换到STA模式,未释放ESP-NOW资源,导致WiFi初始化异常。
- 回调函数中的阻塞操作:
OnDataRecv是ESP-NOW的回调函数,内部执行resetToClientMode里的无限while循环,会阻塞ESP系统的正常调度,导致WiFi模块无法完成连接流程。 - WiFi模式切换顺序不合理:先执行
WiFi.disconnect再切换模式,无法彻底清理SoftAP的配置残留,影响STA模式的初始化。
解决方案及修改后的代码
核心优化点
- 将数据上传逻辑移出ESP-NOW回调,避免阻塞
- 切换WiFi模式前先停止ESP-NOW,释放资源
- 调整WiFi模式切换顺序,彻底重置WiFi状态
- 增加连接重试机制,避免单次失败卡住
修改后的完整代码
#include <WiFi.h> #include <esp_now.h> #include <FirebaseESP32.h> // 自定义数据结构 struct DataStruct { int h; int t; }; // 全局变量:存储接收的数据和状态标记 bool dataReceived = false; DataStruct storedData; // Firebase与WiFi配置(需自行替换为实际值) #define FIREBASE_HOST "your-firebase-host" #define FIREBASE_AUTH "your-firebase-auth" #define WIFI_SSID "your-wifi-ssid" #define WIFI_PASSWORD "your-wifi-password" #define CHANNEL 1 // 需与ESP-NOW发送端频道一致 FirebaseData fbdo; void setup() { Serial.begin(115200); configDeviceAP(); InitESPNow(); esp_now_register_recv_cb(OnDataRecv); } void configDeviceAP() { const char *SSID = "Slave_1"; bool result = WiFi.softAP(SSID, "Slave_1_Password", CHANNEL, 0); if (!result) { Serial.println("AP配置失败。"); } else { Serial.println("AP配置成功,当前AP: " + String(SSID)); Serial.print("AP频道: "); Serial.println(WiFi.channel()); } } void InitESPNow() { if (esp_now_init() != ESP_OK) { Serial.println("ESP-NOW初始化失败"); return; } Serial.println("ESP-NOW初始化成功"); } void resetToClientMode() { // 先停止ESP-NOW,释放WiFi模块资源 esp_now_unregister_recv_cb(); if (esp_now_deinit() != ESP_OK) { Serial.println("ESP-NOW停止失败"); } // 彻底重置WiFi状态 WiFi.mode(WIFI_OFF); delay(100); // 给模块留出切换时间 WiFi.persistent(false); WiFi.mode(WIFI_STA); Serial.println("当前WiFi状态: " + String(WiFi.status())); Serial.println("目标SSID: " + String(WIFI_SSID)); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); int retryCount = 0; const int maxRetries = 10; Serial.print("连接WiFi中.."); while (WiFi.status() != WL_CONNECTED && retryCount < maxRetries) { Serial.print('.'); delay(1000); retryCount++; } if (WiFi.status() == WL_CONNECTED) { Serial.println("\n已连接WiFi,IP地址: " + WiFi.localIP().toString()); } else { Serial.println("\nWiFi连接失败,重试次数耗尽"); } } void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len) { memcpy(&storedData, data, sizeof(DataStruct)); Serial.print("湿度值 : "); Serial.println(storedData.h); Serial.print("温度值 : "); Serial.println(storedData.t); Serial.println(""); dataReceived = true; // 设置标记,在loop中处理后续操作 } void loop() { if (dataReceived) { dataReceived = false; // 重置标记 resetToClientMode(); if (WiFi.status() == WL_CONNECTED) { Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH); Firebase.reconnectWiFi(true); // 上传数据到Firebase bool tempSuccess = Firebase.setInt(fbdo, "/Rooms/Room01/Temp", storedData.t); bool humidSuccess = Firebase.setInt(fbdo, "/Rooms/Room01/Humidity", storedData.h); if (tempSuccess && humidSuccess) { Serial.println("数据上传成功"); } else { Serial.println("数据上传失败"); if(fbdo.error()){ Serial.println("错误信息: " + fbdo.errorReason()); } } // 断开WiFi,恢复ESP-NOW和SoftAP WiFi.disconnect(true); WiFi.mode(WIFI_OFF); delay(100); configDeviceAP(); InitESPNow(); esp_now_register_recv_cb(OnDataRecv); } else { // 连接失败,直接恢复ESP-NOW configDeviceAP(); InitESPNow(); esp_now_register_recv_cb(OnDataRecv); } } }
额外说明
- 确保
CHANNEL的值和ESP-NOW发送端使用的频道一致,也可以匹配目标WiFi的频道,减少切换时的频道扫描时间 - 回调函数中只做数据存储和状态标记,避免任何阻塞或耗时操作,这是嵌入式系统中断/回调处理的最佳实践
- 增加重试机制可以应对WiFi信号波动导致的临时连接失败
内容的提问来源于stack exchange,提问作者yassmine hassouna
相关产品推荐
相关产品推荐

