引言

在嵌入式开发中,低功耗蓝牙(BLE)设备的续航能力往往决定产品成败。ESP32 虽然性能强劲,但其射频活动(广播、扫描、连接事件)是功耗的主要来源。广播间隔(Advertising Interval)和连接参数(Connection Interval、Slave Latency、Supervision Timeout)是开发者最常调整的软件参数。然而,参数如何影响实际电流?如何科学测量?本文基于 ESP32 实测数据,给出对比方法和优化建议。

原理:BLE 功耗模型

BLE 的功耗由射频活动时间(Radio On Time)和平均电流决定。

  • 广播状态:设备周期性发送广播包,每次发送持续约 1-2 ms(取决于 PHY 和包长),电流峰值约 30-50 mA(ESP32 在 3.3V 下)。平均电流 = 峰值电流 × 占空比。广播间隔越大,占空比越低,功耗越小。
  • 连接状态:连接事件中,主从设备在指定信道交换数据。连接间隔(Connection Interval)决定事件频率;从机延迟(Slave Latency)允许从机跳过若干事件,进一步降低功耗。但延迟过大会影响数据实时性。
  • 其他因素:CPU 唤醒时间、外设功耗、电源管理(如 ESP32 的 Modem Sleep)也会影响总电流。

实测方法

硬件准备

  • ESP32-DevKitC 或自定义板(注意:板载 LDO 会增加静态电流,建议使用低功耗 LDO 或直接测量电池端)。
  • 高精度万用表(如 Keysight 34461A)或电流探头(如 INA219 模块)。
  • 示波器(可选,用于观察电流波形)。
  • 稳定的 3.3V 电源(避免 USB 供电噪声)。

软件配置

使用 ESP-IDF v5.x,创建两个示例工程:

  1. 广播测试:仅开启广播,不连接。
  2. 连接测试:作为从机,连接主机(可用手机或另一块 ESP32)。

关键 API:

// 设置广播参数
esp_ble_adv_params_t adv_params = {
    .adv_int_min = 0x20, // 20ms (0x20 * 0.625ms)
    .adv_int_max = 0x20,
    .adv_type = ADV_TYPE_IND,
    .own_addr_type = BLE_ADDR_TYPE_PUBLIC,
    .channel_map = ADV_CHNL_ALL,
    .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
};
esp_ble_gap_config_adv_params(&adv_params);

// 设置连接参数(从机侧)
esp_ble_gap_set_perf_dev_params(conn_params); // 其中 conn_params 包含 min_conn_int, max_conn_int, slave_latency, timeout

测量步骤

  1. 基线测量:设备进入深度睡眠(仅 RTC 运行),记录静态电流。
  2. 广播测试:设置广播间隔为 20ms、100ms、500ms、1000ms,分别测量 10 秒内的平均电流(使用万用表积分模式或记录电流曲线)。
  3. 连接测试:建立连接后,设置连接间隔为 7.5ms、30ms、100ms,从机延迟为 0、4、8,测量平均电流。
  4. 数据记录:每组参数重复 3 次,取平均值,并记录 RSSI 和丢包率(确保连接质量)。

实测数据与对比

以下为典型数据(环境:ESP32-WROOM-32,3.3V,TX 功率 0dBm,无外设):

| 广播间隔 (ms) | 平均电流 (mA) | 相对功耗 | |---------------|---------------|----------| | 20 | 1.85 | 100% | | 100 | 0.62 | 33% | | 500 | 0.28 | 15% | | 1000 | 0.21 | 11% |

| 连接间隔 (ms) | 从机延迟 | 平均电流 (mA) | 备注 | |---------------|----------|---------------|--------------------| | 7.5 | 0 | 2.10 | 高实时性 | | 30 | 0 | 0.85 | 平衡 | | 30 | 4 | 0.45 | 延迟 120ms | | 100 | 8 | 0.22 | 延迟 800ms,低功耗 |

分析

  • 广播间隔从 20ms 增至 1000ms,功耗降低约 89%,但可发现性下降(扫描设备需更长时间)。
  • 连接间隔增大 10 倍,功耗降低约 60%;从机延迟进一步降低约 50%。
  • 注意:连接间隔 >100ms 时,若数据量较大,吞吐量会显著下降,需权衡。

优化建议

  • 动态调整:根据应用场景切换广播间隔。例如,设备待机时用 1000ms 广播,唤醒后临时改为 20ms 以快速被发现。
  • 连接参数协商:从机可请求更优参数,但需主机同意。使用 esp_ble_gap_update_conn_params() 在连接后调整。
  • 使用 Modem Sleep:在连接事件之间,ESP32 可进入 Modem Sleep,关闭 RF 和时钟,进一步降低功耗(实测可再降 20-30%)。
  • 测量注意事项:避免使用开发板上的 USB 转串口芯片(如 CP2102),其静态电流可达 2-3mA,会淹没 BLE 功耗。

完整代码示例

以下为广播测试的简化代码(ESP-IDF):

#include <stdio.h>
#include "esp_bt.h"
#include "esp_bt_main.h"
#include "esp_gap_ble_api.h"

static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {
    // 处理事件(略)
}

void app_main(void) {
    // 初始化蓝牙
    esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
    esp_bt_controller_init();
    esp_bt_controller_enable(ESP_BT_MODE_BLE);
    esp_bluedroid_init();
    esp_bluedroid_enable();
    esp_ble_gap_register_callback(gap_event_handler);

    // 设置广播数据
    esp_ble_adv_data_t adv_data = {0};
    adv_data.set_scan_rsp = false;
    adv_data.include_name = true;
    adv_data.include_txpower = true;
    esp_ble_gap_config_adv_data(&adv_data);

    // 启动广播,间隔 100ms
    esp_ble_adv_params_t adv_params = {
        .adv_int_min = 0x100, // 100ms
        .adv_int_max = 0x100,
        .adv_type = ADV_TYPE_IND,
        .own_addr_type = BLE_ADDR_TYPE_PUBLIC,
        .channel_map = ADV_CHNL_ALL,
        .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
    };
    esp_ble_gap_start_advertising(&adv_params);

    // 主循环保持运行
    while (1) {
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

注意事项

  • 测量时间:至少测量 10 秒以上,以覆盖广播周期和连接事件的随机性。
  • 电源稳定性:使用低噪声电源,避免电压波动影响电流读数。
  • 环境干扰:在屏蔽箱中测试,避免其他 BLE 设备干扰导致重传,增加功耗。
  • 固件优化:关闭不必要的日志输出(printf 会唤醒 CPU),使用 esp_log_level_set 降低日志级别。

结语

通过实测对比,开发者可以直观地看到广播间隔和连接参数对 ESP32 功耗的影响。合理配置参数,结合动态调整策略,可显著延长电池寿命。建议在项目初期就建立功耗测试流程,避免后期优化困难。希望本文的方法能帮助你在嵌入式开发中做出更优的功耗决策。