在VsCode中实现ESP-NOW通信

ESP-NOW介绍

        ESP-NOW 是 Espressif Systems 针对其 ESP8266 和 ESP32 芯片开发的一种低功耗无线通信协议。它允许设备之间进行直接的点对点通信,而不需要中间的路由器或接入点。这种协议使用 Wi-Fi 控制帧进行数据传输,具有非常低的延迟和功耗,非常适合需要快速响应和低能耗的应用。

        具体来讲ESP-NOW有下列优点:

低功耗:ESP-NOW 的设计初衷之一是低功耗。它通过使用 Wi-Fi 的控制帧进行通信,显著降低了能耗。

低延迟:ESP-NOW 的通信延迟很低,通常在几毫秒内。这使得它非常适合实时性要求高的应用,例如传感器数据采集和远程控制。

点对点通信:设备之间可以直接通信,无需依赖中间的路由器或接入点。这简化了网络架构,提高了通信效率和可靠性。

 多对多通信:ESP-NOW 允许一个设备同时与多个设备通信,支持最多 20 个对等设备。这使得它非常适合构建复杂的传感器网络或智能家居系统。

加密支持:ESP-NOW 支持加密通信,可以确保数据传输的安全性,防止数据被截获或篡改。

同时esp32也会有一些缺点,使用时请大家根据实际情况,选择合适的通信方式。

通信距离有限:由于使用的是 Wi-Fi 控制帧,通信距离可能比传统 Wi-Fi 要短。

带宽有限:适用于小数据量的传输,不适合大数据量的高速传输。

网络稳定性:在某些情况下,网络环境的干扰可能会影响通信的稳定性。

代码介绍

        这里我将在VsCode中使用platformio来为大家讲解ESP-NOW通信具体如何通过代码来实现

首先,我们需要两个esp32单片机,一个作为接收端,另一个作为发射端。然后,我们需要知道接收端的Mac地址,才能够知道发送端的信息应该发送给谁。我以使接收端的板载LED闪烁为例为大家讲解esp-now通信。

获取Mac地址

#include <Arduino.h>
#include <esp_now.h>
#include <WiFi.h>

void setup() {
Serial.begin(115200);//初始化串口
String macAddress = WiFi.macAddress();//获取mac地址
Serial.print(macAddress);//通过串口打印mac信息
}

void loop() {
}

 点击上传代码,打开串口监视器即可以得到esp32的mac地址,如果串口没有输出的话,可以按一下单片机上的复位按键,重新运行程序。

如图所示,这是我的单片机的mac地址,实际使用时需要在前面加上0x,表示16进制。

发送端代码详解

        下面我将逐段逐句为大家讲解代码:

引入头文件:
#include <Arduino.h>
#include <esp_now.h>
#include <WiFi.h>
创建一个结构体变量,配置peer信息:

这里的peer我们可以简单理解为通信的设备

// 创建一个结构体变量,用于配置 peer 信息
esp_now_peer_info_t peerInfo;

// 定义发送数据类型结构体
typedef struct struct_message {
  int LED; // LED 状态:1 表示点亮,0 表示熄灭
} struct_message;

// 创建一个结构体变量,用于存储发送的数据
struct_message myData;
定义接收设备的mac地址:
// 定义接收设备的 MAC 地址
uint8_t peerMac[] = {0xD0, 0xEF, 0x76, 0xEF, 0xCF, 0xAC};
初始化代码:

        在setup函数里对espnow以及串口通信进行初始化。 

void setup() {
  Serial.begin(115200); // 初始化串口通信
  WiFi.mode(WIFI_STA); // 设置 WiFi 模式为 STA 模式
  
  // 初始化 ESP-NOW
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }

  // 设置对等设备信息
  memcpy(peerInfo.peer_addr, peerMac, 6); // 将接收设备的 MAC 地址复制到 peerInfo 中
  peerInfo.ifidx = WIFI_IF_STA; // 设置 WiFi 接口为 STA 模式
  peerInfo.channel = 0; // 设置通道为 0(默认通道)
  peerInfo.encrypt = false; // 不加密

  // 添加对等设备到 ESP-NOW
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add peer");
    return;
  }

  myData.LED = 0; // 初始 LED 状态为点亮
}
 循环发送数据包并且转换LED灯的状态:

        在loop函数中我们发送数据包,并且通过返回值检测发送是否成功,再将LED灯的状态取反保证其在0和1之间切换。

void loop() {
  // 发送数据包
  esp_err_t result = esp_now_send(peerMac, (uint8_t*)&myData, sizeof(myData));

  // 打印发送结果
  if (result == ESP_OK) {
    Serial.println("Send success");
  } else {
    Serial.println("Send fail");
  }

  delay(1000); // 每 1 秒发送一次
  
  // 取反 LED 状态,确保在 0 和 1 之间切换
  myData.LED = ~myData.LED & 0x01;

  delay(1000); // 每 2 秒发送一次
}
发送端完整代码:
#include <Arduino.h>
#include <esp_now.h>
#include <WiFi.h>

// 创建一个结构体变量,用于配置 peer 信息
esp_now_peer_info_t peerInfo;

// 定义发送数据类型结构体
typedef struct struct_message {
  int LED; // LED 状态:1 表示点亮,0 表示熄灭
} struct_message;

// 创建一个结构体变量,用于存储发送的数据
struct_message myData;

// 定义接收设备的 MAC 地址
uint8_t peerMac[] = {0xD0, 0xEF, 0x76, 0xEF, 0xCF, 0xAC};

void setup() {
  Serial.begin(115200); // 初始化串口通信
  WiFi.mode(WIFI_STA); // 设置 WiFi 模式为 STA 模式
  
  // 初始化 ESP-NOW
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }

  // 设置对等设备信息
  memcpy(peerInfo.peer_addr, peerMac, 6); // 将接收设备的 MAC 地址复制到 peerInfo 中
  peerInfo.ifidx = WIFI_IF_STA; // 设置 WiFi 接口为 STA 模式
  peerInfo.channel = 0; // 设置通道为 0(默认通道)
  peerInfo.encrypt = false; // 不加密

  // 添加对等设备到 ESP-NOW
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add peer");
    return;
  }

  myData.LED = 0; // 初始 LED 状态为点亮
}

void loop() {
  // 发送数据包
  esp_err_t result = esp_now_send(peerMac, (uint8_t*)&myData, sizeof(myData));

  // 打印发送结果
  if (result == ESP_OK) {
    Serial.println("Send success");
  } else {
    Serial.println("Send fail");
  }

  delay(1000); // 每 1 秒发送一次
  
  // 取反 LED 状态,确保在 0 和 1 之间切换
  myData.LED = ~myData.LED & 0x01;

  delay(1000); // 每 2 秒发送一次
}

接收端代码详解

        接收端的代码与发送端类似,我们需要定义结构体变量、配置peer信息、接收mac地址、初始化串口及espnow、接受数据包。所以这里我直接放上完整的接收端代码,我们需要注意的是接收端的代码必须有回调函数,然而发射端不一定需要,因为接收端每一次收到信息之后就会调用回调函数。

#include <Arduino.h>
#include <esp_now.h>
#include <WiFi.h>

// 定义一模一样的结构体来存储接收到的数据
typedef struct struct_message {
  int LED; // LED 状态:1 表示点亮,0 表示熄灭
} struct_message;

// 创建一个一模一样的结构体变量来存储接收到的数据
struct_message myData;

// 回调函数,当接收到数据时调用
void OnDataRecv(const uint8_t* mac, const uint8_t* incomingData, int len) {
  // 将接收到的数据复制到 myData 结构体变量中
  memcpy(&myData, incomingData, sizeof(myData));

  // 打印接收到的数据长度和LED状态
  Serial.print("Bytes received: ");
  Serial.println(len);
  Serial.print("LED state: ");
  Serial.println(myData.LED);

  // 根据接收到的数据控制 LED 的亮灭
  if (myData.LED == 1) {
    digitalWrite(2, HIGH); // 点亮 LED
  } else {
    digitalWrite(2, LOW); // 熄灭 LED
  }
}

void setup() {
  Serial.begin(115200); // 初始化串口通信

  // 设置板载 LED 引脚为输出模式
  pinMode(2, OUTPUT);

  // 初始化 WiFi 模块,进入 STA 模式
  WiFi.mode(WIFI_STA);

  // 初始化 ESP-NOW,并检查是否成功
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }

  // 注册接收数据的回调函数 当esp32接收到了数据之后会再次调用回调函数以刷新数据
  esp_now_register_recv_cb(OnDataRecv);

  Serial.println("ESP-NOW Initialized");
}

void loop() {
  // 空的主循环逻辑
}

实验现象

        

通过ESP-NOW实现单片机间的通信

总结

        通过LED闪烁这一个简单的实验,我们学习了espnow通信,为我们日后的物联网开发学习打下来坚实的基础,如果有不懂的地方可以私信。

  • 26
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值