yanhy的学习记录匣 - micropython https://yanhy.top/index.php/tag/micropython/ ESP32-Micropython-蓝牙串口 https://yanhy.top/index.php/archives/279/ 2022-11-17T03:10:00+08:00 还是准备玩esp32加小屏幕了,记录一下开发心得,虽然都做到一半多了,但是为了防止忘记或者是因为习惯性记录,还是准备将新学的给记下来,之前WIFI配网都做好了,那就从蓝牙开始吧...原文参考链接:https://www.bilibili.com/read/cv15007387环境配置硬件:ESP32编程语言:Micropython编译器:ThonnyMicropython蓝牙目标:让esp32模块发出蓝牙信号,手机连接并通过软件发送串口数据,模块接收数据并实现点灯效果基础测试代码:from machine import Pin from time import sleep_ms import ubluetooth #导入BLE功能模块 ble = ubluetooth.BLE() #创建BLE设备 ble.active(True) #打开BLE #设置BLE广播数据并开始广播 ble.gap_advertise(100, adv_data = b'\x02\x01\x06\x03\x09\x41\x42')运行后,可以在手机上搜索到一个蓝牙设备名为“AB"如要修改蓝牙名称,可这样修改:name = bytes("aabbcc", 'UTF-8') ble.gap_advertise(100, adv_data = b'\x02\x01\x06\x02\x0A\x08' + bytearray((len(name)+1,0x09))+name) 一个中文占用3字节储存,而广播数据最多只有31字节,除去硬件配置外,命名也要限制一定字数广播数据格式可参考:https://www.bilibili.com/read/cv15007387注:由于esp32模块功率很小,发射的蓝牙信号较小,手机经常连接不上,可通过在广播数据格式内修改发射功率调整,对应的数据为x02x0Ax08 ,完整代码为:name = bytes("aabbcc", 'UTF-8') print("蓝牙开始广播") ble.gap_advertise(100, adv_data = b'\x02\x01\x06\x02\x0A\x08' + bytearray((len(name)+1,0x09))+name)蓝牙可连接后,需要让其处理各种事件,如蓝牙断开、连接以及收发等,可参考以下代码详情:https://www.bilibili.com/read/cv15039837from machine import Pin from time import sleep_ms import ubluetooth #导入BLE功能模块 ble = ubluetooth.BLE() #创建BLE设备 ble.active(True) #打开BLE(此时设备将处于就绪态) #设置BLE广播数据并开始广播(开始广播后设备将处于广播态) ble.gap_advertise(100, adv_data = b'\x02\x01\x06\x03\x09\x41\x42') #定义一个函数,用作蓝牙事件中断 def ble_irq(event, data): # 蓝牙中断函数 if event == 1: #蓝牙已连接(此时蓝牙将处于连接态) print("BLE 连接成功") elif event == 2: #蓝牙断开连接(此时蓝牙将从链接态进入就绪态) print("BLE 断开连接") ble.gap_advertise(100, adv_data = b'\x02\x01\x06\x03\x09\x41\x42')#再次启动广播 elif event == 3: # 收到新write消息 print("BLE 收到新消息") ble.irq(ble_irq) #注册蓝牙中断函数有了中断函数后,可以更方便监听到蓝牙状态。接下来就是准备连接手机并交互了蓝牙服务与特性创建,详情:https://www.bilibili.com/read/cv15049793通过注册蓝牙服务,可以使用安卓APP nRF Connect或者微信小程序 谷雨蓝牙调试 进行数据传输,其中服务id为9011特性一9012为可读可写,9013为可读与通知,从esp32到手机上的消息就是通过9013 Notify这个权限获取信息的。完整代码:from machine import Pin from time import sleep_ms,sleep import ubluetooth #导入BLE功能模块 sleep(1) ble = ubluetooth.BLE() #创建BLE设备 ble.active(True) #打开BLE(此时设备将处于就绪态) #创建要使用的UUID SERVER_1_UUID = ubluetooth.UUID(0x9011) CHAR_A_UUID = ubluetooth.UUID(0x9012) CHAR_B_UUID = ubluetooth.UUID(0x9013) #创建特性并设置特性的读写权限 CHAR_A = (CHAR_A_UUID, ubluetooth.FLAG_READ | ubluetooth.FLAG_WRITE | ubluetooth.FLAG_NOTIFY, ) CHAR_B = (CHAR_B_UUID, ubluetooth.FLAG_READ | ubluetooth.FLAG_NOTIFY, ) SERVER_1 = (SERVER_1_UUID, (CHAR_A , CHAR_B, ) , ) #把特性A和特性B放入服务1 SERVICES = (SERVER_1, ) #把服务1放入服务集和中 ((char_a, char_b), ) = ble.gatts_register_services(SERVICES) #注册服务到gatts #设置BLE广播数据并开始广播(开始广播后设备将处于广播态) name = bytes("aabbcc", 'UTF-8') print("蓝牙开始广播") ble.gap_advertise(100, adv_data = b'\x02\x01\x06\x02\x0A\x08' + bytearray((len(name)+1,0x09))+name) #定义一个函数,用作蓝牙事件中断 def ble_irq(event, data): # 蓝牙中断函数 if event == 1: #蓝牙已连接(此时蓝牙将处于连接态) print("BLE 连接成功") elif event == 2: #蓝牙断开连接(此时蓝牙将从链接态进入就绪态) print("BLE 断开连接") ble.gap_advertise(100, adv_data = b'\x02\x01\x06\x02\x0A\x08' + bytearray((len(name)+1,0x09))+name)#再次启动广播 elif event == 3: # 收到新write消息 onn_handle, char_handle = data #判断是来自那个特性的消息 buffer = ble.gatts_read(char_handle) #读取接收到的消息 print(char_handle, buffer) #打印消息内容 ble.gatts_notify(0, char_handle, 'Hello') #回复Hello ble.irq(ble_irq) #注册蓝牙中断函数这段代码运行后,通过蓝牙调试软件连接模块后,监听9012特性,可对其发送数据,同时在thonny终端内也可以看到发送的数据,并且每发送一条数据,都会收到来自模块的Notify通道的”Hello"回复。上述为读写数据创建特定的uuid,下面是较为常用的两种实际应用:注册电池服务#创建电池服务和特性的UUID BATTERY_SERVER_UUID = ubluetooth.UUID(0x180F) BATTERY_CHAR_UUID = ubluetooth.UUID(0x2A19) #创建特性并设置特性的读写权限 BATTERY_CHAR = (BATTERY_CHAR_UUID, ubluetooth.FLAG_READ , ) BATTERY_SERVER = (BATTERY_SERVER_UUID, (BATTERY_CHAR, ) , ) #把电量特性放入电池服务 SERVICES = (BATTERY_SERVER, ) #把电池服务服务放入服务集和中 ((battery_char,), ) = ble.gatts_register_services(SERVICES) #注册服务到gatts ble.gatts_write(battery_char, b'\x50') #设置电池电量为80%注册温湿度服务#创建环境传感器服务和特性的UUID ENV_SERVER_UUID = ubluetooth.UUID(0x181A) #环境传感器服务 TEM_CHAR_UUID = ubluetooth.UUID(0x2A6E) #温度特性 HUM_CHAR_UUID = ubluetooth.UUID(0x2A6F) #湿度特性 #创建特性并设置特性的读写权限 TEM_CHAR = (TEM_CHAR_UUID, ubluetooth.FLAG_READ , ) HUM_CHAR = (HUM_CHAR_UUID, ubluetooth.FLAG_READ , ) ENV_SERVER = (ENV_SERVER_UUID, (TEM_CHAR, HUM_CHAR, ) , ) #把温湿度特性放入环境服务 SERVICES = (ENV_SERVER, ) #把环境服务放入服务集和中 ((tem_char, hum_char, ), ) = ble.gatts_register_services(SERVICES) #注册服务到gatts ble.gatts_write(tem_char, b'\x06\x08') #设置温度为20.54度(0x0806 = 2054) ble.gatts_write(hum_char, b'\x09\x07') #设置湿度为18.01%(0x0709 = 1801) 对于一些常用的功能,蓝牙组织联盟已经为其定义好了UUID,我们在开发产品的时候直接使用即可。16BitUUID定义文档下载地址:https://btprodspecificationrefs.blob.core.windows.net/assigned-values/16-bit%20UUID%20Numbers%20Document.pdf最后把上面代码结合一起,就可以愉快用蓝牙点灯了!使用方法:执行代码后,使用谷雨蓝牙连接,并监听9012服务中的read,发送任意数据,收到回复“hello”,发送“led_on”,led打开,收到回复“led on!”;发送“led_off”,led关闭,收到回复“led off!”from machine import Pin from time import sleep_ms,sleep import ubluetooth #导入BLE功能模块 sleep(1) ble = ubluetooth.BLE() #创建BLE设备 ble.active(True) #打开BLE(此时设备将处于就绪态) led = Pin(2, Pin.OUT) #led引脚 #创建可读可写可通知的UUID SERVER_1_UUID = ubluetooth.UUID(0x9011) CHAR_A_UUID = ubluetooth.UUID(0x9012) CHAR_B_UUID = ubluetooth.UUID(0x9013) #创建特性并设置特性的读写权限 CHAR_A = (CHAR_A_UUID, ubluetooth.FLAG_READ | ubluetooth.FLAG_WRITE | ubluetooth.FLAG_NOTIFY, ) CHAR_B = (CHAR_B_UUID, ubluetooth.FLAG_READ | ubluetooth.FLAG_NOTIFY, ) SERVER_1 = (SERVER_1_UUID, (CHAR_A , CHAR_B, ) , ) #把特性A和特性B放入服务1 SERVICES = (SERVER_1, ) #把服务1放入服务集和中 ((char_a, char_b), ) = ble.gatts_register_services(SERVICES) #注册服务到gatts #设置BLE广播数据并开始广播(开始广播后设备将处于广播态) name = bytes("aabbcc", 'UTF-8') print("蓝牙开始广播") ble.gap_advertise(100, adv_data = b'\x02\x01\x06\x02\x0A\x10' + bytearray((len(name)+1,0x09))+name) #定义一个函数,用作蓝牙事件中断 def ble_irq(event, data): # 蓝牙中断函数 if event == 1: #蓝牙已连接(此时蓝牙将处于连接态) print("BLE 连接成功") elif event == 2: #蓝牙断开连接(此时蓝牙将从链接态进入就绪态) print("BLE 断开连接") ble.gap_advertise(100, adv_data = b'\x02\x01\x06\x02\x0A\x08' + bytearray((len(name)+1,0x09))+name)#再次启动广播 elif event == 3: # 收到新write消息 onn_handle, char_handle = data #判断是来自那个特性的消息 buffer = ble.gatts_read(char_handle) #读取接收到的消息 print(char_handle, buffer,str(buffer, 'UTF-8')) #打印消息内容 if str(buffer, 'UTF-8')=="led_on": led.on() ble.gatts_notify(0, char_handle, 'led on!') elif str(buffer, 'UTF-8')=="led_off": led.off() ble.gatts_notify(0, char_handle, 'led off!') else: ble.gatts_notify(0, char_handle, 'Hello')#回复Hello ble.irq(ble_irq) #注册蓝牙中断函数