Optimizing NUS client to server latency

Hi!

Background (feel free to skip)
---------------------------------------

We have 3 nRF52840 boards, connected via ble/NUS as follows:

A (NUS server) <---NUS---> (NUS client) B (NUS server) <---NUS---> (NUS client) C

B also advertises bluetooth HID, and both B and C feature a USB HID.

Following text considers the connection between A and B. All other connections are disconnected (although the advertisement is running). I am testing one direction at a time only, unless specified otherwise.

All connections are configured so that:

- data length extension is turned on

- connection interval is set to 7.5ms

    bt_conn_le_data_len_update(conn, BT_LE_DATA_LEN_PARAM_MAX);
    
    static const struct bt_le_conn_param conn_params = BT_LE_CONN_PARAM_INIT( 6, 6, 0, 100);
    bt_conn_le_param_update(conn, &conn_params);

Our main prj.conf CONFIG_BT values:

CONFIG_BT_ATT_PREPARE_COUNT=4
CONFIG_BT_BAS=y
CONFIG_BT_BUF_ACL_RX_SIZE=251
CONFIG_BT_BUF_ACL_TX_SIZE=251
CONFIG_BT_CENTRAL=y
CONFIG_BT_DEVICE_APPEARANCE=961
CONFIG_BT_DEVICE_NAME="UHK 80"
CONFIG_BT_DIS_MANUF="Ultimate Gadget Laboratories"
CONFIG_BT_DIS_PNP_VID=0x37A8
CONFIG_BT_DIS_PNP_VID_SRC=2
CONFIG_BT_DIS_PNP=y
CONFIG_BT_DIS=y
CONFIG_BT_GAP_AUTO_UPDATE_CONN_PARAMS=n
CONFIG_BT_GATT_CLIENT=y
CONFIG_BT_GATT_DM=y
CONFIG_BT_L2CAP_TX_BUF_COUNT=5
CONFIG_BT_L2CAP_TX_MTU=247
CONFIG_BT_MAX_CONN=1
CONFIG_BT_MAX_PAIRED=1
CONFIG_BT_NUS_CLIENT=y
CONFIG_BT_NUS=y
CONFIG_BT_OBSERVER=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_SCAN_ADDRESS_CNT=2
CONFIG_BT_SCAN_FILTER_ENABLE=y
CONFIG_BT_SCAN_UUID_CNT=1
CONFIG_BT_SCAN=y
CONFIG_BT_SETTINGS=y
CONFIG_BT_SHELL=y
CONFIG_BT_SMP=y
CONFIG_BT_USER_DATA_LEN_UPDATE=y
CONFIG_BT=y

Single direction testing
------------------------------

Testing with simple 2-byte pings (sending 50 pings, one each millisecond) reveals:

- Server-to-client (2-byte-messages) accepts and transports all the packets, with send-to-sent time around 15ms (measured from calling send to receiving relevant sent callback).

- Server-to-client (230-byte messages) In this case, sending slows down significantly, send function clearly blocking until there is a free slot in the queue. send-to-sent time increases to ~30ms in that case (which corresponds to a 4 slot long queue, I believe configured by CONFIG_BT_ATT_PREPARE_COUNT). The time of the whole sequence is 336ms.

- Client-to-server accepts one packet for transport every 15ms, and returns -120 otherwise. send-to-sent time is again 15ms.


Round trip time testing
------------------------------

- Round trips take around 15ms, which sounds fine, except that no more than 1 roundtrip succeeds every 15ms.

Questions
-------------

- Seeing above results (especially sending 50 messages in 336ms), am I right that server-to-client communication aggregates and splits our messages into (smaller number of) ble packets?

- Can we achieve the same packet-aggregation behavior for client-to-server communication?

- Is there a way to make the client send a packet every 7.5ms?

  • Hi!

    am I right that server-to-client communication aggregates and splits our messages into (smaller number of) ble packets?

    Could be, but it depends on the negotiated ATT MTU and DLE sizes between server and client, and what packet type is used, etc. A nrf-sniffer trace could confim that. https://www.nordicsemi.com/Products/Development-tools/nRF-Sniffer-for-Bluetooth-LE

    - Can we achieve the same packet-aggregation behavior for client-to-server communication?

    Should be possible, for fast client to server communication, use write command.

    - Is there a way to make the client send a packet every 7.5ms?

    Yeah, that should not be an issue. Likely you are getting the callback in the next connection event, but it's actually is sent every 7.5ms. A nrf-sniffer trace could confim that.

Related