This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Event length configuration on Central for concurrent Connection

Hello, 

I am trying to get central to concurrently connect to multiple (as many as possible) peripherals and stream data from each peripheral concurrently at 12KBytes/s. But I keep getting the error below. The error indicates that it can't send the data within the given event length. But from my calculation below this should not happen.

<error> nrf_ble_gatt: sd_ble_gap_data_length_update() (request) on connection 0x0 returned NRF_ERROR_RESOURCES.
<error> nrf_ble_gatt: The requested TX/RX packet length is too long by 94/94 octets.
<error> nrf_ble_gatt: sd_ble_gap_data_length_update() (request) on connection 0x0 returned NRF_ERROR_RESOURCES.
<error> nrf_ble_gatt: The requested TX/RX packet length is too long by 94/94 octets.

What I need to achieve

  • I need to connect central to as many peripherals as possible while maintaining a baud rate of 12KBytes/s (i.e 600 bytes within 50ms)
    • I can connect to 1 peripheral and get a max through put of 32KBytes/s
  • The connection intervals are 7.5ms 
  • Date Rate: 1Mbps
  • The data length = 251
  • The MTU size = 247
  • Packet per connection interval: 1 (peripheral can only send 1 packet per connection interval) 
  • By my calculations I can connect 3 peripherals and support this baud rate.
    • It would take 3 connection intervals to send all 600 bytes and 3 connection intervals only takes 22.5ms which is well below 50ms.  
    • Set the event length on central to 2.5ms 
      • This should allow the soft device to connect to 3 peripherals within that 7.5ms window. Every event length it connect to another peripheral.
      • To send 265bytes of data on 1Mbps connection only takes 2.12ms
  • I have setup the event length to be 3.75 to just be safe and I still get the error above

SDK configuration applied

  • NRF_SDH_BLE_GAP_DATA_LENGTH = 251

  • NRF_SDH_BLE_PERIPHERAL_LINK_COUNT = 0

  • NRF_SDH_BLE_CENTRAL_LINK_COUNT = 6

  • NRF_SDH_BLE_TOTAL_LINK_COUNT = 6

  • NRF_SDH_BLE_GAP_EVENT_LENGTH = 3 --> 3*1.25 = 3.75ms

  • NRF_SDH_BLE_GATT_MAX_MTU_SIZE = 247

  • I have also enabled extended BLE connection events as seen below
    •     ble_opt_t opt = { 0 };
      
          opt.common_opt.conn_evt_ext.enable = 1;
      
          rc = sd_ble_opt_set(BLE_COMMON_OPT_CONN_EVT_EXT, &opt);
          assert(NRF_SUCCESS == rc);

This is for a S140 softdevice

  • Hi, 
    You are correct that with 1Mbps we can send 265 bytes in 2.12ms. However, it's the theoretical on air data rate. Not the actual data through put in Bluetooth. 

    There are some factor that make the actual throughput is lower than that: 

    - It's two way communication. If you are sending data from the peripheral (P) to the central (C), there would be always a packet (usually empty payload) from C-> P before the packet P -> C

    - Overhead. There is a lot of flags, preamble, addresses, headers, etc. There are about 4 layers until you get to the ATT payload.  The longer the onair packet you sent the less overhead percentage you have to pay. 

    - T_IFS : Inter Frame Space = 150us

    - Clock accuracy. This cause the RX window have to be bigger than the actual transmission time. 

    However 12kB/s through put should be easily achieved. We have seen around 70kB/s with 1Mbps. 

    How large is the payload on each notification/write command you send ? 

    Setting the connection interval to 7.5ms might not bring you the maximum throughput. I would suggest you to refer to the ble_app_att_mtu_throughput example and play around a bit. 

    Could you try re-configure the connection interval and the connection event so that sd_ble_gap_data_length_update() won't return NRF_ERROR_RESOURCES. Let's say 30ms interval with 15ms connection event for example. 

  • A 30ms connection interval means I cannot meet the baud rate with even 1 peripheral. The peripheral only manages to send 1 packet per connection internal. I can't get it to send more. 

    If the peripheral is only sending 1 packet per 30ms that mean it would take 3 packet to send 600bytes. 3 packet would take 90ms, which is well above the 50ms mark. 

    I need to send 600 bytes every 50ms and connect as many peripherals as I can to central. What configuration would allow me to achieve this.

    From my calculation I should be able to achieve this with at least 3 peripheral but none of the configuration I use appear to work. Can you tell me how to configure the peripheral and central to achieve this?

  • I mentioned, we do see 600-700kbps with 1Mbps rate. 

    You can send more than 1 packet per connection event if configured correctly. 


    What's the error when you try to queue 2 message and more per connection interval ? What's the payload size ? 

  • I am trying to get the peripheral to stream data to central. When I connect up one peripheral I get a baud rate of about 32KBytes/s. In a 50ms this is 1600bytes, which is about 6 packets (1600/265). Which indicates that there about 1 packet per connection internval where a connection internval here is 7.5ms, since 7.5ms * 6 = 45ms. So every 7.5ms (connection interval) I am only getting 1 packet.

    The error the peripheral sends returns in wait for tx complete, I believe. But I am just hammering the peripheral to send data as fast as it can. 

    This is being done through the NUS. 

    Since I can only send 1 packet per connection interval it will take 3 connections intervals to send all the data I need to send (i.e 600bytes). 

    Now I just want to setup the event length so that Central can connect to multiple peripherals and stagger in incoming data to maintain the the baud rate of 12KBytes/s. (i.e 600 bytes every 50ms). 

    If I use any event length (NRF_SDH_BLE_GAP_EVENT_LENGTH)  lower than 6.25ms (i.e 5 units) then Central produces the error log about `sd_ble_gap_data_length_update()`. As I indicated above. This how ever doesn't make any sense to me because I should be able to use an event length of 2.5ms and send a packet of 265 bytes.

    I need to send the maximum allowed packet size each connection interval to achieve this baud rate which means I need the  NRF_SDH_BLE_GAP_DATA_LENGTH set to 251 bytes, so I can't reduce it to get rid of the error log. 

    My question is what parameter do I need to use on Central and Peripheral to achieve this? As my math indicate I could use the values I originally said but then I keep getting the error above.

  • When you mentioned "But I am just hammering the peripheral to send data as fast as it can. " what exactly you did ? 

    The way to achieve max through put is to queue as much as possible until you receive NRF_ERROR_RESOURCES error code when you call sd_ble_gatts_hvx. ( call it multiple time) Then you can wait for BLE_GATTS_EVT_HVN_TX_COMPLETE before you can queue again.

    Please do read what I wrote, there should be more than 1 packet per connection event if configured correctly. 

    Please do test with the ble_app_att_mtu_throughput example. 

Related