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

Package lost on multicentral

Description:

For my project I'm using 3 Nrf52840 DK, two of them as peripheral and the other as peripheral and central. I'm using also an iOS device as central. The two peripherals are connected with both centrals. The NRF52840 DK, which is configured as peripheral and central is connected also with iOS device.

The Problem is, that when i sent package and both central are connected, packages are lost. This problem doesn't occur if only one central is connected. It doesn't matter which one.
I dont really have an idea, why this happens so any help is appreciated.

Best regards

Parents
  • I assume you are calling sd_ble_gatts_hvx to send notification to each central from the peripheral. Make sure that you call sd_ble_gatts_hvx for each connection handle, and then monitor if any of the sd_ble_gatts_hvx return an error code, and what the error code is.

  • I should have mentioned, that I'm using the NUS service. I'm calling the ble_nus_data_send, which calls sd_ble_gatts_hvx. It is not important that both central receive the package. The problem is as follows. If only one central device is connected, then the central device receives all packages. If both central devices are connected, the number of packages that aren't sent increases significantly even though the packages are sent to only one of the central devices. Each peripheral is sending 158 bytes package with 25 Hz. I already have a buffer, which saves the package. 

    The error code that I'm receiving is NRF_RESOURCES_ERROR. I already know that the error code means that the tx-buffer is full but I cannot understand, why it works if only one central device is connected.

  • I assume you have included gatt_init() so that you can exchange longer MTU/DLE, that way the 158byte you refer to is sent as one notification instead of several.

    You are not writing anything about the connection parameters, but between the two nRF boards you should be able to decrease the connection interval to as low as 7.5ms after connection is established. While iOS I believe is limited to minimum 30ms. You can enable slave latency on both links, so the peripheral will only actually draw current when there is data to be sent on either of the links. If you have in addition configured the connection event length to 6, then that should ensure you have reserved plenty of time to transmit data in each interval. There will be collisions/overlap between the two links, however the link with the shortest interval will be the one that sometimes must skip a period due to the slower iOS connection, so there should still be plenty of time to send the amount of notifications you have here. Given those parameters I don't really see how you should experience NRF_RESOURCES_ERROR. I assume you have set tolerance of the lfclk to 500ppm here on the peripheral if you are using the internal RC oscillator?

  • Peripheral gatt init and the parameter:

    void BLEConnectionHandler::gatt_init(void)
    {
    	ret_code_t err_code = nrf_ble_gatt_init(this->m_gatt, &BLEConnectionHandler::gatt_evt_handler);
    	APP_ERROR_CHECK(err_code);
    
    	err_code = nrf_ble_gatt_att_mtu_periph_set(this->m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE);
    	APP_ERROR_CHECK(err_code);
    
    	NRF_LOG_INFO("GATT initialized.");
    }
    
    
    // perr manager params
    #define SEC_PARAM_BOND                  1                                       // Perform bonding.
    #define SEC_PARAM_MITM                  0                                       // Man In The Middle protection not required.
    #define SEC_PARAM_LESC                  0                                       // LE Secure Connections not enabled.
    #define SEC_PARAM_KEYPRESS              0                                       // Keypress notifications not enabled.
    #define SEC_PARAM_IO_CAPABILITIES       BLE_GAP_IO_CAPS_NONE                    // No I/O capabilities.
    #define SEC_PARAM_OOB                   0                                       // Out Of Band data not available.
    #define SEC_PARAM_MIN_KEY_SIZE          7                                       // Minimum encryption key size.
    #define SEC_PARAM_MAX_KEY_SIZE          16                                      // Maximum encryption key size.
    
    // gap params
    #define DEVICE_NAME                     "IMU"                               	// Name of device. Will be included in the advertising data.
    #define MIN_CONN_INTERVAL               MSEC_TO_UNITS(20, UNIT_1_25_MS)        // Minimum acceptable connection interval (7.5 ms).
    #define MAX_CONN_INTERVAL               MSEC_TO_UNITS(75, UNIT_1_25_MS)         // Maximum acceptable connection interval (75 ms).
    #define SLAVE_LATENCY                   0                                       // Slave latency.
    #define CONN_SUP_TIMEOUT                MSEC_TO_UNITS(4000, UNIT_10_MS)         // Connection supervisory timeout (4 seconds).
    
    // nus service
    #define NUS_SERVICE_UUID_TYPE           BLE_UUID_TYPE_VENDOR_BEGIN              // UUID type for the Nordic UART Service (vendor specific).
    
    // advertising
    #define APP_ADV_INTERVAL                300                                     // The advertising interval (in units of 0.625 ms. This value corresponds to 187.5 ms).
    #define APP_ADV_TIMEOUT_IN_SECONDS      12000                                     // The advertising timeout in units of seconds.
    #define APP_BLE_CONN_CFG_TAG            1                                       // A tag identifying the SoftDevice BLE configuration.
    
    // ble stack
    #define APP_BLE_OBSERVER_PRIO           3                                       // Application's BLE observer priority. You shouldn't need to modify this value.
    #define APP_FEATURE_NOT_SUPPORTED       BLE_GATT_STATUS_ATTERR_APP_BEGIN + 2    // Reply when unsupported features are requested. */
    
    // connection parameter
    #define FIRST_CONN_PARAMS_UPDATE_DELAY  APP_TIMER_TICKS(5000)                   // Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds).
    #define NEXT_CONN_PARAMS_UPDATE_DELAY   APP_TIMER_TICKS(30000)                  // Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds).
    #define MAX_CONN_PARAMS_UPDATE_COUNT    3                                       // Number of attempts before giving up the connection parameter negotiation.
    

    NRF_SDH_BLE_GATT_MAX_MTU_SIZE is set to 241 and NRF_SDH_BLE_GAP_EVENT_LENGTH to 320. I tried setting NRF_SDH_BLE_GAP_EVENT_LENGTH to 6 but it doesn't solve the problem. The tolerance of the internal lfclk is already set to 500ppm. The ios device reduces the mtu size to 185 and a notification is divided into several packages of size 27. So I think I need to request a DLE. Maybe you can help me with that?

    Thanks a lot.

  • I tried that, but the ios device decides on the connection parameter. I don't really have control over it. In this case (I'm using an iPhone 5SE) I think the ios device is not capable of 251 MTU size. Is there anything else I can try? Any other parameter I can try?

  • You are likely right that for the old phones that DLE is not supported, so in such case I can only think of trying to reduce the functionality somehow to reduce the throughput.

Reply Children
Related