0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

ESP32的ESP-NOW通讯踩坑记

机智云 2025-09-13 10:03 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

1、背景

前段时间看到乐鑫推出了一种很有意思的Wi-Fi通讯协议,它允许设备在连接的时候进行直接通讯

乐鑫对它的概述如下:

ESP-NOW是一种由乐鑫公司定义的无连接Wi-Fi通信协议。在ESP-NOW中,应用程序数据被封装在各个供应商的动作帧中,然后在无连接的情况下,从一个Wi-Fi设备传输到另一个 Wi-Fi 设备。

感觉很有意思,于是找了乐鑫IDF提供的demo进行验证。这里用到的demo在IDF的路径为:esp-idf/examples/wifi/espnow。

找来几个ESP32-C3模组,烧录完之后,确实在没有连接路由器的情况下可以进行直接通讯。

2、例程改造

通过运行demo:esp-idf/examples/wifi/espnow发现这个Demo有点不足的地方是没有连接路由器,那么我在想,有没有可能在既连接路由器的情况下,又可以直接与其他没有连接路由器的设备进行通讯呢?

那么我的想法如下图

e1fdfc06-9045-11f0-8ce9-92fbcf53809c.png

在上面这里,A设备既连接路由器也直接与B/C/D三个设备基于ESP_NOW进行直接通讯。

这里我让A设备工作在STA+AP模式下,其中STA用于连接路由,AP用于ESP_NOW进行通讯。基于此设想,我还专门问了deepSeek,它也给出了方案可行的确定回答;e218362a-9045-11f0-8ce9-92fbcf53809c.png

于是开开心心的写了代码,其中Wi-Fi和ESP_NOW的初始化程序如下,然后分别替换esp-idf/examples/wifi/espnow这里的初始化;

  • Wi-Fi的初始化如下

#defineESP_AP_CHANNEL 6// 固定使用信道6
staticvoidexample_wifi_init(void)
{
wifi_config_twifi_config = {
.sta = {
.ssid ="xLogMonitor",
.password ="1234567890",
},
};
// 配置AP模式参数 - 关键部分!
wifi_config_tap_config = {
.ap = {
.ssid ="", // 空SSID,不广播
.ssid_len =0,
.channel = ESP_AP_CHANNEL,// 这是我们真正关心的参数
.authmode = WIFI_AUTH_OPEN,
.max_connection =0, // 不允许任何站连接
},
};

ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_create_default_wifi_sta();
esp_netif_t*ap_netif = esp_netif_create_default_wifi_ap();
wifi_init_config_tcfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
ESP_EVENT_ANY_ID,
&event_handler,
NULL,
&instance_any_id));
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
IP_EVENT_STA_GOT_IP,
&event_handler,
NULL,
&instance_got_ip));
ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_APSTA) );
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &ap_config));
ESP_ERROR_CHECK( esp_wifi_start());
// ESP_ERROR_CHECK( esp_wifi_set_channel(CONFIG_ESPNOW_CHANNEL, WIFI_SECOND_CHAN_NONE));

#ifCONFIG_ESPNOW_ENABLE_LONG_RANGE
ESP_ERROR_CHECK( esp_wifi_set_protocol(ESPNOW_WIFI_IF, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N|WIFI_PROTOCOL_LR) );
#endif

}

  • ESP_NOW的初始化如下

staticesp_err_texample_espnow_init(void)
{
example_espnow_send_param_t*send_param;

s_example_espnow_queue = xQueueCreate(ESPNOW_QUEUE_SIZE,sizeof(example_espnow_event_t));
if(s_example_espnow_queue ==NULL) {
ESP_LOGE(TAG,"Create mutex fail");
returnESP_FAIL;
}

/* Initialize ESPNOW and register sending and receiving callback function. */
ESP_ERROR_CHECK( esp_now_init() );
ESP_ERROR_CHECK( esp_now_register_send_cb(example_espnow_send_cb) );
ESP_ERROR_CHECK( esp_now_register_recv_cb(example_espnow_recv_cb) );

/* Set primary master key. */
ESP_ERROR_CHECK( esp_now_set_pmk((uint8_t*)CONFIG_ESPNOW_PMK) );

/* Add broadcast peer information to peer list. */
esp_now_peer_info_t*peer =malloc(sizeof(esp_now_peer_info_t));
if(peer ==NULL) {
ESP_LOGE(TAG,"Malloc peer information fail");
vSemaphoreDelete(s_example_espnow_queue);
esp_now_deinit();
returnESP_FAIL;
}
memset(peer,0,sizeof(esp_now_peer_info_t));
peer->channel = ESP_AP_CHANNEL;
peer->ifidx = ESP_IF_WIFI_AP;
peer->encrypt =false;
memcpy(peer->peer_addr, s_example_broadcast_mac, ESP_NOW_ETH_ALEN);
ESP_ERROR_CHECK( esp_now_add_peer(peer) );
free(peer);

/* Initialize sending parameters. */
send_param =malloc(sizeof(example_espnow_send_param_t));
if(send_param ==NULL) {
ESP_LOGE(TAG,"Malloc send parameter fail");
vSemaphoreDelete(s_example_espnow_queue);
esp_now_deinit();
returnESP_FAIL;
}
memset(send_param,0,sizeof(example_espnow_send_param_t));
send_param->unicast =false;
send_param->broadcast =true;
send_param->state =0;
send_param->magic = esp_random();
send_param->count = CONFIG_ESPNOW_SEND_COUNT;
send_param->delay = CONFIG_ESPNOW_SEND_DELAY;
send_param->len = CONFIG_ESPNOW_SEND_LEN;
send_param->buffer =malloc(CONFIG_ESPNOW_SEND_LEN);
if(send_param->buffer ==NULL) {
ESP_LOGE(TAG,"Malloc send buffer fail");
free(send_param);
vSemaphoreDelete(s_example_espnow_queue);
esp_now_deinit();
returnESP_FAIL;
}
memcpy(send_param->dest_mac, s_example_broadcast_mac, ESP_NOW_ETH_ALEN);
example_espnow_data_prepare(send_param);

xTaskCreate(example_espnow_task,"example_espnow_task",2048, send_param,4,NULL);

returnESP_OK;
}

程序跑起来了,确实也是符合我的预期,A设备连接上了路由器,然后同时也和BCD进行了通讯,感觉一切都很完美,如果不出意外的话就好出意外了

3、问题出现了

在当我为改造例程的成功而高兴的时候,问题出现了。我换了一个路由器,发现通讯失败了。esp_send出现了如下错误:

E (12554) ESPNOW: Peer channel is not equal to the home channel, send fail!

这下懵逼了,为啥换个路由器就不行,难道这协议还和路由器有关系,乐鑫的官方文档也没提到呀~

乐鑫文档:https://docs.espressif.com/projects/esp-idf/zh_CN/v4.4.6/esp32c3/api-reference/network/esp_now.html?highlight=esp_now_init#

4、问题分析

从错误的日志上来看这个错误指的是Peer channel和home channel,不一致导致的。

这里Peer指的应该是要发送的对端通道,home应该指的是本身;

但是这两个地方我在配置的时候都是指定了#defineESP_AP_CHANNEL 6 // 固定使用信道6这个通道为啥还会出现这个错误呢?

后续我继续运行多几次,发现只有在A设备连接上网络之后才会出现这个错误。

难道是连接路由器之后A设备的信道发生了变化?经过查阅资料得知,确实是这样的,STA设备在连接路由器之后,设备的Wi-Fi信道是由路由器决定的,所以当路由器分配的信道和#defineESP_AP_CHANNEL 6不一致的时候就会出现问题了。

于是我在esp_now_send之前打印了设备当前的信道信息,获取到信息如下

I (12554) sta_ap_espnow: STA连接信息: SSID=xLogMonitor, 信道=8, RSSI=-61
I (12554) sta_ap_espnow: 当前工作信道: 8
E (12554) ESPNOW: Peer channel is not equal to the home channel, send fail!
E (12564) sta_ap_espnow: ESP-NOW数据发送失败: 0x3066

理论和实验结果一致,当设备连接之后信道变为了8

于是想要解决当前这个问题也很简单了,只需要把所有的ESP_NOW的设备改成和所要连接的路由器同个信道8即可。

结果证实了,当信道改为8之后所有设备通讯就正常了;

5、总结

虽然我们知道了问题,也解决了问题。但是乐鑫文档在描述这一块时也没着重,导致当时看文档也没特别留意。e2267b86-9045-11f0-8ce9-92fbcf53809c.png

ESP32-C3的STA+AP模式,在STA连接完路由器之后,AP模式指定的信道并不能作为ESP_NOW通讯;

如果设备需要连接路由器,需要提前知道连接的路由器信道再给其他设备指定一个统一的信道才能进行ESP_NOW进行通讯。这个在后续的产品落地确实是一个问题,需要看看如何优化

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 通讯
    +关注

    关注

    9

    文章

    940

    浏览量

    36353
  • ESP
    ESP
    +关注

    关注

    0

    文章

    194

    浏览量

    36085
  • ESP32
    +关注

    关注

    24

    文章

    1082

    浏览量

    20836
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    请问使用ESP-NOW通讯的时候如何获取对应的RSSI?

    我需要在使用ESP-NOW传输数据的同时,监控对应的RSSI,请问各位大佬,有对应的办法吗?
    发表于 06-07 07:38

    ESP32S2唤醒后无法收到另外一个机子发送的ESP-NOW的数据,为什么?

    软件版本IDF-4.4, 硬件ESP32S2 程序先初始化ESP-NOW, 启动定时light-sleep, 唤醒后无法收到另外一个机子发送的ESP-NOW的数据, 确定有唤醒,因为在唤醒后打印输出了
    发表于 06-21 08:01

    使用ESP32-C3的蓝牙进行传感器数据上传,ESP-NOW协议的功耗能满足需求吗?

    1.使用ESP32-C3的蓝牙进行传感器数据上传,期望使用纽扣电池供电,ESP-NOW协议的功耗能满足需求吗 2.使用ESP-now协议的设备能否和手机蓝牙或其他未使用ESP-NOW
    发表于 07-01 07:22

    ESP-NOW技术DIY

    ESP-NOW技术DIY
    发表于 07-20 07:08

    ESP-NOW唤醒无法接收数据是怎么回事?

    软件版本IDF-4.4, 硬件ESP32S2程序先初始化ESP-NOW,启动定时light-sleep, 唤醒后无法收到另外一个机子发送的ESP-NOW的数据,确定有唤醒,因为在唤醒后打印输出了
    发表于 02-20 07:37

    ESP32-S2的ESP-NOW的传输距离如何提高?

    1,ESP-NOW能否提供一个接口,错误的数据帧也传递给应用层,因为一个数据包里的数据比较多,不需要数据全部正确,这样可以提高传输距离2,ESP32-S2能不能提供一个GPIO定义RF的收发,因为我想在PCB上接一个RF-PA,现在的RF-PA都需要一个RX-TX的控制
    发表于 02-20 07:14

    如何使用ESP-Now协议连接ESP32ESP8266来控制LED?

    我构建了一个简单的项目,展示了如何使用 ESP-Now 协议连接 ESP32ESP8266 来控制 LED。
    发表于 05-22 08:34

    ESP-NOW技术的介绍和使用方式及示例代码资料免费下载

    本文介绍了乐鑫自主研发的ESP-NOW技术,说明了使用方式并提供了示例代码包括了:1.ESP-NOW技术简介,2.ESP-NOW使用方式,3.示例代码
    发表于 03-15 08:00 59次下载
    <b class='flag-5'>ESP-NOW</b>技术的介绍和使用方式及示例代码资料免费下载

    一款基于ESP32的对讲机传输音频介绍

    这是一款基于ESP32的对讲机。它使用UDP广播或ESP-NOW传输音频。
    的头像 发表于 04-29 09:04 2.9w次阅读
    一款基于<b class='flag-5'>ESP32</b>的对讲机传输音频介绍

    Arduino-IDE配置ESP32-CAM开发环境过的那些

    Arduino-IDE配置ESP32-CAM开发环境过的那些
    发表于 11-30 18:36 24次下载
    Arduino-IDE配置<b class='flag-5'>ESP32</b>-CAM开发环境<b class='flag-5'>踩</b>过的那些<b class='flag-5'>坑</b>

    ESP-32开发历程(三)ESP-IDF 定时器使用

    ESP-32开发历程(三)ESP-IDF 定时器使用前言一、开发基础二、定时器使用1.官方描述2.读入数据总结ESP-32开发
    发表于 12-08 12:06 13次下载
    <b class='flag-5'>ESP</b>-32开发<b class='flag-5'>踩</b><b class='flag-5'>坑</b>历程(三)<b class='flag-5'>ESP</b>-IDF 定时器使用

    ESP8266相互通讯ESP-NOW

    办法,可以用一个ESP8266模块作为一个总的控制,就像一个管家,来和其他ESP8266通讯,来实现我们想要的功能。先说一下ESP-NOW,它是Espressif开发的一种协议,它使多
    发表于 12-29 19:33 10次下载
    <b class='flag-5'>ESP</b>8266相互<b class='flag-5'>通讯</b>(<b class='flag-5'>ESP-NOW</b>)

    ESP32操纵杆手控制器ESP NOW开源

    电子发烧友网站提供《ESP32操纵杆手控制器ESP NOW开源.zip》资料免费下载
    发表于 08-15 14:51 22次下载
    <b class='flag-5'>ESP32</b>操纵杆手控制器<b class='flag-5'>ESP</b> <b class='flag-5'>NOW</b>开源

    ESP-NOW无线通信之ESP32学习之旅-Arduino版

    、WiFi、LoRa、NB-IoT等,本教程将重点介绍乐鑫科技开发的另一种无线通讯协议:ESP-NOW,通过 本教程的学习,你将了解到如何将 ESP-NOW 技术应用到我们的 DIY 项目中。
    发表于 05-30 09:55 0次下载
    <b class='flag-5'>ESP-NOW</b>无线通信之<b class='flag-5'>ESP32</b>学习之旅-Arduino版

    乐鑫低功耗方案 | ESP-NOW

    在日益发展的物联网世界中,无线通信已成为互联各种设备和系统的关键技术。在智能家居、工业自动化、医疗卫生、城市公共设施等领域,无线通信是解决这些问题的关键。在此方面,乐鑫推出了“ESP-NOW
    的头像 发表于 10-21 08:03 3553次阅读
    乐鑫低功耗方案 | <b class='flag-5'>ESP-NOW</b>