14浏览
查看: 14|回复: 4

[项目] 【Arduino 动手做】通过 ESP-NOW 实现 ESP32 到 ESP32 单工通信

[复制链接]
ESP-NOW 协议用于允许 ESP-32 控制器以单工模式进行通信。ESP-NOW是乐鑫(Espressif)开发的一种基于Wi-Fi的无线通信协议,具有以下核心特性和应用场景:

一、主要特点
无连接通信:设备无需建立传统Wi-Fi连接即可传输数据,设备配对后可直接进行点对点通信,无需握手协议,连接持续且稳定。
低延迟:端到端传输仅需3 - 10ms,协议精简,将五层OSI上层协议精简为一层,降低了延时,实现了快速响应。
高能效:相比传统Wi-Fi功耗降低80%以上,专为低功耗应用设计,适用于电池供电的设备。
安全加密:支持AES-128数据加密,基于CCMP(Counter Mode Cipher Block Chaining Message Authentication Code Protocol)加密方式保护通信安全,启用加密通信时,所有设备需共享一个主密钥(PMK),并为每个对等连接派生出一个本地主密钥(LMK),确保通信私密性。
灵活组网:支持单播、广播和组播模式,支持“一对多”和“多对多”的设备连接和控制,适用于大规模数据传输,如网络配置、固件升级和调试等场景。
兼容性好:能够与Wi-Fi和Bluetooth LE共存,支持乐鑫ESP8266、ESP32、ESP32-S和ESP32-C等多系列SoC,支持本地控制+远程控制,与路由器、热点共存。
远距离通信:可在视距500m稳定通信,部分设备射频功率最大能到20dBm(100mW),比几乎所有不带PA的2.4G模块都要强。
资源占用少:CPU、flash资源占用少,减轻了CPU和Flash负担,适合作为设备配置、调试和固件升级的辅助模块。
快速配对:支持快速且用户友好的设备配对,当某一设备突然断电之后,通电重启,会自动连接到对应节点中,实现快速通信。

二、应用场景
智能家居:如灯光/窗帘控制,可实现设备的快速响应和低功耗控制。
工业物联网:用于传感器数据采集,支持大规模设备连接和数据传输。
农业监测:构建温湿度传感器网络,实现远距离、低功耗的数据采集。
运动设备:如可穿戴设备数据同步,满足设备对低功耗和快速响应的需求。
安防系统:实现多节点报警联动,提高安防系统的响应速度和可靠性。
遥控领域:如遥控玩具小车、小飞机、机器人等,可达到毫秒级的控制延时,实现比蓝牙传输更远的控制距离。
低功耗设备:基于ESP32-C2的纽扣电池无线开关方案,无需网关就可以和ESP-NOW结合使用,反应速度灵敏,支持超长待机,且产品形态不会被电池体积限制。

三、工作原理
通信架构:基于IEEE 802.11的动作帧(Action Frame)机制,充分利用了WiFi的物理层,但绕过了繁重的网络层和传输层,直接在数据链路层上实现设备间的简单高效通信。在物理层,完全依赖WiFi的无线电技术来传输数据,使用2.4GHz频段(与标准WiFi相同),采用OFDM或DSSS调制方式,具体取决于设置的数据速率;在数据链路层,使用WiFi标准中的供应商特定动作帧(Vendor Specific Action Frame)进行通信。
数据帧结构:ESP-NOW的数据帧结构有其特定设计,ESP-NOW库已处理相关复杂细节,用户只需知道它允许ESP设备在不建立完整WiFi连接的情况下,直接基于MAC地址进行通信。
工作流程:
初始化Wi-Fi和ESP-NOW。
注册对端设备(Peer)。
设置发送/接收回调函数。
执行数据传输。
处理确认和重传。

四、代码实现示例
以下是一个简单的ESP-NOW通信示例代码框架:
发送端代码:包含头文件、定义接收端MAC地址、数据结构、回调函数声明,在初始化设置中进行串口初始化、WiFi模式设置、ESP-NOW初始化、注册发送回调函数、对端设备配置和添加等操作,在主循环中准备数据并发送。
接收端代码:包含头文件、定义与发送端完全一致的数据结构、接收回调函数,在初始化设置中进行串口初始化、WiFi模式设置、ESP-NOW初始化、注册接收回调函数等操作,主循环通常为空,数据通过回调处理。

【Arduino 动手做】通过 ESP-NOW 实现 ESP32 到 ESP32 单工通信图1

【Arduino 动手做】通过 ESP-NOW 实现 ESP32 到 ESP32 单工通信图2

【Arduino 动手做】通过 ESP-NOW 实现 ESP32 到 ESP32 单工通信图3

【Arduino 动手做】通过 ESP-NOW 实现 ESP32 到 ESP32 单工通信图4


驴友花雕  中级技神
 楼主|

发表于 昨天 18:05

【Arduino 动手做】通过 ESP-NOW 实现 ESP32 到 ESP32 单工通信

发射机代码

  1. //ESP-NOW: Transmitter
  2. //Ref: Random Nerd Tutorials https://randomnerdtutorials.com
  3. //-----------------------------------------------------------
  4. #include <esp_now.h>
  5. #include <WiFi.h>
  6. //-------------------------------------------------------------------------------------
  7. uint8_t RxMACaddress[] = {0x7C, 0x9E, 0xBD, 0xF5, 0xBE, 0x30};
  8. //-------------------------------------------------------------------------------------
  9. typedef struct TxStruct
  10. {
  11.   int potVal;
  12. }TxStruct;
  13. TxStruct sentData;
  14. //-------------------------------------------------------------------------------------
  15. void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) //callback function
  16. {
  17.   Serial.print("\r\nLast Packet Send Status:\t");
  18.   Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
  19. }
  20. //======================================================================================
  21. void setup()
  22. {
  23.   Serial.begin(9600);
  24.   WiFi.mode(WIFI_STA);
  25.   //------------------------------------------------------------------------------------
  26.   if(esp_now_init() != ESP_OK)
  27.   {
  28.     Serial.println("Error initializing ESP-NOW");
  29.     return;
  30.   }
  31.   //-------------------------------------------------------------------------------------
  32.   esp_now_register_send_cb(OnDataSent);
  33.   //-------------------------------------------------------------------------------------
  34.   esp_now_peer_info_t peerInfo;
  35.   memcpy(peerInfo.peer_addr, RxMACaddress, 6);
  36.   peerInfo.channel = 0;  
  37.   peerInfo.encrypt = false;
  38.   //-------------------------------------------------------------------------------------
  39.   if(esp_now_add_peer(&peerInfo) != ESP_OK)
  40.   {
  41.     Serial.println("Failed to add peer");
  42.     return;
  43.   }
  44. }
  45. //======================================================================================
  46. void loop()
  47. {
  48.   sentData.potVal = analogRead(A0);
  49.   //-------------------------------------------------------------------------------------
  50.   esp_err_t result = esp_now_send(RxMACaddress, (uint8_t *) &sentData, sizeof(sentData));
  51.   //-------------------------------------------------------------------------------------
  52.   if (result == ESP_OK) Serial.println("Sent with success");
  53.   else Serial.println("Error sending the data");
  54.   //-------------------------------------------------------------------------------------
  55.   delay(500);
  56. }
复制代码


回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 昨天 18:06

【Arduino 动手做】通过 ESP-NOW 实现 ESP32 到 ESP32 单工通信

接收机代码

  1. //-----------------------------------------------------------
  2. //ESP-NOW: Receiver
  3. //Ref: Random Nerd Tutorials https://randomnerdtutorials.com
  4. //-----------------------------------------------------------
  5. #include <esp_now.h>
  6. #include <WiFi.h>
  7. #include <Wire.h>
  8. #include <Adafruit_GFX.h>
  9. #include <Adafruit_SSD1306.h>
  10. //-------------------------------------------------------------------------------------
  11. Adafruit_SSD1306 display(128, 64, &Wire, -1);
  12. //-------------------------------------------------------------------------------------
  13. typedef struct RxStruct
  14. {
  15.   int potVal;
  16. }RxStruct;
  17. RxStruct receivedData;
  18. //-------------------------------------------------------------------------------------
  19. void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len)
  20. {
  21.   memcpy(&receivedData, incomingData, sizeof(receivedData));
  22. }
  23. //======================================================================================
  24. void setup()
  25. {
  26.   Serial.begin(9600);
  27.   if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C))
  28.   {
  29.     Serial.println(F("SSD1306 allocation failed"));
  30.     for (;;); // Don't proceed, loop forever
  31.   }
  32.   display.clearDisplay();
  33.   //-------------------------------------------------------------------------------------
  34.   WiFi.mode(WIFI_STA);
  35.   if (esp_now_init() != ESP_OK)
  36.   {
  37.     Serial.println("Error initializing ESP-NOW");
  38.     return;
  39.   }
  40.   esp_now_register_recv_cb(OnDataRecv);
  41. }
  42. //======================================================================================
  43. void loop()
  44. {
  45.   display.setTextColor(WHITE); display.clearDisplay();
  46.   display.setTextSize(2); display.setCursor(20,0); display.print("ESP-NOW");
  47.   display.setCursor(10,18); display.print("POT Value");
  48.   display.setTextSize(3); display.setCursor(25,42); display.print(receivedData.potVal);
  49.   display.display();
  50. }
复制代码


回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 昨天 18:08

【Arduino 动手做】通过 ESP-NOW 实现 ESP32 到 ESP32 单工通信

【Arduino 动手做】通过 ESP-NOW 实现 ESP32 到 ESP32 单工通信
项目链接:https://akuzechie.blogspot.com/2 ... on-via-esp-now.html
项目作者:Anas Kuzechie

项目视频 :https://www.youtube.com/watch?v=GzugxHEzB0g
项目代码:https://akuzechie.blogspot.com/2 ... on-via-esp-now.html

【Arduino 动手做】通过 ESP-NOW 实现 ESP32 到 ESP32 单工通信图1

回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 昨天 18:12

【Arduino 动手做】通过 ESP-NOW 实现 ESP32 到 ESP32 单工通信

【Arduino 动手做】通过 ESP-NOW 实现 ESP32 到 ESP32 单工通信图1

【Arduino 动手做】通过 ESP-NOW 实现 ESP32 到 ESP32 单工通信图2
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4 备案 沪公网安备31011502402448

© 2013-2025 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail