You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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
}

问题分析

  1. ESP-NOW与WiFi模式切换的资源冲突:ESP-NOW运行时会占用WiFi模块的底层资源,直接从SoftAP+ESP-NOW模式切换到STA模式,未释放ESP-NOW资源,导致WiFi初始化异常。
  2. 回调函数中的阻塞操作:OnDataRecv是ESP-NOW的回调函数,内部执行resetToClientMode里的无限while循环,会阻塞ESP系统的正常调度,导致WiFi模块无法完成连接流程。
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 12:57:37