ESP-NOW 是由乐鑫开发的另一款无线通信协议,可以使多个设备在没有或不使用 Wi-Fi 的情况下进行通信。这种协议类似常见于无线鼠标中的低功耗 2.4GHz 无线连接——设备在进行通信之前要进行配对。配对之后,设备之间的连接是持续的、点对点的,并且不需要握手协议。它是一种短数据传输、无连接的快速通信技术,可以让低功耗控制器直接控制所有智能设备而无需连接路由器,适用于智能灯、遥控控制、传感器数据回传等场景。
ESP-NOW 是点对点的通讯方式,在发送数据时需要指定接收设备,这好比你给对方发送 QQ 消息必须知道对方的 QQ 号一样。在这里我们一般通过设备的 MAC 地址作为区分不同接收设备的凭证。那什么是 MAC 地址呢?MAC 地址也叫物理地址、硬件地址,每个设备的 MAC 地址在出厂时都是不同的。
下面我们通过 Arduino 代码来获取 ESP32 开发板的 MAC 地址:
c++#include <WiFi.h>
void setup() {
Serial.begin(9600);
Serial.println();
#ifdef ESP8266
Serial.print("ESP8266 Board MAC Address: ");
Serial.println(WiFi.macAddress());
#elif defined ESP32
WiFi.mode(WIFI_MODE_STA);
Serial.print("ESP32 Board MAC Address: ");
Serial.println(WiFi.macAddress());
#endif
}
void loop() {
}
打开串口监视器,就可获得接收端开发板的 MAC 地址:
获取到 MAC 地址后,我们先来看看如何编写发送数据的程序。
C++#include <WiFi.h>
#include <esp_now.h>
// 设置掌控板声音传感器与光线传感器引脚编号
const int soundPin = 36;
const int lightPin = 39;
// 设置数据结构体
typedef struct struct_message {
String board_name;
double light;
double sound;
} struct_message;
struct_message myData;
// 接收设备的 MAC 地址
uint8_t broadcastAddress[] = { 0xE0, 0x5A, 0x1B, 0x60, 0x29, 0xC0 };
// 数据发送回调函数
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
char macStr[18];
Serial.print("Packet to: ");
snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
Serial.println(macStr);
Serial.print("Send status: ");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
Serial.println();
}
void setup() {
Serial.begin(9600);
// 初始化 ESP-NOW
WiFi.mode(WIFI_STA);
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
// 设置发送数据回调函数
esp_now_register_send_cb(OnDataSent);
// 绑定数据接收端
esp_now_peer_info_t peerInfo;
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
peerInfo.ifidx = WIFI_IF_STA; //其他例程没这行,造成配对不成功
// 检查设备是否配对成功
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add peer");
return;
}
}
void loop() {
// 设置要发送的数据
myData.board_name = "mPython_#1";
myData.light = analogRead(lightPin);
myData.sound = analogRead(soundPin);
// 发送数据
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(1000);
}
接下来我们看看接收端的程序如何编写。
C++#include <WiFi.h>
#include <esp_now.h>
// 设置数据结构体
typedef struct struct_message {
String board_name;
double light;
double sound;
} struct_message;
struct_message myData;
// 数据接收回调函数
void OnDataRecv(const uint8_t *mac, const uint8_t *incomingData, int len) {
memcpy(&myData, incomingData, sizeof(myData));
Serial.print("board_name: ");
Serial.println(myData.board_name);
Serial.print("light: ");
Serial.println(myData.light);
Serial.print("sound:");
Serial.println(myData.sound);
Serial.println();
}
void setup() {
Serial.begin(9600);
// 初始化 ESP-NOW
WiFi.mode(WIFI_STA);
if (esp_now_init() != 0) {
Serial.println("Error initializing ESP-NOW");
return;
}
// 设置接收数据回调函数
esp_now_register_recv_cb(OnDataRecv);
}
void loop() {
}
在两块 ESP32 开发板中分别上传发送和接收的程序,然后打开串口监视器来查看一下效果。
本文作者:可乐
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!