ESP32/ESP8266开发板单向一对多ESP-NOW无线通信
ESP32/ESP8266开发板单向一对多ESP-NOW无线通信
- 简介
- 读取ESP32/ESP8266接收方Receiver的MAC地址
- ESP32/ESP8266发送方Sender程序
- ESP32/ESP8266接收方Receiver程序
- ESP-NOW通信验证
- 总结
简介
本实验通过ESP-NOW无线通信协议实现多个ESP32/ESP 8266开发板向ESP32开发板发送数据。例如可以应用于从多个远程传感器上收集数据。

读取ESP32/ESP8266接收方Receiver的MAC地址
读取ESP32开发板的代码
#ifdef ESP32#include <WiFi.h>#include <esp_wifi.h>
#else#include <ESP8266WiFi.h>
#endifvoid setup(){Serial.begin(115200);Serial.print("ESP Board MAC Address: ");#ifdef ESP32WiFi.mode(WIFI_STA);WiFi.STA.begin();uint8_t baseMac[6];esp_err_t ret = esp_wifi_get_mac(WIFI_IF_STA, baseMac);if (ret == ESP_OK) {Serial.printf("%02x:%02x:%02x:%02x:%02x:%02x\n",baseMac[0], baseMac[1], baseMac[2],baseMac[3], baseMac[4], baseMac[5]);} else {Serial.println("Failed to read MAC address");}#elseSerial.println(WiFi.macAddress());#endif
}void loop(){}
通过串口打印读取到接收方ESP32开发板1的MAC地址为:54:43:b2:7f:00:60

ESP32/ESP8266发送方Sender程序
把读取到的接收方的MAC地址填入到uint8_t broadcastAddress[]数组中,并修改结构体的中myData.id的值,ESP32开发板1程序中填入myData.id = 1,ESP32开发板2程序中填入myData.id = 2,ESP32开发板3程序中填入myData.id = 3,接收方以此来分辨是哪一个ESP32开发板发过来的数据。
#include <esp_now.h>
#include <WiFi.h>// REPLACE WITH THE RECEIVER'S MAC Address
uint8_t broadcastAddress[] = {0x54, 0x43, 0xb2, 0x7f, 0x00, 0x60};// Structure example to send data
// Must match the receiver structure
typedef struct struct_message {int id; // must be unique for each sender boardint x;int y;
} struct_message;// Create a struct_message called myData
struct_message myData;// Create peer interface
esp_now_peer_info_t peerInfo;// callback when data is sent
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() {// Init Serial MonitorSerial.begin(115200);// Set device as a Wi-Fi StationWiFi.mode(WIFI_STA);// Init ESP-NOWif (esp_now_init() != ESP_OK) {Serial.println("Error initializing ESP-NOW");return;}// Once ESPNow is successfully Init, we will register for Send CB to// get the status of Trasnmitted packetesp_now_register_send_cb(OnDataSent);// Register peermemcpy(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 sendmyData.id = 1;myData.x = random(0,50);myData.y = random(0,50);// Send message via ESP-NOWesp_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(10000);
}
ESP32/ESP8266接收方Receiver程序
#include <esp_now.h>
#include <WiFi.h>// Structure example to receive data
// Must match the sender structure
typedef struct struct_message {int id;int x;int y;
}struct_message;// Create a struct_message called myData
struct_message myData;// Create a structure to hold the readings from each board
struct_message board1;
struct_message board2;
struct_message board3;// Create an array with all the structures
struct_message boardsStruct[3] = {board1, board2, board3};// callback function that will be executed when data is received
void OnDataRecv(const uint8_t * mac_addr, const uint8_t *incomingData, int len) {char macStr[18];Serial.print("Packet received from: ");snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);Serial.println(macStr);memcpy(&myData, incomingData, sizeof(myData));Serial.printf("Board ID %u: %u bytes\n", myData.id, len);// Update the structures with the new incoming databoardsStruct[myData.id-1].x = myData.x;boardsStruct[myData.id-1].y = myData.y;Serial.printf("x value: %d \n", boardsStruct[myData.id-1].x);Serial.printf("y value: %d \n", boardsStruct[myData.id-1].y);Serial.println();
}void setup() {//Initialize Serial MonitorSerial.begin(115200);//Set device as a Wi-Fi StationWiFi.mode(WIFI_STA);//Init ESP-NOWif (esp_now_init() != ESP_OK) {Serial.println("Error initializing ESP-NOW");return;}// Once ESPNow is successfully Init, we will register for recv CB to// get recv packer infoesp_now_register_recv_cb(esp_now_recv_cb_t(OnDataRecv));
}void loop() {// Acess the variables for each board/*int board1X = boardsStruct[0].x;int board1Y = boardsStruct[0].y;int board2X = boardsStruct[1].x;int board2Y = boardsStruct[1].y;int board3X = boardsStruct[2].x;int board3Y = boardsStruct[2].y;*/delay(10000);
}
ESP-NOW通信验证

分别给左边的3个ESP32开发板下载好发送方Sender程序,给右边的ESP32开发板下载好接收方Receiver程序
若接收方接收到数据串口会打印出接收到对应的ESP32开发板的ID号和ESP32开发板的两个随机数

若发送方数据发送成功串口会打印出数据发送完成,数据接收成功

若发送方数据发送成功串口会打印出数据发送完成,数据接收失败

总结
通过以上例程验证了ESP32开发板之间单向多对一的ESP-NOW无线通信。
相关文章:
ESP32/ESP8266开发板单向一对多ESP-NOW无线通信
ESP32/ESP8266开发板单向一对多ESP-NOW无线通信 简介读取ESP32/ESP8266接收方Receiver的MAC地址ESP32/ESP8266发送方Sender程序ESP32/ESP8266接收方Receiver程序ESP-NOW通信验证总结 简介 本实验通过ESP-NOW无线通信协议实现多个ESP32/ESP 8266开发板向ESP32开发板发送数据。例…...
动态规划-回文串问题——5.最长回文子串
1.题目解析 题目来源:5.最长回文子串——力扣 测试用例 2.算法原理 1.状态表示 判断回文子串需要知道该回文子串的首尾下标,所以需要一个二维数组且数据类型为bool类型来存储每个子字符串是否为回文子串, 即dp[i][j]:以第i个位置为起始&a…...
rtp协议:rtcp包发送和接收规则和报告!
RTCP Packet Send and Receive Rules: 发送和接收 RTCP 包的规则在此列出。允许在多播环境或多点单播环境中运行的实现必须满足第 6.2 节中的要求。这样的实现可以使用本节定义的算法来满足这些要求,或者可以使用其他算法,只要其性能等同或更…...
label数据(或自定义数据集)转imagenet(用于mmclassification)
理论上用于分类的图像一般都不需要用labelme来标注的,笔者是因为刚好手上有这么一组数据,所以就顺带处理了。labelme标注完的数据每张还包含了一个json文件,这个在分类任务中用不上。具体的mmclassification使用方法在我的另一篇文章里有&…...
WebMvcConfigurer
WebMvcConfigurer是Spring MVC框架中的一个核心接口,它允许开发者自定义Spring MVC的配置,以满足应用程序的特定需求。通过实现这个接口,开发者可以注册拦截器、添加视图控制器、配置视图解析器等,而无需使用XML配置。以下是对Web…...
Sigrity Power SI VR noise Metrics check模式如何进行电源噪声耦合分析操作指导
SSigrity Power SI VR noise Metrics check模式如何进行电源噪声耦合分析操作指导 Sigrity Power SI的VR noise Metrics check模式本质上是用来评估和观测器件的电源网络的耦合对于信号的影响,输出S参数以及列出具体的贡献值。 以下图为例...
Python+Appium+Pytest+Allure自动化测试框架-安装篇
文章目录 安装安装ADT安装NodeJs安装python安装appium安装Appium Server(可选)安装Appium-Inspector(可选)安装allure安装pytest PythonAppiumPytestAllure框架的安装 Appium是一个开源工具,是跨平台的,用于…...
Python的socket使用
在 Python 中,可以使用 socket 模块编写一个支持多个客户端连接的服务端。常见的实现方式包括使用多线程、多进程或异步 I/O。下面以多线程为例展示如何编写一个服务端,来同时接收和处理多个客户端的连接。 多线程服务端代码示例 这个示例服务端代码中…...
如何快速搭建一个3D虚拟展厅?
随着元宇宙概念的兴起,一个全新的虚拟、立体数字空间正逐步成为我们生活的一部分。在这个空间里,用户可以沉浸其中,进行丰富的交互操作,体验前所未有的无限可能。而如何快速搭建一个属于自己的元宇宙3D虚拟展厅,正成为…...
Android webview 打开本地H5项目(Cocos游戏以及Unity游戏)
webview打开本地Html文件 1.在路径前面加上file:// String filePath"file://"path;webView.loadUrl( filePath);2.打开权限 <uses-permission android:name"android.permission.READ_EXTERNAL_STORAGE" />3.启用JavaScript 设置本地访问权限 webVi…...
解决项目中图片出不来的bug
在页面端图片呈现割裂状: 查看代码: 将代码改成: 即可正常显示图片。...
手机实时提取SIM卡打电话的信令声音-新的篇章(三、Android虚拟声卡探索)
手机实时提取SIM卡打电话的信令声音-新的篇章(三、Android虚拟声卡探索) 前言 前面的篇章中,我们从理论方向和实际市面上出现的音频线传输声音的方式,讨论绕开手机对SIM卡电话通话声音的封锁场景的可行性,并实际选购几款数字和模拟的USB转接…...
REST APIs与微服务:关键差异
在构建基于微服务的应用程序时RESYful API和微服务这两个术语经常相伴出现。然而,它们指的是截然不同的东西。 了解 RESTful API 和微服务之间差异的最简单方式是这样: 微服务:它们是构成更大规模基于微服务的应用程序的单个服务和功能&…...
【网安案例学习】反向蛮力攻击Reverse Brute Force Attack
【故事一】 在一个温暖的秋日下午,Jack坐在旧金山一家宁静的咖啡馆里,准备开始他的最新写作项目:追溯反向蛮力攻击的起源和发展。这是一个他一直想深入挖掘的主题,因为它揭示了网络安全世界中一个鲜为人知却极具影响力的故事。 …...
TCP/IP网络编程:理解网络编程和套接字
TCP/IP网络编程:理解网络编程和套接字 网络编程又叫做套接字编程,是因为在网络编程中依赖使用套接字(socket),网络编程一般是C/S架构,即客户端/服务器模式,在服务器端依赖套接字绑定自身接口,并开启监听客户端连接&am…...
CSS实现回到顶部且平滑过渡
背景 最近同学在项目开发的时候问了我一个问题:小白,回到顶部该怎么做呀?我当时就愣住了,心想这不是很基础的一个功能吗,然后想到该同学没有系统学过网页三剑客,我就给他讲了该怎么实现这个虽然基础但在很多…...
10 go语言(golang) - 数据类型:哈希表(map)及原理(二)
扩容 在 Go 语言中,当 map 的元素数量达到一定阈值时,会触发扩容操作以保持性能。这个过程称为 rehashing,即重新散列所有的键值对到一个更大的哈希表中。 扩容的条件 源码: func mapassign(t *maptype, h *hmap, key unsafe.…...
【论文解读】Med-BERT: 用于疾病预测的大规模结构化电子健康记录的预训练情境化嵌入
【论文解读】Med-BERT: 用于疾病预测的大规模结构化电子健康记录的预训练情境化嵌入 Med-BERT:pretrained contextualized embeddings on large-scale structured electronic health records for disease prediction 摘要:基于电子健康记录(EHR)的深度学习(DL)预…...
[POI2014] PTA-Little Bird(单调队列优化 DP)
luogu 传送门https://www.luogu.com.cn/problem/P3572 解题思路 先设 表示到 的最小劳累值。 很容易得出转移: 其中 由 和 的大小关系决定,并且 。 很显然,直接暴力是 的,会超时。 于是,考虑优化。 我们发现…...
【含开题报告+文档+PPT+源码】基于SpringBoot的体育馆管理系统的设计与实现
开题报告 近年来,随着人们生活水平的提高和健康意识的增强,体育馆作为提供体育锻和休闲娱乐的重要场所,其使用频率和管理难度也在不断增加。传统的体育馆管理模式通常依赖于人工记录和手动操作,不仅效率低下,而且容易…...
基于matlab策略迭代和值迭代法的动态规划
经典的基于策略迭代和值迭代法的动态规划matlab代码,实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...
【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...
raid存储技术
1. 存储技术概念 数据存储架构是对数据存储方式、存储设备及相关组件的组织和规划,涵盖存储系统的布局、数据存储策略等,它明确数据如何存储、管理与访问,为数据的安全、高效使用提供支撑。 由计算机中一组存储设备、控制部件和管理信息调度的…...
VSCode 使用CMake 构建 Qt 5 窗口程序
首先,目录结构如下图: 运行效果: cmake -B build cmake --build build 运行: windeployqt.exe F:\testQt5\build\Debug\app.exe main.cpp #include "mainwindow.h"#include <QAppli...
CSS 工具对比:UnoCSS vs Tailwind CSS,谁是你的菜?
在现代前端开发中,Utility-First (功能优先) CSS 框架已经成为主流。其中,Tailwind CSS 无疑是市场的领导者和标杆。然而,一个名为 UnoCSS 的新星正以其惊人的性能和极致的灵活性迅速崛起。 这篇文章将深入探讨这两款工具的核心理念、技术差…...
信息收集:从图像元数据(隐藏信息收集)到用户身份的揭秘 --- 7000
目录 🌐 访问Web服务 💻 分析源代码 ⬇️ 下载图片并保留元数据 🔍 提取元数据(重点) 👤 生成用户名列表 🛠️ 技术原理 图片元数据(EXIF 数据) Username-Anarch…...
