大家好,我是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
可選地更改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
?
安卓用戶可下載BLE調試寶
?
評論
查看更多