※本文將透過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的感測器讀數,並顯示自身感測器讀數。

完成

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

2,431 thoughts on “ESP32 WiFi MESH資料收發應用範例 (感測器:MPU6050)

  1. I have to thank you for the efforts you have put in penning this blog. I am hoping to check out the same high-grade blog posts from you later on as well. In fact, your creative writing abilities has encouraged me to get my own blog now 😉

  2. Terrific work! That is the kind of information that should
    be shared around the internet. Disgrace on Google
    for no longer positioning this publish upper! Come on over and consult
    with my site . Thank you =)

  3. Your style is very unique compared to other folks I have read
    stuff from. I appreciate you for posting when you have the opportunity, Guess I’ll just bookmark this web site.

  4. Hello my family member! I want to say that this
    post is amazing, nice written and come with almost all significant infos.
    I’d like to see more posts like this .

  5. Thank you for some other informative site. Where else may just
    I get that kind of info written in such a perfect method?
    I have a venture that I am just now working on, and I have been at
    the look out for such info.

  6. What i don’t realize is in fact how you’re now not really much
    more smartly-preferred than you may be right now.

    You are very intelligent. You already know thus significantly in relation to this topic, produced me for my part believe it from
    numerous various angles. Its like men and women aren’t interested except it is something to
    do with Girl gaga! Your individual stuffs great.
    Always take care of it up!