一、ESP-NOW介绍
乐鑫官网:
(写完上传第一遍报错,不知道这个地方是不是广告,没有打广告)
乐鑫官网提供 Wi-Fi、蓝牙芯片和 AIoT 解决方案 I 乐鑫科技 (espressif.com.cn)https://www.espressif.com.cn/zh-hans/
ESP-NOW 是由乐鑫开发的无线通信协议,可以使多个设备在没有或不使用 Wi-Fi 的情况下进行通信。当设备配对后,设备之间的连接是持续的、点对点的,并且不需要握手协议。ESP-NOW作为短数据传输、无连接的快速通信技术,当某一设备突然断电之后,通电重启,会自动连接到对应节点中,实现快速通信。
ESP-NOW特性如下:
- 单播包加密或单播包不加密通信;
- 加密配对设备和非加密配对设备混合使用;
- 可携带最长为 250 字节的有效 payload 数据;
- 支持设置发送回调函数以通知应用层帧发送失败或成功。
ESP-NOW目前的局限性:
- 暂时不支持广播包;
- 加密配对设备有限制,Station 模式下最多支持10 个加密配对设备;SoftAP 或 SoftAP + Station 混合模式下最多支持 6 个加密配对设备。非加密配对设备支持若干,与加密设备总数和不超过 20 个;
- 有效 payload 限制为 250 字节。
ESP-NOW通信方式:一对一通信、一对多单向通信、多对一单向通信、双向通信。
参考网站:Getting Started with ESP-NOW (ESP32 with Arduino IDE) | Random Nerd Tutorials
作为点对点通信的ESP-NOW,在发送数据的时候必须指定接收设备,在网络通信中,初步了解设备间可以依靠IP地址和端口号作为身份证进行通信。MAC地址就是ESP-NOW通信的身份证,模块的MAC地址是唯一的,依此进行通信。
二、一对一单向通信
单向通信是通信的一方接收数据,另一方发送数据。示意图如上图所示。
2、1 获取模块的MAC地址
打开VScode,安装PlatformIO。相比于之前使用的编译器arduino,PlatformIO更加智能。
新建工程
选择对应开发板,文件保存位置,点击新建。第一次添加开发板时间会很长,很慢,请耐心等待,当然,网要快一点最好。
建立工程完成后,文件夹如下:
设置波特率,最好先添加波特率设置,不然在程序里设置了,串口还是乱码。
找到platformio.ini文件,添加一句
monitor_speed=115200 波特率设置为115200
这时我们打开 main.cpp文件,添加程序如下获取MAC地址
#include <Arduino.h>
#include <ESP8266WiFi.h>
void setup(){
Serial.begin(115200);
WiFi.mode(WIFI_MODE_STA);
Serial.println("hello");//加打印hello原因是模块刚上电有点乱码
Serial.println(WiFi.macAddress());
}
void loop(){
}
点击对钩编译,运行程序。
将程序上传,查看MAC地址 如下
接收方模块MAC地址:
30:83:98:B1:D1:93 由于我们做的是单向通信,只需一个Mac地址
2、2 程序
我加了一个小灯,便于观察发送消息状况。
发送端依次发送让接收方亮红、黄、绿灯消息,在让其一起灭灯。
发送方程序
#include <ESP8266WiFi.h>
#include <espnow.h>
//对方MAC地址
uint8_t broadcastAddress[] = {0x30, 0x83, 0x98, 0xB1, 0xD1, 0x93};
typedef struct struct_message {
int a;
String d;
} struct_message;
//创建一个新的类型变量
struct_message myData;
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() {
//初始化串行监视器以进行调试
Serial.begin(115200);
//将设备设置为Wi-Fi站点
WiFi.mode(WIFI_STA);
//立即初始化ESP
if (esp_now_init() != 0) {
Serial.println("Error initializing ESP-NOW");
return;
}
esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
//先前创建的功能。
esp_now_register_send_cb(OnDataSent);
//与另一个ESP-NOW设备配对以发送数据
esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_SLAVE, 1, NULL, 0);
}
void loop() {
//配置要发送的值
myData.a = 4;
//发送消息
esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
//延时两秒
delay(3000);
myData.a = 5;
//发送消息
esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
//延时两秒
delay(3000);
myData.a = 2;
//发送消息
esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
//延时两秒
delay(3000);
myData.a = 0;
esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
delay(2000);
}
接收方程序
#include <ESP8266WiFi.h>
#include <espnow.h>
int r = 4;
int g = 5;
int y = 2;
typedef struct struct_message {
int a;
String d;
} struct_message;
//创建结构体变量
struct_message myData;
//创建一个回调函数作为接收数据后的串口显示
void OnDataRecv(uint8_t * mac, uint8_t *incomingData, uint8_t len) {
memcpy(&myData, incomingData, sizeof(myData));
Serial.print("String: ");
Serial.println(myData.d);
Serial.println(myData.a);
//接收数据亮灯关灯
if(myData.a ==0){
Serial.println("122");
digitalWrite(4, 0);
digitalWrite(5, 0);
digitalWrite(2, 0);
}
if(myData.a != NULL){
digitalWrite(myData.a, 1);
delay(2000);
}
}
void setup() {
//初始化窗口
Serial.begin(115200);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(2, OUTPUT);
//设置ESP8266模式
WiFi.mode(WIFI_STA);
//初始化 ESP-NOW
if (esp_now_init() != 0) {
Serial.println("Error initializing ESP-NOW");
return;
}
//设置ESP8266角色:
esp_now_set_self_role(ESP_NOW_ROLE_SLAVE);
//先前创建的功能 测试ESP-NOW通信
esp_now_register_recv_cb(OnDataRecv);
}
void loop() {
}
实验现象:
1、断电重启自动连接,在视频结尾我有测试。
2、发送方通过MAC给接收方发消息,消息收发稳定。
esp8266 ESP-NOW通信测试视频
完整工程下载:(使用arduino编译或者复制代码vscode编译也可)