3. BLE广播机制与功耗:广播类型、间隔与数据长度

广播,是BLE设备对外“喊话”的方式。但喊多大声、喊多频繁、喊什么内容,直接决定了你的电池能撑多久。我见过太多工程师,一上来就把广播间隔设成20ms,数据包塞得满满当当,结果产品续航惨不忍睹。

这一章,咱们就把广播机制掰开揉碎,看看功耗到底是怎么被“喊”出去的。

3.1 三种广播类型,功耗天差地别

BLE 4.0/4.1/4.2规范里,广播类型分三种:可连接广播、不可连接广播、可扫描广播。5.0之后又加了扩展广播,但基础逻辑没变。

广播类型 ADV_IND ADV_NONCONN_IND ADV_SCAN_IND
可连接 是 否 否
可扫描 是 否 是
典型功耗 高 低 中
应用场景 手机连接设备 信标/广播器 需扫描响应的信标

可连接广播(ADV_IND):这是最“重”的广播。设备不仅要发广播包,还要在广播事件后留出窗口监听连接请求。我做过一个智能锁项目,一开始用ADV_IND,广播间隔100ms,平均电流直接飙到300μA。后来发现根本不需要一直可连接——用户按门铃时才唤醒监听,平时用不可连接广播就够了。

不可连接广播(ADV_NONCONN_IND):只发不收,发完就睡。这是最省电的模式。信标设备(比如苹果的iBeacon)几乎都用这个。你想想看,一个纽扣电池撑一年,靠的就是这个。

可扫描广播(ADV_SCAN_IND):介于两者之间。设备发广播,但只响应扫描请求,不响应连接请求。我习惯在需要“被动上报”的场景用这个——比如温湿度传感器,手机扫一下就能读到数据,但不会误连。

核心结论:如果设备不需要被连接,永远不要用ADV_IND。省下的功耗,可能是50%以上。

3.2 广播间隔:功耗的“水龙头”

广播间隔,就是两次广播事件之间的时间。BLE规范允许的范围是20ms到10.24s,步进0.625ms。

功耗和间隔的关系,基本是线性的:

  • 间隔100ms:每秒广播10次,平均电流约200-400μA(取决于发射功率和包长)
  • 间隔1s:每秒广播1次,平均电流约20-40μA
  • 间隔5s:每5秒广播1次,平均电流约4-8μA

我在一个资产追踪标签项目里踩过坑。客户要求“手机靠近就能发现”,我把间隔设成50ms。结果标签一天就没电了。后来改成1s间隔,配合手机端的扫描策略优化,续航直接到了两周。

我的经验:广播间隔不要低于100ms,除非你有非常充分的理由。100ms以下,功耗曲线会变得很陡——因为射频启动和关闭的固定开销占比越来越大。

这里有个容易被忽略的点:广播间隔的随机延迟。规范要求在每次广播间隔上增加0-10ms的随机延迟,目的是避免多个设备持续碰撞。这个延迟不会显著影响平均功耗,但会影响峰值电流的分布——设计电源和电容时要留余量。

3.3 广播数据长度:每字节都是电

BLE广播包的有效载荷,最长31字节(经典广播)。扩展广播(5.0)可以到255字节,但功耗也线性增长。

为什么数据长度影响功耗?因为射频发射时间变长了。发射电流通常是8-15mA,每多发射1字节,就多耗约8μs的时间。31字节的包比1字节的包,发射时间多了约250μs。

别小看这250μs。如果广播间隔是100ms,每秒广播10次,那就是2.5ms的额外发射时间。按10mA发射电流算,平均电流多了25μA。一天下来就是0.6mAh——对于100mAh的纽扣电池,这就是0.6%的容量。

广播数据长度 单次发射时间 100ms间隔下额外功耗 1s间隔下额外功耗
1字节 ~128μs 基准 基准
10字节 ~200μs +7.2μA +0.72μA
31字节 ~376μs +24.8μA +2.48μA

所以,我的建议是:

  • 只放必要的数据。比如设备名称、服务UUID、必要的状态标志。
  • 能用1字节表示的,别用2字节。比如用bitmap代替多个独立字段。
  • 如果数据超过31字节,考虑用扫描响应(SCAN_RSP)分担,或者直接上扩展广播。

我曾经踩过的坑:把一个产品的广播数据从20字节压缩到8字节,广播间隔从200ms改成500ms,平均功耗从180μA降到了22μA。但测试时发现手机连接成功率下降了——因为广播间隔太长,手机扫描窗口没对齐。后来折中到300ms+12字节,功耗45μA,连接成功率99.8%。

3.4 扫描响应:免费的“第二包”

扫描响应(SCAN_RSP)是BLE协议里一个很巧妙的设计。当扫描设备发送扫描请求后,广播设备可以额外回复最多31字节的数据。这个回复不占用广播事件的时间,而是由扫描请求触发的。

功耗角度怎么看?

  • 优点:只有被扫描时才发,平时不发。对于“偶尔被扫描”的设备,这比一直广播完整数据省电得多。
  • 缺点:扫描响应会增加一次射频接收和发射。如果设备被频繁扫描(比如每100ms扫一次),功耗反而比直接广播更高。

我习惯的做法是:广播包放“发现”所需的最小数据(比如设备类型、服务UUID),扫描响应放“连接”所需的完整数据(比如设备名称、外观信息)。这样,大部分扫描设备看到广播包就知道要不要继续,只有真正需要的才会触发扫描响应。

3.5 知识图谱:广播功耗的决策树

下面这张图,是我做低功耗设计时脑子里一直挂着的决策逻辑。每次调广播参数,我都会过一遍:

BLE广播功耗决策树 BLE广播参数设计 需要连接? 不需要连接? ADV_IND ADV_NONCONN_IND 间隔 ≥ 100ms? 是→继续;否→功耗飙升 间隔 ≥ 1s? 是→超低功耗;否→中等功耗 数据 ≤ 20字节? 是→OK;否→考虑SCAN_RSP 数据 ≤ 10字节? 是→最优;否→可接受 可连接场景:ADV_IND 间隔100-500ms,数据≤20字节 不可连接场景:ADV_NONCONN_IND 间隔1-5s,数据≤10字节 核心原则:能不发就不发,能少发就少发 广播参数每优化一步,续航就多一分

3.6 实战建议:如何快速估算广播功耗

我一般用这个公式做快速估算:

平均电流 ≈ (发射电流 × 发射时间 + 接收电流 × 接收时间) / 广播间隔

其中:
- 发射电流:通常8-15mA(取决于发射功率)
- 发射时间:约128μs + (数据字节数 × 8μs)
- 接收电流:通常8-12mA(仅ADV_IND需要)
- 接收时间:约150μs(监听窗口)

举个例子:ADV_IND,发射功率0dBm(10mA),数据20字节,间隔200ms。

发射时间 = 128μs + 20×8μs = 288μs
接收时间 = 150μs
单次事件时间 = 288 + 150 = 438μs
平均电流 = (10mA × 438μs) / 200ms ≈ 21.9μA

这个估算值和实测结果通常误差在10%以内。我习惯在原型阶段先用这个公式算一遍,如果超过目标功耗,就调整参数再算,直到满足要求再画板子。

一个小技巧:如果产品需要同时兼容Android和iOS,注意Android的扫描窗口通常是10ms每100ms,iOS是30ms每300ms。广播间隔最好对齐这些扫描窗口的整数倍,否则可能出现“手机扫不到”的尴尬情况。我吃过这个亏,后来学乖了。

好了,广播机制和功耗的关系,说白了就是三个旋钮:广播类型(能不能省掉监听)、广播间隔(多久喊一次)、数据长度(每次喊多久)。拧好这三个旋钮,你的BLE设备续航就能从“一天一充”变成“一周一充”,甚至“一年一充”。