资讯详情

ESP-IDF+vscode开发ESP32 联网篇第六讲——蓝牙 beacon 测距

📅 2026/9/11 18:07:17 | 华诺云谱 👁 阅读
ESP-IDF+vscode开发ESP32 联网篇第六讲——蓝牙 beacon 测距
目录前言一、蓝牙1.1 蓝牙基础知识核心特点两大类型1.2 蓝牙软件架构Bluetooth ControllerHCI与传输层Bluetooth HostBluedroidNimBLEBluetooth ProfilesBluetooth Application1.3 总结二、蓝牙数据包2.1 整体数据包2.2 PDU Header2.3 PDU Payload三、蓝牙测距原理四、卡尔曼滤波五、工程实现5.1 工程总览5.2 工程结构与依赖5.3 工作原理5.3.1 启动事件链5.3.2 测距数据流5.3.3 RSSI 的距离换算5.4 关键函数详解beacon_measure_init(const char *host_name, const char *target_name)BT_GAP_callback(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)static void beacon_range_process(const esp_ble_gap_ext_adv_report_t *rpt)static int rssi_to_distance(int rssi, float k)static int cmd_rssi_cal(int argc, char **argv)5.5 操作指南5.5.1 环境与编译烧录5.5.2 标定与测距流程5.6 调参与扩展注意事项与已知边界六、实测结果展示总结前言蓝牙是一种广泛应用于设备间短距离无线通信通常在10米范围内的无线电技术。与Wi-Fi技术相比蓝牙的特点是传输距离短、传输速率低、能源消耗低。其中低功耗特性是蓝牙的一个显著优势这使得其在某些特定应用场景中成为比Wi-Fi更合适的选择。一、蓝牙1.1 蓝牙基础知识蓝牙Bluetooth是一套工作在2.4 GHz 免授权频段的短距离无线通信技术标准用来让设备直接互联例如手机连接耳机、键盘、鼠标、音箱或传感器它通常不依赖 Wi‑Fi 路由器或接入点。核心特点近距离无线连接典型用于几米到几十米内的设备通信实际范围受发射功率、天线、墙体遮挡和环境干扰影响。全球统一标准蓝牙由 Bluetooth SIG 制定和维护其核心规范定义了不同厂商设备能够互操作所需的技术要求。低功耗与易配对尤其适合电池供电设备如手环、温湿度计、遥控器和各类 IoT 节点。共享 2.4 GHz 频段它与 Wi‑Fi、部分无线鼠标等共用频谱因此会通过跳频等机制降低持续受干扰的概率。两大类型类型常见名称主要用途特点经典蓝牙Bluetooth Classic、BR/EDR无线耳机、音箱、车载音频、较连续的数据传输面向传统音频和外设连接支持 BR 与 EDR 两类速率。低功耗蓝牙Bluetooth Low Energy、BLE传感器、手环、智能锁、Beacon、ESP32 物联网设备以低功耗、短数据包和间歇通信为重点适合长期电池供电设备。注意经典蓝牙和低功耗蓝牙不是简单的“新旧版本”关系而是两套不同的无线传输体系。一台设备可能只支持其中一种也可能同时支持两种即所谓“双模蓝牙”。1.2 蓝牙软件架构Bluetooth ControllerBluetooth Controller蓝牙控制器是协议栈靠近硬件的底层部分。它负责真正的无线收发和实时链路控制可以将它理解为“蓝牙的无线网卡固件 射频控制部分”。乐鑫文档中ESP 蓝牙控制器包括 PHY、基带、链路控制器、链路管理器、设备管理器及 HCI 等模块它直接面向硬件和低级蓝牙协议。关键点Controller 不关心你的“温度数据”或“手机按钮”。它只关心“何时在哪个信道发包、是否收到 ACK、连接是否仍然有效”等无线链路问题。HCI与传输层HCI是 Host 和 Controller 之间的标准逻辑接口。Host 通过它向 Controller 下达命令例如“开始广播”“停止扫描”“建立连接”Controller 则通过它回传事件或数据例如“扫描到某设备”“连接建立成功”“收到一包数据”。对于 ESP-IDFHost 与 ESP 蓝牙 Controller 之间使用的是VHCIVirtual HCI接口。无论上层选择 Bluedroid 还是 NimBLE底层 Controller 本身仍是同一个 ESP Controller。Bluetooth HostBluetooth Host蓝牙主机协议栈位于 Application/Profile 与 Controller 之间主要以软件形式运行。它负责更高层的协议语义设备如何被发现、如何配对、数据如何组织、属性如何读写、服务如何定义等。Host 常包含或处理以下模块模块作用直观理解GAP扫描、广播、连接、设备角色与连接参数“如何发现并连接设备”GATT服务、特征值、读写、通知/指示“数据以怎样的服务接口暴露”ATT属性的访问与传输规则“读写一个特征值的底层规则”L2CAP上层数据复用、分段与传输适配“协议数据的通道和搬运层”SMP配对、绑定、密钥与安全“双方如何建立可信关系”例如手机读取 ESP32 的温湿度值时Host 会处理 GATT/ATT 的读请求把它转换为对应的应用回调或属性访问操作Controller 则只负责把相关蓝牙数据包可靠地收发出去。BluedroidBluedroid 是原生 Android 蓝牙协议栈。它同时支持经典蓝牙Bluetooth Classic / BR/EDR低功耗蓝牙Bluetooth LE / BLEESP-Bluedroid 是基于原生 Android 蓝牙协议栈 Bluedroid 的修改版由两层组成蓝牙上层 (BTU) 和蓝牙传输控制器层 (BTC)。BTU 层负责处理 L2CAP、GATT/ATT、SMP、GAP 等底层蓝牙协议以及其他配置文件提供以 bta 为前缀的接口。BTC 层主要负责向应用层提供以 esp 为前缀的支持接口并处理基于 GATT 的配置文件以及其他任务。ESP-Bluedroid 也同时支持经典蓝牙和低功耗蓝牙不过目前的ESP32很低版本只能使用低功耗蓝牙这是控制器硬件决定的。射频/基带没有 BR/EDR。同时提高丰富的API给开发者使用NimBLENimBLE 是另一套 Host 协议栈实现源自 Apache Mynewt 项目的 NimBLE Host它的定位是只做 BLE但更轻量。ESP-NimBLE 是基于在 Apache Mynewt 开发的 NimBLE 主机协议栈针对各系列ESP芯片和 FreeRTOS 进行了移植和优化。但使用的API是原本 NimBLE API需要其他途径学习。ESP-IDF 明确指出NimBLE 仅支持 BLE不支持经典蓝牙相较于 Bluedroid它通常需要更少的代码空间和运行时内存因此对于 BLE-only 项目更合适。维度BluedroidNimBLE所处位置Host 协议栈Host 协议栈经典蓝牙支持不支持BLE支持支持资源占用通常更高通常更低适合场景SPP、A2DP、Classic BLE 双模需求纯 BLE 传感器、GATT、低资源 IoT底层 ControllerESP Bluetooth Controller同一套 ESP Bluetooth Controller下表总结了 ESP-IDF 中支持蓝牙的 ESP 芯片及其蓝牙类型支持情况Y 支持N 不支持。芯片经典蓝牙 (BR/EDR)低功耗蓝牙 (LE)ESP32-S3NYESP32-C2NYESP32-C3NYESP32-C5NYESP32-C6NYESP32-C61NYESP32-H2NY在BLE-only 场景下NimBLE 在内存、吞吐上限的可调性、BLE 5.x 新特性覆盖上占优Bluedroid 在开箱即用Profile 封装、文档、跨任务调用便利性上占优。空口性能天花板两者相同——因为用的是同一个控制器。Bluetooth ProfilesBluetooth Profile蓝牙 Profile配置文件不是一段单独的硬件驱动而是一套面向具体应用场景的互操作规范。它规定设备应使用哪些协议、扮演什么角色、提供哪些服务或数据格式从而让不同厂商产品能够按一致方式协作。常见 Profile 或基于 Profile 的典型能力名称类型用途GAPBLE 通用访问框架广播、扫描、连接、设备角色GATTBLE 数据组织框架用 Service 和 Characteristic 建立可读、可写、可通知的数据接口HID人机接口设备键盘、鼠标、游戏手柄A2DP经典蓝牙音频向耳机、音箱传输立体声音频SPP串口配置文件模拟串口的数据透传常用于 ESP32 经典蓝牙串口HFP免提配置文件蓝牙通话、车载免提自定义 GATT ServiceBLE 常见做法用自定义 UUID 定义传感器、控制命令和状态数据严格来说GAP、GATT 等在 BLE 架构里具有通用框架和协议层含义在日常 ESP32 开发中人们也常把它们统称为“BLE Profiles”。乐鑫文档说明Profile 实现在 Host 协议栈之上应用可以在 Bluedroid 或 NimBLE 提供的能力上构建蓝牙功能。Bluetooth ApplicationBluetooth Application蓝牙应用层就是你自己写的工程业务代码。它调用 ESP-IDF 的蓝牙 API响应蓝牙事件并将“蓝牙通信”连接到实际产品逻辑例如 GPIO、传感器、显示屏、Wi‑Fi 或 FreeRTOS 任务。1.3 总结Controller 管“电波”Host 管“协议”Profile 管“互通规则”Application 管“产品功能”Bluedroid 和 NimBLE 是 Host 的两种选择。对于主机协议栈的选型若要 BLE GATT、手机控制、传感器数据上报、低资源占用优先考虑 NimBLE。若要 经典蓝牙 SPP 串口、A2DP 音频或 Classic 与 BLE 双模选择 Bluedroid。以上两个主机协议栈ESP32当前各版本均支持不过不支持Bluedroid经典蓝牙功能。二、蓝牙数据包2.1 整体数据包BLE 广播包数据结构如下PreambleAccess AddressPDU HeaderPDU PayloadCRCLE 1M1 BLE 2M2 B4 B2 B637 B3 BPreamble 由 PHY 决定长度这一段是纯硬件行为1M PHY 是 1 字节0xAA或0x55取决于接入地址最高位2M PHY 是 2 字节。Access Address 在广播信道上它是两个固定值之一使用 公开地址或静态随机地址时是0x8E89BED6使用可解析/不可解析私有地址RPA时是0x8E89BED7。注意按 LSB 在前发送。帧尾的 CRC 是 3 字节链路层校验不含接入地址广播信道的初始值固定为0x555555数据信道则用两端地址派生。2.2 PDU Header传统广播的头部只有 2 字节位段划分如下低位在前Byte 0: PDU Type[3:0] | RFU | ChSel | TxAdd | RxAddByte 1: RFU[1:0] | Length[5:0]各字段含义如下子字段位宽含义PDU Type4 bit广播 PDU 类型RFU1 bit保留位发送端应置 0。ChSel1 bit信道选择算法提示位在适用的可连接广播中可指示连接后是否支持 Channel Selection Algorithm #2。TxAdd1 bit发送方地址类型0 表示 Public Device Address1 表示 Random Device Address。RxAdd1 bit接收/目标地址类型仅在 PDU 含有目标地址时有意义例如定向广播或扫描/连接请求。Length6 bitPDU Payload 的字节数不含2 B Header也不含 CRC。传统广播通常最大为 37 B。经常使用的广播 PDU 类型如下值类型PDU Payload组成用途0x00ADV_INDAdvA(6 B) AdvData(0~31 B)可连接、可扫描0x01ADV_DIRECT_INDAdvA(6 B) TargetA(6 B)定向连某个发起者0x02ADV_SCAN_INDAdvA AdvData不可连接、可扫描0x03ADV_NONCONN_INDAdvA AdvData纯 beacon不可连不可扫0x04SCAN_REQScanA(6 B) AdvA(6 B)主机索取扫描响应0x05SCAN_RSPAdvA(6 B) ScanRspData(0~31 B)从机回应另有 31 字节预算2.3 PDU Payload整个数据段大小为 637 B 常见可划分为固定 6B 的 AdvA 加最大 31B 的 AdvData具体取决于PDU Type。6字节的 AdvA 是本机的公共地址。LSB在前0~31字节的 AdvData 结构如下一般简称为AD结构| Len (1B) | Type (1B) | Data (Len-1 字节) | 下一条 AD ... | 剩余补 0x00 |每条AD结构都由Len、Type和Data组成Len 只数 Type 之后的字节即 Len 1 Data 长度不含 Len 自己。09意味着后面跟 9 字节。Len 0x00是列表结束标记其后全是填充部分协议栈会直接补0x00到 31 字节。同一种 Type 在广播数据 扫描响应合并视图里只能出现一次想放两个同类数据就得合成一条 AD例如多 UUID或改用扩展广播。常用 Type如下Type含义备注0x01Flags1 字节bit0 Limited、bit1 General、bit2 No BR/EDR、bit3 Controller 同时支持06是 BLE-only 常见值0x02/0x0316-bit UUID 列表不完整/完整每个 UUID 2 字节小端0x06/0x07128-bit UUID 列表每个 16 字节预算极贵0x08/0x09简短 / 完整 本机名称ASCII0x0A发送信号功率int8dBmC6 −580x16Service Data前 2 字节 UUID私有协议首选容器0x19Appearance2 字节小端0x1BLE Bluetooth Device Address16 字节0xFFManufacturer Specific Data前 2 字节为 SIG 分配的 Company ID一个完整的蓝牙数据包如下AAPreamble1M PHYD6 BE 89 8EAccess Address 0x8E89BED6Public 地址LSB first00 24HeaderType0x00(ADV_IND)Length0x2436AdvA 6 AdvData 30F1 2E 3D 4C 5A 6BAdvA设备地址 6B:5A:4C:3D:2E:F1空口反序31 字节 AdvDataXX XX XXCRC-24三、蓝牙测距原理通常蓝牙测距使用的是蓝牙 Beacon 技术。蓝牙 Beacon通常指BLE Beacon低功耗蓝牙信标是一种利用 Bluetooth Low Energy 广播包周期性、单向地发送少量标识或状态数据的小型无线节点。附近的手机、网关或其他 BLE 扫描设备接收到广播后可根据其内容识别“附近有什么设备/处于哪个区域”再触发应用逻辑。它通常不需要与接收端建立传统蓝牙连接。Beacon 主要适用于邻近检测和粗粒度室内定位例如判断设备处于“远、近、很近”或进入某个区域。接收端常利用 RSSI 与路径损耗模型估距。RSSI (Received Signal Strength Indicator)接收信号强度指示。它是接收端测量到的无线信号功率值通常以 dBm 为单位。路径损耗 (Path Loss)无线信号在传播过程中由于扩散、障碍物遮挡、反射、衍射等原因导致的能量衰减基本逻辑在发射功率已知的情况下接收到的 RSSI 值越小说明路径损耗越大也就意味着距离越远。在实际应用中最常用的是对数距离路径损耗模型 (Log-distance Path Loss Model)。其公式如下或者写成更直观的距离计算公式符号含义d待求的收发端距离。d0参考距离RSSI(d)距离为d处的接收信号强度指示RSSI(d0)参考距离处的接收功率。在室内通常取距离发射端 1 米处的 RSSI 值需要实际标定n路径损耗指数 。它反映了信号衰减的快慢与环境密切相关。自由空间无遮挡 n≈2.0室内视距 n≈1.6∼1.8室内有遮挡/复杂环境 n≈2.7∼4.0障碍物极多 n4.0四、卡尔曼滤波蓝牙发射的 2.4G 信号会经历墙面、地面和金属物体的反射人体遮挡也会导致明显衰减因此 RSSI 不能看作稳定、精确的距离读数。研究中通常会先处理 RSSI 样本再进行距离估算或定位。常见处理方式滑动平均取最近 N 个 RSSI 的均值简单但对突发异常值较敏感中值滤波取窗口中位数对偶发的-85 dBm这类异常点更稳健卡尔曼滤波把 RSSI 看成带噪声的观测值结合上一时刻的估计获得更平滑结果已有 BLE 定位实现会将其用于 RSSI 数据处理。因此蓝牙 Beacon 技术它不适合直接作为高精度测距方案。实际中单个 Beacon 更适合做区域判断多 Beacon 结合滤波、指纹库或三边定位才能尝试实现基本的室内定位。上面的滤波算法最重要的就是卡尔曼滤波我们来学习一下。卡尔曼滤波Kalman Filter是一种利用“过去估计 当前测量”持续推断真实状态的递推算法。它不盲目信任某一次传感器读数而是根据模型和噪声大小动态决定该更相信历史预测还是新测量值。对 BLE RSSI 测距场景来说它的作用就是把不断抖动的 RSSI 序列变得更平稳从而让“距离估算”或“靠近/远离判断”少跳变。BLE 室内定位研究中也常先用卡尔曼滤波净化 RSSI再进行定位或距离推断。假设 ESP32 连续扫描到同一个 Beacon原始 RSSI-60, -62, -59, -80, -61, -63 dBm其中-80 dBm可能是人体瞬间遮挡、Wi-Fi 干扰或多径反射导致的异常读数。卡尔曼滤波会认为“此前一直约为 -61 dBm现在突然变 -80 dBm未必真的移动了那么远。”因此它会适度采纳当前的-80 dBm而不是让输出立刻跳到-80 dBm当后续读数持续接近 -80 dBm时估计值才会逐步向新水平移动。它通过预测和更新两个循环阶段实现这一点。两个循环步骤每来一个新 RSSI 值滤波器执行预测根据上一次的估计推测当前真实 RSSI 是多少。更新对比“预测 RSSI”和“实测 RSSI”再按可信度修正估计结果。完整卡尔曼滤波的状态空间形式如下状态空间形式方程引用自卡尔曼滤波Kalman Filter五个公式及其通俗解释_卡尔曼滤波五个公式-CSDN博客建议去看该博主的原文解释的很好。我这句不重复解释了我这实际应用简单一下直接用下面这个简化公式计算五、工程实现以上完整工程可以进入我的Gitee中下载《https://gitee.com/pai-schoolmate/esp32_project.git》本工程路径esp32_project-main\function/BT_bluedroid/Beacon5.1 工程总览该程序烧到两块板子上即可互测每块板都既广播、又扫描。广播端持续发出携带发射功率的 BLE 报文扫描端锁定指定名称的目标统计其 RSSI再用对数路径损耗模型把信号强度换算成距离通过中文日志输出。核心特性扩展广播Extended AdvertisingBLE 5.0 LEGACY 可扫描不可连接广播间隔 20~40 ms发射功率 6 dBm本机名称经扫描响应下发。主动扩展扫描关闭重复过滤每个广播包都上报主动发扫描请求以拿到对方设备名用于识别。单目标测距通过beacon_measure_init(host, target)的target参数指定一次只测一个设备传NULL则仅广播不测距。现场标定控制台命令rssi_cal在已知参考距离处采集 50 个 RSSI 样本取均值得到模型基准d0_rssi。噪声抑制测距按 20 个样本分组取均值再经一阶低通滤波k0.75平滑输出。广播端和扫描端角色由参数决定发板与收板烧同一个 bin。区别只在app_main里调用beacon_measure_init()时传入的名称被测量的一方主要作为广播源测量方配置target_name指向它。5.2 工程结构与依赖组件依赖关系如下组件REQUIRES职责mainbasic, Bluedroid应用入口串联控制台与测距初始化Bluedroidbasicbtesp_timerBLE 广播/扫描/测距核心逻辑basicIDF console 示例命令组件REPL 环境、系统/分区命令共享状态结构体struct BT_event_data BT_event_data_ptr定义于 BT_event.c声明于 BT_event.h是 beacon.c 与 BT_event.c 之间的唯一桥梁承载本机名 AD 数据、目标名、目标地址、参考距离与标定标志。理解它就理解了两个文件如何协作。5.3 工作原理5.3.1 启动事件链Bluedroid 的 GAP 接口是异步的——每个esp_ble_gap_xxx()调用只是「发起请求」真正完成后通过BT_GAP_callback抛出一个 COMPLETE 事件下一步必须写在对应事件分支里。这条链是读懂本工程的关键5.3.2 测距数据流每收到一个广播包都会进入beacon_range_process()但绝大多数包会被层层过滤掉只有「已锁定目标地址、且非标定期的广播包」才参与测距统计为什么名称和地址要分两步锁定BLE 把「广播数据」和「扫描响应」拆成两条独立 PDU发射功率等在广播包里设备名在扫描响应里。代码先从扫描响应解析名称、匹配目标后缓存其地址target_bda之后只用地址过滤广播包target_locked置位后不再解析名称既省 CPU 又避免同名干扰。5.3.3 RSSI 的距离换算采用对数路径损耗模型。已知参考距离d0默认 100 cm处的基准 RSSId0_rssi由标定得到即可反推任意 RSSI 对应的距离换算公式见第三节RSSI 测距的固有局限RSSI 受多径、遮挡、天线方向、人体吸收影响极大本方案适合区域级近距估计米级、趋势判断不要指望厘米级精度。标定环境应尽量贴近实际使用环境。5.4 关键函数详解以下五个函数覆盖初始化入口、事件回调、数据流处理、算法换算、用户命令。beacon_measure_init(const char *host_name, const char *target_name)整个测距信标的总入口。预组装本机名 AD 数据与目标名 → NVS 初始化 → 释放经典蓝牙内存 → 控制器/Bluedroid 初始化与使能 → 注册 GAP 回调 → 设设备名 → 配置扩展广播参数后续步骤全部交给回调链。host_name本机名称同时作为 GAP 设备名与扫描响应内容。可为NULL/空串此时广播不含名称段仍正常广播超过HOST_NAME_MAX_LEN(29) 会截断。target_name测距目标设备名。NULL/空串 仅广播不测距传名称 只对该名称的信标测距一次一个目标。返回值void。任一环节失败会打印ESP_LOGE并提前 return调用方无需额外处理。注意esp_ble_gap_set_device_name()与广播参数配置必须在esp_bluedroid_enable()之后若启用了目标名此处还会注册rssi_cal命令并打印标定提示。BT_GAP_callback(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)GAP 事件总枢纽一个大switch串起整条事件链。每个 COMPLETE 事件先判status失败打错误日志、成功则发起下一步请求。event事件类型如ESP_GAP_BLE_EXT_ADV_SET_PARAMS_COMPLETE_EVT、ESP_GAP_BLE_EXT_ADV_REPORT_EVT等。param事件参数联合体按事件类型取对应成员如param-ext_adv_report.params。关键分支EXT_ADV_REPORT_EVT是稳态下唯一高频触发的事件直接转交beacon_range_process()其余分支只在启动阶段各执行一次。注意回调运行在 Bluedroid 任务上下文不要阻塞耗时操作应投递到别的任务。static void beacon_range_process(const esp_ble_gap_ext_adv_report_t *rpt)测距的核心数据处理。用一组static变量维护跨包状态样本累加值、标定/测距计数、首次标定完成标志、目标锁定标志。rpt单条扫描报告含event_type、addr、rssi、adv_data。两条主线① 扫描响应 → 解析名称 → 匹配则锁定target_bda② 广播包 → 地址过滤 → 标定模式攒满 50 个样本写d0_rssi测距模式攒满 20 个样本换算距离并输出。注意cal_end为假时不输出任何测距结果——即必须先成功标定一次距离日志才会出现。static状态使其不可重入但单目标场景下安全。static int rssi_to_distance(int rssi, float k)把组平均 RSSI 换算为厘米级估计距离并做一阶低通平滑公式见 3.3。rssi本组平均接收信号强度dBm负值。k低通平滑系数 0~1越大越跟随最新值当前调用固定传0.75。返回值估计距离cm下限截断为 10 cm。注意依赖文件级static float d0_rssi默认 −50 dBm标定后被覆盖与共享的d0_dist_cm。dist_old是滤波状态量跨调用保留。static int cmd_rssi_cal(int argc, char **argv)控制台命令rssi_cal的处理函数触发一次现场标定。它只负责置位cal_in_progress true真正的采样在测距回调里完成。返回值0 标定已启动非0 未满足条件。前置校验未配置目标纯广播→ 拒绝已在标定中 → 拒绝尚未收到目标广播target_bda[0]0→ 仅提示但允许启动。用法把接收板固定在距发送板d0_dist_cm(默认 100 cm) 处保持静止再在控制台输入rssi_cal等待「标定完成」日志。5.5 操作指南5.5.1 环境与编译烧录同一 bin 烧到两块板。修改main.c中beacon_measure_init()的两个名称参数以区分角色被測板用唯一host_name测量板把target_name设为被测板的名称。当前示例为(esp32C6, esp32C6_touch)。5.5.2 标定与测距流程两块板上电确认日志出现「扩展广播已启动」「扩展扫描已启动」。把接收板固定在距发送板 100 cm 处保持静止、无遮挡、远离金属与人体。在接收板控制台输入rssi_cal等待日志「标定完成参考距离 100 cm 处实测 RSSI 均值 ≈ −xx dBm」。标定完成后移动接收板即可看到「测距… 平均RSSI… 估计距离≈x.xx 米」周期性输出。没有标定就没有距离输出首次上电后若未执行rssi_calcal_end为假测距日志不会出现。这是设计行为不是 bug。5.6 调参与扩展参数位置当前值调整影响rssi_nBT_event.c1.8路径损耗指数。环境多径/遮挡越多调越大反之调小直接决定距离换算曲线d0_rssiBT_event.c−50默认参考 RSSI正常应由rssi_cal现场标定覆盖d0_dist_cmBT_event.c 结构体初值100标定参考距离须与实际标定摆放距离一致低通krssi_to_distance 调用处0.75越小越平滑但越迟钝越大越跟手但越抖样本组大小beacon_range_process标定 50 / 测距 20越大越稳但更新越慢tx_powerbeacon.c ext_adv_params6 dBm发射功率0 dBm 起、3 dB 步进须与广播数据里的 TX_PWR 段一致interval_min/maxbeacon.c0x20~0x40广播间隔×0.625 ms 20~40 ms越小越实时越耗电scan_interval/windowBT_event.c0x50 / 0x30扫描占空比window 越接近 interval 收包越密调参建议换环境后先重做rssi_cal若整体距离系统性偏大/偏小微调rssi_n若读数跳动剧烈降低k或增大样本组。注意事项与已知边界单目标设计当前一次只测一个target_name。要多目标需扩展为地址→状态的映射表并去掉target_locked单标志逻辑。不可连接广播类型为 LEGACY 可扫描不可连接本机不接受连接纯做信标。名称容量本机名 AD 上限 29 字符31 字节 PDU 预留 2 字节长度/类型。六、实测结果展示双板实测接收板串口日志。在 100 cm 处执行rssi_cal完成标定后手持接收板在近 / 中 / 远三个距离段移动观察测距输出。阶段平均 RSSI估计距离说明标定rssi_cal 100 cm−61.1 dBm—50 样本均值写入d0_rssi此后才有距离输出近距段−58 ~ −62 dBm0.74 ~ 1.07 m与 1 m 参考距离吻合中距段−63 ~ −66 dBm1.13 ~ 1.71 m过渡平滑远距段−67 ~ −70 dBm2.04 ~ 2.91 m信号衰减后仍保持单调单调性良好RSSI 与距离一一对应−61 dBm ≈ 0.9 m → −64 dBm ≈ 1.5 m → −67 dBm ≈ 2.2 m → −70 dBm ≈ 2.8 m移动过程中读数连续过渡、无跳变。平滑有效静止时段连续输出波动约 ±0.1~0.3 m分组均值 一阶低通抑制了 RSSI 瞬时尖峰。更新节奏约每 2~2.5 s 输出一条测距日志与「20 样本/组」的统计窗口一致。总结本工程基于 ESP-IDF v6 与 Bluedroid 协议栈在 ESP32-C6RISC-V上实现单固件双角色的 BLE 5.0 测距信标每块板既周期广播、又主动扫描。广播侧用扩展广播 API 配置 LEGACY 可扫描不可连接报文间隔 20~40 ms、发射功率 6 dBm本机名称经扫描响应下发扫描侧关闭重复过滤逐包上报 RSSI。测距核心是异步 GAP 事件链beacon_measure_init()完成 NVS、控制器、Bluedroid 使能与回调注册后由BT_GAP_callback逐级推进设参数→配广播数据→配扫描响应→启动广播→设扫描参数→启动扫描稳态下EXT_ADV_REPORT_EVT高频触发beacon_range_process()。该函数先从扫描响应解析名称锁定目标地址再对目标广播包分组统计标定模式攒 50 个样本求均值写入d0_rssi测距模式攒 20 个样本求均值经rssi_to_distance()的对数路径损耗模型n1.8换算距离并以 k0.75 一阶低通平滑后输出中文日志。实测中 100 cm 处执行rssi_cal标定得 −61.1 dBm随后近/中/远三段距离读数分别为 0.74~1.07 m、1.13~1.71 m、2.04~2.91 mRSSI 与距离单调对应、无跳变约每 2~2.5 s 更新一次。需注意 RSSI 测距受多径与遮挡影响大仅适合米级趋势估计。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。