詳解BLE連線建立過程
同一款手機,為什麼跟某些裝置可以連線成功,而跟另外一些裝置又連線不成功?同一個裝置,為什麼跟某些手機可以建立連線,而跟另外一些手機又無法建立連線?同一個手機,同一個裝置,為什麼他們兩者有時候連起來很快,有時候連起來又很慢?Master是什麼?slave又是什麼?什麼又是Connection event和slave latency?希望這篇文章能幫助你回答上述問題。
BLE連線示例
假設我們有一臺手機A(以安卓手機為例),一個裝置B(裝置名稱:Nordic_HRM),如下所示,我們可以通過安卓設定選單裡面的藍芽介面,讓兩者連線起來。
- 開啟安卓設定選單
- 選擇“藍芽”條目
- 開啟藍芽
- 等待系統搜尋結果,不出意外的話,裝置“Nordic_HRM”會出現在結果列表中
- 點選“Nordic_HRM”,手機將與此裝置建立連線
上述即為大家直觀感受到的“連線”,那麼手機要與裝置Nordic_HRM建立連線,具體包含哪些流程?他們為什麼可以連線成功?下面給大家一一道來。
廣播(advertising)
在手機跟裝置B建立連線之前,裝置B需要先進行廣播,即裝置B(Advertiser)不斷髮送如下廣播訊號,t為廣播間隔。每傳送一次廣播包,我們稱其為一次廣播事件(advertising event),因此t也稱為廣播事件間隔。雖然圖中廣播事件是用一根線來表示的,但實際上廣播事件是有一個持續時間的,藍芽晶片只有在廣播事件期間才打開射頻模組,這個時候功耗比較高,其餘時間藍芽晶片都處於idle狀態,因此平均功耗非常低,以Nordic nRF52810為例,每1秒鐘發一次廣播,平均功耗不到11uA
上面只是一個概略圖,按照藍芽spec,實際上每一個廣播事件包含三個廣播包,即分別在37/38/39三個通道上同時廣播相同的資訊,即真正的廣播事件是下面這個樣子的。
裝置B不斷髮送廣播訊號給手機(Observer),如果手機不開啟掃描視窗,手機是收不到裝置B的廣播的,如下圖所示,不僅手機要開啟射頻接收視窗,而且只有手機的射頻接收視窗跟廣播發送的發射視窗匹配成功,手機才能收到裝置B的廣播訊號。由於這種匹配成功是一個概率事件,因此手機掃到裝置B也是一個概率事件,也就是說,手機有時會很快掃到裝置B,比如只需要一個廣播事件,手機有時又會很慢才能掃到裝置B,比如需要10個廣播事件甚至更多。
建立連線(connection)
根據藍芽spec規定,advertiser傳送完一個廣播包之後150us(T_IFS),advertiser必須開啟一段時間的射頻Rx視窗,以接收來自observer的資料包。Observer就可以在這段時間裡給advertiser傳送連線請求。如下圖所示,手機在第三個廣播事件的時候掃到了裝置B,併發出了連線請求conn_req。
上圖的互動流程比較粗略,為此我們引入下圖,以詳細描述連線建立過程。
圖5:連線建立過程
注:圖中M代表手機,S代表裝置B,M->S表示手機將資料包發給裝置B,即手機開啟Tx視窗,裝置B開啟Rx視窗;S->M正好相反,表示裝置B將資料包發給手機,即裝置B開啟Tx視窗,手機開啟Rx視窗。
如圖所示,手機在收到A1廣播包ADV_IND後,以此為初始錨點(這個錨點不是連線的錨點),T_IFS後給Advertiser傳送一個connection request命令,即A2資料包,告訴advertiser我將要過來連你,請做好準備。Advertiser根據connect_req命令資訊做好接收準備,connect_req包含如下關鍵資訊:
- Transmit window offset,定義如圖5所示
- Transmit window size,定義如圖5所示
- connect_req資料包完整定義如下所示
connect_req其實是在告訴advertiser,手機將在Transmit Window期間傳送第一個同步包(P1)給你,請在這段時間裡把你的射頻接收視窗開啟。裝置B收到P1後,T_IFS時間後將給手機回覆資料包P2。一旦手機收到資料包P2,連線即可認為建立成功。後續手機將以P1為錨點(原點),Connection Interval為週期,週期性地給裝置B傳送Packet,Packet除了充當資料傳送功能,它還有如下兩個非常重要的功能:
- 同步手機和裝置的時鐘,也就是說,裝置每收到手機發來的一個包,都會把自己的時序原點重新設定,以跟手機同步。
- 告訴裝置你現在可以傳資料給我了。連線成功後,BLE通訊將變成主從模式,因此把連線發起者(手機)稱為Master或者Central,把被連線者(之前的Advertiser)稱為Slave或者Peripheral。BLE通訊之所以為主從模式,是因為Slave不能“隨性”給Master發信息,它只有等到Master給它發了一個packet後,然後才能把自己的資料回傳給Master。
連線失敗
有如下幾種典型的連線失敗情況:
- 如圖5所示,如果slave在transmit window期間沒有收到master發過來的P1,那麼連線將會失敗。此時應該排查master那邊的問題,看看master為什麼沒有在約定的時間把P1發出來。
- 如果master在transmit window期間把P1發出來了,也就是說master按照connect_req約定的時序把P1發出來了,但slave沒有把P2回過去,那麼連線也會失敗。此時應該排查slave這邊的問題,看一看slave為什麼沒有把P2回過去
- 如果master把P1發出來了,slave也把P2回過去了,此時主機還是報連線失敗,這種情況有可能是master軟體有問題,需要仔細排查master的軟體。
- 還有一種比較常見的連線失敗情況:空中射頻干擾太大。此時應該找一個乾淨的環境,比如遮蔽室,排除干擾後再去測試連線是否正常。
Connection events
連線成功後,master和slave在每一個connection interval開始的時候,都必須互動一次,即master給slave發一個包,slave再給master發一個包,整個互動過程稱為一個connection event。藍芽晶片只有在connection event期間才把射頻模組開啟,此時功耗比較高,其餘時間藍芽晶片都是處於idle狀態的,因此藍芽晶片平均功耗就非常低,以Nordic nRF52810為例,每1秒鐘Master和Slave通訊1次,平均功耗約為6微安左右。Master不可能時時刻刻都有資料發給slave,所以master大部分時候都是發的空包(empty packet)給slave。同樣slave也不是時時刻刻都有資料給master,因此slave回覆給master的包大部分時候也是空包。另外在一個connection event期間,master也可以發多個包給slave,以提高吞吐率。綜上所述,連線成功後的通訊時序圖應該如下所示:
圖7: 連線成功後的通訊時序圖(每個connection event只發一個包)
圖9: 連線成功後的通訊時序圖( connection event可能發多個包)
圖10:connection event細節圖
Slave latency
圖10中出現了slave latency(slave latency = 2),那麼什麼叫slave latency?
如前所述,在每一個connection interval開始的時候,Master和Slave必須互動一次,哪怕兩者之間互動的是empty packet(空包),但如果slave定義了slave latency,比如slave latency = 9,此時slave可以每9個connection interval才回復一次master,也就是說slave可以在前面8個connection interval期間一直睡眠,直到第9個connection interval到來之後,才回復一個packet給master,這樣將大大節省slave的功耗,提高電池續航時間。當然如果slave有資料需要上報給master,它也可以不等到第9個connection interval才上報,直接像正常情況進行傳輸即可,這樣既節省了功耗,又提高了資料傳輸的實時性。
GAP層角色總結
對上面提到的手機和裝置B,在BLE通訊過程中,隨著時間的推移,他們的狀態在發生變化,兩者的關係也在發生變化,為此藍芽spec根據不同的時間段或者狀態給手機和裝置B取不同的名字,即GAP層定義瞭如下角色:
- advertiser。 發出廣播的裝置
- observer或者scanner。可以掃描廣播的裝置
- initiator。能發起連線的裝置
- master或者central。連線成功後的主裝置,即主動發起packet的裝置
- slave或者peripheral。連線成功後的從裝置,即被動回傳packet的裝置
圖11通過時間把observer,initiator和central串起來了,其實這三個角色是相互獨立的,也就是說一個裝置可以只支援observer角色,而不支援initiator和central角色。同樣,圖11也把advertiser和peripheral串起來了,其實advertiser和peripheral也是相互獨立的,即一個裝置可以只作為advertiser角色,而不支援peripheral角色。
圖11:GAP層角色