今天我们来玩儿ESP-NOW

相信每个玩电子的童鞋对无线通信都非常感兴趣,从孩童时期的无线遥控赛车,到学生时期的收音机,到长大后接触的各种无线控制的家电,手机等电子产品,无线通信让我们可以像神话小说中的某些绝技,可以做到隔空控制,每个人都都希望将那个遥控器掌握在自己手中

无线遥控的本质就是发射端发射某个频率的电磁波出去,接收端接收并解码这个信号。我们经常接触的空调,电视,风扇等遥控器很多都是红外的,频率大多是38Khz;窗帘,车库门等大多是315MHz或者433MHz;国外有868MHz、915MHz等;低于1Ghz的泛称为Sub 1Ghz,不同国家有不同的免费频率段;灯,手机等大多是用2.4Ghz的,2.4G这个频段用的比较多,这个频段在全球是免费使用的,我们熟知的WiFi、蓝牙、Zigbee的都是2.4Ghz的;当然还有NBIOT,2G,4G,5G,长波,中波,短波等很多频率的设备。理论来说,在相同功率下,低频能获得更好的传送距离,高频有更好的抗干扰性能,不同领域根据自身特性选择最合适的通信频率。

气象站项目预览

先看一下我们最终的成品视频介绍:

ESP-NOW概述

ESP-NOW 是由 Espressif 开发的一种协议,它使多个设备能够在不使用 Wi-Fi 的情况下相互通信。该协议类似于无线鼠标中用的2.4GHz无线连接。因此,设备之间的配对需要在它们通信之前进行。配对完成后,连接是安全且点对点的,无需握手,也就是他不像TCP/IP等是长连接的,换句话说,它是无连接的,如果其中一个板子突然断电,重新启动后,会自动匹配它的连接设备继续通信。

不同于传统的OSI模型,ESP-NOW去掉了其中一些层,只保留最基本的传输层,减少了网络拥堵造成的丢包延迟,实现快速响应。简单来说,ESP-NOW 是一种快速通信协议,可用于在 ESP32 板之间交换短消息(单次最多 250 字节)。

ESP-NOW的优势

  • 快速响应:开机后,设备无需任何无线连接即可直接传输数据和控制其他配对设备,响应速度以毫秒为单位

  • 远距离通信:ESP-NOW 支持远距离通信,板载天线户外空旷距离能达到200米+

  • 多跳控制:ESP-NOW可以实现设备的多跳控制,可通过单播、广播和群控方式控制数百台设备;

  • 新配网方式:提供了除 Wi-Fi 和蓝牙之外的新方式,通过蓝牙为第一台设备配置网络,其他设备不需要配置SSID/密码等信息,第一台连接到网络的设备可以直接将这些信息发送给其他设备

  • 升级:可用于固件升级或者大量数据升级的场景;

  • 调试:在一些高温高压等不太方便的场合,可以接收多个设备的数据,快速诊断设备故障

  • 低成本:可与WiFi,蓝牙等共存

  • 安全:ESP-NOW 采用 CCMP 方法保护供应商特定动作帧的安全,具体可参考 IEEE Std. 802.11-2012。

ESP-NOW通信

单向通信

一个从机向一个主机发送数据

这种情况适用于一个设备向另一个设备单向发送数据,比如一个从机采集传感器数据或将开关量发送到主机。

一个主机向多个从机发送数据

一个从机从多个主机接收数据

双向通信

主机与从机互相通信

多个设备之间互相通信

ESP-NOW非常适合组建一个小型网络,可以让多个ESP32之间交换数据。

硬件

基本演示不需要加入其它外设,板子接上串口助手观察就好了。

软件

获取板子的MAC地址

ESP-NOW是通过MAC地址做为不同设备的唯一识别的,就像不同设备的ID码一样,当然我们可以通过扫描配对的方式去自动配对,这里为了方便展示程序原理,我们就先采用最基本的方式,先通过下面的代码获取主机设备的MAC地址。

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

获取到主机的MAC地址后,我们记下来。

初始化ESP-NOW

初始化ESP-NOW,在这个函数调用之前必须初始化WiFi。

esp_now_init();

添加配对设备

调用此函数配对设备,将MAC地址,通道,加密信息等进行配置。

esp_now_add_peer();

发送数据

向配对设备发送数据

esp_now_send();

发送数据回调函数

注册一个发送数据时调用的函数,此函数会返回是否发送成功的消息。

esp_now_register_send_cb();

接收数据回调函数

注册一个接收到数据时调用的函数。

esp_now_register_rcv_cb();

还有其它一些函数,我们用到的时候再讲。

完整发送程序

我们将之前打印的MAC地址保存下来,替换到broadcastAddress数组中。代码中,首先定义了一个结构体,包含几种不同类型的数据变量,这个就是我们要发送的数据,在setup()中先设置WiFi工作在STA模式,然后调用esp_now_init()初始化,将配对设备的信息进行添加,简单配置一下发送回调函数,打印是否发送成功,主函数中,每2秒发送一次数据。esp_now_send返回是否发送出去,回调函数中展示是否成功发送给接收方。

#include <esp_now.h>
#include <WiFi.h>// REPLACE WITH YOUR RECEIVER MAC Address
uint8_t broadcastAddress[] = {0x8C, 0xCE, 0x4E, 0xA6, 0x73, 0x74};// Structure example to send data
// Must match the receiver structure
typedef struct struct_message {char a[32];int b;float c;bool d;
} struct_message;// Create a struct_message called myData
struct_message myData;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");
}void setup() {// Init Serial MonitorSerial.begin(115200);// Set device as a Wi-Fi StationWiFi.mode(WIFI_STA);// Init ESP-NOWif (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 packetesp_now_register_send_cb(OnDataSent);// Register peermemcpy(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;}
}void loop() {// Set values to sendstrcpy(myData.a, "THIS IS A CHAR");myData.b = random(1,20);myData.c = 1.2;myData.d = false;// Send message via ESP-NOWesp_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 <esp_now.h>
#include <WiFi.h>// Structure example to receive data
// Must match the sender structure
typedef struct struct_message {char a[32];int b;float c;bool d;
} struct_message;// Create a struct_message called myData
struct_message myData;// callback function that will be executed when data is received
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() {// Initialize Serial MonitorSerial.begin(115200);// Set device as a Wi-Fi StationWiFi.mode(WIFI_STA);// Init ESP-NOWif (esp_now_init() != ESP_OK) {Serial.println("Error initializing ESP-NOW");return;}// Once ESPNow is successfully Init, we will register for recv CB to// get recv packer infoesp_now_register_recv_cb(OnDataRecv);
}void loop() {}

将上面的发送与接收程序烧录到两块板,就实现了数据的单向传输,我们看下接收方的串口打印数据:

这是最简单的一个案例,大家对ESP-NOW先有一个简单的理解,关于ESP-NOW的管理设备,删除设备,扫描从设备,自动配对等,下一期再讲,布置个作业大家可以在发送端添加一个按钮,接收端添加一个LED等,就可以实现一个遥控器的Demo了,快去尝试一下吧。

下一节,我们会实际做一个小项目,增加以下功能:

  • 多个主机,多个从机;

  • 从机按键长按触发下进入广播模式,释放出WIFI信号,主机在上电的时候,会扫描到WIFI信号并自动配对

  • 配对完成之后,主机从机都会将MAC地址自动写入存储空间,下次启动就不用重新配对;

  • 两个从机可以通过按键控制主机上的两个LED灯,主机也可以同时控制两个从机上的LED灯;

  • 两个从机分别采集温度湿度气压数据,传给主机;

  • 主机将数据在本地显示屏显示出来,同时在连接WiFi之后,可以通过Web端实时查看传感器数据

  • 指示灯显示连接状态。

感谢大家,关于ESP32的学习,希望大家Enjoy!想一起学习的可以通过芯片之家公众号加入粉丝群。

参考资料:

1、https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/api-reference/network/esp_now.html

2、https://randomnerdtutorials.com/esp-now-esp32-arduino-ide/

3、https://github.com/espressif/esp-now

老宇哥带你玩转ESP32,12篇基础教程已经更新完毕,接下来是进阶教程

你见过10001000封装的巨型 WS2812B LED吗

一份很棒的外设驱动库!基于STM32F4

欢迎点分享、收藏、点赞、在看

老宇哥带你玩转 ESP32:14 亲自动手做一个双向通讯的无线遥控器(一)相关推荐

  1. 老宇哥带你玩转 ESP32:04 串口玩起来是真方便

    今天我们来玩儿串口. 概述 ESP32 芯片有3 个 UART 接口,UART0,UART1,UART2,支持异步通信和 IrDA,通信速度最高可达 5Mbps,3 个接口可以被 DMA 或 CPU ...

  2. 老宇哥带你玩转ESP32:02使用VSCode+PlatformIO搭建开发环境

    上一篇文章给大家介绍了ESP32使用Arduino官方IDE进行开发的流程. 老宇哥带你玩转ESP32:01入门介绍 (点击阅读) 有部分同学反馈下载的时候特别慢,这个库是托管在GitHub的,国内有 ...

  3. 老宇哥带你玩转 ESP32:09 EEPROM的使用演示

    今天我们来玩儿EEPROM. EEPROM概述 ESP32内部没有专门的EEPROM,但是我们可以通过FLASH模拟EEPROM,FLASH与EEPROM也是非常相似的,都是非易失性存储器,使用EEP ...

  4. 老宇哥带你玩转ESP32:03 GPIO数字输入与数字输出

    今天我们来点灯. 多路复用器与GPIO矩阵 ESP32芯片有34个物理 GPIO Pad,每个Pad可以当作通用IO,也可以当作外设的引脚,GPIO 引脚通过非常复杂的 GPIO 矩阵互连,这基本上就 ...

  5. 老宇哥带你玩转ESP32:01入门介绍

    接触物联网差不多10年了. 先跟大家聊聊,老宇哥11年进入大学,大一就在实验室开始了电子研发,记得那时候师兄介绍我买了一块郭天祥老师的51开发板,还有配套的一本书,虽然从小非常喜欢电子,经常折腾,有一 ...

  6. mysql为什么用b加树_为什么MySQL要用B+树?聊聊B+树与硬盘的前世今生【宇哥带你玩转MySQL 索引篇(二)】...

    为什么MySQL要用B+树?聊聊B+树与硬盘的前世今生 在上一节,我们聊到数据库为了让我们的查询加速,通过索引方式对数据进行冗余并排序,这样我们在使用时就可以在排好序的数据里进行快速的二分查找,使得查 ...

  7. mysql 如何添加索引_MySQL如何创建一个好索引?创建索引的5条建议【宇哥带你玩转MySQL 索引篇(三)】...

    MySQL如何创建一个好索引?创建索引的5条建议 过滤效率高的放前面 对于一个多列索引,它的存储顺序是先按第一列进行比较,然后是第二列,第三列...这样.查询时,如果第一列能够排除的越多,那么后面列需 ...

  8. 蒙文字体怎么安装_焘哥带你玩转字体(三)字体的安装及显示问题

    视频版 焘哥带你玩转字体(三)https://www.zhihu.com/video/1132957888620130304 上两篇文章我们共同了解了[衬线].[非衬线]字体,和如何识别字体的性格,以 ...

  9. 超哥带你玩转正则表达式-(六)

    超哥带你玩转正则 目录 (一)一句话弄明白你的疑问 (二)正则表达式啥玩意? (三)正则表达式的语法(第一招) 1.元字符 2. 重复限定符 3. 分组 4. 转义 5. 条件或 6. 区间 (四)练 ...

  10. 一文带你 GNN 从入门到起飞,做一个饭盆最稳 GNN 饭人!

    摘要:本文介绍了图神经网络在学界和业界的发展情况,并给出了图神经网络的基本概念与表示形式,总结了图神经网络的变体,最后介绍了华为云图神经网络框架. 本文分享自华为云社区<干饭人,干饭魂,搞懂图神 ...

最新文章

  1. (转)Unity3D - 性能优化之Draw Call
  2. Android原生(Native)C开发之二 framebuffer篇
  3. CodeForces - 856B Similar Words(AC自动机+树形dp)
  4. sklearn自学指南(part8)--普通最小二乘法
  5. 【洛谷P4719】动态DP【LCT】【矩阵】
  6. LaTeX——双栏论文插入图片
  7. (四)Trigger
  8. Educational Round 26 C. Two Seals
  9. CCNA培训课总结笔记--静态路由实现负载均衡(四)
  10. pandas获取全部列名_pandas获取全部列名_pandas DataFrame数据重命名列名的几种方式...
  11. java面试宝典-抱你过岸
  12. BIOS的全局变量gST gBS gDS
  13. QTableWidget使用setCellWidget设置控件居中显示
  14. 数据结构-学习笔记整理
  15. 爬动的蠕虫(无循环版)
  16. 使用DOS重定位技术执行isqlw(SQL查询分析器)
  17. 【MTK】PMIC实现掉电复位的方法/PMIC如何实现掉电复位
  18. Kafka学习笔记——使用Kafka记录APP的操作日志
  19. zookeeper客户端使用与集群特性
  20. mysql触发器使用案例

热门文章

  1. protobuf repeated string 赋值
  2. 【渝粤教育】广东开放大学 质量认证认可 形成性考核 (31)
  3. 【python gensim使用】word2vec词向量处理英文语料
  4. 第三种最小生成树算法 Borůvka算法
  5. 使用蒲公英组网实现企业微信访问局域网数据
  6. 数据科学猫:数据分析的主要类型、描述性分析、预测性分析与规范性分析
  7. oracle 用户创建赋权,oracle 建表空间用户及赋权
  8. PowerVR 三十周年:回顾与展望
  9. coffeescript java 执行_CoffeeScript—面向对象
  10. 分享一个Github逆天级别的彩蛋