← 返回机器人编程
ESP32-S3 实战

📡 ESP32-S3 开发实战

从入门到项目落地,每天一篇 ESP32-S3 硬核实战教程,搭配精选视频

ESP32-S3 BLE 入门:蓝牙信标与广播

🎬 精选教程

1. 概述

蓝牙低功耗(BLE, Bluetooth Low Energy)是物联网设备之间通信的核心协议之一。与经典蓝牙(Classic Bluetooth)不同,BLE 专为低功耗、小数据量场景设计——你身边那些蓝牙温湿度计、智能门锁、运动手环,几乎全都跑在 BLE 上。

而"蓝牙信标"(Beacon)是 BLE 最经典的应用形态之一。它本质上是一个只发不收的广播节点,按照固定间隔向外发送固定格式的数据包。任何一个支持 BLE 的手机、平板或电脑都能扫描到它。信标本身不带任何交互能力,但它"在此"这个事实就是信息——商场里的位置推送、博物馆的展品导览、考勤打卡系统,背后都是 Beacon 在工作。

今天我们用 ESP32-S3 分别实现两种主流的蓝牙信标协议:Apple 的 iBeacon 和 Google 的 Eddystone。学完这篇文章,你将掌握 BLE 广播的核心原理,并能自主设计自己的信标应用。

本篇知识点:

  • BLE 协议栈分层结构与 GAP 层作用
  • 广播(Advertising)的工作机制
  • iBeacon 和 Eddystone 的帧结构差异
  • ESP32-S3 上使用 Arduino 框架实现 BLE 广播
  • 如何用手机 App 扫描并验证信标

2. 硬件准备

需要的硬件很简单——基本上就是一块 ESP32-S3 开发板,外加一部能装 BLE 扫描 App 的手机。

  • ESP32-S3 开发板:任何带 USB 口的 ESP32-S3 板子都行,比如 ESP32-S3-DevKitC-1、合宙 ESP32-S3、XIAO ESP32-S3 等
  • USB 数据线:供电 + 刷固件用
  • 电脑:安装好 Arduino IDE(2.x 版)或 VSCode + PlatformIO
  • 手机 App:推荐 nRF Connect(Nordic 出品,iOS/Android 均有)、或 Beacon Scanner

本文全部代码基于 Arduino ESP32 核心库 v3.x 编写,如果你还在用 v2.x,记得升级一下。

3. 代码实现

3.1 安装 BLE 库

在 Arduino IDE 中,ESP32 核心包自带了 BLEDeviceBLEBeacon 库,无需额外安装。如果你用 PlatformIO,在 platformio.ini 中指定 framework = arduino 即可。

3.2 iBeacon 实现

iBeacon 数据帧包含四个关键字段:UUID(16字节,标识组织)、Major(2字节,标识区域)、Minor(2字节,标识具体信标)、TX Power(1字节,1米处信号强度参考值)。

下面是完整的 iBeacon 广播代码:

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEBeacon.h>

// 自定义 UUID(可以用在线 UUID 生成器生成)
#define BEACON_UUID "8f8a7e20-6d3d-4a4b-8e1c-2f3d4e5f6a7b"
#define BEACON_MAJOR 1
#define BEACON_MINOR 1
#define BEACON_TX_POWER -59  // -59 dBm @ 1m

void setup() {
  Serial.begin(115200);
  Serial.println("ESP32-S3 iBeacon Demo");

  // 初始化 BLE 设备
  BLEDevice::init("ESP32-S3 Beacon");
  
  // 创建 BLE 服务器(不需要连接,只是为了创建广播数据)
  BLEServer *pServer = BLEDevice::createServer();
  
  // 配置 iBeacon 广播数据
  BLEBeacon myBeacon = BLEBeacon();
  myBeacon.setProximityUUID(BLEUUID(BEACON_UUID));
  myBeacon.setMajor(BEACON_MAJOR);
  myBeacon.setMinor(BEACON_MINOR);
  myBeacon.setSignalPower(BEACON_TX_POWER);
  
  // 获取广播数据
  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  BLEAdvertisementData advertisementData;
  advertisementData.setFlags(0x06);  // LE General Discoverable + BR/EDR Not Supported
  advertisementData.setManufacturerData(myBeacon.getData());
  pAdvertising->setAdvertisementData(advertisementData);
  
  // 启动广播
  pAdvertising->start();
  
  Serial.println("iBeacon 广播已启动");
  Serial.print("UUID: ");
  Serial.println(BEACON_UUID);
  Serial.print("Major: ");
  Serial.println(BEACON_MAJOR);
  Serial.print("Minor: ");
  Serial.println(BEACON_MINOR);
}

void loop() {
  // 信标不需要做任何事,BLE 硬件会自动广播
  delay(1000);
}

3.3 Eddystone 实现

Eddystone 是 Google 推出的开放信标协议,比 iBeacon 更灵活。它支持多种帧类型:UID(类似 iBeacon)、URL(广播网址,手机靠近自动弹窗)、TLM(遥测数据,如电池/温度)、EID(加密帧)。

最常用的是 Eddystone-URL。手机安装了 Google Chrome(Android)或 Physical Web 应用后,扫描到 Eddystone-URL 信标就会弹窗提示打开对应网址。来看实现:

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEEddystoneURL.h>

// 你想要广播的网址(必须缩短,建议用短链接)
#define BEACON_URL "https://goo.gl/8jFvPJ"

void setup() {
  Serial.begin(115200);
  Serial.println("ESP32-S3 Eddystone-URL Demo");

  BLEDevice::init("ESP32-S3 Eddystone");
  
  BLEEddystoneURL eddystoneURL = BLEEddystoneURL();
  eddystoneURL.setURL(BEACON_URL);
  eddystoneURL.setSignalPower(-59);
  
  // 配置广播
  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  BLEAdvertisementData advertisementData;
  advertisementData.setFlags(0x06);
  advertisementData.setServiceData(eddystoneURL.getData());
  pAdvertising->setAdvertisementData(advertisementData);
  
  // 设置广播间隔(单位:0.625ms,100ms 是推荐值)
  pAdvertising->setMinInterval(160);
  pAdvertising->setMaxInterval(160);
  
  pAdvertising->start();
  
  Serial.println("Eddystone-URL 广播已启动");
  Serial.print("URL: ");
  Serial.println(BEACON_URL);
}

void loop() {
  delay(1000);
}

4. 原理分析

4.1 BLE 协议栈概览

BLE 协议栈分三层:

  • Controller(控制器):物理层 + 链路层,负责无线信号的收发。ESP32-S3 内部集成了完整的 BLE 5.0 控制器
  • Host(主机):包括 L2CAP、ATT、GATT、SM、GAP 等上层协议。GAP(Generic Access Profile)层负责设备的发现和连接管理,信标功能正是由 GAP 层控制
  • Application(应用层):用户的业务代码,我们调用的 BLEDeviceBLEAdvertising 就在这层

4.2 广播(Advertising)机制

BLE 广播使用 3 个专用的广播信道(37/38/39 号信道,分布在 2.4GHz 频段的不同位置),这 3 个信道**不在** WiFi 常用信道(1-13)上,减少了干扰。广播包格式如下:

  • Preamble(1 字节):同步头
  • Access Address(4 字节):固定值 0x8E89BED6
  • PDU(2-39 字节):数据单元,包含广播地址和广播数据
  • CRC(3 字节):校验码

广播间隔(Advertising Interval)默认在 20ms ~ 10.24s 之间。间隔越短,发现越快但功耗越高。对于室内定位等需要低延迟的场景,建议设为 100-200ms;对于电池供电设备,建议 500ms 以上。

4.3 iBeacon vs Eddystone

特性iBeaconEddystone
开发者AppleGoogle
帧类型1 种(固定 UUID+Major+Minor)4 种(UID/URL/TLM/EID)
手机弹窗需 App 监听(无系统级弹窗)Android 通过 Physical Web 弹窗
开放性需购买 Apple 许可完全开源
适合场景iOS 生态内的室内定位通用蓝牙信标、网页推送

5. 扩展与优化

5.1 温湿度 + Beacon 传感器节点

把 BLE Beacon 和温湿度传感器(如 AHT10/BME280)结合,可以实现环境监测+位置感知二合一的物联网节点。用 Eddystone-TLM 帧广播遥测数据,手机 App 收到后即可同时获得位置和环境信息。

5.2 电池供电优化

Beacon 经常部署在无插座的地方。几个省电技巧:

  • 适当增大广播间隔(500ms ~ 1s),功耗可降低 30-50%
  • 调低发射功率(默认 9dBm → 0dBm),覆盖范围从 50m 缩至 10m 但功耗降一半
  • 使用 ESP32-S3 的 Deep Sleep 模式:唤醒 → 广播几次 → 继续睡
// Deep Sleep 版 Beacon:每 5 秒广播 1 次然后睡觉
esp_sleep_enable_timer_wakeup(5 * 1000 * 1000);  // 微秒
esp_deep_sleep_start();

5.3 BLE 5.0 长距离模式

ESP32-S3 支持 BLE 5.0 的 Coded PHY(编码物理层),通过冗余传输将通信距离提升到 300+ 米。使用 pAdvertising->setMinPreferred(0x01)setMaxPreferred(0x01) 即可启用。

6. 踩坑记录

🐛 坑1:广播数据长度限制

现象:自定义广播数据太长,手机扫描不到或 App 闪退。
原因:BLE 广播包 PDU 最大 39 字节,除去地址和协议头,有效数据最多 31 字节。iBeacon 帧约 25 字节,Eddystone-URL 约 20 字节,都卡在极限附近。
解法:如果需要广播更多数据(比如温湿度读数),可以启用 扫描响应(Scan Response) 包,额外提供 31 字节空间。pAdvertising->setScanResponseData(scanData)

🐛 坑2:WiFi + BLE 同时启用冲突

现象:WiFi 和 BLE 同时运行时,BLE 广播经常丢包或异常中断。
原因:ESP32-S3 虽然内置双模蓝牙和 WiFi,但两者共享同一套射频前端(2.4GHz 天线和 PA)。时间片分时复用机制导致 BLE 广播时隙被 WiFi 抢占。
解法:

  • 如果仅需信标功能,不启用 WiFi,主机通过串口/UART 把数据传给 ESP32
  • 如果必须同开,使用 esp_coex_status_t API 调整共存优先级,或使用 ESP-Now 替代 WiFi

🐛 坑3:手机扫描不到信标

现象:代码下载正常,但 nRF Connect 就是找不到你的设备。
可能原因和对策:

  • Android 定位没开:Android 8+ 要求同时开启定位才能扫描 BLE。检查「定位服务」开关
  • iPhone:App 需要 BLE 权限授权
  • 广播间隔太长:先用最小间隔 100ms 测试,扫到了再调整
  • USB 供电不稳:部分开发板通过 USB 供电时射频性能不佳。外接 3.3V LDO 供电可改善

🐛 坑4:Arduino 库版本问题

现象:编译报错 'BLEBeacon' was not declared'BLEEddystoneURL' not found
原因:旧版 ESP32 Arduino 核心(v2.x)没有 BLEBeaconBLEEddystoneURL 类。
解法:升级到 ESP32 Arduino v3.0+: Arduino IDE → 工具 → 开发板管理器 → esp32 → 选 3.0.x

📋 全部文章
#1
ESP32-S3 机器狗实战(一):硬件选型与系统架构
2026年5月3日 · 项目
#2
ESP32-S3 GPIO 编程:点亮你的第一盏LED
2026年5月4日 · 基础
#3
ESP32-S3 ADC 与传感器:读取模拟世界的信号
2026年5月5日 · 传感器
#4
ESP32-S3 Wi-Fi 连接:让你的设备上网
2026年5月6日 · 网络
#5
ESP32-S3 HTTP 客户端:获取天气API数据
2026年5月7日 · 网络
#6
ESP32-S3 Web Server:自建控制面板
2026年5月8日 · 网络