引言
不知道怎么开篇 那就先展示一下过年时玩的esp8266吧
众所周知的wifikiller(可惜不能用来打校园网:
赶上中秋假byr招新项目学了点记了点笔记
最后总结一下留下个资源推荐和踩坑指南收尾吧
关于硬件
从零教你做开发板 — 应该选哪个ESP32S3? 顺便帮没接触的打个基础并引入
然后再在oshwhub找个开源项目分析一下抄一抄硬件任务就完成了(雾)
(这是个伪硬件入门 不过没接触过连选芯片都迷茫)
初入esp32
最开始肯定是整个IDE下来 但…
什么是ESP-IDF 里面包括什么
接下来是下载和跑个helloworld,首要肯定是搞来官方文档
Get Started - ESP32-S3 - — ESP-IDF Programming Guide v5.2.3 documentation ——从官方下载espidf(令人烦躁的是英文的)
找到一个不错的东西【立创·ESP32S3R8N8】IDF入门手册 嘉立创写了一份很不错的文档,下载ide这块可以完全跟着走(flash大小按自己的模块配)
在搜索栏点f1可以打开一个命令面板打开示例
接下来就可以愉快得写工程(bug)了
第一难:玄学bug —— 有的时候再烧一下就可以了
esp32 BLE
第一个任务是实现蓝牙通信
找到官方例程 examples/bluetooth/bluedroid/ble/gatt_serve (gatt(Generic Attribute Profile,通用属性配置文件) 就不用理这词;GATT Server 简单来说是 被动的一方,等待GATT Client发起连接请求)
第二难:build.ninja… 如果同一份代码之前烧过其他的芯片 —— 需要clear一下(遇事不决… 应该是flash或配置文件什么的问题)
第三难:bt.h等报错 —— menuconfig点一下蓝牙 or 点了忘保存了
成功了 有点激动 然后又合并上espnow再处理完爆内存后提交!然后被打回。。好吧 把蓝牙代码研究透吧
【【ESP32教程】第二章: 低功耗蓝牙BLE相关概念及用法】 【ESP32教程】第二章: 低功耗蓝牙BLE相关概念及用法_哔哩哔哩_bilibili 挺好 广播数据包 蓝牙广播数据结构体 广播原理 扫描响应 等等
【蓝牙其实很慢!只有几兆!虽然频率2.4G!蓝牙的工作原理!】 蓝牙其实很慢!只有几兆!虽然频率2.4G!蓝牙的工作原理!_哔哩哔哩_bilibili 爱上半导体的 简略一点
想要实现个什么功能呢:
- 在我手机端输入任何东西时 esp32 都会输出字符串 “Halfapear收到信息啦”;
- 在设备连接后每隔 5 秒发送一次数据 发送 嘟噜噜 连接成功×N N是计的数;
梳理和提取一下代码,800行还是有点难绷(是的 确实有官方文档介绍函数 不过在中文文档里还掺着英文。。晚点我去pr一下教程)
首先 搜索蓝牙设备时看到的名字 来源
‘ #define TEST_DEVICE_NAME “ESP_GATTS_DEMO” ‘
ps:为了观感 晚点把原代码整个粘贴一下
主要函数:
-
gatts_profile_a_event_handler:处理 Profile A 的事件,例如设备连接、数据读写、通知启用等。
-
gatts_profile_b_event_handler:处理 Profile B 的事件,和 Profile A 类似。
-
gap_event_handler:处理通用的蓝牙事件,比如广播(广告)数据的设置和启动等。
-
gatts_event_handler:分配事件给对应的 Profile(A 或 B),决定由哪个 Profile 处理蓝牙事件。
-
example_write_event_env:处理设备接收到的写入请求(当手机发送数据到 ESP32 时调用)。
-
example_exec_write_event_env:完成写入操作,通常用于处理长数据写入。
-
app_main:主函数,初始化蓝牙相关的设置和功能,并启动服务。
看来我们需要重点关注gatts_profile_a_event_handler 函数(负责处理 Profile A 的所有 GATT(通用属性协议)事件)
在 例程 中,事件 ESP_GATTS_WRITE_EVT 里使用了esp_ble_gatts_send_indicate 里面包括了发生的数据
C
| 1 2 3 4 | uint8_t notify_data[15]; for (int i = 0; i < sizeof(notify_data); ++i) { notify_data[i] = i % 0xff; } |
|---|
esp_ble_gatts_send_indicate里面的内容就体现了刚刚学的蓝牙内容
C
| 1 2 3 4 5 6 | esp_ble_gatts_send_indicate(gatts_if, param->write.conn_id, gl_profile_tab[PROFILE_A_APP_ID].char_handle, sizeof(notify_data), notify_data, false); |
|---|
在gatts_profile_a_event_handler中 除了ESP_GATTS_WRITE_EVT 还有很多的EVT(即event) 这些函数可以实现发生什么事件然后干什么事;比如在发生客户端写入时就会输出一堆ff
-
ESP_GATTS_REG_EVT 当应用程序成功注册到 GATT 服务器时触发
-
ESP_GATTS_CREATE_EVT 当服务创建成功时触发
-
ESP_GATTS_ADD_CHAR_EVT 当特征添加成功时触发
-
ESP_GATTS_CONNECT_EVT 当客户端(如手机)连接到服务器时触发
-
ESP_GATTS_DISCONNECT_EVT 当客户端断开连接时触发
-
ESP_GATTS_READ_EVT 当客户端请求读取特征值时触发
-
ESP_GATTS_WRITE_EVT 当客户端写入特征或描述符时触发
-
ESP_GATTS_EXEC_WRITE_EVT 当执行长写操作时触发
-
ESP_GATTS_MTU_EVT 当 MTU(最大传输单元)大小发生变化时触发
关于客户端 我用的是手机软件 edebug(e调试)
edebug下载
-
- Generic Access Profile(GAP):用于定义 BLE 设备的基本属性,如设备名称、可连接性等。UUID 为 0x1800
-
- Generic Attribute Profile(GATT):定义了如何组织和交换数据。UUID 为 0x1801。
-
- Unknown Service:这是自定义的服务,因为调试软件无法识别定义的 UUID,所以显示为 "Unknown Service" 两个分别是profile_a和b
函数与配置都讲完了 可以实现想要的效果了
达成目的之前还是会出一些问题
第四难:字面意思 —— 启用手机通知(不同软件开启地方不一样)
I (296092) GATTS_DEMO: Notifications disabled
I (296132) GATTS_DEMO: Timer callback triggered
I (296132) GATTS_DEMO: Notifications not enabled by client
第五难:通过 BLE 发送的特征(attribute)的值超过了 20 字节 —— 每个中文字符占用 3 个字节(所以有点懒 直接中文改英文了)
I (473612) GATTS_DEMO: Timer callback triggered
W (473612) BT_GATT: attribute value too long, to be truncated to 20
最终 我在例程的基础上修改了以下地方,也算是整明白了一点蓝牙
esp32 espnow
紧接着试一试espnow
初步构想:espnow的用途也就是智能家居嘛,能不能收到什么消息然后转发到第二块esp32 比如像按键遥控点灯?
espnow的原理比起蓝牙简单很多,一种基于 Wi-Fi 协议的简化通信协议,特点是低功耗
但官方example仍然有400多行 包含着从Wi-Fi 初始化到ESPNOW 初始化再到开始广播的完整配置流程
浅聊几个:谁广播谁监听 如何规定的?在 example_espnow_task() 函数中,设备在等待 5 秒后(vTaskDelay(5000 / portTICK_PERIOD_MS);),调用 esp_now_send() 函数向广播地址 FF:FF:FF:FF:FF:FF 发送广播数据;在初始化时都会生成一个随机的 magic 数字(send_param->magic = esp_random();)当设备收到对方的广播消息后,会提取对方的 magic 数字并与自己的进行比较,如果自己的 magic 数字较大,则认为自己应当作为发送者,停止广播并开始单播发送
新手入门还是不要硬攻最复杂的版本 此时可以引入arduino库了
在jlc工程库里面有一份项目:使用ESPNOW远程点个灯
里面使用了Thonny(一个简单易用的 Python 集成开发环境 (IDE));当然可以用vscode 用arduino库需要arduino as component
这里还是先试用thonny 配置很简单 ESP32+Thonny环境搭建_thonny esp32
几乎没有各种配置 就很简单移植一下
简单说一下流程——上电或复位时,固件开始执行 app_main() 函数;接着睡NVS、wifi等一堆初始化;然后当接收到数据时,会调用注册的 on_receive 回调函数
话说那while呢?就像arduino只有setup没有loop?——app_main() 函数不包含循环逻辑,但由于 ESP-IDF 内部运行了事件循环(由 esp_event_loop_create_default() 创建),程序会持续监听接收到的消息并根据不同的命令控制 LED 状态esp32 综合
分别完成两个功能后 试着把两个挪到一块板子(比如s3)上
第六难:.bin 文件大小是 0x128da8(约 1.2 MB),而设置的闪存大小只有 1 MB(0x100000) 闪存爆了 ——
先把flash设高 jlc文档配置最后有讲或直接去menuconfig里面搜flash;
然后还是报错 这时需要修改分区表(感谢两位Y佬)
文档在esp官方文档:自己新建一个partitions.csv(记事本改名),将factory改成合适的值(需要整数)
分区表可以写成
C
| 1 2 3 4 5 | # ESP-IDF Partition Table # Name, Type, SubType, Offset, Size, Flags nvs, data, nvs, 0x9000, 0x6000, phy_init, data, phy, 0xf000, 0x1000, factory, app, factory, 0x10000, 2M, |
|---|
第七难:应用程序的二进制文件大小超过了为其分配的闪存分区空间 —— 是不是没有调flash大小或者调得比分区表小?
第八难:busy~ —— 是不是其他地方正在监控这个板子?
结束!新手任务完成了