4. 2.4GHz 频段共存问题:Wi-Fi与BLE的干扰机制、自适应跳频(AFH)原理

做物联网这行,2.4GHz 频段就是个“菜市场”。Wi-Fi、蓝牙、Zigbee、甚至微波炉都挤在这 83.5MHz 的带宽里。你想想看,大家都不交“保护费”,抢信道是家常便饭。这一章,我们就聊聊 Wi-Fi 和 BLE 这对“冤家”是怎么互相干扰的,以及 BLE 怎么靠自适应跳频(AFH)来“躲子弹”。

4.1 为什么偏偏是 2.4GHz?

说白了,2.4GHz 是个“黄金频段”。它不需要授权,穿透性比 5GHz 好,全球通用。但代价就是——太拥挤了。我见过一个智能家居项目,客户家里装了 6 个 Wi-Fi AP,结果 BLE 门锁经常离线。排查到最后,发现是 Wi-Fi 把 BLE 的跳频信道给“淹”了。

核心矛盾:Wi-Fi 占带宽(20/40MHz),BLE 靠跳频(2MHz 窄带)。Wi-Fi 一铺开,BLE 的“落脚点”就少了。

4.2 Wi-Fi 与 BLE 的干扰机制

我们先看一张图,直观感受一下两者的频谱占用差异。

Wi-Fi 与 BLE 频谱占用对比 2400 MHz 2483.5 MHz Wi-Fi CH1 (20MHz) Wi-Fi CH6 (20MHz) Wi-Fi CH11 (20MHz) 绿色小方块 = BLE 2MHz 窄带跳频信道 红色虚线 = Wi-Fi 20MHz 宽带覆盖区域(干扰源) Wi-Fi 一个信道占 20MHz,可覆盖 10 个 BLE 信道。3 个不重叠 Wi-Fi 信道就能覆盖 30 个 BLE 信道(共 40 个数据信道)。

4.3 干扰的三种“姿势”

在实际项目中,我总结出 Wi-Fi 干扰 BLE 的三种典型场景:

  1. 同频阻塞:Wi-Fi 信号太强,直接把 BLE 接收机的前端放大器“推”到饱和。BLE 收不到任何包,哪怕 Wi-Fi 没在传数据。
  2. 邻频干扰:Wi-Fi 的带外泄漏(ACLR)不够好,能量溅射到相邻的 BLE 信道。这在小体积产品上特别常见——天线隔离度不够。
  3. 互调干扰:多个 Wi-Fi 信号在 BLE 接收机的非线性器件上“混频”,产生新的频率分量,正好落在 BLE 信道上。嗯,这个比较难排查,我曾经在产线上遇到过一批设备,只有同时开两个 Wi-Fi AP 时 BLE 才掉线,最后发现是 LNA 的线性度不够。
干扰类型 根本原因 典型表现 排查难度
同频阻塞 Wi-Fi 功率过高 BLE 完全收不到包 低
邻频干扰 天线隔离度差 特定信道丢包率高 中
互调干扰 接收机线性度不足 多 Wi-Fi 源时异常 高

4.4 自适应跳频(AFH)原理

BLE 怎么应对这些干扰?靠的就是 AFH。说白了,就是“打一枪换一个地方”,但只换到“安全”的地方。

AFH 的核心流程分三步:

  • 信道映射(Channel Map):BLE 协议栈维护一个 40 位的信道映射表,每一位代表一个 2MHz 信道(0 表示“坏”,1 表示“好”)。
  • 信道质量评估:链路层会统计每个信道的丢包率、RSSI 和 CRC 错误数。我习惯把阈值设为丢包率 > 20% 就标记为“坏信道”。
  • 跳频序列重排:主设备(Master)根据信道映射表,重新计算跳频序列。坏信道被跳过,只用好信道。

我的经验:AFH 的“学习速度”很关键。如果评估窗口太短(比如 1 秒),信道状态会频繁抖动,导致跳频序列不稳定。我一般建议窗口设为 5-10 秒,兼顾响应速度和稳定性。

4.5 AFH 的“避坑”实战

光讲原理不够,我们来看看代码里怎么配。以下是一个基于 Nordic nRF5 SDK 的 AFH 配置片段:

// 初始化 BLE 连接参数,开启 AFH
ble_gap_conn_params_t   gap_conn_params;
ble_gap_conn_sec_mode_t sec_mode;

BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);

gap_conn_params.min_conn_interval = MSEC_TO_UNITS(7.5, UNIT_0_625_MS);
gap_conn_params.max_conn_interval = MSEC_TO_UNITS(30, UNIT_0_625_MS);
gap_conn_params.slave_latency     = 0;
gap_conn_params.conn_sup_timeout  = MSEC_TO_UNITS(4000, UNIT_10_MS);

// 关键:设置信道映射,默认全 1(所有信道可用)
// 实际应用中,需要根据 RSSI 和丢包率动态更新
uint8_t ch_map[5] = {0xFF, 0xFF, 0xFF, 0xFF, 0x1F}; // 40 信道全开

sd_ble_gap_adv_set_phys(&adv_handle, &gap_conn_params, ch_map, NULL, NULL);

注意:千万不要在连接建立后频繁更新信道映射。我曾经有个项目,每 2 秒就根据 RSSI 更新一次 ch_map,结果导致连接频繁断开。原因是 AFH 重排需要时间,频繁更新会让链路层“晕头转向”。建议连接建立后,至少稳定 10 秒再开始调整。

4.6 如何“手动”优化共存?

AFH 是 BLE 自带的“被动防御”。但作为工程师,我们还可以做“主动防御”:

  • 物理隔离:Wi-Fi 天线和 BLE 天线尽量拉开距离,至少 20mm。如果做不到,中间加一块接地铜皮做隔离。
  • 时分复用(TDM):如果 Wi-Fi 和 BLE 共用一颗 SoC(比如 ESP32),可以错开两者的收发时隙。我习惯在 Wi-Fi 的 Beacon 间隔(100ms)里,预留 10ms 给 BLE 做广播扫描。
  • 信道规划:手动指定 Wi-Fi 只使用 CH1、CH6、CH11 中的一个,避免使用 40MHz 绑定模式。这样 BLE 至少还有 30 个“干净”信道可用。

一句话总结:AFH 是 BLE 的“保命技能”,但别全指望它。好的硬件布局和信道规划,能让 AFH 事半功倍。