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

Connection Parameter Selection for Central Device with 10 Peripheral Simultaneous Connections

Hi,

I am developing both Central and Peripheral devices with nRF52840. For consistency, both are using SDK 15.3.0 and S140 V7.

I am able to connect to peripherals and negotiate MTU ATT size of 247 and I am able to negotiate 2 Mbps phy. Logging on both peripheral and central devices confirm this is working.

My challenge is getting notification data from my peripherals to my central. If I set up (for example) 2 peripherals to notify my central device every 500 mSec with approx 160 bytes of data, all data comes into the BLE event handler (BLE_GATTC_EVT_HVX) within my central device just fine. If I double the data speed on peripherals (ie. 160 bytes every 250 mSec from each of the 2 devices), I only get BLE_GATTC_EVT_HVX events notifying me of incoming data from the first peripheral only.

I believe that I am not getting correct connection service intervals setup after peripheral connection.

For a scenario where a central is talking to 10 peripherals and getting notification data from each every 250 mSec, what would good connection interval, slave latency values be? I cannot seem to find a good reference for setup of connection intervals for multiple simultaneous peripheral connections to a central device - where each peripheral is notifying the central independently.

Note that my connection event length is 6 x 1.25 mSec or 7.5 mSec. This should be plenty long enough to get an MTU of 247 bytes transferred.

I have been using default min and max connection intervals of 7.5 and 30 mSec respectively and a slave latency of 0 (for both central and peripheral devices).

Suggestions for my scenario would be much appreciated.

Thanks in advance,

Mark J

Parents
  • Hello Mark,

    Sorry for the late reply. We are quite short staffed on support due to summer holidays. I am sorry, I didn't have time to reply before the weekend. Answering only your first post first:

    Are you sure that you are only receiving data from one peripheral connection? Perhaps you are spending too much time in the interrupt from the first device, so that the second device is not handling. I assume (based on your case history) that you are using the Nordic Uart Service (NUS). Do you print all the incoming data on the UART? What happens if you only try to leave the interrupt immediately, and just print something like: NRF_LOG_INFO("notification received from conn_handle %02x", conn_handle) whenever you receive data? Do you get both devices then?

Reply
  • Hello Mark,

    Sorry for the late reply. We are quite short staffed on support due to summer holidays. I am sorry, I didn't have time to reply before the weekend. Answering only your first post first:

    Are you sure that you are only receiving data from one peripheral connection? Perhaps you are spending too much time in the interrupt from the first device, so that the second device is not handling. I assume (based on your case history) that you are using the Nordic Uart Service (NUS). Do you print all the incoming data on the UART? What happens if you only try to leave the interrupt immediately, and just print something like: NRF_LOG_INFO("notification received from conn_handle %02x", conn_handle) whenever you receive data? Do you get both devices then?

Children
  • So the second post:

    Total throughput:

    160bytes  * 10 devices * 4Hz * 8bit/byte = 51 200bps, which is within the theoretical limit.

     

    Mark J said:

    - each of 10 connections for 2.5 mSec each or 25 mSec total for 10 connections.

    - scan window that will be 50% of the scan interval / connection interval. If I use 30 mSec - I will use a scan interval and connection interval of 60 mSec.

     Things start to get a bit messy when you do a lot of things at the same time, and expect a high throughput. First of all, a 50% scan window will block up to half of your possible throughput. There is only one radio, so you can only do one thing at the time. Advertise, scan or maintain a connection.

     

    Mark J said:
    1. Setting the NRF_SDH_BLE_GAP_EVENT_LENGTH to 2 (2.5 mSec) causes problems with sd_ble_gattc_write(). Periodically - it is returning BLE_ERROR_INVALID_CONN_HANDLE - even though this handle (0x0000) is successfully used before the sd_ble_gattc_write() call that fails (ie. it works for some time and then fails) Not sure how the NRF_SDH_BLE_GAP_EVENT_LENGTH could effect a handle validity. Softdevice Bug? If I use a NRF_SDH_BLE_GAP_EVENT_LENGTH value of 6 - I never see this issue. I also see it when using a valud of 3 (3.75 mSec).

     If you try to ignore this return (don't pass it onto APP_ERROR_CHECK()), do you get a disconnected event immediately after this?

     

    Mark J said:
    2. Even when I do NOT see the first issue (1 above) I am not able to consistently get all notifications to my BLE event handler (BLE_GATTC_EVT_HVX event). I do get all notifications from both peripherals sometimes, but during most tests I only get notifications from 1 peripheral device. On occasion, I do not get notifications from either peripheral device.

     Can you test not printing all the data from the notification, but just monitoring that they have arrived? Does it still behave like that?

    The NRF_SDH_BLE_GAP_EVENT_LENGTH will apply for all connections (individially), but unless you are using the entire event length in one connection, it will finish off the event when both parts are satisfied. 

    Mark J said:
    Perhaps far more packets are read/written during a connection event?

     Indeed they are. They can keep sending everything that is queued up before the connection event for as long as the connection event length has not ran out.

     

    Mark J said:
    Perhaps I misunderstand what the connection interval means for multiple connections. I expect it to be the time taken to service ALL connections plus the scan window. So, if each connection needs 7.5 mSec (if event time is 7.5 mSec) and I have 10 connections, I will need 75 mSec to handle all connection events and then more time for scanning before the connection interval has completed. Is this understanding correct?

     That is correct. And to make it even more complicated. Your connection events may not be nicely stacked in the beginning of your connection event cycle. They can be spread around, so you may not have that large time at the end to do scanning.

    This is mentioned a couple of times (in other tickets on the forum), but I'll copy one that I wrote not too long ago in a private ticket:

    The first thing you need to decide on is what you want your scan_window/scan_interval is going to be. This will decide how many % of the total time you will spend scanning, and hence, how big the probability of picking up an advertisement is. 

    The second thing you need to consider is that the softdevice can only schedule complete scan windows. If a scan window crashes with a planned advertising packet, it will have to pick one. This scheduler is dynamic, so if it has skipped many advertising packets earlier, advertisements will have higher priority. The same applies to scan windows. As you can see from the "SoftDevice timing-activities and priorities" from infocenter, you can see that connection related events have the highest priority, then comes scanning and advertising after that. 

    Back to your case. Every 70ms you want to maintain 4 connections. As a peripheral you have no control on where in this 70ms timeslot these connection events are placed. They can be placed nicely very close together, or they can be scattered out randomly:

    In addition, you will have the 1 - 2 advertisement events scattered around.

    So what you need to do is to make an educated worst case guess. As you can imagine, setting the scan window to 50ms will only work flawless if the connection events are stacked nicely together, which is very unlikely. In the "Worst case", you have 4 connection events and 2 advertisemen events scattered with equal distance, 70ms/(4+2) = 11ms.

    But even if you set your advertising and scan window to match 11ms, you they can still collide with the connection events. As you see, it starts to become very difficult to predict the best scan interval/window when you have advertisements and 4 connections at the same time. 

    It is likely that if you set the scan window to ~10ms you will be able to fit a couple of them into each connection interval. Setting it to ~50ms you are almost guaranteed that you will have many connection intervals without any scan windows. 

    But even if you set it to 10ms, there may be some connection intervals where you don't scan any of the 50ms advertisements, and there is also possible that you don't get to send out an advertisement every advertising interval, due to collisions with scan windows and connection events. 

    My suggestion to you is that you experiment with different scan intervals, scan windows, and advertising intervals. I think I would start with a scan interval of 70ms/4, and scan window of 10ms. If you still get too few packets, you can try to increase the advertising interval, but be aware that this will also cause more scan windows to not be prioritized. 

    I see that you wrote a new comment while I was writing this answer:
    P.S. Maybe it will be better to have 27 bytes packages instead of 251 but send a few packages within connection interval and have one confirmation. Is it good?

    It doesn't really matter. It is not really the length of the connection events, but the number of them that really matters when you try to fit scan windows in between. 

    I know that this is a lot of information, but hopefully it gave a bit more insight in how the softdevice handles scanning together with advertising and connections. 

  • Hi 

    As per my last entry: Increase Supported Links to Peripherals on a Central Device

    ... I took out NUS as it would not work in providing me a proper reference. I am now using direct connection handles and this is working better in that I always seem to get the correct reference to the connected peripheral sending me notification data.

    I am leaving the interrupt quickly and running my code on the main thread using a scheduler.  Here is my main loop:

     // Enter main loop.
      while (true)
      {
        // Proc USB events.
        while (app_usbd_event_queue_process()) { /* Nothing to do */  }
    
        // if(tempCnt++ >= 300000) { SEGGER_RTT_printf(0, "X\n"); tempCnt = 0;}
    
        // Handled scheduler actions.
        app_sched_execute();
    
        // Manage power.
        // nrf_pwr_mgmt_run(); 
      }

    By printing "x" I can see that my loop iterates < 10 uSec, so I am leaving the interrupt quickly and able to service the scheduler quickly on the main thread. I suspected that scheduling delay and handler execution time (ie. too long in a handler) may be the issue, but I am quite convinced it is related to the radio. More in my next reply below.

    IMPORTANTLY - I am not interested in scanning when transferring data. I am only scanning to setup connections. I scan, stop scanning, connect to my 10 peripherals and then I request that they notify me every 250 mSec. I have to setup a ble_gap_scan_params_t* to pass to sd_ble_gap_connect() - when connecting to each peripheral. I have been using the same scan interval and window within this ble_gap_scan_params_t object. Maybe that is my issue? If I want no scanning after connection, can I set this ble_gap_scan_params_t* to null or some other value that drastically or totally eliminates scanning after connections?

    Regards,

    Mark J 

  • Ok, so by browsing through your issue. Is the issue that you are lacking data from devices? Just as a test. If you don't send a lot of data, only a couple of bytes e.g. every 10 seconds. Do you receive the events from all devices?

    And when you crank it up, you are lacking data? If you are continuously queuing up data from all the devices. Does all of them return NRF_SUCCESS when you call the softdevice hvx calls from the peripherals?

  • Yes. The issue appears to be that I am lacking data from devices. I have sent the same data slower and I receive all data. For example, If I send 160 bytes every second, I get all data.

    When I go faster, notification data only comes in from 1 of 2 connected peripherals. As I am using notifications, I am not making hvx calls.

    I had suspected that the issue related to a scan window interrupting my connection events, but if I am NOT CURRENTLY SCANNING, I think that the scan window will not affect connection event servicing. Is this true?

    If I setup a connection scan window (say 100 mSec) and a connection interval of 120 mSec and I am not scanning, will there be any effect on connection event servicing and the ability for peripherals to notify me of data changes?

    I do not need to scan when getting notification data from peripherals. I will scan, connect, then get data.

    Mark J

  • BLE is a lossless protocol (ensured by ACKing and retransmission), so scanning shouldn't affect this. As long as you are not disconnected, all packet should arrive eventually, and in the same order as you send them.

    Perhaps you can show me how you are sending the data where you see the loss?

    You are still using SDK15.3.0, right? The reason I ask is that from SDK16.0.0 they did something to the ble_nus_c_string_send() which in my opinion makes it unreliable. The 15.3.0 implementation of this should be good.

Related