使用ESP32实现蓝牙通信

RF/无线

1823人已加入

描述

大家好,我是ST!

上次给大家分享了如何使用ESP32实现UDP通信,今天跟大家聊聊如何使用ESP32实现蓝牙通信。

蓝牙通信

一、蓝牙简介

蓝牙是一种无线通讯技术,可实现固定设备、移动设备之间的数据交换。一般将蓝牙3.0之间的BR/EDR蓝牙称为传统蓝牙,而将蓝牙4.0规范下的LE蓝牙称为低功耗蓝牙。目前,蓝牙技术已经应用到各个领域,并已经成为接入物联网的主要技术。如今,借助于ESP32平台,MicroPython中也能够使用蓝牙BLE协议进行通信。这对MicroPython平台而言,自然丰富了其生态,增强了其技能,反过来讲,蓝牙BLE能够在MicroPython中得以集成,借助Python语言的易用性,亦将大大降低其入门门槛。

二、miropython有关蓝牙的实现方法

在miropython官网中,提供蓝牙接口模块为bluetooth,下面简单介绍一下本次实验用到的一些方法。

网址:http://docs.micropython.org/en/v1.18/library/bluetooth.html

1)BLE.active([active, ]/)

可选地更改BLE无线电的活动状态,并返回当前状态。在此类上使用任何其他方法之前,必须使无线电处于活动状态。

2)BLE.config(*, param=value, ...)

获取或设置 BLE 接口的配置值。要获取一个值,参数名称应该作为字符串引用,并且一次只查询一个参数。要设置值,请使用关键字语法,一次可以设置一个或多个参数。

3)BLE.irq(handler, /)

为来自 BLE 堆栈的事件注册回调。如下官方给出的事件处理程序(部分截图):

蓝牙通信

4)BLE.gap_advertise(interval_us, adv_data=Non,*,resp_data=None,...)

以指定的时间间隔(以微秒为单位)开始广播。此间隔将向下舍入到最接近的 625us。要停止广播,请将interval_us设置为None。

adv_data和resp_data可以是实现缓冲协议的任何类型(例如bytes, bytearray, str)。adv_data包含在所有广播中,resp_data发送以回复主动扫描。

注意:如果adv_data(或resp_data)是None,那么传递给先前调用的数据gap_advertise将被重新使用。这允许广播公司仅使用gap_advertise(interval_us). 要清除广告有效载荷,请传递一个空的bytes,即b''。

5)BLE.gatts_register_services(services_definition, /)

用指定的服务配置服务器,替换任何现有的服务。services_definition是一个服务列表,其中每个服务是一个包含一个UUID和一个特征列表的双元素元组。每个特征都是两个或三个元素的元组,包含一个UUID、一个标志值和可选的描述符列表。每个描述符都是一个包含UUID和标志值的双元素元组。这些标志是下面定义的标志的位或组合。这些设置了特征(或描述符)的行为以及安全和隐私需求。返回值是一个元组列表(每个服务一个元素)(每个元素是一个值句柄)。按照定义的顺序,特征和描述符句柄被平展到同一个元组中。

以下官方示例注册了两个服务(Heart Rate, and Nordic UART):

 

HR_UUID = bluetooth.UUID(0x180D)
HR_CHAR = (bluetooth.UUID(0x2A37), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,)
HR_SERVICE = (HR_UUID, (HR_CHAR,),)
UART_UUID = bluetooth.UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E')
UART_TX = (bluetooth.UUID('6E400003-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,)
UART_RX = (bluetooth.UUID('6E400002-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_WRITE,)
UART_SERVICE = (UART_UUID, (UART_TX, UART_RX,),)
SERVICES = (HR_SERVICE, UART_SERVICE,)
( (hr,), (tx, rx,), ) = bt.gatts_register_services(SERVICES)

 

6)BLE.gatts_read(value_handle, /)

读取此句柄(已由gatts_write或远程客户端写入)的本地值。

7)BLE.gatts_notify(conn_handle, value_handle, data=None, /)

向已连接的客户端发送通知请求。

如果data不是None,那么该值将作为通知的一部分发送给客户端。本地值不会被修改。否则,如果data为None,则将发送当前本地值(与gatts_write设置的一样)。注意:无论客户端对该特性的订阅状态如何,通知都将被发送。

8)bluetooth.UUID(value, /)

使用指定的值创建一个UUID实例。取值为:

16位整数,例如0 x2908

128位的UUID字符串,例如:'6E400001-B5A3-F393-E0A9-E50E24DCCA9E'

三、我的实验代码

 

from machine import Pin
from machine import Timer
from time import sleep_ms
import bluetooth


BLE_MSG = ""


class ESP32_BLE():
    def __init__(self, name):
        self.led = Pin(22, Pin.OUT)
        self.timer1 = Timer(0) #创建定时器0对象
        self.name = name
        self.ble = bluetooth.BLE() #创建蓝牙对象
        self.ble.active(True) #启动蓝牙
        self.ble.config(gap_name=name) #给蓝牙设置一个名字
        self.disconnected()
        self.ble.irq(self.ble_irq) #蓝牙中断函数
        self.register()
        self.advertiser()


    def connected(self):
        self.led.value(0)  #点亮LED指示灯
        self.timer1.deinit() #取消定时器


    def disconnected(self):  #100ms调用一次 mode循环计时  lambda匿名函数      
        self.timer1.init(period=100, mode=Timer.PERIODIC, callback=lambda t: self.led.value(not self.led.value()))


    def ble_irq(self, event, data):
        global BLE_MSG  #替换外部的同名变量
        if event == 1: #_IRQ_CENTRAL_CONNECT 手机链接了此设备
            self.connected()
        elif event == 2: #_IRQ_CENTRAL_DISCONNECT 手机断开此设备
            self.advertiser() #向外发送信号,广播
            self.disconnected()
        elif event == 3: #_IRQ_GATTS_WRITE 手机发送了数据 
            buffer = self.ble.gatts_read(self.rx)
            BLE_MSG = buffer.decode('UTF-8').strip()
            
    def register(self):        
        service_uuid = '6E400001-B5A3-F393-E0A9-E50E24DCCA9E'
        reader_uuid = '6E400002-B5A3-F393-E0A9-E50E24DCCA9E'
        sender_uuid = '6E400003-B5A3-F393-E0A9-E50E24DCCA9E'
        #创建一个元组
        services = (
            (
                bluetooth.UUID(service_uuid), #服务ID,可以定义多个服务
                (
                    (bluetooth.UUID(sender_uuid), bluetooth.FLAG_NOTIFY), #服务具体类型
                    (bluetooth.UUID(reader_uuid), bluetooth.FLAG_WRITE),  #服务具体类型
                )
            ), 
        )
        ((self.tx, self.rx,), ) = self.ble.gatts_register_services(services)


    def send(self, data):
        self.ble.gatts_notify(0, self.tx, data + '
')


    def advertiser(self):
        name = bytes(self.name, 'UTF-8')
        adv_data = bytearray('x02x01x02') + bytearray((len(name) + 1, 0x09)) + name
        self.ble.gap_advertise(100, adv_data)  #100us发布一次广告
        print(adv_data)
        print("
")


def buttons_irq(pin):
    led.value(not led.value())
    print('LED is ON.' if led.value() else 'LED is OFF')
    ble.send('LED is ON.' if led.value() else 'LED is OFF')


if __name__ == "__main__":
    ble = ESP32_BLE("ESP32BLE")
    but = Pin(0, Pin.IN)
    but.irq(trigger=Pin.IRQ_FALLING, handler=buttons_irq)
    led = Pin(22, Pin.OUT)
    while True:                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
        if BLE_MSG == 'read_LED':
            led.value(not led.value())
            print(BLE_MSG)
            BLE_MSG = ""
            print('LED is ON.' if led.value() else 'LED is OFF')
            ble.send('LED is ON.' if led.value() else 'LED is OFF')
        sleep_ms(100)

 

程序代码思路:蓝牙在未连接时,指示灯不断闪烁,当蓝牙被连接时,指示灯由闪烁变为常亮。当用户用手机APP发送“read_LED”时,指示灯翻转,并打印出接收到的消息。用户可通过手机APP设置提醒功能。ESP32可通过中断控制指示灯亮灭并提醒手机用户。

四、手机调试APP

IOS用户可下载LightBlue

 

安卓用户可下载BLE调试宝

 

  审核编辑:汤梓红
 
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分