14

我一直在尋找適用於所有三種操作平臺的所需藍牙連接參數。我正在使用此項目的HOGP(HID GATT藍牙)配置文件。適用於Android,iOS和Win8的藍牙低能耗連接參數

我的項目是我自己編寫的一個嵌入式系統,帶有一個BLE模塊,可以控制以下連接參數。

  1. 連接間隔最小
  2. 連接間隔最大
  3. 從延遲
  4. 監督超時
  5. 發佈時間間隔最小
  6. 發佈時間間隔最大

我的目標設備連接將是以滿足Android> = 4.3,iOS7,和> = Win 8.1。

Apple在以下鏈接中提供了適當參數的文檔,內容如下。我一直沒能找到有關Android和Win 8

https://developer.apple.com/hardwaredrivers/bluetoothdesignguidelines.pdf

我對iOS7當前工作設置完全與雙向溝通與免費lightBlue如下測試的任何信息。我的嵌入式代碼和主機軟件適用於iOS7。

  1. 連接間隔最小30毫秒
  2. 連接間隔最大56.25ms
  3. 從延遲3
  4. 監督超時值爲5000ms

我從另一個堆棧溢出頁面發現涉嫌的android上工作7.5ms以下鏈接的連接間隔。

  1. Android BLE Connection time interval
  2. http://processors.wiki.ti.com/index.php/Bluetooth_SensorTag?DCMP=lprf-stdroid&HQS=lprf-stdroid-pr-wiki1#Supported_Android_devices

不幸的是,從蘋果iOS規範的第二個要求是 「間隔最小≥20毫秒」。

我不理解這些範圍或它們是如何解釋的?如果我將Android的Interval min設置爲7.5ms,那麼這不會導致無效的蘋果要求?如果可能的話,我怎樣才能同時滿足這兩個系統和Win8呢?

我的理解是,從設備提供最小和最大值之間的建議設置,主設備(智能手機)會向用戶提示該範圍內的實際選定值。

我很感謝這個問題的任何幫助,並希望這篇文章能夠讓其他人考慮到BLE相當新的和不完整的知識庫。

提前致謝!

+0

您可能要問了三個獨立的平臺,三個獨立的問題。因爲只有一個平臺知道答案的人不可能回答,並且/或者你只能接受三個正確答案中的一個。 – 323go

+0

@ 323go - 問題的一部分似乎是如何實現與平臺*衝突*細節的兼容性。 –

+1

可能值得檢查7.5ms是否與期望15或22.5毫秒的內容兼容 –

回答

12

首先,連接間隔定義了一個時間窗,在此期間兩個設備使用相同的頻率傳輸數據。總共有37個數據通道,並且連接的設備在每個連接間隔中跳過。

因此,兩個設備必須從一開始就這些參數的精確值達成一致,以便同步,即連接。

其次,當連接建立時,主站(或中央站)發送它支持的連接參數。其他設備(或外設)只是盲目地拿走它們。 iOS默認將連接間隔設置爲30毫秒。連接建立後,外設可以根據蘋果公司提供的指導方針,通過定義最小值和最大值來請求更新連接參數。接收部分,在這種情況下閱讀iOS,會在[min; max]之間選擇最適合它的任何內容,然後將回復它所選擇的確切值。如果這些值不符合指導原則,它也可以拒絕該請求。

最後,7.5ms是藍牙規範定義的連接間隔的最小長度。最大值是4秒。它越低,帶寬越高,但功耗也越高。而更高的值則相反。最好的價值取決於具體的應用。考慮到您使用HID配置文件,我假設延遲對您很重要。 iOS說它支持低至20ms的連接間隔(儘管我發現很難實現這一點),但在你的情況下(HID配置文件),它們也允許11.25毫秒。

希望有所幫助。

+11

那麼你如何修改這些參數? – shim

4

要修改參數的Android(從中央請求外設),你可以做這樣的事情:

private String CONN_SERVICE_UUID = "00001800-0000-1000-8000-00805f9b34fb"; 
private static final UUID CONN_CHARACTERISTIC_UUID = UUID.fromString("00002a04-0000-1000-8000-00805F9B34FB"); 
private static final int CONN_INTERVAL = 0x0006; 
private static final int SUPERVISION_TIMEOUT = 0x000A; 
private void findServiceForConnectionParams(List<BluetoothGattService> gattServices){ 
    BluetoothGattService connGattService = filterServices(gattServices, CONN_SERVICE_UUID); 
    if (connGattService != null) { 
     setConnectionInterval(connGattService); 
    } 
} 
private void setConnectionInterval(BluetoothGattService gattService) { 
    if (gattService == null) { 
     Log.e(TAG, "setConnectionInterval. Gatt service is null!"); 
     return; 
    } 
    BluetoothGattCharacteristic connCharacteristic = 
      gattService.getCharacteristic(CONN_CHARACTERISTIC_UUID); 
    if (connCharacteristic != null) { 
     byte[] value = { (byte) (CONN_INTERVAL & 0x00FF), // gets LSB of 2 byte value 
       (byte) ((CONN_INTERVAL & 0xFF00) >> 8), // gets MSB of 2 byte value 
       (byte) (CONN_INTERVAL & 0x00FF), 
       (byte) ((CONN_INTERVAL & 0xFF00) >> 8), 
       0, 0, 
       (byte) (SUPERVISION_TIMEOUT & 0x00FF), 
       (byte) ((SUPERVISION_TIMEOUT & 0xFF00) >> 8) 
     }; 
     connCharacteristic.setValue(value); 
     boolean status = mBluetoothGatt.writeCharacteristic(connCharacteristic); 
     Log.d(TAG, "setConnectionInterval. Change connection interval result: " + status); 
    } else { 
     Log.e(TAG, "setConnectionInterval. Connection characteristic is null!"); 
    } 

} 
private BluetoothGattService filterServices(List<BluetoothGattService> gattServices, String targetUuid) { 
    for(BluetoothGattService gattService : gattServices){ 
     String serviceUUID = gattService.getUuid().toString(); 
     Log.i(TAG, "serviceUUID: " + serviceUUID); 

     if(serviceUUID.equals(targetUuid)){ 
      Log.i(TAG, "serviceUUID matches! UUID: " + serviceUUID + " Type: " + gattService.getType()); 
      // no needed, just to check which characteristics are offered 
      for(BluetoothGattCharacteristic characteristic : gattService.getCharacteristics()) { 
       Log.i(TAG, "serviceUUID characteristics: " + characteristic.getUuid().toString()); 
      } 
      return gattService; 
     } 
    } 
    return null; 
} 

我必須說,它並沒有採用Android 5個設備都爲周圍對我的工作和中央,因爲通用訪問服務(0x1800)不提供我的設備特徵0x2a04爲首選連接參數。它只提供0x2a00(設備名稱)和0x2a01(外觀)。 參考文獻:

http://www.cumulations.com/blogs/7/Doing-firmware-upgrade-over-BLE-in-Android

https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.peripheral_preferred_connection_parameters.xml

https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.generic_access.xml

https://farwestab.wordpress.com/2011/02/05/some-tips-on-android-and-bluetooth/

+0

我無法寫入0x2A04的特性。它只有READ屬性。 – cxphong

+0

我不認爲寫入優先連接參數實際*改變*連接參數。 (我同意它是愚蠢的。)你可以在Android上執行此操作的唯一方法是使用['requestConnectionPriority()'](https://android.googlesource.com/platform/frameworks/base/+/master/core/java /android/bluetooth/BluetoothGatt.java#1169)或從外設(例如,在nRF51使用['sd_ble_gap_conn_param_update()'](http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom) nordic.infocenter.s332.api.v2.0.0%2Fgroup ___ b_l_e ___ g_a_p ___ f_u_n_c_t_i_o_n_s.html&anchor = gaf89b434841998ab384e0612dca9e12f8) – Timmmm

0

我相信,這一特性只是爲了提供信息給中央設備。這就是爲什麼它通常是隻讀的(對我和cxphong)。賓根的答案並不普遍,我不確定它是否會這樣工作。有人真的有它的工作在一個特定的設備?

看來,Android和iOS不會諮詢這個只讀特性的信息,所以我不確定它是非常有用的。

對於我來說,適用於Cypress外圍設備和Android中央設備的情況如下。類似的方法應該與其他設備一起工作。

  1. 在外設上,在CYBLE_GAP_CONN_UPDATE_PARAM_T結構「params」中定義首選連接參數。
  2. 經過GATT連接後,在CYBLE_EVT_GATT_CONNECT_IND事件處理程序(例如)中,調用CyBle_L2capLeConnectionParamUpdateRequest(connHandle,& params)。

在中央,沒有什麼可做的。接收到請求後,它稍後將啓動參數更新。

乾杯,

大衛

+0

一個例子可以在以下網址找到:https://github.com/cypresssemiconductorco/PSoC-4-BLE/tree/master/100_Projects_in_100_Days/ Day019_Connection_Parameters – Brian