第9节 BLE 编程
本教程的核心逻辑适用于所有 ESP32 开发板,但所有操作步骤均以 微雪 ESP32-S3-Zero 迷你开发板 为例进行讲解。如果您使用其他型号的开发板,请根据实际情况修改相应设置。
本节介绍 ESP32 低功耗蓝牙 (BLE) 的基础知识,并通过一个 GATT 服务器示例,演示创建 BLE 服务与特征,以及使用手机 App 与开发板进行蓝牙通信的过程。
0. 蓝牙 (Bluetooth)
ESP32 系列芯片内置了强大的蓝牙功能,使其成为智能穿戴、无线传感和设备间近场通信的理想选择。蓝牙技术分为两种主要类型:
- 经典蓝牙 (Bluetooth Classic):为持续性、高吞吐量的数据传输设计,常见于无线音频设备。
- 低功耗蓝牙 (Bluetooth Low Energy, BLE):专为低功耗、间歇性、小数据包通信而优化,是物联网(IoT)应用的主流选择,如智能手环、无线传感器。
ESP32 芯片的蓝牙支持情况有所不同:
- 经典的 ESP32 芯片同时支持经典蓝牙和 BLE;
- 而后续的新型号均只支持 BLE(具体支持情况请查看:ESP32 产品概览)。在物联网、可穿戴设备等领域,BLE 因其低功耗和高兼容性成为首选。
本教程将聚焦于低功耗蓝牙(BLE)技术的应用。
1. 低功耗蓝牙 (BLE) 概述
BLE(Bluetooth Low Energy,低功耗蓝牙)是一种专为低功耗、间歇性数据传输设计的无线通信协议。它在蓝牙 4.0 标准中被引入,与经典蓝牙(Bluetooth Classic)不兼容。BLE 的典型应用场景包括物联网(IoT)设备、智能开关、智能传感器、可穿戴设备等。与经典蓝牙相比,BLE 的通信速率更低,但功耗极低,非常适合需要长时间电池续航的设备。
ESP-IDF(Espressif IoT Development Framework)为 ESP32 系列芯片提供了完整的 BLE 协议栈支持。其 BLE 协议栈采用分层架构,主要包括:
- 蓝牙控制器层 (Controller):负责底层硬件接口和链路管理。
- 蓝牙主机层 (Host):ESP-IDF 支持两种主机协议栈:
- ESP-Bluedroid:支持经典蓝牙和 BLE(部分芯片仅支持 BLE),架构清晰但资源占用较大。
- ESP-NimBLE:仅支持 BLE,资源占用更小,适合对内存和固件尺寸有较高要求的场景。
- 蓝牙规范层 (Profiles):如 ESP-BLE-MESH(基于 Zephyr Mesh 协议栈)、BluFi(通过 BLE 配置 Wi-Fi)等。
- 应用层 (Applications):开发者可基于上述 API 和规范开发各种 BLE 应用。
2. BLE 主要协议
BLE 的核心协议包括 GAP(Generic Access Profile,负责设备发现、连接管理、广播等)和 GATT(Generic Attribute Profile,定义数据通信格式)。详细介绍可以参考 ESP32 Arduino 入门教程 - BLE 基础概念 和 低功耗蓝牙的分层架构。
- GAP(Generic Access Profile):定义设备发现、连接管理、广播等,规定了设备的连接行为和角色(如广播者、扫描者、连接发起者、外围设备、中央设备),并支持多角色和多连接拓扑。
- GATT/ATT(Generic Attribute Profile / Attribute Protocol):定义数据的表示和交换方式。ATT 以属性为基本数据结构,采用客户端/服务器架构。GATT 在 ATT 基础上定义了特征(Characteristic)、服务(Service)、规范(Profile)等概念,实现数据的分层和复用。
- L2CAP(逻辑链路控制与适配协议):负责数据分段、重组和复用,为上层协议提供数据通道。
- SMP(安全管理协议):负责身份验证、加密和安全配对。
3. 示例程序
基于官方代码示例 NimBLE_GATT_Server 演示如何用 ESP-IDF 在 ESP32-S3 上实现一个低功耗蓝牙应用,并通过 LightBlue 手机调试 App 控制 LED 并读取模拟心率数据,以此建立对低功耗蓝牙功能的直观认识。有关使用 nRF Connect for Mobile 的替代方法,请参阅 ESP-IDF 编程指南 - BLE 入门指南。
3.1 打开示例项目
-
打开 VS Code,点击图标启动 ESP-IDF 扩展。在 "Advanced" 选项中点击 "显示示例项目"。
-
选择 ESP-IDF 版本。
-
在示例列表中的 "bluetooth" 分类下选择 "NimBLE_GATT_Server"。然后,点击 "Select location for creating NimBLE_GATT_Server project" 选择项目存放文件夹。
ESP-IDF 扩展将自动复制示例代码到指定位置并打开新项目。
注意项目存放路径中不要包含空格、中文和特殊字符。
3.2 修改项目配置
该示例项目默认配置了一个用于状态指示的 LED。为了让程序能正确控制开发板的板载 LED,需要根据开发板的实际硬件连接来修改 LED 的类型和 GPIO 引脚。
-
点击
打开 SDK 配置编辑器。
不同于
idf.py menuconfig
提供的命令行配置工具 (TUI),ESP-IDF VS Code 插件提供了更直观的图形化配置界面。 -
根据开发板板载 LED 修改配置:
- Blink LED type:选择 LED 类型。
GPIO
:普通 LED。LED strip
: 可寻址 LED (如 WS2812)。
- Blink GPIO number:设置 LED 所连接的 GPIO 引脚编号。
- Blink period in ms: 设置 LED 闪烁的周期(单位:毫秒)。
信息本教程使用的 微雪 ESP32-S3-Zero 迷你开发板 板载了一颗 WS2812 可寻址 LED,它连接在 GPIO 21 引脚上。
- Blink LED type:选择 LED 类型。
-
修改完成后,点击 "保存" 按钮。
3.3 构建、烧录和监视
-
配置烧录选项
首先,在构建和烧录之前,请务必检查并设置正确的目标设备、串口和烧录方式。参考 第 2 节 运行示例 - 1.3 配置项目。
-
点击
一键自动依次执行构建、烧录和监视这三个步骤。
-
烧录完成后,串口监视器会开始打印信息。可以看到 BLE 初始化的日志,以及随机生成的心率数据以约 1 Hz 的频率在 60-80 范围内更新。
3.4 通过蓝牙连接开发板
本示例需要使用蓝牙调试工具,如 LightBlue。iOS 用户可在 Apple Store 下载,安卓用户可在应用商店搜索 LightBlue 下载。
打开 LightBlue,按照下面步骤操作:
-
连接开发板:
首先,搜索 "GATT",找到 "NimBLE_GATT" 设备。点击右侧按钮可展开查看广播信息,然后点击 "Connect" 进行连接。
在设备详情页中,可以看到该设备有两个服务,每个服务下各有一个特征。这两个服务都采用了标准的 Bluetooth SIG UUID,因此被自动识别为 "Heart Rate" 和 "Automation IO",分别提供心率数据读取和 LED 控制功能。
-
接收心率数据:
点击进入 "Heart Rate Measurement" 特征。然后点击右上角的 "HEX" 设置数据类型。将 "Byte Limit" 设为 1,选择 "1 Byte Unsigned Integer" 并保存,以便后续查看数据。
保存后返回特征详情页,点击 "Read" 读取数据。也可以点击 "Subscribe" 订阅数据,当心率更新时会自动推送。
-
控制 LED:
点击左上角的返回按钮,回到上个页面。然后进入 "0x00001525-1212-EFDE-1523-785FEABCD123" 特征。
这个 UUID 不是蓝牙标准定义的 SIG UUID,因此不会被自动识别,而是直接显示原始 UUID。(在 Nordic Semiconductor 开发的 nRF Connect for Mobile 中能够被识别为 LED)
它实际上是几个知名厂商(特别是 Nordic Semiconductor)在示例代码中广泛使用的 UUID,通常代表 LED 状态特征。它接收 1 字节整数:写入
0x01
表示"开",写入0x00
表示"关"。点击 "Write new value",写入数值 1,LED 随即亮起。如果写入数值 0,LED 会随之熄灭。