ESP32连接AP后无法接收ESP-NOW数据包的问题求助
问题:ESP32连接路由器时无法接收ESP-NOW数据包
需要实现ESP32连接路由器的同时接收ESP-NOW数据包,已配置双方MAC地址和与路由器一致的WiFi信道,但连接路由器后出现无法接收ESP-NOW数据的问题。
ESP8266发送端代码
#include <ESP8266WiFi.h> #include <espnow.h> #define WIFI_CHANNEL 8 uint8_t peer[] = {0x12,0x34,0x56,0x78,0x9A,0xBC}; // ESP32的MAC地址 void onRecv(uint8_t *mac, uint8_t *data, uint8_t len) { Serial.print(" in "); Serial.println(*data); } void onSent(const uint8_t* mac, uint8_t status) { Serial.print("send callback status: "); Serial.println(status); } void setup() { Serial.begin(74880); WiFi.mode(WIFI_STA); WiFi.disconnect(); wifi_set_channel(WIFI_CHANNEL); if (esp_now_init() != 0) { return; } esp_now_set_self_role(ESP_NOW_ROLE_COMBO); esp_now_add_peer(peer, ESP_NOW_ROLE_COMBO, 3, NULL, 0); esp_now_register_recv_cb(esp_now_recv_cb_t(onRecv)); esp_now_register_send_cb(esp_now_send_cb_t(onSent)); } void loop() { static uint8_t counter = 0; esp_now_send(peer, &counter, sizeof(counter)); Serial.print("out "); Serial.println(counter); counter++; delay(1000); }
ESP32接收端代码
#include <WiFi.h> #include <esp_now.h> #include "esp_wifi.h" #define MODE_PASSIVE 1 #define MODE_CREATE_AP 2 #define MODE_CONNECT_TO_WIFI 3 #define MODE MODE_CONNECT_TO_WIFI #define WIFI_CHANNEL 8 const char* routerSsid = "myRouterSSID"; const char* routerPwd = "myRouterPWD"; const char* apSsid = "myAP"; const char* apPwd = "12345678"; const uint8_t peer_addr[] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}; // ESP8266的MAC地址 void onRecv(const uint8_t* mac_addr, const uint8_t* data, int len) { Serial.print(" in "); Serial.println(*data); } void onSent(const uint8_t* mac_addr, esp_now_send_status_t status) { Serial.print("send callback status: "); Serial.println(status == ESP_NOW_SEND_SUCCESS ? "ESP_NOW_SEND_SUCCESS" : "ESP_NOW_SEND_FAIL"); } void setup() { Serial.begin(115200); WiFi.mode(WIFI_AP_STA); #if MODE == MODE_PASSIVE esp_wifi_set_promiscuous(true); esp_wifi_set_channel(WIFI_CHANNEL, WIFI_SECOND_CHAN_NONE); esp_wifi_set_promiscuous(false); #elif MODE == MODE_CREATE_AP WiFi.softAP(apSsid, apPwd, WIFI_CHANNEL, false, 1); #elif MODE == MODE_CONNECT_TO_WIFI WiFi.begin(routerSsid, routerPwd); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.print("."); } #endif delay(1000); Serial.print("Station IP Address: "); Serial.println(WiFi.localIP()); Serial.printf("MAC Address: %s\n", WiFi.macAddress().c_str()); Serial.print("Wi-Fi Channel: "); Serial.println(WiFi.channel()); delay(100); if (esp_now_init() != ESP_OK) { Serial.println("Error initializing ESP-NOW"); return; } esp_now_register_recv_cb(esp_now_recv_cb_t(onRecv)); esp_now_register_send_cb(esp_now_send_cb_t(onSent)); esp_now_peer_info_t peer = {}; memcpy(peer.peer_addr, peer_addr, 6); peer.channel = 0; peer.encrypt = false; esp_now_add_peer(&peer); } void loop() { static uint8_t counter = 0; delay(700); Serial.print("out "); Serial.println(counter); Serial.print("esp_now_send returned "); switch (esp_now_send(peer_addr, (uint8_t*)&counter, sizeof(counter))) { case ESP_OK: Serial.println("ESP_OK"); break; case ESP_ERR_ESPNOW_NOT_INIT: Serial.println("ESP_ERR_ESPNOW_NOT_INIT"); break; case ESP_ERR_ESPNOW_ARG: Serial.println("ESP_ERR_ESPNOW_ARG"); break; case ESP_ERR_ESPNOW_INTERNAL: Serial.println("ESP_ERR_ESPNOW_INTERNAL"); break; case ESP_ERR_ESPNOW_NO_MEM: Serial.println("ESP_ERR_ESPNOW_NO_MEM"); break; case ESP_ERR_ESPNOW_NOT_FOUND: Serial.println("ESP_ERR_ESPNOW_NOT_FOUND"); break; case ESP_ERR_ESPNOW_IF: Serial.println("ESP_ERR_ESPNOW_IF"); break; case ESP_ERR_ESPNOW_CHAN: Serial.println("ESP_ERR_ESPNOW_CHAN"); break; } counter++; }
测试现象
- ESP32不连接家庭WiFi(MODE_PASSIVE或MODE_CREATE_AP模式)时,ESP-NOW通信正常;手机连接ESP32创建的AP也能正常工作。
- ESP8266即使配置错误WiFi信道,仍能接收ESP32的数据。
- 即使ESP32连接家庭WiFi无法接收数据,其onSent回调仍能正确识别ESP8266是否在监听;仅当ESP8266信道错误时,ESP32会返回ESP_NOW_SEND_FAIL,但ESP8266仍能接收数据。
- ESP32连接家庭WiFi无法接收数据时,ESP8266的发送回调会正确报告发送失败。
- 将路由器信道改为1后问题仍未解决。
补充测试
- 调整发射功率无效果。
- 若ESP32尝试连接不存在的WiFi,会显示处于信道14,ESP-NOW传输偶尔成功。
已测试ESP32CAM和Wemos D1 mini ESP32,结果一致。
解决方案
1. 强制ESP32连接路由器后保持指定信道
ESP32连接路由器后会自动切换到路由器的信道,需确保该信道与ESP-NOW发送端一致。在MODE_CONNECT_TO_WIFI代码块中添加信道设置:
#elif MODE == MODE_CONNECT_TO_WIFI WiFi.begin(routerSsid, routerPwd); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.print("."); } // 连接后强制设置WiFi信道为指定值 esp_wifi_set_channel(WIFI_CHANNEL, WIFI_SECOND_CHAN_NONE);
2. 修正ESP-NOW Peer的信道配置
添加Peer时,明确指定信道为WIFI_CHANNEL,而非默认的0:
esp_now_peer_info_t peer = {}; memcpy(peer.peer_addr, peer_addr, 6); peer.channel = WIFI_CHANNEL; // 替换原有的0 peer.encrypt = false; esp_now_add_peer(&peer);
3. 关闭ESP32 WiFi休眠模式
WiFi休眠可能导致ESP-NOW接收中断,在设置WiFi模式后添加休眠关闭代码:
WiFi.mode(WIFI_AP_STA); WiFi.setSleep(false); // 关闭WiFi休眠
4. 验证路由器实际信道与配置一致
通过路由器管理页面确认当前使用的信道,确保两端代码中WIFI_CHANNEL宏的值与路由器信道完全匹配,避免信道配置不一致导致通信失败。
内容的提问来源于stack exchange,提问作者mqnc




