You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PC与Android设备间BLE吞吐量差异问题排查求助

BLE数据传输速率低(20-30样本/秒 vs 预期250样本/秒)问题排查与修复

问题背景

基于nRF52840自定义固件的BLE设备,采样率250Hz,通过nRF Connect测试传输正常,但在Galaxy Z Flip3/S22上用RxAndroidBle接收时,仅能达到20-30样本/秒。商用设备可正常跑满250Hz,判断问题出在代码实现层面。

代码问题分析

  1. 主线程阻塞数据流:将通知数据流直接切换到主线程AndroidSchedulers.mainThread()处理,主线程需承担UI渲染、系统任务,无法及时处理高频BLE数据,导致丢包或延迟。
  2. 未配置MTU:默认BLE MTU为23字节(有效载荷仅20字节),高频小数据包会产生大量协议开销,大幅降低实际传输效率。
  3. 未优化连接参数:默认连接间隔过大,导致Android设备无法及时接收BLE设备发送的数据包。
  4. 通知订阅逻辑冗余:setupNotification的处理存在无效操作,数据流订阅方式未最大化传输效率。

解决方案

1. 调整线程调度,避免主线程处理原始数据

将原始数据处理放在IO线程执行,仅在需要更新UI时切换到主线程:

fun readDataFromDevice() {
    scanSubscription.dispose()

    bleNotification()
        ?.flatMap { notificationObservable -> 
            // 在IO线程处理原始数据解析、计算
            notificationObservable.observeOn(Schedulers.io())
                .doOnNext { bytes ->
                    val sample = parseBytesToSample(bytes) // 自定义样本解析逻辑
                    Log.v(TAG, "解析样本: $sample")
                }
                .observeOn(AndroidSchedulers.mainThread()) // 仅UI更新时切主线程
        }
        ?.subscribe(
            { /* 这里处理UI更新,如刷新图表、显示数据 */ },
            { it.printStackTrace() }
        )
}

2. 连接成功后请求最大MTU

BLE最大MTU为247字节(有效载荷244字节),连接后立即协商MTU,减少数据包数量:

fun connectDevice() {
    rxBleDevice = rxBleClient.getBleDevice(lxDeviceAddress)
    connectSubscription = rxBleDevice.establishConnection(false)
        .flatMap { connection ->
            // 请求MTU为247,同步等待协商结果
            connection.requestMtu(247)
                .map { connection } // 保留连接对象
        }
        .subscribe(
            { rxBleConnection ->
                this.rxBleConnection = rxBleConnection
                Log.v(TAG, "连接成功,MTU已设置")
            },
            { it.printStackTrace() }
        )
}

3. 优化BLE连接参数

设置更紧凑的连接间隔、合理的从机延迟,提升通信频率:

fun connectDevice() {
    rxBleDevice = rxBleClient.getBleDevice(lxDeviceAddress)
    // 配置高吞吐量的连接参数
    val connectionParameters = ConnectionParameters.Builder()
        .setMinConnectionInterval(ConnectionInterval.INTERVAL_7_5_MS) // 最小连接间隔7.5ms
        .setMaxConnectionInterval(ConnectionInterval.INTERVAL_15_MS) // 最大连接间隔15ms
        .setSlaveLatency(0) // 从机延迟0,确保每次连接都传输数据
        .setSupervisionTimeout(SupervisionTimeout.TIMEOUT_4000_MS)
        .build()

    connectSubscription = rxBleDevice.establishConnection(false)
        .flatMap { connection ->
            // 先协商MTU,再设置连接参数
            connection.requestMtu(247)
                .flatMap { connection.requestConnectionParameters(connectionParameters) }
                .map { connection }
        }
        .subscribe(
            { rxBleConnection ->
                this.rxBleConnection = rxBleConnection
                Log.v(TAG, "连接成功,MTU和连接参数已配置")
            },
            { it.printStackTrace() }
        )
}

4. 修正通知订阅逻辑

简化bleNotification方法,去除冗余操作:

fun bleNotification(): Observable<ByteArray>? {
    return rxBleConnection?.setupNotification(lxDeviceUUID)
        ?.flatMap { it } // 直接展开通知数据流
}

额外注意事项

  • 确保nRF52840固件支持MTU协商,且发送的数据包大小不超过协商后的MTU有效载荷。
  • 避免在数据处理逻辑中执行耗时操作,即使在IO线程也会影响数据接收速率。
  • 测试时关闭Android设备的省电模式,部分省电策略会限制BLE通信频率。

内容的提问来源于stack exchange,提问作者LYG

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 14:05:23