ESP32 ESP-NOW Kết Nối nhiều ESP32 Với Nhau.
PHẦN 1: GIỚI THIỆU.
Tìm hiểu cách sử dụng ESP-NOW để trao đổi dữ liệu giữa các ESP32 được lập trình với Arduino IDE. ESP-NOW là một giao thức truyền thông không kết nối được phát triển bởi Espressif có tính năng truyền gói tin ngắn. Giao thức này cho phép nhiều thiết bị giao tiếp với nhau một cách dễ dàng.
Các hướng giao tiếp như sau:
1. Giao tiếp hai chiều ESP-NOW giữa các bo mạch ESP32
2. ESP-NOW với ESP32: Gửi dữ liệu Từ 1 ESP32 đến nhiều ESP32 (một-nhiều)
3.ESP-NOW với ESP32: Nhận dữ liệu từ nhiều BOARD ESP32(nhiều-một)
ESP-NOW hỗ trợ các tính năng sau:
-Giao tiếp unicast được mã hóa và không được mã hóa;
-Các thiết bị ngang hàng được mã hóa và không được mã hóa hỗn hợp;
-Có thể mang tải trọng lên đến 250 byte;
-Gửi chức năng gọi lại có thể được đặt để thông báo cho lớp ứng dụng về truyền thành công hay thất bại.
Công nghệ ESP-NOW cũng có những hạn chế sau:
-Đồng đẳng được mã hóa hạn chế. 10 đồng nghiệp được mã hóa nhiều nhất được hỗ trợ ở chế độ Trạm; Tối đa là 6 ở chế độ SoftAP hoặc SoftAP + Station;
-Nhiều ứng dụng ngang hàng không được mã hóa được hỗ trợ, tuy nhiên, tổng số của chúng phải nhỏ hơn 20, bao gồm cả các đối tượng được mã hóa;
-Tải trọng được giới hạn ở 250 byte.
Phần 1: ESP-NOW One-Way Communication
(ESP - NOW giao tiếp 1 Chiều ).
Nhược điểm của phương thức này là : Bên nhận có nhận được giữ liệu hay không, bên truyền không biết được.
PHẦN 2 : Một ESP32 “chính - MASTER ” gửi dữ liệu đến nhiều “CON-SLAVES” ESP32.
PHẦN 3 : Nhiều ESP32 “Phụ- slaver” gửi dữ liệu đến Một “Chính-Master” ESP32.
PHẦN 4 : ESP-NOW GIAO TIẾP 2 CHIỀU.
#include "WiFi.h"
void setup(){
Serial.begin(115200);
WiFi.mode(WIFI_MODE_STA);
Serial.println(WiFi.macAddress());
}
void loop(){
}
ESP32 Sender Sketch (ESP-NOW)
#include <esp_now.h>
#include <WiFi.h>
// REPLACE WITH YOUR RECEIVER MAC Address
uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
// Structure example to send data
// Must match the receiver structure
typedef struct struct_message {
char a[32];
int b;
float c;
String d;
bool e;
} struct_message;
// Create a struct_message called myData
struct_message myData;
// callback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
Serial.print("\r\nLast Packet Send Status:\t");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}
void setup() {
// Init Serial Monitor
Serial.begin(115200);
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
// Init ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
// Once ESPNow is successfully Init, we will register for Send CB to
// get the status of Trasnmitted packet
esp_now_register_send_cb(OnDataSent);
// Register peer
esp_now_peer_info_t peerInfo;
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
// Add peer
if (esp_now_add_peer(&peerInfo) != ESP_OK){
Serial.println("Failed to add peer");
return;
}
}
void loop() {
// 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_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
if (result == ESP_OK) {
Serial.println("Sent with success");
}
else {
Serial.println("Error sending the data");
}
delay(2000);
}
uint8_t broadcastAddress[] = {0x30, 0xAE, 0xA4, 0x07, 0x0D, 0x64};
struct_message myData;
Tiếp theo, xác định hàm OnDataSent (). Đây là một hàm gọi lại sẽ được thực thi khi một tin nhắn được gửi đi. Trong trường hợp này, chức năng này chỉ in ra nếu tin nhắn đã được gửi thành công hay chưa.
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) { Serial.print("\r\nLast Packet Send Status:\t"); Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail"); }
Initialize ESP-NOW: ( KHỞI TẠO ESP- NOW THẤT BẠI).
if (esp_now_init() != ESP_OK) { Serial.println("Error initializing ESP-NOW"); return; }
Sau khi khởi tạo thành công ESP-NOW, hãy đăng ký chức năng gọi lại sẽ được gọi khi có tin nhắn được gửi đi. Trong trường hợp này, chúng ta đăng ký hàm OnDataSent () đã được tạo trước đó.
esp_now_register_send_cb(OnDataSent);
esp_now_register_send_cb(OnDataSent);
Sau đó, chúng ta cần ghép nối với một thiết bị ESP-NOW khác để gửi dữ liệu. Đó là những gì chúng Ta làm trong những dòng tiếp theo:
//Register peer esp_now_peer_info_t peerInfo; memcpy(peerInfo.peer_addr, broadcastAddress, 6); peerInfo.channel = 0; peerInfo.encrypt = false; //Add peer if (esp_now_add_peer(&peerInfo) != ESP_OK){ Serial.println("Failed to add peer"); return; }
Trong vòng lặp (), chúng tôi sẽ gửi tin nhắn qua ESP-NOW 2 giây một lần (bạn có thể thay đổi thời gian trễ này).Đầu tiên, chúng tôi đặt các giá trị biến như sau:
esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
Kiểm tra xem tin nhắn đã được gửi thành công chưa:
delay(2000);
ESP32 Receiver Sketch (ESP-NOW)
#include <esp_now.h>
#include <WiFi.h>
// Structure example to receive data
// Must match the sender structure
typedef struct struct_message {
char a[32];
int b;
float c;
String d;
bool e;
} struct_message;
// Create a struct_message called myData
struct_message myData;
// callback function that will be executed when data is received
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int 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);
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
// Init ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
// Once ESPNow is successfully Init, we will register for recv CB to
// get recv packer info
esp_now_register_recv_cb(OnDataRecv);
}
void loop() {
}
struct_message myData;
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
memcpy(&myData, incomingData, sizeof(myData));
Đăng ký một hàm gọi lại sẽ được gọi khi dữ liệu được nhận. Trong trường hợp này, chúng tôi đăng ký hàm OnDataRecv () đã được tạo trước đó.
esp_now_register_recv_cb(OnDataRecv);