Comunicating at least 300 kbp/s via BLE nrf5340 with Android phones

Hello,

I'm trying to achieve at least 300 kbp/s via BLE nrf5340 with Android phones (Bluetooth ver.4.2 and ver.5.x).

I use the "nRF Connect" and "Serial Bluetooth" apps. On board I use custom GATT service.

Unfortunately, the maximum effective throupoint is still only 6 kbp/s or less. 

Example throupoint.c between two boards works perfectly around 2Mbit/s.

I also tryed modified (patched) example (@ SDK ver.:1.8.0) mentioned in this thread:

https://devzone.nordicsemi.com/f/nordic-q-a/84487/ble-uart-nus-altering-mtu-and-faster-interval

These questions and answers are very informative, but changing the MTU or connection time has no effect:

devzone.nordicsemi.com/.../nrf5340---communicating-with-android-app-at-2-mbps

https://devzone.nordicsemi.com/f/nordic-q-a/69999/what-is-the-relation-between-connection-interval-and-the-throughput

https://devzone.nordicsemi.com/f/nordic-q-a/54013/nordic-uart-service-nus-speed-improvement

https://devzone.nordicsemi.com/f/nordic-q-a/43061/how-to-achieve-max-throughput-with-nus-service

https://devzone.nordicsemi.com/f/nordic-q-a/83562/file-transfer-large-data-transfer-example-nrf-connect-sdk

https://devzone.nordicsemi.com/f/nordic-q-a/84151/maximum-nus-data-length/350180#350180

https://github.com/nrfconnect/sdk-nrf/tree/v1.9.0-rc1/samples/bluetooth/throughput

Is it posible to make reliable firmware where 300kbp/s will be achivable with any phones that have Bluetooth 3.x and above?

This is my prf.conf file:

#
# Copyright (c) 2019 Nordic Semiconductor
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#
CONFIG_SHELL=y

CONFIG_BT_DEVICE_NAME="Nordic_Throughput"
CONFIG_BT=y
CONFIG_BT_DEBUG_LOG=y
CONFIG_BT_SMP=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_CENTRAL=y
CONFIG_BT_MAX_CONN=2

CONFIG_BT_SCAN=y
CONFIG_BT_SCAN_FILTER_ENABLE=y
CONFIG_BT_SCAN_UUID_CNT=1

CONFIG_BT_THROUGHPUT=y

CONFIG_BT_GATT_DM=y
CONFIG_HEAP_MEM_POOL_SIZE=2048

CONFIG_BT_USER_DATA_LEN_UPDATE=y
CONFIG_BT_USER_PHY_UPDATE=y
CONFIG_BT_GAP_AUTO_UPDATE_CONN_PARAMS=n

CONFIG_BT_BUF_ACL_RX_SIZE=251
CONFIG_BT_GATT_CLIENT=y
CONFIG_BT_ATT_PREPARE_COUNT=2
CONFIG_BT_CONN_TX_MAX=10
CONFIG_BT_L2CAP_TX_BUF_COUNT=10
CONFIG_BT_L2CAP_TX_MTU=247
CONFIG_BT_BUF_ACL_RX_SIZE=251
CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y

CONFIG_DK_LIBRARY=y
CONFIG_DK_LIBRARY_DYNAMIC_BUTTON_HANDLERS=y
CONFIG_SPI=y
CONFIG_SPI_SLAVE=y
CONFIG_NRFX_SPIS1=y
CONFIG_DEBUG_THREAD_INFO=y
CONFIG_DEBUG_OPTIMIZATIONS=y
CONFIG_BT_BUF_ACL_TX_COUNT=10
CONFIG_BT_BUF_ACL_TX_SIZE=251
CONFIG_BT_CTLR=y

connectd callback (It prints out: MTU = 23)

static void connected(struct bt_conn *conn, uint8_t err)
{
	if (err) {
		LOG_ERR("Connection failed (err %u)", err);
		return;
	}

	LOG_INF("Connected %d", 0);

	static struct bt_gatt_exchange_params exchange_params;
	exchange_params.func = exchange_func;
	err = bt_gatt_exchange_mtu(conn, &exchange_params);
	if (err) {
		LOG_ERR("bt_gatt_exchange_mtu failed: %d", err);
		return;
	}
	LOG_INF("bt_gatt_exchange_mtu OK %d", err);

	err = bt_conn_le_param_update(conn, conn_param);
	if (err) {
		LOG_ERR("bt_conn_le_param_update failed: %d", err);
		return;
	}
	LOG_INF("bt_conn_le_param_update OK %d", err);

	LOG_INF("MTU = %d", bt_gatt_get_mtu(conn)); 

	current_conn = bt_conn_ref(conn);
}

Parents
  • Hello,

    Attached below is an example I made to test notification throughput on the nRF5340. All you have to do on the Android side is connect with the nRF connect app and enable the notification. It will then start sending a notifications as fast and possible and print the measured throughput out on the UART. Could you please try this and see if it gives you any better throughput with the Android phone you are using?

    Example log:

    [00:06:11.570,281] <inf> nus_throughput: Connected FF:5B:6D:CB:57:9A (random)
    [00:06:11.595,031] <inf> nus_throughput: ATT MTU size updated to 247 bytes
    [00:06:11.631,988] <inf> nus_throughput: Data length updated. RX length: 251, TX length: 251
    [00:06:12.316,436] <inf> nus_throughput: 0 kbps
    [00:06:13.316,436] <inf> nus_throughput: 0 kbps
    [00:06:14.316,436] <inf> nus_throughput: 0 kbps
    [00:06:15.316,436] <inf> nus_throughput: 0 kbps
    [00:06:16.316,436] <inf> nus_throughput: 0 kbps
    [00:06:17.316,436] <inf> nus_throughput: 0 kbps
    [00:06:18.316,436] <inf> nus_throughput: 0 kbps
    [00:06:18.853,302] <inf> nus_throughput: PHY updated. RX PHY: 2, TX PHY: 2
    [00:06:19.316,436] <inf> nus_throughput: 0 kbps
    [00:06:20.316,436] <inf> nus_throughput: 0 kbps
    [00:06:21.316,467] <inf> nus_throughput: 55 kbps
    [00:06:22.316,497] <inf> nus_throughput: 1014 kbps
    [00:06:23.316,528] <inf> nus_throughput: 1050 kbps
    [00:06:24.316,558] <inf> nus_throughput: 1046 kbps
    [00:06:25.316,589] <inf> nus_throughput: 1042 kbps
    [00:06:26.316,619] <inf> nus_throughput: 905 kbps
    [00:06:27.316,650] <inf> nus_throughput: 1016 kbps
    [00:06:28.316,680] <inf> nus_throughput: 1029 kbps
    [00:06:29.316,711] <inf> nus_throughput: 1027 kbps
    [00:06:29.804,595] <inf> nus_throughput: Disconnected: FF:5B:6D:CB:57:9A (random) (reason 19)
    

    Example tested with SDK v.1.9.0:

    peripheral_uart_throughput.zip

    Best regards,

    Vidar

Reply
  • Hello,

    Attached below is an example I made to test notification throughput on the nRF5340. All you have to do on the Android side is connect with the nRF connect app and enable the notification. It will then start sending a notifications as fast and possible and print the measured throughput out on the UART. Could you please try this and see if it gives you any better throughput with the Android phone you are using?

    Example log:

    [00:06:11.570,281] <inf> nus_throughput: Connected FF:5B:6D:CB:57:9A (random)
    [00:06:11.595,031] <inf> nus_throughput: ATT MTU size updated to 247 bytes
    [00:06:11.631,988] <inf> nus_throughput: Data length updated. RX length: 251, TX length: 251
    [00:06:12.316,436] <inf> nus_throughput: 0 kbps
    [00:06:13.316,436] <inf> nus_throughput: 0 kbps
    [00:06:14.316,436] <inf> nus_throughput: 0 kbps
    [00:06:15.316,436] <inf> nus_throughput: 0 kbps
    [00:06:16.316,436] <inf> nus_throughput: 0 kbps
    [00:06:17.316,436] <inf> nus_throughput: 0 kbps
    [00:06:18.316,436] <inf> nus_throughput: 0 kbps
    [00:06:18.853,302] <inf> nus_throughput: PHY updated. RX PHY: 2, TX PHY: 2
    [00:06:19.316,436] <inf> nus_throughput: 0 kbps
    [00:06:20.316,436] <inf> nus_throughput: 0 kbps
    [00:06:21.316,467] <inf> nus_throughput: 55 kbps
    [00:06:22.316,497] <inf> nus_throughput: 1014 kbps
    [00:06:23.316,528] <inf> nus_throughput: 1050 kbps
    [00:06:24.316,558] <inf> nus_throughput: 1046 kbps
    [00:06:25.316,589] <inf> nus_throughput: 1042 kbps
    [00:06:26.316,619] <inf> nus_throughput: 905 kbps
    [00:06:27.316,650] <inf> nus_throughput: 1016 kbps
    [00:06:28.316,680] <inf> nus_throughput: 1029 kbps
    [00:06:29.316,711] <inf> nus_throughput: 1027 kbps
    [00:06:29.804,595] <inf> nus_throughput: Disconnected: FF:5B:6D:CB:57:9A (random) (reason 19)
    

    Example tested with SDK v.1.9.0:

    peripheral_uart_throughput.zip

    Best regards,

    Vidar

Children
  • Hello,

    you example works great @ 200-600kb/s. Based on the example code I was able to correct missing configurations in prf.conf file. Now my GATT service works at similar speeds.

    For comparason your measurement is around 1Mbit/s, I tried two different phones (BLE 4.x 5.x) but none of that have throupoint above 600kb/s. Do you have any idea why?

    Thank you,

    Martin

  • Hello,

    Maybe the phone is not requesting a PHY update? If so, the connection will stay on the slower 1M bitrate.  But you can try to request a PHY update from the application as well. For instance, from the data length update callback here:

    static void data_len_updated(struct bt_conn *conn, struct bt_conn_le_data_len_info *info)
    {
    	int err;
    
    	LOG_INF("Data length updated. RX length: %d, TX length: %d", info->rx_max_len,
    		info->tx_max_len);
    
    	err = bt_conn_le_phy_update(conn, BT_CONN_LE_PHY_PARAM_2M);
    	if (err) {
    		LOG_ERR("bt_conn_le_phy_update() returned %d", err);
    	}
    }

    Also, the throughput can vary quite a bit between different phones/chipsets and by how much priority the connection is given. Wifi and other connections can result in a lower priority for your connection.

    Best regards,

    Vidar

  • Hello,

    my output is:

    [00:00:03.776,702] <inf> app: Connected 72:78:7B:51:C3:73 (random)
    [00:00:04.285,797] <inf> app: PHY updated. RX PHY: 2, TX PHY: 2
    [00:00:04.346,069] <inf> app: Data length updated. RX length: 251, TX length: 251
    [00:00:04.406,066] <inf> app: ATT MTU size updated to 247 bytes
    [00:00:04.436,889] <wrn> bt_l2cap: Ignoring data for unknown channel ID 0x003a

    I tried several phones (Realme 8 PRO, Xioami Redmi 5, iPhone 11). What phone did you use?

    Thank you,

    Martin

  • Hello Martin,

    I would expect highest throughput from the Android phones. iOS seems to always cap the data rate at around 300 kbps.

    The output you posted is showing a connection with the iPhone. Do you also get the phy update when you test with your android phones.

    This is log message you will get if the PHY has been updated to 2M:

             <inf> app: PHY updated. RX PHY: 2, TX PHY: 2

    Best regards,

    Vidar

Related