问题
处理Jetson Nano开发版Ubuntu系统读取外部设备蓝牙传输的数据时,串口调试无法连接。lsusb
命令可以查看到蓝牙适配器是存在的,hcitool scan
也是可以搜索到外部的蓝牙设备的,ls /dev/rf*
没有返回任何的rfcomm*,只有一个/dev/rfkill,绑定蓝牙物理设备地址的时候,`sudo rfcomm bind 0 xx:xx:xx:xx:xx:xx,返回错误,RFCOMM TTY support not availabel。
原因
Jetson nano默认的内核不支持RFCOMM协议,可以用一下命令查看
1 | zcat /proc/config.gz |grep RFCOMM |
显示的信息如下所示
1 | CONFIG_BT_RFCOMM = y |
所以我们需要重新编译kernel的源代码,编译的过程下面介绍,我们需要修改的就是menuconfig上面Bluetooth subsystem support中找到RFCOMM TTY support选项,将它开启即可。
重新编译内核过程
教程参考自一个国外大佬的博客
首先你可以使用一个脚本查看你的当前linux内核模块的开启情况
1 | wget https://github.com/moby/moby/raw/master/contrib/check-config.s |
然后执行该脚本
1 | ./check-config.sh |
然后你就会得到下图所示的结果
事实上,这一步的检查如果已经通过上面的命令确定了RFCOMM未开启,不做此检查也是可以的。
在Jetson nano内核编译之前,我们首先需要确认所有的需要的构建工具都已经安装好了
1 | sudo apt-get update |
- 下载适用于Jetson Nano 的Linux内核资源文件
我们可以在nvidia开发者的官网找到下载链接https://developer.nvidia.com/embedded/,下载BSP Sources。
1 | $ cd |
然后解压下载得到的文件
1 | tar -xvf public_sources.tbz2 Linux_for_Tegra/source/public/kernel_src.tbz2 --strip-components=3 |
首先编译一下未修改的内核,以此确认我们已经安装了所有的依赖,并且熟悉一下编译内核的过程,保证后续的不会出错。
在编译之前,首先需要导入kernel configuration文件,在我们下载的资源里面是没有这个文件的,我们可以直接从当前系统导出。
1 | cd ~/kernel/kernel-4.9 |
然后确认一下config文件内容
1 | head -10 .config |
然后开始内核编译工作
1 | make prepare |
上述命令执行整个过程大概需要一个小时左右,可以直接在Jetson nano上进行上述工作。
首先可以使用uname -a
命令查看当前内核信息,方便后面对比
在安装内核前,首先备份当前的内核,方便出现问题是我们能够替换回原来的内核。
1 | #backup the old kernel Image file |
然后重新启动系统即可,重启后可使用uname -a
命令查看当前内核是否已经更改。
ps:每次更改内核设置都需要编译一个新的内核,然后安装kernel Image和kernel Modules
我们使用内核设置的可视化面板menuconfig
来更改内核设置。这个工具在我们之前安装的libncurses5-dev
中已经包含。相关命令如下:
1 | #备份内核设置 |
找到如图所示的位置,按Y键启用该模块。然后重新执行内核编译命令,最后替换到boot/Image
1 | cd /kernel/kernel-4.9 |
重启操作系统,即完成模块修改和内核替换。
调试蓝牙模块
在上面重新编译内核之后,并没有完全解决问题,蓝牙串口模块仍然无法连接。
这里我使用的是pybluez来进行蓝牙通讯,代码使用的官方实例代码,例子如下:
1 | from bluetooth import * |
执行此代码,提示错误如下:
1 | Traceback (most recent call last): |
这里有两个方法可以尝试,可以选择对自己有效的方法:
方法1:
修改/etc/systemd/system/dbus-org.bluez.service
文件中ExecStart=/usr/lib/bluetooth/bluetoothd
为ExecStart=/usr/lib/bluetooth/bluetoothd -C
,然后执行sudo sdptool add SP
,这样便能够生成/var/run/sdp
文件,我的情况是已经存在这个文件,所以我没有执行最后一条命令。
方法2:
创建一个覆盖文件在/etc/systemd/system/bluetooth.service.d/override.conf
内容如下
1 | [Service] |
这里的文件夹和文件可能不存在,不存在的话直接创建即可。
然后重启bluetooth service或者重启操作系统。
再次执行上面的pybluez代码,通过手机蓝牙串口调试软件即可正常连接。
其他问题记录
- no advertisable device
原因:由于蓝牙不可见导致
相关帖子:https://stackoverflow.com/questions/63788077/how-can-i-make-raspberry-pis-bluetooth-discoverable-to-iphone
解决方案:增加代码在检测到这类错误时,开启蓝牙可发现 - no such file or directory
原因:Bluez 5的bug导致,需要使用兼容模式蓝牙
相关帖子:https://stackoverflow.com/questions/36675931/bluetooth-btcommon-bluetootherror-2-no-such-file-or-directory
解决方案:增加代码在发生该问题时,修改相应文件内容,并重启服务 - Permission denied
原因:sdp执行没有权限
相关帖子:https://bbs.archlinux.org/viewtopic.php?id=201672
解决方案:增加代码修改/var/run/sdp的权限