ESP32和ESP8266的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 Santos
  Complete 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       5555

Scheduler userScheduler; // to control your personal task
painlessMesh  mesh;

// User stub
void sendMessage() ; // Prototype so PlatformIO doesn't complain

Task 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 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);

  userScheduler.addTask( taskSendMessage );
  taskSendMessage.enable();
}

void loop() {
  // it will run the user scheduler as well
  mesh.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 well
  mesh.update();
}

四、示范

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

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

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

在这里插入图片描述

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

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

  • 53
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

物联网程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值