一、安装蓝牙依赖库 升级安装蓝牙相关软件包 cpp代码:sudo apt-get update sudo apt-get upgrade -y sudo apt-get dist-upgrade -y sudo apt-get install pi-bluetooth bluez bluez-firmware blueman 最关键一点:添加pi用户到蓝牙组 cpp代码:sudo usermod -G bluetooth -a pi 重启树莓派 cpp代码:sudo reboot 二 ,开启蓝牙设备 启动/增加SPP cpp代码:sudo vi /etc/systemd/system/dbus-org.bluez.service 修改文件中这两个语句。 重启树莓派后,输入hciconfig命令(类似ifconfig命令)查看蓝牙服务 如果有看到hci0设备则蓝牙已经开启工作。如果没有则没有识别到蓝牙设备。 注意:如果/boot/config.txt文件中有 dtoverlay=pi3-miniuart-bt 这语句需要注释掉,否则蓝牙设备不能正常工作。 查看蓝牙适配器提供的各种功能 cpp代码:pi@raspberrypi:~ $ sudo sdptool browse local Browsing FF:FF:FF:00:00:00 ... Service RecHandle: 0x10000 Service Class ID List: "PnP Information" (0x1200) Profile Descriptor List: "PnP Information" (0x1200) Version: 0x0103 Browsing FF:FF:FF:00:00:00 ... Service Search failed: Invalid argument Service Name: Serial Port Service Description: COM Port Service Provider: BlueZ Service RecHandle: 0x10001 Service Class ID List: "Serial Port" (0x1101) Protocol Descriptor List: "L2CAP" (0x0100) "RFCOMM" (0x0003) Channel: 1 Language Base Attr List: code_ISO639: 0x656e encoding: 0x6a base_offset: 0x100 Profile Descriptor List: "Serial Port" (0x1101) Version: 0x0100 Service Name: Generic Access Profile Service Provider: BlueZ Service RecHandle: 0x10002 Service Class ID List: "Generic Access" (0x1800) Protocol Descriptor List: "L2CAP" (0x0100) PSM: 31 "ATT" (0x0007) uint16: 0x0001 uint16: 0x0008 Service Name: Generic Attribute Profile Service Provider: BlueZ Service RecHandle: 0x10003 Service Class ID List: "Generic Attribute" (0x1801) Protocol Descriptor List: "L2CAP" (0x0100) PSM: 31 "ATT" (0x0007) uint16: 0x0010 uint16: 0x0010 Service Name: AVRCP CT Service RecHandle: 0x10004 Service Class ID List: "AV Remote" (0x110e) "AV Remote Controller" (0x110f) Protocol Descriptor List: "L2CAP" (0x0100) PSM: 23 "AVCTP" (0x0017) uint16: 0x0103 Profile Descriptor List: "AV Remote" (0x110e) Version: 0x0105 Service Name: AVRCP TG Service RecHandle: 0x10005 Service Class ID List: "AV Remote Target" (0x110c) Protocol Descriptor List: "L2CAP" (0x0100) PSM: 23 "AVCTP" (0x0017) uint16: 0x0103 Profile Descriptor List: "AV Remote" (0x110e) Version: 0x0104 三、链接蓝牙设备 输入如下命令进入蓝牙控制界面,(可进入界面输入help查看命令列表) cpp代码:sudo bluetoothctl agent on 然后进入界面之后(可进入界面输入help查看命令列表) cpp代码:agent on default-agent scan on之后 就可以看到扫描得到的蓝牙设备的物理地址了,类似XX:XX:XX:XX:XX:XX之类的地址 配对使用以下命令(以下请把XX:XX:XX:XX:XX:XX替换为你自己设备的地址,android手机可以在设置->关于手机->状态信息中看到蓝牙地址。) pair XX:XX:XX:XX:XX:XX 配对之后把设备添加到信任列表 trust XX:XX:XX:XX:XX:XX 之后连接设备 connect XX:XX:XX:XX:XX:XX 最后quit退出就可以了,以后蓝牙设备开机后树莓派会自动进行连接。 四,手机端通过蓝牙发送数据到树莓派 运行如下命令后等待链接 cpp代码:sudo rfcomm watch hci0 手机端打开蓝牙软件(例如 WS EDR),搜索蓝牙设备并链接到树莓派 如果没有搜索到树莓派蓝牙,可以运行如下命令开启蓝牙可发现。 另外打开一个终端运行如下命令可以看到/dev目录下有一个rfcomm0设备,只有蓝牙设备连接上树莓派后才有这个设备。 运行如下命令,用串口软件minicom 打开这个设备。(如果没有安装minicom,可以运行sudo apt-ge install minicom 安装) cpp代码:sudo minicom -D /dev/rfcomm0 minicom界面如下,此时按下手机中的方向键,minicom会接受到相应的指令。 按Ctrl+A,再按Z进入菜单,再按Q退出minicom。 四,蓝牙控制小车示例程序 废话也不多说,直接上代码。bluetooth.py文件 cpp代码:#!/usr/bin/python # -*- coding:utf-8 -*- import serial import time import json from AlphaBot import AlphaBot LOW_SPEED = 30 MEDIUM_SPEED = 50 HIGH_SPEED = 80 Ab = AlphaBot() BT = serial.Serial("/dev/rfcomm0",115200) print('serial test start ...') BT.flushInput() try: while True: data = "" while BT.inWaiting() > 0: data += BT.read(BT.inWaiting()) if data != "": #print data try: s = json.loads(data) cmd = s.get("Forward") if cmd != None: if cmd == "Down": BT.write("{\"State\":\"Forward\"}") elif cmd == "Up": BT.write("{\"State\":\"Stop\"}") Ab.stop() cmd = s.get("Backward") if cmd != None: if cmd == "Down": BT.write("{\"State\":\"Backward\"}") elif cmd == "Up": BT.write("{\"State\":\"Stop\"}") Ab.stop() cmd = s.get("Left") if cmd != None: if cmd == "Down": BT.write("{\"State\":\"Left\"}") elif cmd == "Up": BT.write("{\"State\":\"Stop\"}") Ab.stop() cmd = s.get("Right") if cmd != None: if cmd == "Down": BT.write("{\"State\":\"Right\"}") elif cmd == "Up": BT.write("{\"State\":\"Stop\"}") Ab.stop() cmd = s.get("Low") if cmd == "Down": BT.write("{\"State\":\"Low\"}") Ab.setPWMA(LOW_SPEED); Ab.setPWMB(LOW_SPEED); cmd = s.get("Medium") if cmd == "Down": BT.write("{\"State\":\"Medium\"}") Ab.setPWMA(MEDIUM_SPEED); Ab.setPWMB(MEDIUM_SPEED); cmd = s.get("High") if cmd == "Down": BT.write("{\"State\":\"High\"}") Ab.setPWMA(HIGH_SPEED); Ab.setPWMB(HIGH_SPEED); BT.flushInput() except ValueError: #not json format continue except KeyboardInterrupt: if BT!= None: BT.close() {程序分析]: 1.由上一节可知,蓝牙只需作为串口使用即可,不需要了解复杂的蓝牙协议。关于Python串口控制可以参考树莓派系列教程13:Serial串口 2.BT = serial.Serial("/dev/rfcomm0",115200) 创建蓝牙设备示例,波特率115200 3.BT.flushInput() 清空接受缓存,丢弃之前的数据。 4.BT.inWaiting() 读取接受缓冲区是否有数据。 5.BT.read() 读取数据 6.BT.write() 发送数据 7.s = json.loads(data) 将json格式的字符转化为Python字典对象。如果蓝牙发送的字符串不是json格式,则会出现ValueError异常,数据丢弃继续接收。 8.cmd = s.get("Forward") 查询字典中是否有Forward键,返回的是键值,如果没有则返回None 运行如下命令启动程序 cpp代码:sudo rfcomm watch hci0 1 python bluetooth.py [命令分析]: 通过rfcomm 命令检测 hci0设备,当蓝牙设备连接到树莓派时,会创建/dev/rfcomm0 节点。 参数 1 表示有设备连接时创建一个进程来运行 python bluetooth.py 当连接成功时进程启动,连接断开时进程结束,或当进程结束时连接断开。 |