BLE连接参数优化:Connection Interval、Slave Latency、Supervision Timeout

做BLE开发,连接参数这块儿,我敢说90%的坑都出在这里。

你想想看,蓝牙连上了,数据也通了,但功耗高得离谱,或者动不动就断连。这时候别急着怀疑硬件,先看看你的连接参数配得对不对。我当年做第一个BLE项目时,就被这个“连接参数”狠狠教育了一回。

连接参数到底是什么?

BLE建立连接后,主设备和从设备之间不是一直说话的。它们按固定的时间间隔“碰头”一次,这个间隔就叫Connection Interval。说白了,就是两个设备约好每多少毫秒交换一次数据。

但光有这个还不够。从设备可以偷懒——如果没数据要发,它可以跳过几次“碰头”,这就是Slave Latency。而Supervision Timeout则是保底机制:如果主设备连续多久没收到从设备的回应,就认为连接断了。

这三个参数,就是BLE连接性能的“铁三角”。

核心公式:

实际连接间隔 = Connection Interval × (1 + Slave Latency)

最大断连检测时间 = Supervision Timeout

Connection Interval:快与慢的博弈

Connection Interval的单位是1.25ms,取值范围从7.5ms到4s。但实际开发中,常用的范围是7.5ms到100ms。

我个人习惯这样选:

  • 7.5ms - 15ms:低延迟场景,比如游戏手柄、实时控制。功耗高,但响应快。
  • 30ms - 50ms:大多数数据采集场景,比如传感器读数、心率监测。平衡之选。
  • 100ms以上:低功耗场景,比如温湿度计、ibeacon广播。省电,但别指望实时性。

我在项目中遇到过一件事:一个智能锁项目,客户要求开锁响应时间小于200ms。我一开始用了50ms的Connection Interval,结果功耗超标。后来改成100ms,配合Slave Latency优化,响应时间反而更稳定了。嗯,这里要注意——不是越快越好,快意味着频繁唤醒,功耗直线上升。

Slave Latency:从设备的“摸鱼”机会

Slave Latency允许从设备在指定次数内不响应主设备的连接事件。取值范围是0到499,但不能让实际连接间隔超过Supervision Timeout。

举个例子:

  • Connection Interval = 30ms
  • Slave Latency = 4
  • 实际连接间隔 = 30ms × (1 + 4) = 150ms

这意味着从设备最多可以连续跳过4次连接事件,也就是150ms才真正收发一次数据。这期间从设备可以深度睡眠,省电效果非常明显。

我的经验:

Slave Latency设成3-5是比较安全的范围。设太大,主设备那边容易误判断连。我曾经把Slave Latency设成10,结果主设备那边Supervision Timeout没调大,连接频繁断开。排查了两天才找到原因——说白了就是参数不匹配。

Supervision Timeout:最后的防线

Supervision Timeout是主设备用来检测连接是否还活着的超时时间。单位是10ms,范围从100ms到32s。但实际开发中,建议不要低于500ms,也不要超过6s。

为什么?

  • 太短:容易误判断连,尤其在信号不稳定的环境中。
  • 太长:断连后要等很久才能发现,用户体验差。

我建议的配置原则:

Supervision Timeout > 实际连接间隔 × 3

比如实际连接间隔是150ms,那Supervision Timeout至少设450ms。留点余量,我一般会设成600ms或800ms。

功耗与延迟的权衡

这其实是个老生常谈的问题。但BLE里有个很直观的权衡曲线:

场景 Connection Interval Slave Latency Supervision Timeout 功耗 延迟
实时控制 7.5ms 0 500ms
数据采集 30ms 3 1s
低功耗传感 100ms 5 3s

你想想看,如果设备每7.5ms就要醒来一次,那电池能撑多久?反过来,如果允许从设备跳过几次连接事件,它就能多睡一会儿。但代价是——主设备发数据,从设备要等好几个间隔才能收到。

避坑指南:

我曾经在一个穿戴设备项目里,为了省电把Slave Latency设到8,Connection Interval设到80ms。结果实际连接间隔变成了720ms。用户按一下手表上的按钮,要等将近1秒才有反应。产品经理差点没把我吃了。后来我改成Connection Interval 30ms + Slave Latency 4,延迟降到150ms,功耗也只多了15%。

Android端如何请求连接参数?

在Android上,从设备(比如你的外设)可以主动请求连接参数。核心API是BluetoothGatt#requestConnectionPriority,但注意——这只是请求,主设备不一定接受。

// 请求低延迟连接
bluetoothGatt.requestConnectionPriority(
    BluetoothGatt.CONNECTION_PRIORITY_HIGH
)

// 请求平衡模式
bluetoothGatt.requestConnectionPriority(
    BluetoothGatt.CONNECTION_PRIORITY_BALANCED
)

// 请求低功耗模式
bluetoothGatt.requestConnectionPriority(
    BluetoothGatt.CONNECTION_PRIORITY_LOW_POWER
)

这三个优先级对应不同的Connection Interval范围:

  • HIGH:7.5ms - 15ms
  • BALANCED:30ms - 50ms
  • LOW_POWER:100ms以上

但有个坑——Android系统不保证一定会采纳你的请求。我记得有一次在小米手机上测试,请求HIGH优先级,结果系统还是给了30ms的间隔。后来发现是手机蓝牙协议栈的限制。嗯,这种情况只能认了。

连接参数协商流程

BLE的连接参数不是单方面决定的。主设备和从设备可以协商。流程大致是这样:

  1. 从设备发送Connection Parameter Update Request
  2. 主设备收到后,决定接受、拒绝或提出新参数
  3. 如果接受,连接参数立即生效
  4. 如果拒绝,从设备可以再次请求,但别太频繁

在Android端,从设备不能直接发起参数更新请求。你需要通过BluetoothGatt#requestConnectionPriority来间接影响。或者,如果你是自己写固件,可以在从设备端主动发起L2CAP层的参数更新请求。

核心建议:

不要频繁请求连接参数。每次请求都会打断正常的数据传输。我一般只在连接建立后的前3秒内请求一次,之后就不再动了。

SVG:连接参数优化决策流程

BLE连接参数优化决策流程 开始配置连接参数 是否需要低延迟?(< 50ms) 是:使用 HIGH 优先级 否:考虑 BALANCED 或 LOW Connection Interval: 7.5-15ms Slave Latency: 0-2 Connection Interval: 30-100ms Slave Latency: 3-8 检查 Supervision Timeout 是否匹配

实际项目中的参数调优步骤

说了这么多理论,来点实际的。我一般按这个步骤调优:

  1. 先确定延迟要求:用户能接受多少毫秒的响应时间?
  2. 再算功耗预算:电池能撑多久?每天用几次?
  3. 选Connection Interval:在延迟和功耗之间取平衡点。
  4. 配Slave Latency:从设备没数据时能睡多久?
  5. 设Supervision Timeout:留够余量,别误判断连。
  6. 实际测试:用BLE抓包工具(比如nRF Connect)看实际参数。

小技巧:

调试时,用nRF Connect或LightBlue抓一下连接参数。你会发现很多手机厂商会修改默认参数。比如华为手机经常把Connection Interval强制拉到50ms以上。这时候你只能适应它,别硬刚。

好了,连接参数这块儿,说白了就是三个数字的排列组合。但每个数字背后都是功耗、延迟、稳定性的权衡。我做了这么多年BLE,最深的体会就是——没有完美的参数,只有适合场景的参数。多测、多调、多踩坑,慢慢就有感觉了。


公众号:蓝海资料掘金营,微信deep3321