ESP32 BLE 长连接保活参数调优:连接间隔、从机延迟与 Supervision Timeout 的权衡

在 BLE 连接中,主从设备通过周期性的事件交换数据,而连接参数决定了这种交换的频率和容忍度。对于 ESP32 这类资源受限的嵌入式设备,不合理的参数配置会导致功耗飙升或连接频繁掉线。本文将带你深入理解这三个核心参数,并给出可落地的调优方案。

一、参数原理与作用

1. 连接间隔(Connection Interval)

连接间隔是两次连接事件之间的时间间隔,范围在 7.5ms 到 4s(以 1.25ms 为步进)。它决定了数据吞吐量和功耗的平衡:

  • 短间隔(如 15ms):数据交互频繁,延迟低,但设备唤醒次数多,功耗高。
  • 长间隔(如 100ms):功耗降低,但数据发送延迟增加,适合低频数据传输。

2. 从机延迟(Slave Latency)

从机延迟允许从设备在指定次数的连接事件中跳过响应,从而减少唤醒次数。例如,延迟为 4 表示从机可以连续 4 个连接事件不监听,只在第 5 个事件响应。

  • 作用:显著降低功耗,尤其适合周期性上报数据的场景。
  • 代价:主机发送的数据可能被延迟最多 (连接间隔 × (从机延迟+1)) 才能被从机接收。

3. 监督超时(Supervision Timeout)

监督超时是主从设备在失去连接事件后,判定连接丢失的最大时间。范围 100ms 到 32s。它必须满足公式: Supervision Timeout > (1 + Slave Latency) × Connection Interval × 2 否则连接会被视为无效。

  • 作用:保护连接稳定性,防止因瞬时干扰导致误判。
  • 权衡:超时过长,连接丢失后重连慢;超时过短,容易因环境干扰而掉线。

二、ESP32 配置步骤

在 ESP32 中使用 ESP-IDF 或 Arduino 框架,通过 esp_ble_gap_update_conn_params() 函数动态调整参数。以下以 ESP-IDF 为例:

1. 初始化连接参数结构体

#include "esp_gap_ble_api.h"

void update_ble_conn_params(uint16_t min_interval, uint16_t max_interval, 
                            uint16_t latency, uint16_t timeout) {
    esp_ble_conn_update_params_t conn_params = {
        .latency = latency,  // 从机延迟,单位:连接事件次数
        .timeout = timeout,  // 监督超时,单位:10ms(例如 500 = 5s)
    };
    // 连接间隔单位:1.25ms,所以 80 = 100ms
    conn_params.min_int = min_interval;  // 例如 80
    conn_params.max_int = max_interval;  // 例如 80
    
    esp_err_t ret = esp_ble_gap_update_conn_params(&conn_params);
    if (ret != ESP_OK) {
        ESP_LOGE("BLE", "Failed to update conn params: %s", esp_err_to_name(ret));
    }
}

2. 在连接事件后调用

当 ESP32 作为从机时,在 ESP_GAP_BLE_OPEN_EVT 事件中调用更新函数:

static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {
    switch (event) {
        case ESP_GAP_BLE_OPEN_EVT:
            // 连接建立后,立即调整参数
            update_ble_conn_params(80, 80, 4, 500); // 100ms间隔,延迟4,超时5s
            break;
        default:
            break;
    }
}

3. 注意:主机端可能拒绝参数

BLE 规范允许主机拒绝从机发起的参数更新请求。因此,建议在从机端也设置合理的默认参数(通过 esp_ble_gap_set_device_name 和广播数据中的连接参数),并监听 ESP_GAP_BLE_UPD_CONN_PARAMS_EVT 事件确认结果。

三、调优策略与权衡

场景 1:低功耗传感器(如温湿度计)

  • 需求:每 10 秒上报一次数据,功耗优先。
  • 推荐参数:连接间隔 200ms(160),从机延迟 9,超时 6s(600)。
  • 计算:有效监听周期 = 200ms × (9+1) = 2s,功耗降低约 90%。超时满足 > 200ms × 10 × 2 = 4s,6s 安全。

场景 2:实时控制(如智能灯)

  • 需求:响应快,数据交互频繁。
  • 推荐参数:连接间隔 15ms(12),从机延迟 0,超时 1s(100)。
  • 权衡:功耗较高,但延迟低至 15ms。超时 1s 保证掉线快速检测。

场景 3:平衡型(如智能手环)

  • 需求:兼顾续航和通知响应。
  • 推荐参数:连接间隔 50ms(40),从机延迟 4,超时 4s(400)。
  • 计算:有效监听周期 = 50ms × 5 = 250ms,功耗适中,通知延迟 ≤250ms。

四、完整代码示例(ESP-IDF)

以下是一个完整的从机初始化与参数更新示例:

#include <stdio.h>
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_bt.h"
#include "esp_gap_ble_api.h"
#include "esp_gatts_api.h"

#define TAG "BLE_DEMO"

static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {
    switch (event) {
        case ESP_GAP_BLE_OPEN_EVT:
            // 连接建立,更新参数:间隔100ms,延迟4,超时5s
            esp_ble_conn_update_params_t conn_params = {
                .latency = 4,
                .timeout = 500,  // 500 * 10ms = 5s
                .min_int = 80,   // 80 * 1.25ms = 100ms
                .max_int = 80,
            };
            esp_ble_gap_update_conn_params(&conn_params);
            break;
        case ESP_GAP_BLE_UPD_CONN_PARAMS_EVT:
            ESP_LOGI(TAG, "Conn params updated, status: %d", param->update_conn_params.status);
            break;
        default:
            break;
    }
}

void app_main(void) {
    // 初始化 NVS 和蓝牙
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES) {
        nvs_flash_erase();
        nvs_flash_init();
    }
    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();
    
    // 注册 GAP 回调
    esp_ble_gap_register_callback(gap_event_handler);
    
    // 配置广播数据(省略细节)
    // ...
    
    ESP_LOGI(TAG, "BLE device started");
}

五、注意事项

  • 参数范围合法性:连接间隔必须满足 min_int <= max_int,且超时必须大于 (1+latency) × max_int × 2(单位换算后)。否则 ESP32 会返回错误。
  • 主机兼容性:iOS 和 Android 对连接参数有各自限制(如 iOS 要求间隔在 30ms 以上),建议在开发时测试不同主机。
  • 动态调整:不要在连接事件中频繁调用更新函数,建议在连接建立后一次性设置,或根据业务状态(如低功耗模式)切换。
  • 功耗测量:使用电流表或 ESP32 的功耗监控功能,实际测量不同参数下的平均电流,避免理论计算偏差。
  • 调试技巧:开启 CONFIG_BT_LOG_LEVEL 为 INFO,观察连接参数更新日志,确认主机是否接受。

六、总结

连接间隔、从机延迟和超时是 BLE 长连接的三驾马车,没有万能配置,只有针对场景的权衡。通过理解原理,结合 ESP32 的 API,你可以轻松实现功耗与性能的平衡。记住:先满足超时公式,再根据业务需求调整间隔和延迟,最后用实际测试验证。希望本文能助你在 BLE 开发中少走弯路。