This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

nRF51822 S110 versus Android Connection Inverval

For improving my data trouchput (both directions, using »Write without response« and »Notification« like e.g. nRF Uart Example do9, I'd performed some tests regarding the connection parameters (especially connection interval) with different Android devices.

On the Android side, I tested with my own tiny app but also with Nordic nRF Master Control Panel (Mcp).

IMHO, the test results are very surprising. They may hardly depend upon BT hardware (mostly Broadcom versus Qualcomm) and also on the installed Android version (4.3 versus 4.4.2 versus 4.4.3 and even Android stock release versus Cyanogen).

To get the fastest connection intervall, I'd set on my nRF51822 side both min and max to 7,5ms:

#define MIN_CONN_INTERVAL    6    ///<  7,5 ms
#define MAX_CONN_INTERVAL    6    ///<  7,5 ms

(I also tried Min=11,25 ms and Max= 15 ms like the Nordic Bootloader example do.) To verify the applied setting, I'd added some debug output to my code, were I hook:

  • the ble event BLE_GAP_EVT_CONNECTED
  • the ble event BLE_GAP_EVT_CONN_PARAM_UPDATE
  • ble_conn_params_init_t.evt_handler for BLE_CONN_PARAMS_EVT_FAILED

My tested Android devices are mainly:

  1. Samsung Note SM-P605 with Android 4.3 stock release
  2. Sony Xperia Z with both Android 4.3 stock release
  3. Sony Xperia Z with both Android 4.4.2 stock release
  4. Htc One with Android 4.4.2 stock release
  5. Samsung Note GT-N8000 with Android 4.4.2 stock release (Broadcom BCM4334)
  6. Nexus 7 2012 with Android 4.4.3 stock release (Broadcom BCM4330)
  7. Nexus 7 2013 with Android 4.4.3 stock release (Qualcomm Atheros WCN3660)
  8. Nexus 7 2013 with Android 4.4.3 cyanogenmod (Qualcomm Atheros WCN3660)

When connecting, on the most devices I'll get a BLE_GAP_EVT_CONNECTED with a connection interval of 48,75 ms and afterwards a BLE_GAP_EVT_CONN_PARAM_UPDATE with my desired 7,5 ms.

A (positive) exception is the (2) Sony Xperia with Android 4.3, were I get 7,5 ms upon connect (without BLE_GAP_EVT_CONN_PARAM_UPDATE).

The best throughput, I measured with (4) Htc One and (8) Nexus 7 2013 with cyanogenmod at about 8-10 kB/s in both directions (don't checked the number of packets per event until now).

But there are also some negative exceptions:

(1) Samsung Note SM-P605

Ok, the SM-P605 central connects with 48,75 ms. But it stubbornly refuses my peripheral's connection parameter update request (were I ask for 7,5 ms). My debug output:

INFO : Connected
TRACE: Ble event id=10h len=22, name=GAP_EVT_CONNECTED, range=Gap event
TRACE:   Connect: peer=0 76-5D-C2-19-57-80, irk_match=0, irk_match_idx=0
TRACE:   ConnParams: minInterv = 39 = 48,75ms, maxInterv = 39 = 48,75ms, slaveLatency = 0, connSupTimeout = 700 = 7000ms
TRACE: Ble event id=12h len=14, name=GAP_EVT_CONN_PARAM_UPDATE, range=Gap event
TRACE:   ConnParams: minInterv = 39 = 48,75ms, maxInterv = 39 = 48,75ms, slaveLatency = 0, connSupTimeout = 700 = 7000ms
TRACE: Ble event id=12h len=14, name=GAP_EVT_CONN_PARAM_UPDATE, range=Gap event
TRACE:   ConnParams: minInterv = 39 = 48,75ms, maxInterv = 39 = 48,75ms, slaveLatency = 0, connSupTimeout = 700 = 7000ms
TRACE: Ble event id=12h len=14, name=GAP_EVT_CONN_PARAM_UPDATE, range=Gap event
TRACE:   ConnParams: minInterv = 39 = 48,75ms, maxInterv = 39 = 48,75ms, slaveLatency = 0, connSupTimeout = 700 = 7000ms
WARN : CONN_PARAMS_EVT_FAILED - Connection Parameter Update Request failed, but we'll decide to keep connected.

→ And now the question: Does anyone noticed a behavior like this? How could I motivate this device to accept a faster connection interval than 48,75 ms ?

I got the same if I try e.g. min=30 ms max=47,5 ms - for every range were the max value is lower than 48,75 ms. Looks like the device won't be communicate faster than 48,75 ms. When I try with e.g. with min=200 ms max=250 ms, the negotiation succeeds:

INFO : Connected
TRACE: Ble event id=10h len=22, name=GAP_EVT_CONNECTED, range=Gap event
TRACE:   Connect: peer=0 76-5D-C2-19-57-80, irk_match=0, irk_match_idx=0
TRACE:   ConnParams: minInterv = 39 = 48,75ms, maxInterv = 39 = 48,75ms, slaveLatency = 0, connSupTimeout = 700 = 7000ms
TRACE: Ble event id=12h len=14, name=GAP_EVT_CONN_PARAM_UPDATE, range=Gap event
TRACE:   ConnParams: minInterv = 198 = 247,50ms, maxInterv = 198 = 247,50ms, slaveLatency = 0, connSupTimeout = 2000 = 20000ms
INFO : Connection Parameter Update Request succeeded.

I also tried to put my desired connection interval range into the advertising data like this:

ble_advdata_conn_int_t connParams;
connParams.min_conn_interval = 6;
connParams.max_conn_interval = 9;
advdata.p_slave_conn_int = &connParams;
scanrsp.p_slave_conn_int = &connParams;

and I'd been happy to see that an my Android device running Mcp: image description

But unfortunately, my Android device seems to ignore this information completely when connecting.

  • In my tests with iOS and KitKat 4.4.3 on a Nexus 4... the short answer is "you can't". Android BlueTooth is as vendor-specific as Android Audio... on some devices it's great, on most devices it's okay, and on a lot of devices it's horrible.

    If you look at the Android Open Source Project (AOSP), you can see that all the native C/C++ code for BlueTooth is firmly in the vendors' hands, so quality is going to vary greatly.

    There is no way to "force" a central to connect outside of its offered connection parameters.

  • Thanks for your reply (although I do not like the answer ;-).

  • I seem to have found a way around this very issue, assuming the device is capable of a faster connection interval. I was seeing behavior where sometimes it would connect with a 7.5 ms interval, and sometimes it would be 48.75 ms. Our application requires 7.5 ms. Basically what I do is check the connection interval after a connection is fully established (BLE_HIDS_EVT_REPORT_MODE_ENTERED), and if it is not fast enough, I do a disconnect with this parameter (BLE_HCI_CONN_INTERVAL_UNACCEPTABLE) telling the Central device that I want it faster. It seems to do the trick and doesn't take more than 2 connect attempts to work so far with my testing.

    sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE);

  • Although I can't comment on the BLE stack in Android precisely, because it is closed-source, we've used tricks like this for quite a while in the Android audio space. And my advice is do not do this for production.

    It is vendor-specific, hardware-specific, and Version 0.0.X-specific. It will break. Your customers will hate you. Then they will talk down Bluetooth on Android forever.

    I'd be willing to bet money that your "trick" will be flagged as a "bug" in the bluetooth stack, unfortunately. Because it relates to power usage, I expect that "bug" to be one of the few to be fixed.

    Yes, it's a gloomy outlook. Sorry... but that's my experience.

Related