回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页

【Arduino 动手做】ESP-NOW与ESP32:板间最简单的无线通信 简单

头像 驴友花雕 2025.06.24 11 0

这里将向您展示如何使用 ESP-NOW 通信协议在两个 ESP32 板之间建立双向通信。例如,两个 ESP32 板将交换传感器读数(在开阔场地的范围可达 220 米 ~ 722 英尺)。

ESP-NOW 简介
ESP-NOW 是乐鑫开发的一种无连接通信协议,具有短数据包传输的特点。此协议使多个设备能够在不使用 Wi-Fi 的情况下相互通信。

这是一种快速通信协议,可用于在 ESP32 板之间交换小消息(最大 250 字节)。ESP-NOW 用途广泛,您可以采用不同的安排进行单向或双向通信。
在本教程中,我们将向您展示如何在两个 ESP32 板之间建立双向通信。

注意:请阅读我们的 ESP-NOW 入门指南,了解有关 ESP32 的 ESP-NOW 协议的完整介绍。
项目概况

■ 在这个项目中,我们将有两个 ESP32 板。每块板都连接到一个 OLED 显示屏和一个 BME280 传感器;
■ 每个板子都从相应的传感器获取温度、湿度和压力读数;
■ 每个开发板都通过 ESP-NOW 将其读数发送到另一个开发板;
■ 当电路板收到读数时,它会将其显示在 OLED 显示屏上;
■ 发送读数后,如果消息成功传递,则板会显示在 OLED 上;
■ 每个板都需要知道另一个板的 MAC 地址才能发送消息。

在此示例中,我们在两个板之间使用双向通信,但您可以向此设置添加更多板,并让所有板相互通信。
先决条件
在继续此项目之前,请确保检查以下先决条件。
ESP32 插件 Arduino IDE
我们将使用 Arduino IDE 对 ESP32 进行编程,因此在继续本教程之前,您应该在 Arduino IDE 中安装 ESP32 插件。请按照以下指南作:
■ 在 Arduino IDE 中安装 ESP32 开发板(Windows、Mac OS X 和 Linux)
安装库
在 Arduino IDE 中安装以下库。这些库可以通过 Arduino Library Manager 进行安装。转到 Sketch > Include Library> Manage Libraries 并搜索库名称。
■ OLED 库(ESP32 OLED 指南):Adafruit_SSD1306 库和 Adafruit_GFX 库
■ BME280 库(ESP32 BME280 指南):Adafruit_BME280 库和 Adafruit 统一传感器库

所需零件
对于本教程,您需要以下部分:
■ 2 个 ESP32 开发板(阅读最佳 ESP32 开发板)
■ 2 个 BME280 传感器(BME280 完整指南)
■ 2 个 0.96 英寸 OLED 显示器(OLED 完整指南)
■ 面包板
■ 跳线
您可以使用前面的链接或直接访问 MakerAdvisor.com/tools 以最优惠的价格找到适合您项目的所有零件!

获取 Boards MAC 地址
要在每个板之间发送消息,我们需要知道它们的 MAC 地址。每个开发板都有一个唯一的 MAC 地址(了解如何获取和更改 ESP32 MAC 地址)。

 

00.jpg
01.jpg
02.jpg
03.jpg
04.jpg
05.jpg
06.jpg
08.jpg

项目代码

 

 

代码
/*
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete project details at https://RandomNerdTutorials.com/esp-now-two-way-communication-esp32/
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
#include <esp_now.h>
#include <WiFi.h>

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128  // OLED display width, in pixels
#define SCREEN_HEIGHT 64  // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

Adafruit_BME280 bme;

// REPLACE WITH THE MAC Address of your receiver 
uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

// Define variables to store BME280 readings to be sent
float temperature;
float humidity;
float pressure;

// Define variables to store incoming readings
float incomingTemp;
float incomingHum;
float incomingPres;

// Variable to store if sending data was successful
String success;

//Structure example to send data
//Must match the receiver structure
typedef struct struct_message {
    float temp;
    float hum;
    float pres;
} struct_message;

// Create a struct_message called BME280Readings to hold sensor readings
struct_message BME280Readings;

// Create a struct_message to hold incoming sensor readings
struct_message incomingReadings;

esp_now_peer_info_t peerInfo;

// 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 == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
  if (status ==0){
    success = "Delivery Success :)";
  }
  else{
    success = "Delivery Fail :(";
  }
}

// Callback when data is received
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
  memcpy(&incomingReadings, incomingData, sizeof(incomingReadings));
  Serial.print("Bytes received: ");
  Serial.println(len);
  incomingTemp = incomingReadings.temp;
  incomingHum = incomingReadings.hum;
  incomingPres = incomingReadings.pres;
}
 
void setup() {
  // Init Serial Monitor
  Serial.begin(115200);

  // Init BME280 sensor
  bool status = bme.begin(0x76);  
  if (!status) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }

  // Init OLED display
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { 
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }
 
  // Set device as a Wi-Fi Station
  WiFi.mode(WIFI_STA);

  // Init ESP-NOW
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }

  // Once ESPNow is successfully Init, we will register for Send CB to
  // get the status of Trasnmitted packet
  esp_now_register_send_cb(OnDataSent);
  
  // Register peer
  memcpy(peerInfo.peer_addr, broadcastAddress, 6);
  peerInfo.channel = 0;  
  peerInfo.encrypt = false;
  
  // Add peer        
  if (esp_now_add_peer(&peerInfo) != ESP_OK){
    Serial.println("Failed to add peer");
    return;
  }
  // Register for a callback function that will be called when data is received
  esp_now_register_recv_cb(esp_now_recv_cb_t(OnDataRecv));
}
 
void loop() {
  getReadings();
 
  // Set values to send
  BME280Readings.temp = temperature;
  BME280Readings.hum = humidity;
  BME280Readings.pres = pressure;

  // Send message via ESP-NOW
  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &BME280Readings, sizeof(BME280Readings));
   
  if (result == ESP_OK) {
    Serial.println("Sent with success");
  }
  else {
    Serial.println("Error sending the data");
  }
  updateDisplay();
  delay(10000);
}
void getReadings(){
  temperature = bme.readTemperature();
  humidity = bme.readHumidity();
  pressure = (bme.readPressure() / 100.0F);
}

void updateDisplay(){
  // Display Readings on OLED Display
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println("INCOMING READINGS");
  display.setCursor(0, 15);
  display.print("Temperature: ");
  display.print(incomingTemp);
  display.cp437(true);
  display.write(248);
  display.print("C");
  display.setCursor(0, 25);
  display.print("Humidity: ");
  display.print(incomingHum);
  display.print("%");
  display.setCursor(0, 35);
  display.print("Pressure: ");
  display.print(incomingPres);
  display.print("hPa");
  display.setCursor(0, 56);
  display.print(success);
  display.display();
  
  // Display Readings in Serial Monitor
  Serial.println("INCOMING READINGS");
  Serial.print("Temperature: ");
  Serial.print(incomingReadings.temp);
  Serial.println(" ºC");
  Serial.print("Humidity: ");
  Serial.print(incomingReadings.hum);
  Serial.println(" %");
  Serial.print("Pressure: ");
  Serial.print(incomingReadings.pres);
  Serial.println(" hPa");
  Serial.println();
}

【Arduino 动手做】ESP-NOW与ESP32:板间最简单的无线通信
项目链接:https://randomnerdtutorials.com/esp-now-two-way-communication-esp32/
项目作者:鲁伊桑托斯
项目参考:ESP-NOW 入门(ESP32 与 Arduino IDE)
https://randomnerdtutorials.com/esp-now-esp32-arduino-ide/
项目视频 :https://www.youtube.com/watch?v=qxwXwNS3Avw
项目代码:https://raw.githubusercontent.com/RuiSantosdotme/Random-Nerd-Tutorials/master/Projects/ESP32/ESP_NOW/ESP_NOW_Two_Way_Communication.ino

 

07.jpg
09.jpg

评论

user-avatar
icon 他的勋章
    展开更多