ESP-NOW 协议介绍及应用

什么是ESP-NOW

ESP-NOW 是由乐鑫开发的一款无线通信协议,可以使多个设备在没有或不使用 Wi-Fi 的情况下进行通信。这种协议类似常见于无线鼠标中的低功耗 2.4GHz 无线连接——设备在进行通信之前要进行配对。配对之后,设备之间的连接是持续的、点对点的,并且不需要握手协议。

使用了 ESP-NOW 通信之后,如果某一个设备突然断电之后,只要它一旦重启,就是自动连接到对应的节点中重新进行通信。

传输距离可达200米。

ESP-NOW 支持如下特性:

  • 单播包加密或单播包不加密通信;
  • 加密配对设备和非加密配对设备混合使用;
  • 可携带最长为 250 字节的有效 payload 数据;
  • 支持设置发送回调函数以通知应用层帧发送失败或成功。

ESP-NOW 支持多种通信方式:

  • 一对一单向通信
  • 一对多单向通信
  • 多对一单向通信
  • 双向通信

多对一通信

多对一单向通信

ESP-NOW应用流程

实现最基础的ESP-NOW传输,我们需要准备两块ESP32开发板,其中一块作为发送端,另一块作为接收端。后续可以继续添加ESP32作为发送/接受端。

然后编写以下三个项目编译上载到ESP32中:

获取接收端MAC地址

获取MAC地址代码

    #include "WiFi.h"
    void setup() {
      Serial.begin(115200);
      WiFi.mode(WIFI_MODE_STA);
      Serial.println(WiFi.macAddress());
    }
    void loop(){}
  

然后在串口看到打印的接收端MAC地址,保存记录。

接收端代码部署

接受数据并进行相应处理。

接收端代码

struct MessageData{
  int x;
  int y;
};
MessageData messageData;

void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) { if (len == 0){ return; } memcpy(&messageData, incomingData, sizeof(messageData)); String inputData ; inputData = inputData + "values " + messageData.x + " " + messageData.y; Serial.println(inputData); }

void setup() { Serial.begin(115200); WiFi.mode(WIFI_STA); // Init ESP-NOW if (esp_now_init() != ESP_OK) { Serial.println("Error initializing ESP-NOW"); return; } Serial.println("initializing ESP-NOW"); esp_now_register_recv_cb(OnDataRecv); }

发送端代码部署

  1. 设置发送目标的MAC地址
  2. 进行配对
  3. 准备发送数据
  4. 循环进行发送
发送端代码

// REPLACE WITH YOUR RECEIVER MAC Address
uint8_t receiverMacAddress[] = {0x24,0x0A,0xC4,0x16,0x0C,0xF8};  //24:0A:C4:16:0C:F8

struct MessageData { int x; int y; };

MessageData messageData;

// callback when data is sent void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status){ Serial.print("\r\nLast Packet Send Status:\t "); Serial.println(status); Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Message sent" : "Message failed"); }

void setup() { Serial.begin(115200); WiFi.mode(WIFI_STA); // Init ESP-NOW if (esp_now_init() != ESP_OK) { Serial.println("Error initializing ESP-NOW"); return; } else{ Serial.println("Succes: Initialized ESP-NOW"); } esp_now_register_send_cb(OnDataSent); // Register peer esp_now_peer_info_t peerInfo; memcpy(peerInfo.peer_addr, receiverMacAddress, 6); peerInfo.channel = 0;
peerInfo.encrypt = false; peerInfo.ifidx = WIFI_IF_STA; // Add peer
if (esp_now_add_peer(&peerInfo) != ESP_OK){ Serial.println("Failed to add peer"); return; } else{ Serial.println("Succes: Added peer"); }
}

void loop() { messageData.x = 11; messageData.y = 22; esp_err_t result = esp_now_send(receiverMacAddress, (uint8_t *) &messageData, sizeof(messageData)); if (result == ESP_OK) { Serial.println("Sent with success"); } else { Serial.println(result); Serial.println("Error sending the data"); }
delay(1000); }


本文章使用limfx的vscode插件快速发布