4、广播间隔与微调:广播间隔范围(20ms-10.24s),微调延迟(0-10ms),如何影响功耗与发现速度

好,咱们来聊聊广播间隔。这个参数,说白了就是蓝牙芯片每隔多久发一次广播包。你想想看,它就像你在人群中举着牌子,每隔几秒晃一下。晃得太勤快,你累(费电);晃得太慢,别人半天看不见你(发现慢)。

我个人习惯,拿到一个新项目,第一件事就是问产品经理:这个设备对功耗敏感,还是对被发现的速度敏感?答案不同,广播间隔的设置天差地别。

4.1 广播间隔的范围:从20ms到10.24s

蓝牙规范里,广播间隔的范围很宽。从20毫秒到10.24秒,跨度超过500倍。为什么给这么大范围?因为应用场景太不一样了。

  • 20ms - 100ms:极速发现场景。比如蓝牙遥控器、游戏手柄,你按一下按键,希望电视立刻响应。我做过一个遥控器项目,广播间隔设成30ms,用户体验很好,但电池只能撑两周。
  • 100ms - 1s:常见于可穿戴设备。比如手环、心率带。发现速度可以接受,功耗也还行。
  • 1s - 10.24s:低功耗场景。比如温湿度传感器、ibeacon信标。这些设备不急着被发现,省电是第一要务。

核心要点:广播间隔每增加一倍,平均功耗大约降低一半。但发现时间也会线性增加。这是一个典型的“鱼与熊掌”问题。

4.2 微调延迟:0-10ms的“小把戏”

嗯,这里要注意。广播间隔不是严格固定的。蓝牙协议允许一个“微调延迟”(advDelay),范围是0到10毫秒。为什么要有这个微调?

原因很简单:避免多个设备在同一时刻广播,造成碰撞。你想啊,如果两个蓝牙芯片都把间隔设成100ms,它们可能每次都在同一时刻发广播,互相干扰。微调延迟就是给每个广播周期加一个随机的小偏移,让碰撞概率大大降低。

我曾经踩过一个坑。有个项目,批量生产1000个信标,广播间隔都设成500ms,微调延迟设成0。结果在仓库里测试,发现很多手机搜不到设备。后来抓包一看,好家伙,广播包全撞在一起了。从那以后,我只要做广播类产品,微调延迟至少设成5ms。

我的建议:微调延迟不要设成0。哪怕设成1ms,也能显著改善碰撞问题。如果你对功耗极度敏感,可以设小一点,比如2ms。但千万别省这1ms的代价。

4.3 功耗与发现速度的量化关系

咱们用数据说话。假设广播包长度固定,发射功率固定,那么功耗和广播间隔的关系大致如下:

广播间隔 微调延迟 平均功耗(参考) 平均发现时间
20ms 5ms ~5mA <100ms
100ms 5ms ~1mA ~500ms
1s 5ms ~0.1mA ~3s
10s 5ms ~0.01mA ~30s

注意,这只是参考值。实际功耗还跟芯片型号、发射功率、广播信道数有关。但趋势很明显:间隔越大,功耗越低,发现越慢。

4.4 实战中的权衡策略

那在实际项目中怎么选?我一般分三步走:

  1. 先定发现时间要求:产品经理说“用户打开App后3秒内必须看到设备”,那广播间隔就不能超过1秒。因为扫描端通常需要扫描1-2个完整间隔才能稳定发现。
  2. 再算功耗预算:电池容量除以目标续航,得到平均电流上限。比如100mAh电池,目标续航30天,平均电流不能超过0.14mA。那广播间隔至少得设到1秒以上。
  3. 最后微调:在满足发现时间的前提下,尽量把间隔拉大。微调延迟固定设成5ms,除非有特殊需求。

避坑指南:我曾经遇到过一个情况,广播间隔设成20ms,结果手机扫描端反而发现不了设备。为什么?因为广播太密集,扫描端的接收缓冲区被撑爆了。所以,不是间隔越小越好。极端情况下,过短的间隔反而会降低发现成功率。

4.5 代码示例:如何配置广播间隔

以Nordic nRF5 SDK为例,配置广播间隔的代码长这样:

// 广播间隔设置
// 单位:0.625ms
// 例如:160 * 0.625ms = 100ms
#define ADV_INTERVAL_MS      100
#define ADV_INTERVAL_UNITS   (ADV_INTERVAL_MS * 1000 / 625)

// 微调延迟范围:0-10ms
// 单位:0.625ms
#define ADV_DELAY_MS         5
#define ADV_DELAY_UNITS      (ADV_DELAY_MS * 1000 / 625)

// 初始化广播参数
ble_gap_adv_params_t adv_params;
memset(&adv_params, 0, sizeof(adv_params));
adv_params.type        = BLE_GAP_ADV_TYPE_ADV_IND;
adv_params.p_peer_addr = NULL;
adv_params.fp          = BLE_GAP_ADV_FP_ANY;
adv_params.interval    = ADV_INTERVAL_UNITS;  // 广播间隔
adv_params.timeout     = 0;                   // 永不超时

注意看,interval的单位是0.625ms。这是蓝牙协议规定的。很多新手在这里算错,把100ms直接填成100,结果实际间隔只有62.5ms。我刚开始也犯过这个错,后来养成了习惯,每次都用宏定义换算。

4.6 动态调整广播间隔

高级一点的玩法,是让广播间隔动态变化。比如:

  • 设备刚上电时:用短间隔(50ms),方便快速被发现。
  • 连接建立后:切换成长间隔(1s),省电。
  • 断开连接后:再切回短间隔,等待下次连接。

我做过一个智能门锁项目,就是用的这个策略。用户靠近时,门锁用短间隔广播,手机秒连。平时没人时,门锁用10秒间隔广播,电池撑了一年多。

小技巧:动态调整时,注意不要频繁切换。每次切换广播参数,芯片需要重新初始化广播通道,会额外消耗几十毫秒的电流。我一般建议,切换间隔不要小于1秒。

4.7 总结一下

广播间隔和微调延迟,看似简单,但直接影响产品的功耗和用户体验。我的经验是:

  • 先明确需求:要快还是要省电?
  • 微调延迟别设0,5ms是个好起点。
  • 动态调整是王道,但别切换太频繁。
  • 代码里用宏定义换算单位,避免算错。

嗯,这一节就聊到这儿。下一节咱们讲讲广播信道的选择,那个也有不少门道。