You are currently viewing ESP NOW -帶有Arduino IDE的ESP8266

ESP NOW -帶有Arduino IDE的ESP8266

ESP-NOW入門(帶有Arduino IDE的ESP8266 NodeMCU)

在本文中,我們將向您展示如何使用ESP-NOW在使用Arduino IDE編程的ESP8266 NodeMCU板之間交換數據。ESP-NOW是由Espressif開發的無連接通信協議,具有短數據包傳輸功能,可與ESP8266和ESP32板一起使用。

使用Arduino IDE的ESP-NOW ESP8266 NodeMCU入門

我們還有其他有關ESP8266的ESP-NOW的教程:

  • ESP8266 NodeMCU板之間的ESP-NOW雙向通信
  • ESP-NOW與ESP8266:將數據發送到多個開發板(一對多)
  • ESP-NOW與ESP8266:從多個開發板接收數據(多對一)

Arduino IDE 

我們將使用Arduino IDE對ESP8266 NodeMCU板進行編程,因此在繼續本教程之前,您應該在Arduino IDE中安裝ESP8266插件。遵循下一個指南:

介紹ESP-NOW 

ESP-NOW是Espressif開發的一種協議,在Espressif網站上表示,它可使多個設備無需使用Wi-Fi即可相互通信。該協議類似於低功率的2.4GHz無線連接(…)。設備之間需要進行配對,然後才能進行通信。配對完成後,連接安全且點對點,無需接觸。”
ESP-NOW-ESP32徽標

這意思為只要將設備彼此配對後,連接將保持不變。換句話說,如果您的一塊板突然斷電或複位,則在重新啟動時,它將自動連接到其對等端以繼續通信。

ESP-NOW支持以下功能:

  • 加密和未加密的單播通信;
  • 混合加密和未加密對等設備;
  • 最多可以承載250-byte有效負載;
  • 發送回饋函數,可以設置為通知應用層在傳輸成功或失敗時。

ESP-NOW技術還具有以下限制:

  • 有限的加密對等體。工作站模式下最多支持10個加密對等體;在SoftAP或SoftAP + Station模式下最多6個;
  • 支持多個未加密的對等方,但是它們的總數應少於20,其中包括已加密的對等方;
  • 有效負載限制為250個bytes

簡而言之,ESP-NOW是一種快速通信協議,可用於在ESP8266板之間交換小消息(最大250 bytes)。

ESP-NOW具有多種用途,您可以在不同的設置中進行單向或雙向通信。

ESP-NOW單向通信

例如,在單向通信中,您可能會遇到以下情形:

  • 一個ESP8266開發板向另一個ESP8266開發板發送數據

這種配置非常容易實現,並且很容易將數據從一塊板發送到另一塊板,例如感測器讀取數據或控制GPIO的ON和OFF命令。

  • 一個“Master” ESP8266將數據發送到多個ESP8266“Slave”

一塊ESP8266開發板向不同的ESP8266開發板發送相同或不同的命令。此配置是建構遙控器之類的理想選擇。整個房屋中可以有幾塊ESP8266板,由一塊主ESP8266板控制。

  • 一個ESP8266“Slave”從多個“Masters”接收數據

如果要將多個感測器節點的數據收集到一個ESP8266板中,則此配置非常理想。例如,可以將其配置為Web Server以顯示來自所有其他板的數據。

注意:在ESP-NOW檔案中,沒有“發送方/主方”和“接收方/從方”之類的東西。每個板都可以是發送者或接收者。只是,為讓內容架構清楚,這裡將使用“發送者”和“接收者”或“主”和“從”這類的術語說明解釋。

ESP-NOW雙向通訊

使用ESP-NOW,每個板可以同時是發送者和接收者。因此,您可以在開發板之間建立雙向通信。

例如,您可以使兩個開發板彼此通信。

也可以在此配置中增加更多開發板,並使它們看起來像一個網絡(所有ESP8266開發板都可以相互通信)。

總而言之,ESP-NOW是建置網絡的理想選擇,在該網絡中,您可以有多個ESP8266開發板相互交換數據。

ESP8266:取得開發板MAC地址 

要通過ESP-NOW進行通信,您需要知道ESP8266接收器的MAC地址。這樣您便知道將信息發送到哪個設備。 每個ESP8266都有一個唯一的MAC地址,這就是我們確定每個板使用ESP-NOW向其發送數據的方式。 要獲取主板的MAC地址,請上傳以下代碼。
// 完成和更改ESP MAC地址的完整說明: 
// http://honeststore.com.tw/blog/esp8266-esp-now/

#include <ESP8266WiFi.h> 

void setup(){
  Serial.begin(115200);
  Serial.println();
  Serial.print("ESP8266 Board MAC Address:  ");
  Serial.println(WiFi.macAddress());
}
 
void loop(){
}

上載程式碼後,以115200的鮑率打開Serial Monitor,然後按ESP8266 RESET按鈕。MAC地址應如下打印:先保存查詢到開發板的MAC地址,因為您需要它通過ESP-NOW將數據發送到正確的開發板。

ESP-NOW與ESP8266的單向點對點通訊 

為了使您開始使用ESP-NOW無線通信,我們將建置一個簡單的專案,展示如何從一個ESP8266向另一個ESP8266發送消息。一個ESP8266將充當“發送方”,另一個ESP8266將充當“接收方”。

我們將發送一個結構,其中包含charintfloatStringboolean類型的變數。然後,您可以修改結構以發送適合您項目的任何變數類型(例如感測器讀取數據或boolean變數以開啟或關閉某些內容)。

為了更好的理解,我們將ESP8266#1稱為“發送方”,將ESP8266#2稱為“接收方”。

這是我們應該包含在發件人草稿圖中的內容:

  1. 初始化ESP-NOW;
  2. 在發送數據時註冊回饋函數– OnDataSent發送消息時將執行功能。可以告訴我們消息是否成功發送;
  3. 增加對等設備(接收方)。為此,您需要知道接收者的MAC地址;
  4. 向對等設備發送消息。

接收方,草稿圖應包括:

  1. 初始化ESP-NOW;
  2. 註冊接收回饋函數(OnDataRecv)。收到消息後將執行的功能。
  3. 在該回饋函數內部,將消息保存到變數中以執行具有該信息的任何任務。

ESP-NOW與設備接收消息或發送消息時調用的回饋函數一起使用(您可以確定消息是否已成功發送或失敗)。

ESP-NOW有用的功能 

以下是最基本的ESP-NOW功能的摘要:
函數名稱和說明
esp_now_init()初始化ESP-NOW。您必須先初始化Wi-Fi,然後再初始化ESP-NOW。如果成功,則返回0。
esp_now_set_self_role(role) role可以是: ESP_NOW_ROLE_IDLE = 0, ESP_NOW_ROLE_CONTROLLER, ESP_NOW_ROLE_SLAVE, ESP_NOW_ROLE_COMBO, ESP_NOW_ROLE_MAX
esp_now_add_peer(uint8 mac_addr,uint8 role,uint8 channel,uint8 key,uint8 key_len) 調用此功能以配對設備。
esp_now_send(uint8 mac_address,uint8 data,int len) 使用ESP-NOW發送數據。
esp_now_register_send_cb()註冊在發送數據時觸發的回饋函數。發送消息後,將調用一個函數–此函數返回傳遞是否成功。
esp_now_register_rcv_cb()註冊在接收數據時觸發的回饋函數。通過ESP-NOW接收到數據後,將調用一個函數。

有關這些功能的更多信息:

ESP8266 NodeMCU發送方草稿圖(ESP-NOW)

以下是ESP8266 NodeMCU Sender開發板的程式碼。將程式碼複製到您的Arduino IDE,上傳前,您需要先進行一些修改。

/*
  Terry Lee
  完整說明請參閱 http://honeststore.com.tw/blog/esp8266-esp-now/
*/

#include <ESP8266WiFi.h> 
#include <espnow.h> 

// 替換成接收方的MAC Address
uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

// 結構範例發送數據必須匹配接收方結構
typedef struct struct_message {
  char a[32];
  int b;
  float c;
  String d;
  bool e;
} struct_message;

// 新建一個訊息傳送結構,變數名稱叫myData
struct_message myData;

unsigned long lastTime = 0;  
unsigned long timerDelay = 2000;  // 發送讀數計時器

// 發送數據時的回饋函數
void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
  Serial.print("Last Packet Send Status: ");
  if (sendStatus == 0){
    Serial.println("Delivery success");
  }
  else{
    Serial.println("Delivery fail");
  }
}
 
void setup() {
  // Init Serial Monitor
  Serial.begin(115200);
 
  // 將設備設置為Wi-Fi工作站
  WiFi.mode(WIFI_STA);

  // Init ESP-NOW
  if (esp_now_init() != 0) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }

  // 一旦Espnow成功初始化,我們將註冊發送回饋函數至獲取數據包的狀態  
  esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
  esp_now_register_send_cb(OnDataSent);
  
  // 註冊同行
  esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_SLAVE, 1, NULL, 0);
}
 
void loop() {
  if ((millis() - lastTime) > timerDelay) {
    // 設定預發送的值
    strcpy(myData.a, "THIS IS A CHAR");
    myData.b = random(1,20);
    myData.c = 1.2;
    myData.d = "Hello";
    myData.e = false;

    // 從ESP-NOW傳送訊息
    esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));

    lastTime = millis();
  }
}

程式碼如何工作

首先,包括 ESP8266WiFi.h 和 espnow.h 庫。

#include <ESP8266WiFi.h> 
#include <espnow.h> 

在下一行中,應插入ESP8266接收器MAC地址。

uint8_t broadcastAddress[] = {0x5C, 0xCF, 0x7F, 0x99, 0x9A, 0xEA};

在我們的例子中,接收者的MAC地址是: 5C:CF:7F:99:9A:EA,但您需要用自己的MAC地址替換該變量。 然後,建立一個包含我們要發送的數據類型的結構。我們稱這種結構struct_message它包含5種不同的變數類型。您可以更改它以發送所需的任何變量類型。

typedef struct struct_message {
  char a[32];
  int b;
  float c;
  String d;
  bool e;
} struct_message;

建一個新的類型變數 struct_message 它被稱作 myData 將存儲變數值。

struct_message myData;

接下來,定義 OnDataSent()功能。這是一個回饋函數,將在發送消息時執行。在這種情況下,無論是否成功發送此消息,都只會印出該消息。

void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
  Serial.print("Last Packet Send Status: ");
  if (sendStatus == 0){
    Serial.println("Delivery success");
  }
  else{
    Serial.println("Delivery fail");
  }
}

在setup()裡,初始化序列監視器以進行調試:

Serial.begin(115200);

將設備設置為Wi-Fi工作站點:

WiFi.mode(WIFI_STA);

初始化ESP:

if (esp_now_init() != 0) {
  Serial.println("Error initializing ESP-NOW");
  return;
}

設置ESP8266角色:

esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);

它接受以下角色: ESP_NOW_ROLE_CONTROLLER, ESP_NOW_ROLE_SLAVE, ESP_NOW_ROLE_COMBO, ESP_NOW_ROLE_MAX

成功初始化ESP-NOW之後,註冊將在發送消息時調用的回饋函數。在這種情況下,我們註冊OnDataSent() 先前建置的功能。

esp_now_register_send_cb(OnDataSent);

然後,與另一個ESP-NOW設備配對以發送數據:

esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_SLAVE, 1, NULL, 0);

esp_now_add_peer 按此順序接受以下參數:mac address,role,Wi-Fi channel,key和key長度。 在loop()裡,我們將每2秒通過ESP-NOW發送一條消息(您可以更改延時時間在 timerDelay 變數)。 首先,我們將變數值設置如下:

strcpy(myData.a, "THIS IS A CHAR");
myData.b = random(1,20);
myData.c = 1.2;
myData.d = "Hello";
myData.e = false;

請記住 myData是一個結構。在這裡,我們分配要在結構內部發送的值。例如,第一行分配一個char,第二行分配一個隨機的Int,一個Float,一個String和一個Boolean變數。 我們建立這種結構來向您展示如何發送最常見的變數類型。您可以更改結構以發送任何其他類型的數據。 最後,發送消息如下:

esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));

loop() 函數裡,每2000毫秒(2秒)執行一次。

if ((millis() - lastTime) > timerDelay) {
  // Set values to send
  strcpy(myData.a, "THIS IS A CHAR");
  myData.b = random(1,20);
  myData.c = 1.2;
  myData.d = "Hello";
  myData.e = false;

  // Send message via ESP-NOW
  esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));

  lastTime = millis();
}

ESP8266 NodeMCU接收器草稿圖(ESP-NOW)

將以下程式碼上傳至ESP8266 NodeMCU接收板。

/*
  Terry Lee
  完整說明請參閱 http://honeststore.com.tw/blog/esp8266-esp-now/
*/

#include <ESP8266WiFi.h> 
#include <espnow.h> 

// 結構範例接收數據必須匹配發送方結構
typedef struct struct_message {
    char a[32];
    int b;
    float c;
    String d;
    bool e;
} struct_message;

// 新建一個訊息接收結構,變數名稱叫myData
struct_message myData;

// 收到數據時將執行的回饋函數
void OnDataRecv(uint8_t * mac, uint8_t *incomingData, uint8_t len) {
  memcpy(&myData, incomingData, sizeof(myData));
  Serial.print("Bytes received: ");
  Serial.println(len);
  Serial.print("Char: ");
  Serial.println(myData.a);
  Serial.print("Int: ");
  Serial.println(myData.b);
  Serial.print("Float: ");
  Serial.println(myData.c);
  Serial.print("String: ");
  Serial.println(myData.d);
  Serial.print("Bool: ");
  Serial.println(myData.e);
  Serial.println();
}
 
void setup() {
  // Initialize Serial Monitor
  Serial.begin(115200);
  
  // 將設備設置為Wi-Fi工作站
  WiFi.mode(WIFI_STA);

  // Init ESP-NOW
  if (esp_now_init() != 0) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }
  
  // 一旦Espnow成功初始化,我們將註冊發送回饋函數至獲取數據包的狀態
  esp_now_set_self_role(ESP_NOW_ROLE_SLAVE);
  esp_now_register_recv_cb(OnDataRecv);
}

void loop() {
  
}

程式碼如何工作

與發送方類似,首先包括以下庫:

#include <ESP8266WiFi.h> 
#include <espnow.h> 

建立一個結構以接收數據。此結構應與發件人草稿圖中定義的結構相同。

typedef struct struct_message {
  char a[32];
  int b;
  float c;
  String d;
  bool e;
} struct_message;

建立一個 struct_message 變數稱為 myData

struct_message myData;

建立一個回饋函數,當ESP8266通過ESP-NOW接收數據時將調用該函數。該函數稱為onDataRecv() 並應接受以下幾個參數:

void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {

我們複製內容將 incomingData 數據變數放入 myData 變數中。

memcpy(&myData, incomingData, sizeof(myData));

現在 myData結構內部包含幾個變數,以及發送方ESP8266發送的值。例如,訪問變數a,我們只需要呼叫 myData.a。 在此範例中,我們僅印出接收到的數據,但是在實際應用中,您可以在顯示器上印出數據。

Serial.print("Bytes received: ");
  Serial.println(len);
  Serial.print("Char: ");
  Serial.println(myData.a);
  Serial.print("Int: ");
  Serial.println(myData.b);
  Serial.print("Float: ");
  Serial.println(myData.c);
  Serial.print("String: ");
  Serial.println(myData.d);
  Serial.print("Bool: ");
  Serial.println(myData.e);
  Serial.println();
}

在 setup()裡,初始化序列通信以進行調試。

Serial.begin(115200);

將設備設置為Wi-Fi工作站。

WiFi.mode(WIFI_STA);

初始化ESP:

if (esp_now_init() != ESP_OK) {
  Serial.println("Error initializing ESP-NOW");
  return;
}

設置ESP8266角色:

esp_now_set_self_role(ESP_NOW_ROLE_SLAVE);

註冊接收數據時將調用的回饋函數。在這種情況下,我們註冊OnDataRecv() 先前建置的功能。

esp_now_register_recv_cb(OnDataRecv);

測試ESP-NOW通信 

將發送方草稿圖上傳到一個開發板,將接收方草稿圖上傳到另一開發板。不要忘記在發送方草稿圖上插入接收者MAC地址。

現在,打開兩個Arduino IDE窗口。一個給接收者,另一個給發送者。打開每個開發板的序列監視器。每個開發板應該是不同的COM端口。

下面就是您在發送方獲得的東西。

下面是您應該在接收端得到的。請注意,Int變數會在每次接收到的讀取數據之間變化(因為我們在發送方將其設置為1-50之間的隨機數)

總結 

在本教程中,您學習了如何將ESP-NOW與ESP8266 NodeMCU控制板一起使用。現在,您可以組合發送方和接收方草稿圖,以便進行雙向通信(每個開發板同時當接收方和發送方)。您還可以使用更多的控制板來在多個控制板之間進行通信。

ESP8266和ESP32板可以使用ESP-NOW通訊協議進行通訊。您只需要將適當的草稿圖上傳到每個控制板上。要了解如何將ESP-NOW與ESP32結合使用,可以閱讀ESP32的ESP-NOW入門指南。

我們希望您對本教程有所幫助。要了解有關ESP8266開發板的更多信息,請確保您了解我們的資源:

  • ESP8266的家庭自動化
  • 使用ESP32和ESP8266進行MicroPython編程
  • 更多ESP8266資源…

謝謝閱讀。

發佈留言