※本文將透過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不會發生這種情況。

傳統Wi-Fi網絡ESP32 ESP8266

ESP-MESH網絡架構

使用ESP-MESH,節點無需連接到中央節點。節點負責彼此中繼傳輸。這允許多個設備分佈在較大的物理區域上。節點可以自組織並彼此動態對話,以確保數據包到達其最終節點目的地。如果從網絡中刪除了任何節點,則它可以自我組織以確保數據包到達其目的地。

ESP-MESH網絡ESP32 ESP8266i

painlessMesh程式庫

painlessMesh庫使我們能夠用一個簡單的程式庫,於ESP32上建立一個MESH傳輸架構的網路。

painlessMesh函式庫所建立的是真正的自組織網路,這意味著不需要中央控制器或路由器。任何由1個或多個節點組成的系統都將自組織為功能齊全的網格。

安裝painlessMesh庫

您可以通過Arduino程式庫管理器安裝painlessMesh。點擊草稿碼>匯入程式庫>管理程式庫。即可開啟程式庫管理器。

於程式庫管理器搜尋欄位搜尋「 painlessmesh 」並安裝該庫。本文正在使用1.4.7版。

該庫還需要其他一些額外程式庫支援。應該會彈出一個新窗口,要求您安裝所有缺少的額外程式庫。
請選擇「全部安裝」。

如果未顯示此窗口或不確定是否已安裝所有額外程式庫,則需要安裝以下3項額外程式庫:

WiFi MESH基本示例(廣播消息)

接著開始使用WiFi MESH,我們首先嘗試該庫的基本範例。本範例創建一個網狀網絡,其中所有板均向所有其他板廣播消息。

我們用四個ESP32對這個範例進行實驗。您可以依自身情況增減ESP32數量。
(該範例對ESP32與ESP8266皆可兼容。)

ESP-MESH painlessMesh基本示例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板Arduino串行監視器

當網路上發生改變時,您還應該看到其他訊息:節點離開或加入網路時。

ESP MESH基本示例串行監視器更改的連接

使用ESP-MESH交換感測器讀數

在下一個範例中,我們將在4個板之間交換感測器讀數(您可以使用不同數量的板)。每個板都接收其他板的讀數。

ESP-MESH交流BME280傳感器讀數ESP32 ESP8266

例如,我們將交換來自感測器:MPU6050的讀數,不過您也可以使用任何其他感測器。

所需零件

這是此範例所需的零件:

  • 4個ESP32板
  • 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的感測器讀數,並顯示自身感測器讀數。

完成

以上即為本範例所有教學內容。

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>