Arduino for ESP32 您所在的位置:网站首页 arduino型号介绍 Arduino for ESP32

Arduino for ESP32

#Arduino for ESP32| 来源: 网络整理| 查看: 265

ESP-NOW ESP-NOW介绍ESP-NOW支持以下特性ESP-NOW技术也存在以下局限性获取ESP32的MAC地址ESP-NOW单向通信(One-way communication)ESP32单板间的双向通信一对多通信(一发多收)一对多通信(多发一收) 部分图片来自网络

ESP-NOW介绍

ESP-NOW是一种由Espressif开发的协议,可以让多个设备在不使用Wi-Fi的情况下相互通信。该协议类似于低功耗的2.4GHz无线连接。设备之间的配对需要在通信之前完成。配对完成后,连接是安全的、点对点的,不需要握手。这意味着在设备彼此配对后,连接是持久的。换句话说,如果你的某块单板突然失去电源或复位,当它重启时,它将自动连接到它的频道继续通信

ESP-NOW支持以下特性 混合加密和未加密的对端设备加密和不加密的单播通信最多可携带250字节的有效载荷(小数据传输);发送回调函数,可以设置为通知应用层传输成功或失败; ESP-NOW技术也存在以下局限性 有限的加密。Station模式最多支持10个加密对等体;“软拨号”或“软拨号+工作站”模式最多为6个支持多个未加密的对等体,包括加密的对等体,总数不能超过20个3.最大消息长度限制在250字节 获取ESP32的MAC地址

在使用ESP-NOW协议前需要知道ESP32 的MAC地址

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

上串口打开串口监视器,可以得到板子的MAC地址,例如 在这里插入图片描述 最好拿个小纸条记下来

ESP-NOW单向通信(One-way communication)

一个ESP32作为发送方,另一个ESP32作为接收方

在这里插入图片描述 发送端的程序

#include #include // 接收端的MAC地址 uint8_t broadcastAddress[] = {0x30, 0xAE, 0xA4, 0x07, 0x0D, 0x64}; // 发送结构体类型 typedef struct struct_message { char a[32]; int b; float c; bool d; } struct_message; // 创建一个结构体变量 struct_message myData; // 回调函数,函数将在发送消息时执行。此函数告诉我们信息是否成功发送; 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"); } void setup() { // 初始化串口波特率 Serial.begin(115200); // 设置WIFI模式为STA模式,即无线终端 WiFi.mode(WIFI_STA); // 初始化ESP-NOW if (esp_now_init() != ESP_OK) { Serial.println("Error initializing ESP-NOW"); return; } //注册回调函数 esp_now_register_send_cb(OnDataSent); // 注册通信频道 esp_now_peer_info_t peerInfo; memcpy(peerInfo.peer_addr, broadcastAddress, 6); peerInfo.channel = 0; //通道 peerInfo.encrypt = false;//是否加密为False if (esp_now_add_peer(&peerInfo) != ESP_OK){ Serial.println("Failed to add peer"); return; } } void loop() { //设置要发送的值 strcpy(myData.a, "THIS IS A CHAR"); myData.b = random(1,20); myData.c = 1.2; myData.d = false; //发送信息到指定ESP32上 esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData)); //判断是否发送成功 if (result == ESP_OK) { Serial.println("Sent with success"); } else { Serial.println("Error sending the data"); } delay(2000); }

接收端的程序

#include #include // 创建一个结构体接收数据 typedef struct struct_message { char a[32]; int b; float c; bool d; } struct_message; // 创建一个结构体变量 struct_message myData; // 回调函数,当收到消息时会调佣该函数 void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int 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("Bool: "); Serial.println(myData.d); Serial.println(); } void setup() { // 初始化串口波特率 Serial.begin(115200); // 设置wifi模式 WiFi.mode(WIFI_STA); // 初始化esp-now if (esp_now_init() != ESP_OK) { Serial.println("Error initializing ESP-NOW"); return; } //注册接收信息的回调函数 esp_now_register_recv_cb(OnDataRecv); } void loop() { }

分别长传到两块ESP32上,打开串口监视器 发送端: 在这里插入图片描述接收端:在这里插入图片描述

ESP32单板间的双向通信

两块ESP32之间互相发送接收 在这里插入图片描述这里我们用BME280温湿度传感器做实验,并在OLED上显示 相关库连接(前两个是关于OLED的,后两个是BME280的驱动库): 1.Adafruit_GFX library 2.Adafruit_SSD1306 library 3.Adafruit_BME280_Library 4.Adafruit_Sensor

上传下面的代码到两块开发板上,注意MAC地址是两块板子的地址 ,关于如何获取板子的MAC地址,前面已经有介绍

#include #include #include #include #include #include #include #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; // 这里换为对方板子的MAC地址 uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // 定义几个浮点型变量存储BME280传感器的数值,用于发送 float temperature; float humidity; float pressure; // 这里定义的变量用于接收 注意类型也是浮点型 float incomingTemp; float incomingHum; float incomingPres; // 数据发送成功标志 String success; //定义结构体 typedef struct struct_message { float temp; float hum; float pres; } struct_message; // 创建一个结构体变量 用于发送 struct_message BME280Readings; // 创建一个结构体变量 用于接收 struct_message incomingReadings; // 发送数据回调函数 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 :("; } } // 收到消息的回调函数 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() { // 初始化波特率 Serial.begin(115200); // 初始化BME280 bool status = bme.begin(0x76); if (!status) { Serial.println("Could not find a valid BME280 sensor, check wiring!"); while (1); } // 初始化OLED if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { Serial.println(F("SSD1306 allocation failed")); for(;;); } // 设置ESP32为STA模式 WiFi.mode(WIFI_STA); //初始化 ESP-NOW if (esp_now_init() != ESP_OK) { Serial.println("Error initializing ESP-NOW"); return; } //注册发送回调函数 esp_now_register_send_cb(OnDataSent); // 注册通信频道 esp_now_peer_info_t peerInfo; memcpy(peerInfo.peer_addr, broadcastAddress, 6); peerInfo.channel = 0; peerInfo.encrypt = false; if (esp_now_add_peer(&peerInfo) != ESP_OK){ Serial.println("Failed to add peer"); return; } //注册接收回调函数 esp_now_register_recv_cb(OnDataRecv); } void loop() { getReadings(); // 准备发送的变量 BME280Readings.temp = temperature; BME280Readings.hum = humidity; BME280Readings.pres = pressure; //发送数据 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(){ // 收掉信息在OLED上显示 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(); // 串口打印信息 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(); }

实验效果图 在这里插入图片描述

一对多通信(一发多收)

在这里插入图片描述

一块ESP32发送多个ESP32作为接收 同样需要先获取接收板子的Mac地址 发送端的程序: #include #include /*接收端板子的Mac地址,这里为三块板子*/ uint8_t broadcastAddress1[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; uint8_t broadcastAddress2[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; uint8_t broadcastAddress3[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; //用于测试的数据 typedef struct test_struct { int x; int y; } test_struct; test_struct test; // 发送时的回调函数 void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) { char macStr[18]; Serial.print("Packet to: "); /**串口提示向哪块板子发送**/ snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); /** 以下几句将在串口输出接收端的板子是否接收到了消息,方便调试 **/ Serial.print(macStr); Serial.print(" send status:\t"); Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail"); } void setup() { Serial.begin(115200); WiFi.mode(WIFI_STA); if (esp_now_init() != ESP_OK) { Serial.println("Error initializing ESP-NOW"); return; } //注册回到函数 esp_now_register_send_cb(OnDataSent); // 注册通信频道 esp_now_peer_info_t peerInfo; peerInfo.channel = 0; peerInfo.encrypt = false; //配置第一块接收接收的Mac地址 memcpy(peerInfo.peer_addr, broadcastAddress1, 6); if (esp_now_add_peer(&peerInfo) != ESP_OK){ Serial.println("Failed to add peer"); return; } // 配置第二块接收接收的Mac地址 memcpy(peerInfo.peer_addr, broadcastAddress2, 6); if (esp_now_add_peer(&peerInfo) != ESP_OK){ Serial.println("Failed to add peer"); return; } /// 配置第三块接收接收的Mac地址 memcpy(peerInfo.peer_addr, broadcastAddress3, 6); if (esp_now_add_peer(&peerInfo) != ESP_OK){ Serial.println("Failed to add peer"); return; } } void loop() { //这里使用随机数作为发送的数据 test.x = random(0,20); test.y = random(0,20); //esp_now_send()中的第一个参数为0表示向所有接收的板子发送,也可以传入指定的板子地址 esp_err_t result = esp_now_send(0, (uint8_t *) &test, sizeof(test_struct)); if (result == ESP_OK) { Serial.println("Sent with success"); } else { Serial.println("Error sending the data"); } delay(2000); }

接收端

#include #include //发送的端是数据是结构体,所以这里也创建一个结构体 typedef struct test_struct { int x; int y; } test_struct; test_struct myData; //收到消息时的回调函数 void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) { memcpy(&myData, incomingData, sizeof(myData)); Serial.print("Bytes received: "); Serial.println(len); Serial.print("x: "); Serial.println(myData.x); Serial.print("y: "); Serial.println(myData.y); Serial.println(); } void setup() { //初始化串口波特率 Serial.begin(115200); //设置为WIFI_STA模式 WiFi.mode(WIFI_STA); //初始化ESP_NOW if (esp_now_init() != ESP_OK) { Serial.println("Error initializing ESP-NOW"); return; } // 注册接收的回调函数 esp_now_register_recv_cb(OnDataRecv); } void loop() { }

经过本人测试,并不是每次发送所有的板子都能成功的接收到信息 在这里插入图片描述

一对多通信(多发一收)

在这里插入图片描述

一块ESP32板作为接收;多个ESP32板充当发送,本次示例程序采用3块板子作为发送ESP32接收板接收来自所有发送方的消息,并识别发送消息的板子还是一样,需要先获取接收板子的MAC地址

发送端的程序

#include #include // 这里改为接收板子的MAC地址 uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // 还是创建一个结构体类型 typedef struct struct_message { int id; //注意这里的id非常重要,作为区分不同发送端板子的标 int x; int y; } struct_message; struct_message myData; //发送回调函数 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"); } void setup() { Serial.begin(115200); WiFi.mode(WIFI_STA); // 初始化ESP_NOW if (esp_now_init() != ESP_OK) { Serial.println("Error initializing ESP-NOW"); return; } // 注册发送回调函数 esp_now_register_send_cb(OnDataSent); // 注册通信频道 esp_now_peer_info_t peerInfo; memcpy(peerInfo.peer_addr, broadcastAddress, 6); peerInfo.channel = 0; peerInfo.encrypt = false; if (esp_now_add_peer(&peerInfo) != ESP_OK){ Serial.println("Failed to add peer"); return; } } void loop() { // 设置发送的数据 myData.id = 1; //注意这里的id,每块发送的板子不能重复 myData.x = random(0,50); myData.y = random(0,50); // 向指定MAC地址发送数据 esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData)); if (result == ESP_OK) { Serial.println("Sent with success"); } else { Serial.println("Error sending the data"); } delay(10000); }

接收端:

#include #include // 和发送端一样,这里也声明一个结构体 typedef struct struct_message { int id; int x; int y; }struct_message; struct_message myData; //创建三个结构体变量来保存每个板上的读数 struct_message board1; struct_message board2; struct_message board3; // 创建一个结构体数组 struct_message boardsStruct[3] = {board1, board2, board3}; // 接收回调函数 void OnDataRecv(const uint8_t * mac_addr, const uint8_t *incomingData, int len) { char macStr[18]; Serial.print("Packet received from: "); snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); Serial.println(macStr); memcpy(&myData, incomingData, sizeof(myData)); Serial.printf("Board ID %u: %u bytes\n", myData.id, len); // 更新数据 boardsStruct[myData.id-1].x = myData.x; boardsStruct[myData.id-1].y = myData.y; Serial.printf("x value: %d \n", boardsStruct[myData.id-1].x); Serial.printf("y value: %d \n", boardsStruct[myData.id-1].y); Serial.println(); } void setup() { Serial.begin(115200); WiFi.mode(WIFI_STA); //初始化ESP_NOW if (esp_now_init() != ESP_OK) { Serial.println("Error initializing ESP-NOW"); return; } //注册接收回调函数 esp_now_register_recv_cb(OnDataRecv); } void loop() { /*int board1X = boardsStruct[0].x; int board1Y = boardsStruct[0].y; int board2X = boardsStruct[1].x; int board2Y = boardsStruct[1].y; int board3X = boardsStruct[2].x; int board3Y = boardsStruct[2].y;*/ delay(10000); }


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有