ESP32 使用NOW进行一对一双向通讯互发数据的例子
目录
实现效果
在之前的例程中,实现了ESP32NOW一对一的单向通讯,一个ESP32负责发送数据,一个ESP32负责接收数据。
https://lingshunlab.com/book/esp32/esp32-now-introduce-and-one-way-communication
现在,这个例程要实现ESP32NOW一对一的双向通讯,每个ESP32既要负责发送数据,又要负责接收数据。
注意!数据能够相互传送的条件是他们的数据结构必须是一样的,并且数据大小不能超过250字节。
确认MAC地址
首先,找到各自ESP32的MAC地址,可以使用以下链接的程序找到ESP32的MAC地址(或者在初始化NOW之前改变当前的ESP32的MAC地址,本文并不关注这一点)
上传获取MAC地址的程序,查看串口输出,可以看到类似的信息,
例如,在我的ESP32上这就是MAC地址:E0:5A:1B:6B:49:9C
用同样的方法获取其他ESP32的MAC地址,并且记录区分好每一块ESP32,经常搞错地址而导致通讯失败。
程序修改
双向通讯的程序其实非常简单,就是把在ESP32NOW一对一 单向通讯的发送和接受数据的2个程序,合并成一个程序,并且互相定义接受端的mac地址即可,例如:
ESP32-A的接收端MAC地址写ESP32-B的
ESP32-B的接收端MAC地址写ESP32-A的
完整代码
以下是已经合成完整的代码,
切记把broadcastAddress中的地址替换成你各自接收端的ESP32的MAC地址。
然后分别把程序上传到ESP32。
// Welcome to lingshunlab.com
// 完整说明 :https://lingshunlab.com/book/esp32/esp32-now-introduce-and-one-way-communication
// 加载需要的库
#include <esp_now.h>
#include <WiFi.h>
// 定义接收端的mac地址,这里的地址请替换成你的接收端ESP32的MAC地址
uint8_t broadcastAddress[] = {0xC8, 0xF0, 0x9E, 0xF1, 0x35, 0xF0};
// 接收数据的结构示例
// 在C中使用 typedef struct 定义一个结构体类型,名为struct_message
// 必须与发送方的结构相匹配一致
typedef struct struct_message {
char a[40];
int b;
float c;
bool d;
} struct_message;
// 创建 结构为struct_message的myData变量
struct_message myData;
// 声明对等网络信息实体类变量
esp_now_peer_info_t peerInfo;
// 当发送信息时,触发的回调函数
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 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("Bool: ");
Serial.println(myData.d);
Serial.println();
}
void setup() {
// 设置串口波特率
Serial.begin(115200);
// 设置设备WIFI模式为WIFI_STA
WiFi.mode(WIFI_STA);
// 初始化ESPNOW
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
// 配置对等(对等点)网络
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
// 添加对等(对等点)网络
if (esp_now_add_peer(&peerInfo) != ESP_OK){
Serial.println("Failed to add peer");
return;
}
// 当ESPNOW初始化成功,我们将会注册一个回调函数(callback,CB)
// 获得数据包的发送情况
esp_now_register_send_cb(OnDataSent);
// 当ESPNOW初始化成功,我们将会注册一个回调函数(callback,CB)
// 获得回收的包装信息
esp_now_register_recv_cb(OnDataRecv);
}
void loop() {
// 赋值需要发送的变量数据
// 可以设置不同的数值,在串口中查看数据,确认是否互相能通讯
strcpy(myData.a, "Welcome to Lingshunlab.com via A or B");
myData.b = random(1,20);
myData.c = 11.11;
myData.d = false;
// 通过ESPNOW发送信息
esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
// 根据 result 返回结果判断是否发送成功
if (result == ESP_OK) {// 当 发送成功 时
Serial.println("Sent with success");
}
else { // 当 发送失败 时
Serial.println("Error sending the data");
}
delay(2000);
}
两个ESP32都连接电脑,配置好串口,即可看到两个ESP32在互发信息。