Arduino for ESP-NOW介绍及使用

本文详细介绍了ESP-NOW协议,包括其特性、局限性,以及如何在Arduino环境下进行单向、双向及一对多通信的实践。通过示例程序展示了如何设置MAC地址,实现不同场景下的数据传输。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

ESP-NOW介绍

ESP-NOW支持以下特性

ESP-NOW技术也存在以下局限性

Espnow库函数注释​​​​​​​

获取ESP32的MAC地址

修改MAC地址

ESP-NOW单向通信(One-way communication)

 发送端的程序

 接收端的程序

 ESP32单板间的双向通信

 一对多通信(一发多收)

 发送端的程序:

 接收端的程序

 一对多通信(多发一收)

 发送端的程序

接收端的程序:


ESP-NOW介绍


ESP-NOW是一种由Espressif开发的协议,可以让多个设备在不使用Wi-Fi的情况下相互通信。该协议类似于低功耗的2.4GHz无线连接。设备之间的配对需要在通信之前完成。配对完成后,连接是安全的、点对点的,不需要握手。这意味着在设备彼此配对后,连接是持久的。换句话说,如果你的某块单板突然失去电源或复位,当它重启时,它将自动连接到它的频道继续通信

ESP-NOW支持以下特性

  1. 混合加密和未加密的对端设备
  2. 加密和不加密的单播通信
  3. 最多可携带250字节的有效载荷(小数据传输);
  4. 发送回调函数,可以设置为通知应用层传输成功或失败;

ESP-NOW技术也存在以下局限性

  1. 有限的加密。Station模式最多支持10个加密对等体;“软拨号”或“软拨号+工作站”模式最多为6个
  2. 支持多个未加密的对等体,包括加密的对等体,总数不能超过20个
  3. 最大消息长度限制在250字节

Espnow库函数注释


#ifndef __ESPNOW_H__
#define __ESPNOW_H__
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
enum esp_now_role {
    ESP_NOW_ROLE_IDLE = 0,//未设置角色,不允许发送数据
    ESP_NOW_ROLE_CONTROLLER,//控制方
    ESP_NOW_ROLE_SLAVE,//被控制方
    ESP_NOW_ROLE_COMBO,//控制方&被控制方双角色,双向通信时就用它
    ESP_NOW_ROLE_MAX,//不懂
};
 
//回调函数
typedef void (*esp_now_recv_cb_t)(u8 *mac_addr, u8 *data, u8 len);
typedef void (*esp_now_send_cb_t)(u8 *mac_addr, u8 status);
 
int esp_now_init(void);//初始化esp_now
int esp_now_deinit(void);//取消esp_now的初始化
 
int esp_now_register_send_cb(esp_now_send_cb_t cb);//使用该函数之后,接收到数据会自动调用接收回调函数,回调函数的写法可以参考我上面的代码
int esp_now_unregister_send_cb(void);//与上面的函数作用相反
 
int esp_now_register_recv_cb(esp_now_recv_cb_t cb);//使用该函数之后,发送数据后会自动调用发送回调函数,回调函数的写法可以参考我上面的代码
int esp_now_unregister_recv_cb(void);//与上面的函数作用相反
 
int esp_now_send(u8 *da, u8 *data, int len);//发送数据,MAC地址中传入NULL会广播
 
int esp_now_add_peer(u8 *mac_addr, u8 role, u8 channel, u8 *key, u8 key_len);//与新设备配对
int esp_now_del_peer(u8 *mac_addr);//将已配对的设备删除
 
int esp_now_set_self_role(u8 role);//设定设备自己的角色
int esp_now_get_self_role(void);//获取设备自己的角色
 
int esp_now_set_peer_role(u8 *mac_addr, u8 role);//设定某个已配对设备的角色
int esp_now_get_peer_role(u8 *mac_addr);//获取某个已配对设备的角色
 
int esp_now_set_peer_channel(u8 *mac_addr, u8 channel);//设定某个已配对设备的WiFi通道
int esp_now_get_peer_channel(u8 *mac_addr);//获取某个已配对设备的WiFi通道
 
int esp_now_set_peer_key(u8 *mac_addr, u8 *key, u8 key_len);//设定某个已配对设备的密钥
int esp_now_get_peer_key(u8 *mac_addr, u8 *key, u8 *key_len);//获取某个已配对设备的密钥
 
u8 *esp_now_fetch_peer(bool restart);//不懂
 
int esp_now_is_peer_exist(u8 *mac_addr);//检查已经配对的设备是否在线
 
int esp_now_get_cnt_info(u8 *all_cnt, u8 *encrypt_cnt);//不懂
 
int esp_now_set_kok(u8 *key, u8 len);//对通信的key进行加密,不设置时使用默认的PMK
 
#ifdef __cplusplus
}
#endif
 
#endif

获取ESP32的MAC地址

在使用ESP-NOW协议前需要知道ESP32 的MAC地址

#include "WiFi.h"
 
void setup(){
  Serial.begin(115200);
  WiFi.mode(WIFI_MODE_STA);
  Serial.println(WiFi.macAddress());
}
 
void loop(){

}

上串口打开串口监视器,可以得到板子的MAC地址,例如

 最好拿个小纸条记下来

修改MAC地址

#include <ESP8266WiFi.h>

// Set your new MAC Address
uint8_t newMACAddress[] = {0x00, 0x08, 0x22, 0xa0, 0xa1, 0x34};

void setup(){
  Serial.begin(9600);
  Serial.println();
  
  WiFi.mode(WIFI_STA);
  WiFi.softAP("SD", "sd168888");
  
  Serial.print("[OLD] ESP8266 Board MAC Address:  ");
  Serial.println(WiFi.macAddress());

  // For Soft Access Point (AP) Mode
  //wifi_set_macaddr(SOFTAP_IF, &newMACAddress[0]);
  // For Station Mode
  wifi_set_macaddr(STATION_IF, &newMACAddress[0]);
  
  Serial.print("[NEW] ESP8266 Board MAC Address:  ");
  Serial.println(WiFi.macAddress());
}
 
void loop(){

}

ESP-NOW单向通信(One-way communication)

一个ESP32作为发送方,另一个ESP32作为接收方

 发送端的程序

#include <esp_now.h>
#include &l
### 关于ESP-NOW.h库的使用 #### 1. 安装ESP32开发板支持 为了在Arduino IDE中使用`ESP-NOW.h`库,首先需要确保已正确安装ESP32开发板的支持。按照提供的资料[^1],打开Arduino IDE并进入工具菜单下的“Board Manager”。在此处搜索关键词“ESP32”,找到由乐鑫官方发布的ESP32开发板包,并完成安装。 #### 2. 配置ESP-NOW功能 ESP-NOW是一种低功耗、快速响应的数据传输协议,适用于短距离无线通信场景。其核心在于通过Wi-Fi芯片实现设备间数据交换而不依赖传统网络连接。要启用此功能,在代码初始化阶段需调用如下函数: ```cpp #include <WiFi.h> #include <esp_now.h> // 初始化ESP-NOW void setup() { Serial.begin(115200); WiFi.mode(WIFI_STA); // 设置模式为STA if (esp_now_init() != ESP_OK) { Serial.println("Error initializing ESP-NOW"); return; } } ``` 上述代码片段展示了如何启动ESP-NOW模块。如果初始化失败,则会打印错误消息至串口监视器[^2]。 #### 3. 数据发送与接收机制 利用ESP-NOW可以轻松构建点对点(Peer-to-Peer)或者一对多(Master-Slave)架构的应用程序。下面分别描述两种主要操作——发送和接收数据的方法。 ##### 发送端设置 定义目标MAC地址用于指定接收方的身份标识符。随后注册回调函数处理状态更新事件。 ```cpp uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; bool sendStatus; // 注册发送成功/失败后的回调方法 esp_now_register_send_cb(onSend); // 构建结构体存储待传信息 struct __attribute__((packed)) myDataStruct{ int value; }; myDataStruct dataToSend; dataToSend.value = 42; sendStatus = esp_now_send(broadcastAddress, (uint8_t *) &dataToSend, sizeof(dataToSend)); if(sendStatus){ Serial.println("Message sent successfully"); } else { Serial.println("Failed to send message"); } void onSend(const uint8_t *mac_addr, esp_now_send_status_t status) { Serial.print("\r\nLast Packet Send Status:\t"); Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail"); } ``` 此处需要注意的是,当广播地址设为全FF时表示向所有监听该信道的节点散发消息;反之则仅针对特定单一装置通讯[^3]。 ##### 接收端配置 同样也需要设定相应的回调逻辑以便及时捕获到来的信息流。 ```cpp struct __attribute__((packed)) receivedDataStruct{ int value; }; receivedDataStruct incomingData; void onDataReceived(const uint8_t * mac, const uint8_t *incomingData, int len) { memcpy(&incomingData, incomingData, sizeof(incomingData)); Serial.printf("Bytes received: %d", len); Serial.printf(", Value: %d\r\n", incomingData.value); } esp_now_register_recv_cb(onDataReceived); ``` 以上部分实现了基础框架下简单的数值传递演示案例。实际项目里可根据需求扩展更复杂的消息格式设计以及增强型差错校验算法等附加特性。 --- ###
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值