一个带BLE的项目中,有个需求是通过手机升级设备的单片机程序,单片机通过CC2640R2F间接和手机通信。本文记录了调试过程中提升BLE吞吐速率的一些方法,能力有限,如有错误,欢迎指正。
由于BLE的低功耗特性,每个连接事件可以交换一次数据,一次连接事件仅能传输20字节有效数据,故对于大数据量传输来说,吞吐量是非常低的。假设每次传输的升级包数据是128字节,连接间隔是30ms,每次传输16字节有效数据,那么需要8次连接事件,即最快240ms才能发送有效128字节升级包数据。假设升级包是64KB,并且不算其他时间,那么最快需要约123秒,显然太慢了。
提升BLE通信吞吐量的方法有如下:
- 如果主从机都支持BLE4.2及4.2以上时,改大MTU,默认的MTU是23字节,用户可用的字节数是MTU-3字节。这样就可以在一次连接事件中交换更多数据。注意,MTU交换请求只能由Client端主动发起。
- 减小连接间隔和从机延迟。连接间隔是指主从机每隔多久交互一次数据,即使应用没有数据交互,也会有空包数据进行交互。从机延迟是指主机发送的数据,从机能忽略几次,如果改成0,那么从机收到数据后必须应答主机。
- 如果主从机都支持蓝牙5,那么可以使用2Mbps速率进行通信。
Master端需要在应用上尽可能地减小包与包之间的间隔,即减小空包(Empty PDU)的传输。Client端则结合了前面三种优化方法来提升升级速度:
- 将MTU从23改大到185,实际上程序里使用的是150。图4-3和图4-4分别是MTU修改前后的MTU交换抓包截图。
- IOS的连接参数有如下要求,一般最小连接间隔为30ms。
Interval Max * (Slave Latency + 1) <= 2 s
Interval Min >= 20 ms
Interval Min + 20 ms <= Interval Max
Slave Latency <= 4
ConnSupervisionTimeout <= 6 s
Interval Max * ( Slave Latency + 1) * 3 < ConnSupervisionTimeout
- 开启2Mbps速率通信,但主要还是取决于主机端是否支持蓝牙5,如果主机不支持蓝牙5,那么会采用默认的通信速率。
图1 MTU交换(修改前)
图2 MTU交换(修改后)
图3 MTU修改前交互升级数据
图4 MTU修改后交互升级数据
图3是MTU修改前的抓包数据,可以看到,每次连接间隔才交换1次数据,交互一包数据所需时间较长;图4是修改MTU后的抓包数据,虽然MTU改大了,但实际上BLE在L2CAP层上会分片发送27字节数据,只不过可以在一次连接间隔内交互多次数据。注意,对于MTU修改前,Master发送一次数据然后Slave应答一次就是一次连接事件,由图3可知,设置的连个间隔是30ms;对于MTU修改后,一个连接间隔中,不一定Master发送一次数据然后Slave应答一次,在一次连接间隔中,允许发生多个连接事件,由图4中数据交互时的时间差也能看出,2次连接时间的间隔不再是30ms了。
实测优化后,BLE传输64KB升级包数据,支持蓝牙4.2的手机升级需要98秒,支持蓝牙5的手机升级需要62秒。这些时间还包含了CC2640R2F和单片机串口传输的时间,实际BLE传输所需时间是小于该时间的。当前MTU使用的是150,每次传输147字节协议数据,理论上极限吞吐速率约为147/0.03 = 4.78KB/s,实际上由于有Empty PDU的传输,因此实际上达不到这一速率。其实还可以继续改大MTU来进一步优化传输速度。