ESP32 入门笔记07: ESP-NOW (ESP32 for Arduino)

news2024/11/27 8:38:21

【B站乐鑫】 ESP-NOW 无线通信方案


简介

ESP-NOW 是一种快速、无连接的通信技术,具有短数据包传输的特点。

ESP-NOW 是乐鑫开发的一种“协议”,它使多个设备无需使用 Wi-Fi 即可相互通信。该协议类似于低功耗 2.4GHz 无线连接 。在通信之前需要设备之间的配对。配对完成后,连接是安全的点对点连接,不需要握手

这意味着在设备彼此配对后,连接是持久的。换句话说,如果你的一块板突然断电或复位,当它重新启动时,它会自动连接到它的对端以继续通信。

ESP-NOW 是智能灯、遥控设备、传感器和其他应用的理想选择。

ESP-NOW 支持以下功能:

  • 加密和未加密的单播通信;
  • 混合加密和未加密的对等设备;
  • 最多可携带250字节的有效载荷
  • 发送回调函数,可设置通知应用层发送成功或失败。

ESP-NOW 技术也有以下限制:

  • 有限的加密对等体。Station 模式最多支持10个加密节点;SoftAP 或SoftAP+Station 模式下最多 6 个;
  • 支持多个未加密的 peer,但包括加密的 peer 在内,总数应小于20;
  • 有效负载限制为 250 字节。

简单来说,ESP-NOW 是一种快速通信协议,可用于在 ESP32 开发板之间交换小消息(最多 250 字节)。


ESP-NOW 通信方式

1. ESP-NOW 单向通信

一块 ESP32 板向另一块 ESP32 板发送数据

这种配置非常容易实现,并且非常适合将数据从一块板发送到另一块板,例如传感器读数或打开和关闭命令以控制 GPIO。

在这里插入图片描述

一个ESP32“主设备” 向多个 ESP32“从设备”发送数据

一块 ESP32 开发板向不同的 ESP32 开发板发送相同或不同的命令。此配置非常适合构建类似遥控器的东西。可以在房子周围安装多个 ESP32 板,这些板由一个主 ESP32 板控制。

在这里插入图片描述

注意:在 ESP-NOW 文档中没有sender/masterreceiver/slave这样的东西。每个板都可以是发送者或接收者。但是,为了清楚起见,我们将使用术语“发送方”和“接收方”或“主控方”和“从属方”。


2. ESP-NOW 双向通信

使用 ESP-NOW,每个板可以同时作为发送器和接收器。因此,可以在板之间建立双向通信。

例如,可以让两个板相互通信。

在这里插入图片描述

可以在此配置中添加更多电路板,并拥有一个看起来像网络的东西(所有 ESP32 电路板都相互通信)。

在这里插入图片描述


ESP32获取开发板 MAC 地址

要通过 ESP-NOW 进行通信,您需要知道ESP32 接收器的 MAC 地址。这就是您知道要将数据发送到哪个设备的方式。

什么是 MAC 地址?

MAC地址代表媒体访问控制地址,它是识别网络上每个设备的硬件唯一标识符。

MAC 地址由六组 两位 十六进制数字组成,以冒号分隔,例如:30:AE:A4:07:0D:64

MAC 地址由制造商分配,但您也可以为开发板提供自定义 MAC 地址。但是,每次板子重置时,它都会返回到其原始 MAC 地址。因此,您需要在每个草图中包含设置自定义 MAC 地址的代码。

每个 ESP32 都有一个唯一的 MAC 地址,这就是我们识别每个开发板以使用 ESP-NOW 向其发送数据的方式(了解如何获取和更改 ESP32 MAC 地址)。

获取开发板的 MAC 地址

要获取开发板的 MAC 地址,请上传以下代码。

#ifdef ESP32
  #include <WiFi.h>
#else
  #include <ESP8266WiFi.h>
#endif

void setup(){
  Serial.begin(115200);
  Serial.println();
  Serial.print("ESP Board MAC Address:  ");
  Serial.println(WiFi.macAddress());
}
 
void loop(){

}

重置自定义 MAC 地址

在某些应用程序中,为您的开发板提供自定义 MAC 地址可能很有用。但是,如前所述,这不会覆盖制造商设置的 MAC 地址。因此,每次您重置电路板或上传新代码时,它都会恢复为默认 MAC 地址。

#include <WiFi.h>
#include <esp_wifi.h>

// 设置你自定义的 MAC 地址
uint8_t newMACAddress[] = {0x32, 0xAE, 0xA4, 0x07, 0x0D, 0x66};

void setup(){
  Serial.begin(115200);
  Serial.println();
  
  WiFi.mode(WIFI_STA);
  
  Serial.print("[OLD] ESP32 Board MAC Address:  ");
  Serial.println(WiFi.macAddress());
  
  // ESP32 Board add-on before version < 1.0.5
  //esp_wifi_set_mac(ESP_IF_WIFI_STA, &newMACAddress[0]);
  
  // ESP32 Board add-on after version > 1.0.5
  esp_wifi_set_mac(WIFI_IF_STA, &newMACAddress[0]);
  
  Serial.print("[NEW] ESP32 Board MAC Address:  ");
  Serial.println(WiFi.macAddress());
}
 
void loop(){

}

上传代码后,以 115200 的波特率打开串口监视器。重新启动 ESP32,你应该得到它的旧 MAC 地址和新 MAC 地址。

在这里插入图片描述

实验:ESP-NOW 单向/点对点通信

构建一个简单的项目,展示如何将消息从一个 ESP32 发送到另一个。

  • sender :一个 ESP32 将成为“发送端”;

  • receiver: 另一个 ESP32 将成为“接收端”。

在这里插入图片描述

发送一个结构,其中包含类型为char、int、float和boolean的变量。然后,您可以修改结构以发送适合您的项目的任何变量类型(例如传感器读数,或用于打开或关闭某些东西的布尔变量)。

为了更好地理解,我们将 ESP32 #1 称为“发送方”,将 ESP32 #2 称为“接收方”。

发送端 程序中包含的内容:

  • 初始化 ESP-NOW;
  • 发送数据时注册一个回调函数——数据发送发送消息时将执行函数。这可以告诉我们消息是否成功传递;
  • 添加对等设备(接收器)。为此,您需要知道接收方的 MAC 地址;
  • 向对等设备发送消息。

接收端 程序中包括:

  • 初始化 ESP-NOW;
  • 注册接收回调函数(数据接收). 这是一个将在收到消息时执行的函数。
  • 在该回调函数中,将消息保存到变量中以使用该信息执行任何任务。

ESP-NOW 与设备接收消息或发送消息时调用的回调函数一起使用(您会收到消息是成功传递还是失败)。

ESP-NOW 函数功能

函数名称描述
esp_now_init()初始化 ESP-NOW。在初始化 ESP-NOW 之前,您必须先初始化 Wi-Fi。
esp_now_add_peer()调用此函数以配对设备并将peer MAC 地址作为参数传递。
esp_now_send()使用 ESP-NOW 发送数据
esp_now_register_send_cb()注册发送数据时触发的回调函数。发送消息时,将调用一个函数——此函数返回传递是否成功。
esp_now_register_rcv_cb()注册接收数据时触发的回调函数。当通过 ESP-NOW 接收到数据时,将调用一个函数。

有关这些功能的更多信息,请阅读ESP-IDF 编程指南中的 ESP-NOW 文档。

ESP32 发送器

// Sender发送端
#include <esp_now.h>
#include <WiFi.h>

//  ESP32 接收器 MAC 地址
uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; //将该变量替换为您自己的 MAC 地址。

// 创建一个包含我们要发送的数据类型的结构体
typedef struct struct_message {
  char a[32];
  int b;
  float c;
  bool d;
} struct_message;

// 创建struct_message结构体类型的变量存储数据
struct_message myData;
// 创建esp_now_peer_info_t类型变量存储有关peer方的信息。
esp_now_peer_info_t peerInfo;

// 数据发送回调函数-此函数仅打印消息是否成功发送
void OnDataSent(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");
}
 
void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA); // 设置为WiFi站点

  // 初始化 ESP-NOW
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }

  // 注册发送消息时调用的回调函数 OnDataSent
  esp_now_register_send_cb(OnDataSent);
  
  // Register peer
  memcpy(peerInfo.peer_addr, broadcastAddress, 6);
  peerInfo.channel = 0;  
  peerInfo.encrypt = false;
  
  // Add peer        
  if (esp_now_add_peer(&peerInfo) != ESP_OK){
    Serial.println("Failed to add peer");
    return;
  }
}
 
void loop() {
  // Set values to send
  strcpy(myData.a, "THIS IS A CHAR");
  myData.b = random(1,20);
  myData.c = 1.2;
  myData.d = false;
  
  // Send message via ESP-NOW
  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
   
  if (result == ESP_OK) {
    Serial.println("Sent with success");
  }
  else {
    Serial.println("Error sending the data");
  }
  delay(2000);
}

ESP32 接收器

// Receiver接收端

#include <esp_now.h>
#include <WiFi.h>

// 创建一个结构体接收数据
typedef struct struct_message {
    char a[32];
    int b;
    float c;
    bool d;
} struct_message;

// 
struct_message myData;

// 创建一个回调函数,当 ESP32 通过 ESP-NOW 接收到数据时将被调用
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
  memcpy(&myData, incomingData, sizeof(myData));
  Serial.print("Bytes received: ");
  Serial.println(len);
  Serial.print("Char: ");
  Serial.println(myData.a);
  Serial.print("Int: ");
  Serial.println(myData.b);
  Serial.print("Float: ");
  Serial.println(myData.c);
  Serial.print("Bool: ");
  Serial.println(myData.d);
  Serial.println();
}
 
void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);// 将设备设置为 Wi-Fi Station

  // 初始化 ESP-NOW
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }
  
  // 注册在接收到数据时调用的回调函数 OnDataRecv
  esp_now_register_recv_cb(OnDataRecv);
}
 
void loop() {

}

还有更多与 ESP-NOW 相关的功能可以使用。

例如:管理peers、删除peers、扫描从属设备等……在 Arduino IDE 中转到文件>示例> ESP32 > ESPNow 并选择其中一个示例查看完整示例。


参考资料

  • [1] 【RNT】Getting Started with ESP-NOW (ESP32 with Arduino IDE)
  • [2] 【ESPRESS】ESP-NOW(用户指南) | 【ESPRESS】ESP-NOW编程指南
  • [3] 【RNT】ESP32 开发板之间的 ESP-NOW 双向通信
  • [4] 【RNT】带有 ESP32 的 ESP-NOW:将数据发送到多个板(一对多)
  • [5] 【RNT】带有 ESP32 的 ESP-NOW:从多个板接收数据(多对一)
  • [6] 【RNT】ESP32:ESP-NOW Web 服务器传感器仪表板(ESP-NOW + Wi-Fi)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/27187.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

什么是数字孪生?数字孪生技术有没有真正的实用价值?

可以很确定地说&#xff0c;数字孪生技术为我们的生活与工作都提供了巨大的价值。过去几年&#xff0c;在经历了”三起三落”之后&#xff0c;数字孪生再次成为资本和舆论关注的焦点。“数字孪生就像是给你了一个水晶球&#xff0c;能够根据过去和当下发生的事情来预测并模拟未…

HDMI接口类型种类区分图(高清图)

HDMI接口类型这么多种啊&#xff0c;主要有A、B、C、D、E五种类型。 1、A类&#xff08;Type A&#xff09; HDMI A Type是使用最广泛的HDMI线缆&#xff0c;HDMI A接口共有19pin&#xff0c;宽度为13.9毫米&#xff0c;厚度为4.45毫米。 2、B类&#xff08;Type B&#xff…

【SpringCloud】04 网关springcloud gateway

网关springcloud gateway 上面的架构&#xff0c;会存在着诸多的问题&#xff1a; 客户端多次请求不同的微服务&#xff0c;增加客户端代码或配置编写的复杂性 认证复杂&#xff0c;每个服务都需要独立认证。 存在跨域请求&#xff0c;在一定场景下处理相对复杂。 网关可以做…

【QT】编译QtWebEngine(Build QtWebEngine from source)Win10+QT5.7.1_x64+VS2015

1、前言 关于QtWebEngine是干什么的&#xff0c;怎么用的&#xff0c;不在此赘述。 1.1、为什么要编译QtWebEngine QT默认的QtWebEngine是不支持mp3、mp4解码的&#xff0c;也就是说&#xff0c;如果想要在QT浏览网页的时候支持在线播放音视频&#xff0c;就需要让QtWebEngi…

前端品优购项目准备工作

网站制作流程&#xff1a; 初稿审核&#xff1a;网页美工会制作原型图和psd效果图 品优购项目规划&#xff1a; 1 品优购项目整体介绍 描述&#xff1a;电商网站&#xff0c;要完成PC端首页&#xff0c;列表页&#xff0c;注册页面的制作 2 品优购项目学习目的 电商类网站比…

nRF Connect for Desktop[自己的APP环境搭建]

本文源码仓库地址:https://github.com/NordicSemiconductor/pc-nrfconnect-ble/blob/main/package.json nRF Connect for Desktop是nordic自己做的一个PC端的蓝牙工具,配合nordic的dongle可以实现蓝牙的很多功能,要浏览本文要有如下知识储备: 1.nRF Connect for Desktop的APP是…

ELFK集群部署与Logstash的过滤模块

ELFK集群部署与Logstash的过滤模块ELFK集群部署与Logstash的过滤模块一、ELFK集群部署&#xff08;FilebeatELK&#xff09;Filebeatfilebeat 结合 logstash 带来好处&#xff1a;1.1 部署ELK集群1.2 安装Filebeat&#xff08;Apache节点&#xff09;1.3 设置 filebeat 的主配置…

TimeSformer:Is Space-Time attention all you need for video understanding?

【实践】CV领域的Transformer模型TimeSformer实现视频理解 - 飞桨AI Studio本项目选取CV中的transformer模型TimeSformer进行项目开发&#xff0c;在UCF101数据集上训练、验证、评估 - 飞桨AI Studiohttps://aistudio.baidu.com/aistudio/projectdetail/3413254?contributionT…

Zookeeper系列文章-Curator

之前我们讲解了Zookeeper安装与Zookeeper常用命令讲解 linux安装Zookeeper3.5.7详解_兜兜转转m的博客-CSDN博客 Zookeeper系列文章—入门_兜兜转转m的博客-CSDN博客 由于我们需要利用Java进行开发&#xff0c;因此我们使用Curator对Zk进行操控 导入依赖&#xff0c;由于使用…

作业-11.22

1、TCP服务器和客户端交互 服务器 #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <string.h> #include <unistd.h> #define ERR_MSG(msg) do{\ …

Java基础—反射

反射 我们来探讨Java中的一些动态特性&#xff0c;包括反射、注解、动态代理、类加载器等。利用这些特性&#xff0c;可以优雅地实现一些灵活通用的功能&#xff0c;它们经常用于各种框架、库和系统程序中&#xff0c;比如&#xff1a; 1&#xff09;14.5节介绍的Jackson&…

MAC苹果电脑关闭系统完整性保护SIP

苹果电脑从 macOS 10.11 开始引入了系统完整性保护机制SIP&#xff08;System Integrity Protection&#xff09;&#xff0c;目的是帮助普通用户避免恶意 app 通过用户授权的方式获得所有系统权限。通过 System Integrity Protection&#xff0c;苹果实现了对第三方软件的限制…

SpringBoot SpringBoot 开发实用篇 5 整合第三方技术 5.14 SpringBoot 整合 quartz

SpringBoot 【黑马程序员SpringBoot2全套视频教程&#xff0c;springboot零基础到项目实战&#xff08;spring boot2完整版&#xff09;】 SpringBoot 开发实用篇 文章目录SpringBootSpringBoot 开发实用篇5 整合第三方技术5.14 SpringBoot 整合 quartz5.14.1 任务【定时任务…

Linux-cut

cut命令介绍 cut命令将文件的每一行剪切字节&#xff0c;字符和字段&#xff0c;并将这些字节&#xff0c;字符和字段写到标准输出 提取列&#xff0c;cut命令不能提取空格&#xff0c;可以是制表符或者其他字符 cut [选项][文件] 选项&#xff1a; -b&#xff1a;以字节为单…

2.5、信道的极限容量!

2.5、信道的极限容量&#xff01; 2.5.1、因素影响 由于信号在传输过程中会受到各种因素的影响 例如&#xff1a;这是一个数字信号 当它通过实际的信道后&#xff0c;波形会产生失真。 失真不严重时&#xff0c;在输出端还可根据已失真的波形还原出发送的码元 当失真严重…

G1D20-AnacondaCSKE综述AttacKG终于配好环境啦KG book CTF

先下一个anaconda emmmpipenv install requirements.txt好像不太好用&#xff0c;还不如pycharm中的自动安装 先读论文啦~ 一、CS KE综述 &#xff08;一&#xff09;NER systems 1、判别式模型&生成式模型 判别式模型&#xff1a;学习P&#xff08;Y|X&#xff09;&am…

C语言-结构体(7)

目录 思维导图&#xff1a; 1. 结构体的声明 1.1 结构的基础知识 1.2 结构的声明 1.3 结构成员的类型 1.4 结构体变量的定义和初始化 2. 结构体成员的访问 3. 结构体传参 写在最后&#xff1a; 思维导图&#xff1a; 1. 结构体的声明 1.1 结构的基础知识 结构是一些…

python一键去PDF水印,只需十行代码,超级简单...

用python制作去除 pdf 文件水印脚本前因后果去除水印原理代码剖析1、先查看PDF文档中的水印rgb值是多少2、pdf转换成图片&#xff0c;并去除水印3、图片转为pdf代码整合总结前因后果 弟弟最近要考试&#xff0c;临时抱佛脚在网上找了一堆学习资料复习&#xff0c;这不刚就来找…

机器学习-sklearn-高斯混合模型-学习笔记

文章目录前言一、如何估计参数二、二分类原生代码实现三、sklearn实现模型总结前言 学习笔记 学习视频&#xff1a;https://www.bilibili.com/video/BV1rB4y1v7dA/?spm_id_from333.788&vd_sourceaf83080eba7b379d3fda36e341bdb195 使用高斯混合模型的原因&#xff1a; 模…

03137计算机网络原 - 物理层

物理层 基础概念 OSI模型最底层 功能 为在链路实体间传送比特流而对物理连接的 接通 维持 和 拆除 提供机械,电气,功能和规程方面的方法作用 尽可能屏蔽现有多种多样的硬件设备,传输媒体和通信手段的差异。确保原始数据可以在各种物理媒介上传输任务特性 机械特性 指明接…