蓝牙连接为什么总在最需要时断开
旧记录整理:这是一次 BLE 压力测试的复盘。文中的数值来自当时的实验记录,结论只适用于同类架构,不能代替对具体设备的测量。
故障表现很会迷惑人:空闲时连接可以保持一整晚,一旦连续读取传感器并刷新屏幕,手机端就会在三到十分钟内提示断开。重新连接通常成功,因此最初大家都怀疑手机系统“杀后台”。真正的问题不是一个点,而是四种小延迟在高负载时叠加。
把“断开”拆成可观察事件
先停止用“蓝牙不稳定”描述问题,改为记录五个时间点:最后一次成功通知、最后一次收到确认、控制器报告的断开原因、应用层检测到断开、重连开始。设备端和上位机都写入递增序号,丢包与重复包可以直接计算。
抓到的主要断开原因为 supervision timeout。它说明在连接监督窗口内没有完成有效链路事件,但没有说明是谁先变慢。于是我分别关闭屏幕刷新、降低采样频率、固定发射功率,并记录每组二十分钟的结果。
四条线索
第一条是连接参数。手机协商出的 interval 比预期长,而固件仍按较短周期塞通知,队列逐渐积压。第二条是主线程阻塞:SPI 刷屏使用了大块同步传输,同一任务还承担 BLE 事件分发。第三条是通知没有背压,发送 API 返回“已入队”就被当成“已送达”。第四条是电源,背光和无线同时处于峰值时,3.3V 有短暂下陷,虽然不足以复位,却会增加射频错误。
关键修改不是一味增大超时,而是把节奏对齐:
采样任务 -> 有界数据队列 -> BLE发送任务
-> 屏幕摘要任务
BLE 发送任务只在控制器有可用缓冲时取下一包;屏幕只显示最近状态,不逐条重绘。连接参数更新后,以实际协商值重新计算最大通知频率。
验证矩阵
| 变量 | 低档 | 高档 | 观察项 |
|---|---|---|---|
| 通知频率 | 5 Hz | 30 Hz | 丢包、队列水位 |
| 屏幕刷新 | 2 Hz | 20 Hz | 任务占用、SPI时长 |
| 发射功率 | 中 | 高 | RSSI、电源最低点 |
| 手机距离 | 0.5 m | 8 m | 重传、断开原因 |
每次只改变一个变量,并在两台不同系统的手机上重复。最终版本在高档组合下运行六小时,未出现监督超时;断开电源、关闭蓝牙等预期异常也能在界面上给出明确原因。
排查清单
- [ ] 读取控制器给出的原始断开码,而不是只看“连接失败”
- [ ] 记录实际协商的 interval、latency 与 supervision timeout
- [ ] 确认通知发送存在背压和队列上限
- [ ] 测量最长临界区与屏幕、存储等同步操作
- [ ] 用示波器看无线峰值时的供电,而非只看万用表平均值
- [ ] 在弱信号、高吞吐、长时间三种条件下分别回归
这次问题留下的习惯是:无线故障要同时看协议时间、电源时间和应用时间。单独把某个超时改大,可能只是把问题推迟。能说清每一层什么时候忙、队列里有多少数据、下一次链路事件何时发生,断连才从“玄学”变成工程问题。
评论区