※本文將透過ESP32上的藍芽4.2,以BLE MESH架構的資訊收發方式進行資料傳輸,本範例使用之感測器為MPU6050(三軸陀螺儀+三軸加速計感測模組),將接收到的感測器數值作為資料並以MESH架構進行接收與傳輸。
Arduino IDE
首先,要在Arduino IDE上使用ESP32 需先進行開發版的安裝,此部分本文不詳細說明。 詳情請於網路上收尋關鍵字 「Arduino ESP32 開發環境安裝」 即可找到教學。
MESH簡易介紹
MESH是建立在Wi-Fi協議之上的網路協議。MESH允許散佈在較大物理區域(室內和室外)中的眾多設備(稱為節點)在單個WLAN(無線區域網路)下互連。
同時MESH具有自我組織和自我修復的功能,這意味著該網路可以自動構建和維護。
傳統的Wi-Fi網絡架構
在傳統的Wi-Fi網路體系結構中,單個節點(訪問點–通常為路由器)連接到所有其他節點(站)。每個節點都可以使用訪問點相互通信。但是,這僅限於接入點的Wi-Fi覆蓋範圍。每個站點必須在範圍內才能直接連接到接入點。ESP-MESH不會發生這種情況。
ESP-MESH網絡架構
使用ESP-MESH,節點無需連接到中央節點。節點負責彼此中繼傳輸。這允許多個設備分佈在較大的物理區域上。節點可以自組織並彼此動態對話,以確保數據包到達其最終節點目的地。如果從網絡中刪除了任何節點,則它可以自我組織以確保數據包到達其目的地。
painlessMesh程式庫
該painlessMesh庫 使我們能夠用一個簡單的程式庫,於ESP32上建立一個MESH傳輸架構的網路。
painlessMesh函式庫所建立的是真正的自組織網路,這意味著不需要中央控制器或路由器。任何由1個或多個節點組成的系統都將自組織為功能齊全的網格。
安裝painlessMesh庫
您可以通過Arduino程式庫管理器安裝painlessMesh。點擊草稿碼 >匯入程式庫 >管理程式庫 。即可開啟程式庫管理器。
於程式庫管理器搜尋欄位搜尋「 painlessmesh 」並安裝該庫。本文正在使用1.4.7版。
該庫還需要其他一些額外程式庫支援。應該會彈出一個新窗口,要求您安裝所有缺少的額外程式庫。 請選擇「全部安裝」。
如果未顯示此窗口或不確定是否已安裝所有額外程式庫,則需要安裝以下3項額外程式庫:
WiFi MESH基本示例(廣播消息)
接著開始使用WiFi MESH,我們首先嘗試該庫的基本範例。本範例創建一個網狀網絡,其中所有板均向所有其他板廣播消息。
我們用四個ESP32對這個範例進行實驗。您可以依自身情況增減ESP32數量。 (該範例對ESP32與ESP8266皆可兼容。)
程式碼– painlessMesh庫基本示例
將以下程式碼複製到您的Arduino IDE 即可進行上傳並察看結果。(或者點擊檔案 >範例 >Painless Mesh >basic )
#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 (就像WiFi名稱一樣)和 MESH_PASSWORD (WiFi密碼)。
然後,我們建議您為每個ESP32更改以下欄位,以輕鬆識別發送消息的節點。 例如,對於節點1,更改消息,如下所示:
String msg = "Hi from node 1 ";
程式碼如何運作
首先載入painlessMesh程式庫。
#include "painlessMesh.h"
MESH資訊
然後,添加網格詳細資料。這MESH_PREFIX指網路的名稱。您可以將其更改為任何您喜歡的。
#define MESH_PREFIX "whateverYouLike"
這 MESH_PASSWORD,顧名思義就是網路密碼。您可以將其更改為任何您喜歡的。
#define MESH_PASSWORD "somethingSneaky"
網格中的所有節點應使用相同的 MESH_PREFIX 和 MESH_PASSWORD。
這 MESH_PORT指您要在其上運行網狀服務器的TCP端口。默認值為5555。
#define MESH_PORT 5555
排程器
建議避免使用 delay()在網狀網路代碼中。為了維護網路,需要在後台執行一些任務。使用delay() 會阻止這些任務的發生,並可能導致網路失去穩定性或崩潰。
相反,建議使用 TaskScheduler 運行您在painlessMesh本身中使用的任務。
以下行創建了一個新的 排程器 叫 userScheduler。
Scheduler userScheduler; // to control your personal task
painlessMesh
建立一個 painlessMesh 對象稱為 mesh 來處理網狀網路。
painlessMesh mesh;
建立任務
建立一個名為 taskSendMessage 負責處理 sendMessage() 只要程序正在執行,便每秒執行一次。
Task taskSendMessage(TASK_SECOND * 1 , TASK_FOREVER, &sendMessage);
發送訊息到網路
這 sendMessage()功能將訊息發送到訊息網路中的所有節點(廣播)。
void sendMessage() {
String msg = "Hi from node 1";
msg += mesh.getNodeId();
mesh.sendBroadcast( msg );
taskSendMessage.setInterval(random(TASK_SECOND * 1, TASK_SECOND * 5));
}
該訊息包含【Hi from node 1 】,以及該ESP32的晶片ID。
String msg = "Hi from node 1";
msg += mesh.getNodeId();
要廣播訊息,只需使用 sendBroadcast() 上的方法,以網路為對象並將訊息作為參數傳遞(msg)發送。
mesh.sendBroadcast(msg);
每次發送新訊息時,代碼都會更改訊息之間的間隔(一到五秒)。
taskSendMessage.setInterval(random(TASK_SECOND * 1, TASK_SECOND * 5));
網路回調函數
接下來,建立多個回調函數,當特定事件在網路上發生時將被啟用。
這 receiveCallback() 函式負責顯示訊息發件人(from )和訊息的內容(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()中程式碼
在setup()裡面初始化序列埠監控器。
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
用前面定義的WiFi資訊初始化網路。
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();
}
執行結果
將上述的程式碼上傳到所有ESP32上。不要忘記修改訊息以輕鬆識別發送的節點。
將ESP32連接到電腦後,打開每個ESP32的序列埠監控視窗。
您應該看到所有ESP32都收到彼此的訊息。例如,這些是節點1收到的訊息。它從節點2、3和4接收訊息。
當網路上發生改變時,您還應該看到其他訊息:節點離開或加入網路時。
使用ESP-MESH交換感測器讀數
在下一個範例中,我們將在4個板之間交換感測器讀數(您可以使用不同數量的板)。每個板都接收其他板的讀數。
例如,我們將交換來自感測器:MPU6050的讀數,不過您也可以使用任何其他感測器。
所需零件
這是此範例所需的零件:
Arduino_JSON程式庫
在此範例中,我們將以JSON格式交換感測器讀數。為了使處理JSON變量更容易,我們將使用Arduino_JSON 程式庫。
您可以在Arduino IDE庫管理器中安裝該庫。只需轉到 草稿碼 > 匯入函式庫 > 管理程式庫, 然後按以下方式搜索庫名稱:
電路圖
如下圖所示,將MPU6050感測器連接到ESP32默認的I2C引腳。
程式碼– ESP-MESH廣播感測器讀數
將以下程式碼上傳到您的每個ESP32上,並修改nodeNumber 欄位的變數。該程式碼讀取當前X軸、Y軸、Z軸讀數,並將其廣播到網狀網路上的所有ESP32。讀數以JSON字符串的形式發送,其中還包含用於標示發送訊息之ESP32的節點號。
#include "painlessMesh.h"
#include <Wire.h>
#include <MPU6050.h>
#include <Arduino_JSON.h>
#define MESH_PREFIX "whateverYouLike" //name for your MESH
#define MESH_PASSWORD "somethingSneaky" //password for your MESH
#define MESH_PORT 5555 //default port
//Number for this node
int nodeNumber = 1;
//MPU6050 Pin/SDA-21,SCL-22
MPU6050 mpu;
//String to send to other nodes with sensor readings
String readings;
Scheduler userScheduler; // to control your personal task
painlessMesh mesh;
// User stub
String getReadings(); // Prototype so PlatformIO doesn't complain
void sendMessage();
Task taskSendMessage( TASK_SECOND * 0.5 , TASK_FOREVER, &sendMessage );
String getReadings () {
JSONVar jsonReadings;
Vector normAccel = mpu.readNormalizeAccel();
Vector normGyro = mpu.readNormalizeGyro();
jsonReadings["node"] = nodeNumber;
jsonReadings["Accel_X"] = String(normAccel.XAxis);
jsonReadings["Accel_Y"] = String(normAccel.YAxis);
jsonReadings["Accel_Z"] = String(normAccel.ZAxis);
jsonReadings["Gyro_X"] = String(normGyro.XAxis);
jsonReadings["Gyro_Y"] = String(normGyro.YAxis);
jsonReadings["Gyro_Z"] = String(normGyro.ZAxis);
readings = JSON.stringify(jsonReadings);
return readings;
}
void sendMessage() {
String msg = getReadings();
mesh.sendBroadcast( msg );
}
// Needed for painless library
void receivedCallback( uint32_t from, String &msg ) {
//Serial.printf("Received from %u msg=%s\n", from, msg.c_str());
Serial.println();
Serial.println("----------------------------------");
Serial.printf("Received from %u ", from);
Serial.println();
Serial.printf("msg=%s\n",msg.c_str());
JSONVar myObject = JSON.parse(msg.c_str());
int node = myObject["node"];
//三軸加速度(Accel)
double X = myObject["Accel_X"];
double Y = myObject["Accel_Y"];
double Z = myObject["Accel_Z"];
//三軸陀螺儀(Gyro)
double GX = myObject["Gyro_X"];
double GY = myObject["Gyro_Y"];
double GZ = myObject["Gyro_Z"];
Serial.println("**********************************");
//三軸加速度(Accel)
Vector normAccel = mpu.readNormalizeAccel();
Serial.print(" Accel_X:");
Serial.print(normAccel.XAxis);
Serial.print(" Accel_Y:");
Serial.print(normAccel.YAxis);
Serial.print(" Accel_Z:");
Serial.println(normAccel.ZAxis);
//三軸陀螺儀(Gyro)
Vector normGyro = mpu.readNormalizeGyro();
Serial.print(" Gyro_X:");
Serial.print(normGyro.XAxis);
Serial.print(" Gyro_Y:");
Serial.print(normGyro.YAxis);
Serial.print(" Gyro_Z:");
Serial.println(normGyro.ZAxis);
}
void newConnectionCallback(uint32_t nodeId) {
Serial.printf("-->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);
}
/*******MPU6050三軸加速度(Accel)主程式******/
void MPU_Accel_set(){
while(!mpu.begin(MPU6050_SCALE_2000DPS, MPU6050_RANGE_2G))
{
Serial.println("Could not find a valid MPU6050 sensor, check wiring!");
delay(500);
}
switch(mpu.getRange()){
case MPU6050_RANGE_2G:
Serial.println("+/- 2 g");
break;
}
}
/*******MPU6050三軸陀螺儀(Gyro)主程式******/
void MPU_Gyro_set(){
while(!mpu.begin(MPU6050_SCALE_2000DPS, MPU6050_RANGE_2G)){
Serial.println("Could not find a valid MPU6050 sensor, check wiring!");
delay(500);
}
// Set threshold sensivty. Default 3.
mpu.setThreshold(3);
switch(mpu.getScale()){
case MPU6050_SCALE_250DPS:
Serial.println("250 dps");
break;
}
}
/*************************************/
void setup() {
Serial.begin(115200);
MPU_Accel_set();
MPU_Gyro_set();
//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();
}
程式碼如何運作
繼續閱讀本節以了解代碼如何運行。
程式庫
首先載入所需的庫: Wire 和 MPU6050用於感測器的連接;painlessMesh處理網狀網路和 Arduino_JSON 輕鬆建立和處理JSON字符串。
#include "painlessMesh.h"
#include <Wire.h>
#include <MPU6050.h>
#include <Arduino_JSON.h>
網路資訊
在以下各行中插入網格詳細信息。
#define MESH_PREFIX "whateverYouLike" //name for your MESH
#define MESH_PASSWORD "somethingSneaky" //password for your MESH
#define MESH_PORT 5555 //default port
這 MESH_PREFIX指網路的名稱。您可以將其更改為任何您喜歡的。 這MESH_PASSWORD,就是網路密碼。您可以將其更改為任何您喜歡的。 網路中的所有節點應使用相同的MESH_PREFIX 和 MESH_PASSWORD。 這 MESH_PORT指您要在其上運行網狀服務器的TCP端口。默認值為5555。
MPU6050
建立一個 MPU6050 對象稱為 mpu 在默認的ESP32 I2C引腳上。
//MPU6050 Pin/SDA-21,SCL-22
MPU6050 mpu;
在裡面 nodeNumber變量為您的ESP32個別節點編號。每個板的編號必須不同。
//Number for this node
int nodeNumber = 1;
這 readings 變量將用於保存要發送到其他ESP32的讀數。
String readings;
排程器
以下行創建了一個新的 排程器 叫 userScheduler。
Scheduler userScheduler; // to control your personal task
painlessMesh
建立一個 painlessMesh 對象稱為 mesh 來處理網狀網路。
painlessMesh mesh;
建立任務(tasks)
建立一個名為 taskSendMessage 負責發送 sendMessage() 只要程序正在執行,便每0.5秒鐘執行一次。 假如今天從Node2、3接收到資料,則Node1序列埠視窗顯示接收到之資料數共為4筆,(Node2、3各兩筆資料)。
Task taskSendMessage(TASK_SECOND * 0.5 , TASK_FOREVER, &sendMessage);
getReadings()
這 getReadings() 函數從MPU6050感測器讀取當前X軸、Y軸、Z軸讀數,並連接所有訊息,包括稱為JSON變量的節點號 jsonReadings。
JSONVar jsonReadings;
Vector normAccel = mpu.readNormalizeAccel();
Vector normGyro = mpu.readNormalizeGyro();
jsonReadings["node"] = nodeNumber;
//三軸加速度(Accel)
jsonReadings["Accel_X"] = String(normAccel.XAxis);
jsonReadings["Accel_Y"] = String(normAccel.YAxis);
jsonReadings["Accel_Z"] = String(normAccel.ZAxis);
//三軸陀螺儀(Gyro)
jsonReadings["Gyro_X"] = String(normGyro.XAxis);
jsonReadings["Gyro_Y"] = String(normGyro.YAxis);
jsonReadings["Gyro_Z"] = String(normGyro.ZAxis);
這 jsonReadings 將該變量轉換為JSON字符串 stringify()並保存在 readings 變量。
readings = JSON.stringify(jsonReadings);
然後該變量由函數回傳。
return readings;
發送消息到網路
這 sendMessage() 函數發送帶有讀數和節點號的JSON字符串(getReadings())到網路中的所有節點(廣播)。
void sendMessage () {
String msg = getReadings();
mesh.sendBroadcast(msg);
}
網路回傳函數
接下來,創建多個回傳函數,這些事件將在網格上發生某些事件時被執行。
這 receiveCallback() 函數顯示訊息發件人(from)和訊息的內容(msg.c_str())。
void receivedCallback( uint32_t from, String &msg ) {
Serial.println();
Serial.println("----------------------------------");
Serial.printf("Received from %u ", from);
Serial.println();
Serial.printf("msg=%s\n",msg.c_str());
該消息採用JSON格式,因此,我們可以按以下方式訪問變量:
JSONVar myObject = JSON.parse(msg.c_str());
int node = myObject["node"];
//三軸加速度(Accel)
double X = myObject["Accel_X"];
double Y = myObject["Accel_Y"];
double Z = myObject["Accel_Z"];
//三軸陀螺儀(Gyro)
double GX = myObject["Gyro_X"];
double GY = myObject["Gyro_Y"];
double GZ = myObject["Gyro_Z"];
最後,在串行監視器上打印所有信息。
Serial.println("**********************************");
//三軸加速度(Accel)
Vector normAccel = mpu.readNormalizeAccel();
Serial.print(" Accel_X:");
Serial.print(normAccel.XAxis);
Serial.print(" Accel_Y:");
Serial.print(normAccel.YAxis);
Serial.print(" Accel_Z:");
Serial.println(normAccel.ZAxis);
//三軸陀螺儀(Gyro)
Vector normGyro = mpu.readNormalizeGyro();
Serial.print(" Gyro_X:");
Serial.print(normGyro.XAxis);
Serial.print(" Gyro_Y:");
Serial.print(normGyro.YAxis);
Serial.print(" Gyro_Z:");
Serial.println(normGyro.ZAxis);
這 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);
}
初始化MPU6050感測器
這 void MPU_Accel_set( ) 、 void MPU_Gyro_set( ) 功能為初始化MPU6050感測器。
/*******MPU6050三軸加速度(Accel)主程式******/
void MPU_Accel_set(){
while(!mpu.begin(MPU6050_SCALE_2000DPS, MPU6050_RANGE_2G))
{
Serial.println("Could not find a valid MPU6050 sensor, check wiring!");
delay(500);
}
switch(mpu.getRange()){
case MPU6050_RANGE_2G:
Serial.println("+/- 2 g");
break;
}
}
/*******MPU6050三軸陀螺儀(Gyro)主程式******/
void MPU_Gyro_set(){
while(!mpu.begin(MPU6050_SCALE_2000DPS, MPU6050_RANGE_2G)){
Serial.println("Could not find a valid MPU6050 sensor, check wiring!");
delay(500);
}
// Set threshold sensivty. Default 3.
mpu.setThreshold(3);
switch(mpu.getScale()){
case MPU6050_SCALE_250DPS:
Serial.println("250 dps");
break;
}
}
setup()
在 setup()裡面初始化序列埠監控器。
void setup() {
Serial.begin(115200);
啟用 MPU_Accel_set( ) 、 MPU_Gyro_set( ) 初始化MPU6050感測器。
MPU_Accel_set();
MPU_Gyro_set();
選擇所需的調試訊息類型:
//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
用前面定義的WiFi資訊初始化網路。
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();
}
執行結果
將代碼上傳到所有ESP32(每個ESP32具有不同的節點號)後,您應該看到每個ESP32都在接收其他ESP32的訊息。
以下截圖顯示了節點1收到的消息。它接收來自節點2的感測器讀數,並顯示自身感測器讀數。
以下截圖顯示了節點2收到的消息。它接收來自節點1的感測器讀數,並顯示自身感測器讀數。
完成
以上即為本範例所有教學內容。