【IOT开发】蓝牙SPP协议的使用

之前有个项目需要在PC端通过蓝牙发送数据给单片机,由于当时还不太懂蓝牙协议,使用的是PC-USB-BT 到BT-MCU的方案,会多出来一个USB-UART-BT模块硬件。之后调研学习了解到 可以通过搭建SPP协议使得连接到PC蓝牙后生成一个COM号,进行数据传输。
本次使用基于 ESP32 的蓝牙串口协议,具体见官方例程:
esp-idf\examples\bluetooth\bluedroid\classic_bt\bt_spp_acceptor

SPP

把例程编译下载后,在PC端连接上对应的蓝牙服务,会发现多出来两个端口:
SPP-COM
很自然的生成了两个端口号 注意其中一个是 pc发送,下位机接收服务,另一个是pc接收,ESP32发送服务。具体哪个是发送,可以在蓝牙设备-更多蓝牙选项-COM端口中查看。

在使用时,遇到了带宽不够的问题,在论坛也遇到了类似问题,但是没有现成的回答。不过之后通过调研找到了可能的解决方案。
https://github.com/espressif/esp-idf/issues/9356
我之后给ESPRESSIF技术支持发邮件,他答复了一下,然后我答复了一下他的答复:

Thanks for reply. I think I have solved this problem by increasing the frequency of sending and the amount of data per packet.
1.BT SPP speed is not affected by baud rate, because RFCOMM, the configuration file under SPP, will try to transmit data packets as fast as possible. You can change Virtue BT COM in the Device Manager, but it’s useless for transmission speed. We are used to the design of hardware UART, and the best way to increase the data rate is to change the baud rate, but this is not necessary when using Bluetooth SPP.
2.The default MTU size is 990 bytes, but you can send a larger MTU to get more bandwidth. When increasing the packet size is useless, you can increase the sending frequency. Don’t config the send interval less than 10 ms, because the MAX ACK Fre of BT is about 100 Hz. Higher fre may lead to packet loss. In my Windows PC, the data speed can achieve 1200 kbps-150 kB/s with 20 send interval and 3 kB Per packet.

Hi @naragururaj,
Thanks for reporting the issue. The SPP throughput can be affected by many reasons:
The default MTU size of classic Bluetooth SPP on ESP32 is 990 bytes, and higher throughput can be achieved in the case that data chunck size is close to the MTU size or multiple of MTU size. For example, sending 100 bytes data per second is much better than sending 10 bytes every 100 milliseconds.
SPP uses credit based flow control. If the receiver can’t give the credit back to the sender as soon as possible, it can also slow down the throughput.
Unnecessary logs in the SPP callback functions.
The coexistence of BLE or Wi-Fi on ESP32.
Complex electromagnetic environment.

总结一下:
1.是PC端生成的虚拟串口波特率太低影响的速率吗,如果是的话应该如何更改PC端COM波特率呢?
打开蓝牙串口的波特率是协议栈内规定的,貌似没有给出修改接口,但是不影响带宽。蓝牙SPP基于RFCOMM,底层会尽可能多地传输数据,所以改带宽的关键不在波特率。
2.我之前开到一个解释:SPP协议的波特率不会影响通信速率,SPP协议层中也没有给出baudrate的配置选项,是因为底层通信不是基于波特率时钟吗?那通信时会有ACK吗?
有的。RFCOMM基于Scoket,有ACK。
3.在windows PC 与 ESP32 间进行约100kB/s的无线数据传输,SPP可以实现吗?如果SPP无法实现,有其他的协议推荐吗?
大概能实现,看PC蓝牙的硬件及其是否有其他蓝牙设备,周围的2.4GHz频段有多少干扰。

SPP对蓝牙模块串口的读写实现通信,建立在串口仿真协议RFCOMM上实现;服务端和客户端对应为BluetoothServerSocket和BluetoothSocket,通过流进行数据传输,和java中的socket很像。
RFCOMM,它是蓝牙客户端和服务端的Socket通道,其目的为了解决如何在两个不同设备上的应用程序之间保证一条完整的通信路径,并在它们之间保持同一通信段的问题。设备配对后,还没有通信通道,BluetoothServerSocket监听RFCOMM,BluetoothSocket发起建立RFCOMM连接完成通信通道的建立。大致就像是下面这样:

RFCOMM

什么是socket?
socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“open –> write/read –> close”模式操作。Socket就是该模式的一个实现,是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭。
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。其实socket也没有层的概念,它只是一个facade设计模式的应用,让编程变的更简单。是一个软件抽象层。

socket

Socket抽象层,会有请求-应答,也就是ACK。那这个ACK是总体传输开始时候的ACK呢,还是同步时钟用的ACK呢?这两个发送的速率是怎样的。如果没有每次包的同步ACK,那么应该有同步位检测,如果同步失败则返回错误ACK。在不同的线程调用同一个socket通道,会致错误产生.

所以如果要改PC端盖的蓝牙串口,重点是改RFCOMM服务。
RFCOMM通过L2CAP来处理单连接上的多路复用,并提供到多个设备的连接,从而提供多个并发连接。
RFCOMM数据速率将限制在涉及物理串行端口(类型2设备)的设备中。实现可以选择在虚拟串行端口(类型1设备中)上对数据进行调整。在允许范围内,RFCOMM将提供尽可能高的数据速率
什么是类型2?
RFCOMM支持两种类型的设备:
• 类型1–内部模拟串行端口(或等效端口)。
• 类型2–带物理串行端口的中间设备

PC是type1 PC没有把数据传给真实物理端口。通道打开后,如果持续一段时间(60s)没有数据传输,就会自动关闭通道。或者一方发送关闭通道的命令也行。


【IOT开发】蓝牙SPP协议的使用
http://example.com/2022/09/06/【IOT开发】蓝牙SPP协议的使用/
作者
Chery Young
发布于
2022年9月6日
许可协议