嵌入式人工智能(41-基于树莓派4B的串口蓝牙模块AT09-cc2541)

avatar
作者
筋斗云
阅读量:0

1、串口蓝牙模块AT-09

AT-09是一种串口蓝牙模块,可实现串口与蓝牙之间的数据传输。AT-09模块基于蓝牙4.0技术,具有低功耗、高传输速率和广泛的应用范围。

AT-09模块支持AT指令,通过串口与外部设备进行通信。用户可以使用AT指令对模块进行配置和控制,例如设置蓝牙名称、密码、通信速率等。通过串口,用户可以与AT-09模块进行数据传输,实现与蓝牙设备的无线通信。

AT-09模块通常用于无线传输、数据采集等应用场景。它可以与各种主控板和设备进行连接,如Arduino、Raspberry Pi等。通过AT-09模块,用户可以方便地将串口设备无线化,实现无线控制和数据传输。

有了这个串口蓝牙模块,我们就可以用手机远程控制很多物联网设备了。有了通信网,整个世界都变得更加丰富多彩了。

2、蓝牙cc2541模块

串口蓝牙模块所用的蓝牙芯片是CC2541,而真正的无线通信是靠CC2541收发数据。串口仅仅是用来将无线收发的数据通过串口送开发板微处理器。

CC2541是一款针对低能耗以及私有2.4GHz应用的功率优化的真正片载系统(SoC)解决方案。它使得使用低总体物料清单成本建立强健网络节点成为可能。CC2541将领先RF收发器的出色性能和一个业界标准的增强型8051MCU、系统内可编程闪存存储器、8kBRAM和很多其它功能强大的特性和外设组合在一起。CC2541非常适合应用于需要超低能耗的系统。

通过下图可以看出真正片载系统Soc即串口底板+片上蓝牙模块。具体的原理,内部结构,功能,引脚等等请看数据手册把。

通过USB-TTL与电脑或者开发板连接,与电脑的连接可以参考我这个专栏的语音模块syn6288那一部分。

我们这里还是介绍与树莓派的接线,引脚引出线只有4根,这样就好接线了,VCC接开发板5V,GND接地,TXD接开发板的RXD0(BOARD10),RXD接开发板的TXD0(BOARD8)

3、手机蓝牙助手连接CC2541

这个部分最简单,但是也最重要,因为手机上要有应用程序和蓝牙模块建立连接。手机上的蓝牙应用程序可不是C或Python写的,具体我们也不要管它了,我们下载一个别人写好的能用的蓝牙助手,安卓手机安装包的名称为HCbluetooth.apk。然后将蓝牙模块也插上电,上电后蓝牙模块的指示灯不停闪烁。

在手机上找到刚刚安装的HC蓝牙助手,点击打开,打开后搜索到该模块,点击连接就OK了。

连接上之后,蓝牙模块的灯就不会闪了,一直亮着,然后把这几个模块都看看。

这个发送速度就设置为中就可以,经测试为波特率为9600,停止位1位,数据位8位,奇偶校验无,回头开发板的串口也设置为一样即可。

4、踩坑必看

本以为很简单的事情,运行程序后收到的数据不正常,或者收不到数据。耽误了大半天时间,经过我一顿思考和尝试,这里有个坑,同学们注意。如果你还没有运行程序,请先看第5部分。

(1)如果在运行程序出现:(提示权限问题,可以sudo chmod 666 /dev/ttyS0 暂时解决)

(3)手机HC蓝牙助手也出现这样的echo:

这些看似很多问题,可能是由于同一个问题导致的,就是蓝牙串口使用了ttyS0设备,该设备默认让用户通过串口登录,很久以前,windows有个超级终端的串口登录,估计同学们都不知道了,那已经是20多年前的事情了,以前都是都过串口登录到设备,做一些调试,比如路由器、交换机。该树莓派也是打开串口让用户登录。所以在通过蓝牙串口发送数据给树莓派时,开启了串口终端登录。我们到树莓派配置里面将这个功能给关闭。

点击OK后重启。估计就不会出现上述问题了。

4、实验代码与现象

有了这个模块我们就可以发送数据给开发板了,比如打开第1个灯,关闭第1个灯;或者开1,关1;总之python语言中对字符串的处理是非常方便的。只要包含开关这两个字就知道状态给0还是1;然后再从字符串中提取数字,把这个值赋值给变量即可。我这边为了节省IO口,仍然用TM1638扩展板做,如果同学们没有就直接放2个LED实现效果即可。

iimport serial import TM1638 import time import re   def init():     global tm     tm=TM1638.TM1638(stb=36,clk=38,dio=40)      tm.brightness(2)     DEVICE = "/dev/ttyS0"     global ser     ser=serial.Serial(DEVICE,baudrate=9600,bytesize=8,parity="N",stopbits=1,timeout=0.1)   def main_loop():     while True:         if ser.in_waiting > 0:             # 读取串口数据             data = ser.readall().decode('utf-8').strip()             print("收到的数据:", data)             if '开' in data:                 status = 1             elif '关' in data:                 status = 0             elif data=='结束程序':                 break             else:                 ser.write(bytes('没有给出正确的指令','utf-8'))                firstnum = re.search(r'\d',data)             if firstnum:                 first_number = firstnum.group()                  if int(first_number)>0 and int(first_number)<=8:                     tm.led(int(first_number)-1,status)              else:                 ser.write(bytes('没有给出正确的LED号码(1-8)','utf-8'))  if __name__ == '__main__':     init()     try:         main_loop()     except KeyboardInterrupt:         print("程序结束!")     finally:         tm.clear()         ser.close() 

程序解释:

(1)程序代码没有多少行,这就体现了Python语言的精练,同样的代码用C来写你试试把。可能有同学觉得树莓派毕竟是一台口袋电脑,用来做物联网成本有点高,而低成本的处理器可能不支持python。我这里有个想法,但是还没有考虑成熟,等我把树莓派栏目写完,我打算用ESP32或ESP8266做MicroPython的实验或项目,看看MicroPython在物联网上面和C的性能差距有多少。

(2)串口设置,不管有些参数是不是默认值,还是将波特率、数据位、停止位、奇偶校验都设置下。ser=serial.Serial(DEVICE,baudrate=9600,bytesize=8,parity="N",stopbits=1,timeout=0.1)

串口通信超时解决方案在进行串口通信时,可能会遇到以下两个问题:a读取串口数据时阻塞时间过长,造成程序无法及时响应。b进行写操作时,设备没有及时响应。
为了解决这些问题,我们可以使用Python的serial库提供的timeout参数来设置超时时间。timeout参数是一个浮点数,代表等待数据的最长时间(以秒为单位)。当没有数据可读时,等待超过指定的超时时间后,将触发超时异常。

(3)serial-三方库,提供了一系列的方法来处理串行通信。

in_waiting:返回输入缓冲区中的字节数。

        if ser.in_waiting > 0:
            # 读取串口数据
            data = ser.readall().decode('utf-8').strip()

收到的数据都是以字节流的形式放到接收缓冲区,上面是正确的接收,我之前写的代码是

data = ser.readall()

if data:

        text = data..decode('utf-8')

结果发现utf8编码的汉字被拆成3个字节,一个一个的print,python就没有办法解码了。

(4)输入相关指令对LED进行控制,可以先让程序发一段解释说明给手机,这样最好。

            if '开' in data:                 status = 1             elif '关' in data:                 status = 0             elif 'help' in data:                 ser.write(bytes('请输入开/关 1-8的字样\n','utf-8'))                elif data=='结束程序':                 break             else:                 ser.write(bytes('没有给出正确的指令\n','utf-8'))   

当然我这个程序if的嵌套逻辑结构不是最好的,如果业务逻辑比较丰富的话,可以参考模块化编程的思想和方法。

(5)指令包括2个参数,一个是第几个灯,一个是状态,所以状态通过开关来给定,第几个灯要从用户输入的内容里面提取数字再判断数字的有效范围。

从字符串里面提取第一个数字firstnum = re.search(r'\d',data)这里用到了正则表达式,需要导入re库,‌正则表达式是一种强大的文本处理工具,用于匹配、查找、替换复杂的文本模式。它由普通字符和特殊字符(元字符)组成,能够描述和匹配一系列符合特定规则的字符串。

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!