连接间隔详解:7.5ms到4s的范围选择

连接间隔,说白了就是两个设备之间「多久聊一次天」。

BLE协议规定,这个间隔可以在7.5ms到4s之间任意选择。但你别以为随便选一个就行。我见过太多项目,就是因为间隔没选好,要么功耗爆炸,要么数据丢包。

今天我就把这块掰开揉碎了讲清楚。

连接间隔到底是什么?

连接间隔,指的是两个BLE设备之间,两次连接事件的时间差。

每次连接事件,主设备和从设备会交换一次数据。你可以把它想象成两个人打电话——

  • 短间隔:相当于每7.5ms就通一次话,每次说几句话就挂
  • 长间隔:相当于每4s才通一次话,每次可以多说点

嗯,这个比喻虽然糙了点,但道理是一样的。

7.5ms到4s,这个范围怎么来的?

这个范围不是随便定的。我查过蓝牙Core Spec 5.x,里面明确规定了连接间隔的单位是1.25ms。

所以实际可选的间隔值是:

连接间隔 = N × 1.25ms

其中N的范围是:6 ~ 3200

6 × 1.25ms = 7.5ms
3200 × 1.25ms = 4000ms = 4s

你可能会问:为什么是1.25ms?

其实这是为了兼容蓝牙时钟的精度。BLE的时钟基频是3.2kHz,周期正好是312.5μs。1.25ms是它的4倍,方便硬件做分频。

短间隔的利弊分析

短间隔,我一般指7.5ms到30ms这个范围。

优点:

  • 延迟低。数据从发送到接收,最快7.5ms就能完成
  • 适合实时性要求高的场景,比如游戏手柄、鼠标
  • 数据吞吐量大。单位时间内能传输更多数据包

缺点:

  • 功耗高。设备频繁唤醒,电流消耗直线上升
  • 信道拥挤。频繁占用射频资源,容易碰撞
  • 对硬件要求高。MCU需要频繁处理中断

我记得有个项目是做蓝牙鼠标的。当时我选了7.5ms的间隔,结果电池两天就没电了。后来改成15ms,功耗降了一半,用户也感觉不到延迟差异。

所以你看,不是越短越好。

长间隔的利弊分析

长间隔,我一般指100ms以上,甚至到4s。

优点:

  • 功耗极低。设备大部分时间都在休眠
  • 信道利用率高。射频资源占用少
  • 适合电池供电的传感器设备

缺点:

  • 延迟高。数据从产生到发送,可能要等几百毫秒甚至几秒
  • 吞吐量低。单位时间内能传的数据有限
  • 不适合实时控制类应用

我曾经做过一个温湿度传感器项目,要求电池用一年。我选了1s的连接间隔,配合深度睡眠,最终实现了两节AA电池用18个月。

但如果你拿这个间隔去做智能锁,那用户按一下按钮要等1秒才有反应,体验就太差了。

如何选择连接间隔?

这里我给出一个经验法则:

应用场景 推荐间隔 原因
游戏手柄、鼠标 7.5ms ~ 15ms 需要低延迟
音频传输 15ms ~ 30ms 平衡延迟和吞吐量
健康监测(心率、血氧) 50ms ~ 100ms 数据量不大,但需要实时性
环境传感器(温湿度、气压) 500ms ~ 2s 数据变化慢,省电为主
信标、定位标签 1s ~ 4s 极低功耗,偶尔上报位置

当然,这只是参考。实际项目中,你还要考虑:

  • 主设备的处理能力
  • 射频环境是否嘈杂
  • 电池容量和寿命要求
  • 数据包的大小和频率

避坑指南

我曾经踩过的坑:

有一次做多设备连接的项目,一个手机同时连了6个传感器。我每个传感器都设了7.5ms的间隔。结果呢?手机蓝牙直接崩溃了,因为每个连接事件都要处理,根本忙不过来。

后来我把间隔错开,有的设10ms,有的设15ms,有的设20ms,问题就解决了。

所以,多设备场景下,不要所有设备都用同一个间隔。错开一点,能大大降低主设备的负担。

连接间隔的协商机制

你可能不知道,连接间隔不是主设备单方面决定的。

从设备可以通过「连接参数更新请求」来协商。具体流程是:

  1. 从设备发送LL_CONNECTION_PARAM_REQ
  2. 主设备收到后,可以选择接受或拒绝
  3. 如果接受,双方在新的间隔下工作

嗯,这里要注意:iOS对连接参数更新有严格限制。苹果要求从设备必须在连接建立后5秒才能发起更新请求,而且间隔不能低于30ms。

我建议你在做iOS兼容时,直接设好30ms以上的间隔,省得后面还要协商。

实际项目中的经验

我个人习惯的做法是:

  • 先根据应用场景选一个初始间隔
  • 然后做功耗测试,看实际电流曲线
  • 如果功耗超标,逐步增大间隔,每次增加50%
  • 如果延迟超标,逐步减小间隔,每次减少30%

你想想看,这样迭代几次,总能找到最优值。

另外,我建议你在产品中预留一个动态调整间隔的接口。这样用户可以根据自己的使用习惯来调节,比如「省电模式」用长间隔,「性能模式」用短间隔。

小技巧:

如果你用的是Nordic的nRF5 SDK,可以直接调用sd_ble_gap_conn_param_update()来更新连接间隔。代码大概是这样:

ble_gap_conn_params_t conn_params;
conn_params.min_conn_interval = 80;  // 100ms
conn_params.max_conn_interval = 120; // 150ms
conn_params.slave_latency = 0;
conn_params.conn_sup_timeout = 4000; // 4s

sd_ble_gap_conn_param_update(conn_handle, &conn_params);

总结

连接间隔的选择,本质上是在功耗和性能之间做权衡。

短间隔适合实时控制,但费电。长间隔省电,但延迟高。没有完美的值,只有适合你项目的值。

我建议你:

  • 先明确你的核心需求(低延迟还是低功耗)
  • 参考上面的表格选一个初始值
  • 实际测试后微调
  • 别忘了考虑多设备场景和iOS兼容性

下一章,我会讲从设备延迟(Slave Latency)这个参数。它能在不增加延迟的情况下,进一步降低功耗。敬请期待。