ESP8266-Arduino网络编程实例-ESP-Now点对点单向通信

ESP-Now点对点单向通信

在面的文章中,对ESP-Now做了详细的介绍。ESP-Now有四种通信方式:One-Way(点对点单向)、Two-Way(点对点双向)、One-to-Many(一对多)和Many-to-One(多对一)。本文将详细介绍如何使用One-Way通信方式。

1、硬件准备

  • ESP8266 NodeMCU开发板两块
  • 数据线两条

2、软件准备

  • Arduino IDE或VSCode + PlatformIO

在前面的文章中,对如何搭建ESP8266开发环境做了详细的介绍,请参考:

ESP8266 NodeMCU的引脚介绍在前面的文章中做了详细的介绍,请参考:

3、代码实现

在实现设备通信之前,需要查询ESP8266本机的MAC地址:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <ESP8266WiFi.h>

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

void loop(){

}

ESP-Now的One-Way通信方式,一个通信节点作为主机,另一个通信节点作为机。主机负责发向从机发送数据,从机接收主机发送过来的数据,因此主机和从机通信代码需要分开。

1)主机通信代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <ESP8266WiFi.h>
#include <espnow.h>

// 从机MAC地址,需要根据从机实际的MAC地址替换
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;


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() {
// 初始化串口
Serial.begin(115200);

// 设置WiFi工作模式
WiFi.mode(WIFI_STA);

// 初始化ESP-Now
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\_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\_send(broadcastAddress, (uint8\_t \*) &myData, sizeof(myData));

lastTime = millis();
}
}

在实例代码中,主机核心逻辑如下:

a)初始化ESP-Now

1
2
3
4
5
6
// 初始化ESP-Now
if (esp\_now\_init() != 0) {
Serial.println("Error initializing ESP-NOW");
return;
}

b)设置通信方式

1
2
3
// 设置通信模式,这里设置为主机模式(发送者)
esp\_now\_set\_self\_role(ESP_NOW_ROLE_CONTROLLER);

c)注册数据发送回调

1
2
3
// 注册数据发送回调函数
esp\_now\_register\_send\_cb(OnDataSent);

d)添加从机通信节点

1
2
3
// 添加从机通信节点
esp\_now\_add\_peer(broadcastAddress, ESP_NOW_ROLE_SLAVE, 1, NULL, 0);

e)向从机发送数据

1
2
3
// 发送消息
esp\_now\_send(broadcastAddress, (uint8\_t \*) &myData, sizeof(myData));

2)从机通信代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#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;

// 数据接收回调
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() {
// 初始化串口
Serial.begin(115200);

// 设置WiFi工作模式
WiFi.mode(WIFI_STA);

// 初始化 ESP-NOW
if (esp\_now\_init() != 0) {
Serial.println("Error initializing ESP-NOW");
return;
}

// 设置通信方式
esp\_now\_set\_self\_role(ESP_NOW_ROLE_SLAVE);
// 注册数据接收回调函数
esp\_now\_register\_recv\_cb(OnDataRecv);
}

void loop() {

}


从机(数据接收)设备的步骤相对简单一些:

a)初始化ESP-Now

1
2
3
4
5
6
// 初始化 ESP-NOW
if (esp\_now\_init() != 0) {
Serial.println("Error initializing ESP-NOW");
return;
}

b)设置通信方式

1
2
3
// 设置通信方式
esp\_now\_set\_self\_role(ESP_NOW_ROLE_SLAVE);

c)注册数据接收回调函数

1
2
3
// 注册数据接收回调函数
esp\_now\_register\_recv\_cb(OnDataRecv);

文章来源: https://iotsmart.blog.csdn.net/article/details/127506046