ESP32和ESP8266的ESP-MESH

ESP32和ESP8266的ESP-MESH

  • 功能介绍
  • 一、介绍ESP-MESH
  • 二、安装painlessMesh库
  • 三、ESP-MESH基本示例(广播消息)
  • 四、示范


功能介绍

了解如何使用ESP-MESH网络协议通过ESP32和ESP8266 NodeMCU板构建网状网络。 ESP-MESH允许多个设备(节点)在单个无线局域网下相互通信。 ESP32和ESP8266板均支持该功能。 在本指南中,我们将向您展示如何使用Arduino内核开始使用ESP-MESH。
在这里插入图片描述


本文涵盖以下主题:

介绍ESP-MESH
ESP-MESH基本示例(广播消息)
使用ESP-MESH交换传感器读数(广播)

一、介绍ESP-MESH

根据Espressif文档:

“ ESP-MESH是建立在Wi-Fi协议之上的网络协议。 ESP-MESH允许散布在较大物理区域(室内和室外)中的众多设备(称为节点)在单个WLAN(无线局域网)下互连。
ESP-MESH具有自我组织和自我修复的功能,这意味着该网络可以自动构建和维护。” 有关更多信息,请访问ESP-MESH官方文档。

传统的Wi-Fi网络架构
在传统的Wi-Fi网络体系结构中,单个节点(访问点–通常为路由器)连接到所有其他节点(站)。 每个节点都可以使用访问点相互通信。 但是,这仅限于接入点的Wi-Fi覆盖范围。 每个站点必须在范围内才能直接连接到接入点。 ESP-MESH不会发生这种情况。

在这里插入图片描述

ESP-MESH网络架构
使用ESP-MESH,节点无需连接到中央节点。 节点负责彼此中继传输。 这允许多个设备分布在较大的物理区域上。 节点可以自组织并彼此动态对话,以确保数据包到达其最终节点目的地。 如果从网络中删除了任何节点,则它可以自我组织以确保数据包到达其目的地。

在这里插入图片描述

painlessMesh库使我们能够以简单的方式使用ESP8266或/和ESP32板创建网状网络。

“ painlessMesh是真正的自组织网络,这意味着不需要计划,中央控制器或路由器。 任何包含1个或多个节点的系统都将自组织成功能齐全的网格。 网格的最大大小受堆中可分配给子连接缓冲区的内存量的限制(我们认为),因此应该确实很高。 有关painlessMesh库的更多信息。

二、安装painlessMesh库

您可以通过Arduino库管理器安装painlessMesh。 转到工具>管理库。 图书馆管理器应打开。

搜索“ painlessmesh”并安装该库。 我们正在使用1.4.5版

在这里插入图片描述
该库还需要其他一些库依赖项。 应该会弹出一个新窗口,要求您安装所有缺少的依赖项。 选择“全部安装”。

在这里插入图片描述

如果未显示此窗口,则需要安装以下库依赖项:

ArduinoJson(来自bblanchon)
任务计划程序
ESPAsyncTCP(ESP8266)
AsyncTCP(ESP32)
如果您使用的是PlatformIO,则将以下行添加到platformio.ini文件中,以添加库并更改监视器速度。
For the ESP32:

monitor_speed = 115200 lib_deps = painlessmesh/painlessMesh @ ^1.4.5
ArduinoJson
arduinoUnity
TaskScheduler
AsyncTCP

For the ESP8266:

monitor_speed = 115200 lib_deps = painlessmesh/painlessMesh @ ^1.4.5
ArduinoJson
TaskScheduler
ESPAsyncTCP

三、ESP-MESH基本示例(广播消息)

要开始使用ESP-MESH,我们首先尝试使用该库的基本示例。 本示例创建一个网状网络,其中所有板均向所有其他板广播消息。

我们以四个板(两个ESP32和两个ESP8266)为例进行了实验。 您可以添加或删除板。 该代码与ESP32和ESP8266板均兼容。
在这里插入图片描述

代码– painlessMesh库基本示例
将以下代码复制到您的Arduino IDE(库示例中的代码)。 该代码与ESP32和ESP8266板均兼容。

/*Rui SantosComplete project details at https://RandomNerdTutorials.com/esp-mesh-esp32-esp8266-painlessmesh/This is a simple example that uses the painlessMesh library: https://github.com/gmag11/painlessMesh/blob/master/examples/basic/basic.ino
*/#include "painlessMesh.h"#define   MESH_PREFIX     "whateverYouLike"
#define   MESH_PASSWORD   "somethingSneaky"
#define   MESH_PORT       5555Scheduler userScheduler; // to control your personal task
painlessMesh  mesh;// User stub
void sendMessage() ; // Prototype so PlatformIO doesn't complainTask taskSendMessage( TASK_SECOND * 1 , TASK_FOREVER, &sendMessage );void sendMessage() {String msg = "Hi from node1";msg += mesh.getNodeId();mesh.sendBroadcast( msg );taskSendMessage.setInterval( random( TASK_SECOND * 1, TASK_SECOND * 5 ));
}// Needed for painless library
void receivedCallback( uint32_t from, String &msg ) {Serial.printf("startHere: Received from %u msg=%s\n", from, msg.c_str());
}void newConnectionCallback(uint32_t nodeId) {Serial.printf("--> startHere: New Connection, nodeId = %u\n", nodeId);
}void changedConnectionCallback() {Serial.printf("Changed connections\n");
}void nodeTimeAdjustedCallback(int32_t offset) {Serial.printf("Adjusted time %u. Offset = %d\n", mesh.getNodeTime(),offset);
}void setup() {Serial.begin(115200);//mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types onmesh.setDebugMsgTypes( ERROR | STARTUP );  // set before init() so that you can see startup messagesmesh.init( MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT );mesh.onReceive(&receivedCallback);mesh.onNewConnection(&newConnectionCallback);mesh.onChangedConnections(&changedConnectionCallback);mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);userScheduler.addTask( taskSendMessage );taskSendMessage.enable();
}void loop() {// it will run the user scheduler as wellmesh.update();
}

在上传代码之前,您可以设置MESH_PREFIX(类似于MESH网络的名称)和MESH_PASSWORD变量(可以将其设置为任意值)。

然后,我们建议您为每个板更改以下行,以轻松识别发送消息的节点。 例如,对于节点1,更改消息,如下所示:

String msg = "Hi from node 1 ";

代码如何工作
首先包括painlessMesh库。

#include “painlessMesh.h”

MESH详细信息
然后,添加网格详细信息。 MESH_PREFIX引用网格的名称。 您可以将其更改为任何您喜欢的。

#define MESH_PREFIX “whateverYouLike”

顾名思义,MESH_PASSWORD是MESH密码。 您可以将其更改为任何您喜欢的。

#define MESH_PASSWORD “somethingSneaky”

网格中的所有节点应使用相同的MESH_PREFIX和MESH_PASSWORD。

MESH_PORT指您要在其上运行网格服务器的TCP端口。 默认值为5555。

#define MESH_PORT 5555

Scheduler
建议避免在网状网络代码中使用delay()。 为了维护网格,需要在后台执行一些任务。 使用delay()将阻止这些任务的发生,并可能导致网格失去稳定性/崩溃。

相反,建议使用TaskScheduler运行在painlessMesh本身中使用的任务。

下面的行创建了一个名为userScheduler的新Scheduler。

painlessMesh
创建一个名为mesh的painlessMesh对象,以处理网格网络。
Create tasks
创建一个名为taskSendMessage的任务,该任务负责在程序运行时每秒调用一次sendMessage()函数。

Task taskSendMessage(TASK_SECOND * 1 , TASK_FOREVER, &sendMessage);
Send a Message to the Mesh sendMessage()函数将消息发送到消息网络(广播)中的所有节点。

void sendMessage() {String msg = "Hi from node 1";msg += mesh.getNodeId();mesh.sendBroadcast( msg );taskSendMessage.setInterval(random(TASK_SECOND * 1, TASK_SECOND * 5));
}

The message contains the “Hi from node 1” text followed by the board chip ID.

String msg = “Hi from node 1”;
msg += mesh.getNodeId();

要广播消息,只需在网格对象上使用sendBroadcast()方法,然后将要发送的消息(msg)作为参数传递。

mesh.sendBroadcast(msg);

每次发送新消息时,代码都会更改消息之间的间隔(一到五秒)。

taskSendMessage.setInterval(random(TASK_SECOND * 1, TASK_SECOND * 5));

Mesh Callback Functions
接下来,创建多个回调函数,当特定事件在网格上发生时将被调用。
receiveCallback()函数打印消息发件人(来自)和消息内容(msg.c_str())。

void receivedCallback( uint32_t from, String &msg ) {Serial.printf("startHere: Received from %u msg=%s\n", from, msg.c_str());
}

每当新节点加入网络时,newConnectionCallback()函数就会运行。 此功能仅打印新节点的芯片ID。 您可以修改功能以执行任何其他任务。

void newConnectionCallback(uint32_t nodeId) {Serial.printf("--> startHere: New Connection, nodeId = %u\n", nodeId);
}

每当网络上的连接发生更改时(节点加入或离开网络时),changedConnectionCallback()函数都会运行。

void changedConnectionCallback() {Serial.printf("Changed connections\n");
}

当网络调整时间时,nodeTimeAdjustedCallback()函数将运行,以便所有节点都同步。 打印偏移量。

void nodeTimeAdjustedCallback(int32_t offset) {Serial.printf("Adjusted time %u. Offset = %d\n", mesh.getNodeTime(),offset);
}

setup()
选择所需的调试消息类型:
//mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on

mesh.setDebugMsgTypes( ERROR | STARTUP );  // set before init() so that you can see startup messages

用前面定义的细节初始化网格。

mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);

将所有回调函数分配给它们相应的事件。

mesh.onReceive(&receivedCallback);
mesh.onNewConnection(&newConnectionCallback);
mesh.onChangedConnections(&changedConnectionCallback);
mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);

最后,将taskSendMessage函数添加到userScheduler。 调度程序负责在正确的时间处理和运行任务。
userScheduler.addTask(taskSendMessage);
最后,启用taskSendMessage,以便程序开始将消息发送到网格。
taskSendMessage.enable();
为了使网格保持运行,将mesh.update()添加到loop()中。

void loop() {// it will run the user scheduler as wellmesh.update();
}

四、示范

将提供的代码上传到所有主板。 不要忘记修改邮件以轻松识别发件人节点

将板连接到计算机后,打开每个板的串行连接。 您可以使用串行监视器,也可以使用类似PuTTY的软件并为所有板打开多个窗口。

您应该看到所有板都收到彼此的消息。 例如,这些是节点1收到的消息。它从节点2、3和4接收消息。

在这里插入图片描述

当网格上发生更改时,您还应该看到其他消息:板子离开或加入网络时。

在这里插入图片描述
使用ESP-MESH交换传感器读数
在下一个示例中,我们将在4个板之间交换传感器读数(您可以使用不同数量的板)。 每个板都接收其他板的读数。
在这里插入图片描述
例如,我们将交换来自BME280传感器的传感器读数,但是您可以使用任何其他传感器。

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

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

相关文章

位运算的高频算法题

关卡名 位运算的高频算法题 我会了✔️ 内容 1.理解位运算如何统计1的个数的 ✔️ 2.理解位运算如何实现加法 ✔️ 3.理解递归乘法是如何实现的 ✔️ 1 位移的妙用 位移操作是一个很重要的问题,可以统计数字中1的个数,在很多高性能软件中也大量应…

群晖NAS配置之自有服务器frp实现内网穿透

什么是frp frp 是一个专注于内网穿透的高性能的反向代理应用,支持 TCP、UDP、HTTP、HTTPS 等多种协议,且支持 P2P 通信。可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网。今天跟大家分享一下frp实现内网穿透 为什么使用 frp &a…

基于瑞芯微rk3588+寒武纪 | 38TOPS INT8算力的AI边缘计算盒子,智能安防、智慧工地、智慧城管、智慧油站

边缘计算盒子 瑞芯微rk3588寒武纪 | 38TOPS INT8算力 ● 采用 Big-Little 大小核架构,搭载四核 A76四核 A55,CPU主频高达 2.4GHz ,提供1MB L2 Cache 和 3MB L3 ,Cache提供更强的 CPU 运算能力。 ● 高性能四核 Mali-G610 GPU&a…

【2024秋招】2023-9-22 金山云文档服务端开发一面

1 OS 1.1 堆和栈的区别,什么时候用到堆,什么时候用到栈呢 堆和栈是两种不同的内存分配方式,它们在计算机编程中有着各自的用途和特点。以下是它们之间的主要区别以及在何时使用它们: 1.1.1 堆(Heap)&…

在vue中如何书写 SSR 友好的代码

文章目录 前言服务端的响应性​组件生命周期钩子​访问平台特有 API​跨请求状态污染​激活不匹配​自定义指令​teleports​后言 前言 hello world欢迎来到前端的新世界 😜当前文章系列专栏:vue.js 🐱‍👓博主在前端领域还有很多…

i++和++i的区别

i和i的区别 一、基本概念 两者的作用都是自增加1。 单独拿出来说的话,i和i,效果都是一样的,就是ii1 public static void main(String[] args) {int i 0;i;System.out.println(i);}public static void main(String[] args) {int i 0;i;Sys…

【开源】基于JAVA语言的校园电商物流云平台

项目编号: S 034 ,文末获取源码。 \color{red}{项目编号:S034,文末获取源码。} 项目编号:S034,文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 商品数据模块2.3 快…

FH Admin Shiro反序列化漏洞复现

0x01 产品简介 FH Admin 是一款 java 快速开发平台。 0x02 漏洞概述 FH Admin CMS 存在 shiro 反序列化漏洞,该漏洞源于软件存在硬编码的 shiro-key,攻击者可利用该 key 生成恶意的序列化数据,在服务器上执行任意代码,执行系统命…

python自动化第二篇——合并ppt

简述 python合并ppt的方法有很多,但网上常说的python-pptx的方法,我用不了,这里我用了一个python-office的库。但又两个缺点,第一个生成的文档在你的用户名下的文档里,第二个是名字随机。 import office import os im…

华为OD机试真题-查找接口成功率最优时间段-2023年OD统一考试(C卷)

题目描述: 服务之间交换的接口成功率作为服务调用关键质量特性,某个时间段内的接口失败率使用一个数组表示,数组中每个元素都是单位时间内失败率数值,数组中的数值为0~100的整数,给定一个数值(minAverageLost)表示某个时间段内平均失败率容忍值,即平均失败率小于等于minA…

vue3-vite-ts:编写Rollup插件并使用 / 优化构建过程

一、vue3-vite-ts项目,编写Rollup插件并使用的意义 在使用Vue3 Vite TypeScript这种技术栈时,可以使用Rollup插件来优化构建过程,例如使用rollup-plugin-typescript2插件来编译TypeScript代码,使用rollup-plugin-vue插件来处理…

【开源】基于Vue+SpringBoot的康复中心管理系统

项目编号: S 056 ,文末获取源码。 \color{red}{项目编号:S056,文末获取源码。} 项目编号:S056,文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 普通用户模块2.2 护工模块2.3 管理员…

版本控制系统Git学习笔记-Git服务器

文章目录 概述一、协议1.1 本地协议1.2 HTTP协议1.3 SSH协议1.4 Git协议 二、在服务器上搭建 Git 四智武童 一月一,捡花衣。二月二,练大字。三月三,穿新衣。四月四,去考试。考一个状元郎,坐著马车平天下。 概述 Git访…

OpenStack-train版安装之安装Keystone(认证服务)、Glance(镜像服务)、Placement

安装Keystone(认证服务)、Glance(镜像服务)、Placement 安装Keystone(认证服务)安装Glance(镜像服务)安装Placement 安装Keystone(认证服务) 数据库创建、创…

WebSocket 实战:构建高效的实时应用

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…

使用Spark写入数据到数据库表

项目场景: 使用Spark写入数据到数据库表 问题描述 Column "20231201" not found in schema Some(StructType(StructField(sdate,IntegerType,false),StructField(date_time,StringType,true),StructField(num,LongType,false),StructField(table_code,S…

数据结构详解各种算法

1、设有两个整型顺序表L1,L2,其元素值递增有序存放,请定义该顺序表的元素类型及表类型,设计以下自定义函数: (1)录入顺序表中所有元素的值。 (2)将顺序表L1,L2合并为到…

LeetCode 8 字符串转整数

题目描述 字符串转换整数 (atoi) 请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C 中的 atoi 函数)。 函数 myAtoi(string s) 的算法如下: 读入字符串并丢弃无用的前导空格检查下一…

解决woocommerce产品方面遇到的小问题记录

问题1.通过自定义代码在woocommerce的任意一个产品的价格下面,加上一段文字 id,换成你自己的产品id,div里面的文字换成你自己的自定义文字,代码是加在function.php里面的哦 //添加文字产品价格下面 function insert_custom_cont…

SpringMVC利用@ControllerAdvice和ResponseBodyAdvice接口统一处理返回值

在我们进行Java的Web应用开发时,如何写更少的代码,做更多的事情。如何让开发更容易上手,更专注于业务层面,不需要太关心底层的实现。这里就分享一些我平时在搭建基础框架时候的一些心得体验。 统一处理返回值 在web应用中&#x…