How to set connection interval?

I'm working on a project about two BLE device: one, which streams inertial data, acts as peripheral  and the other, which is a custom USB dongle, acts as central device. To stream data between theese devices I activated the notify feature with 2M PHY and max data length parameters to maximize throughput. Now I noticed that the peripheral send data with an minimum fixed interval: the time between the call of bt_gatt_notify_cb and the call of the bt_gatt_notify_params.func is 100ms.

static void Ble_Connection_Inertial_Data_Tx_On_Sent( struct bt_conn *conn, void *user_data )
{
    ARG_UNUSED( user_data );
    k_sem_give( &inertialTxSemaphore );
}


static void Ble_Connection_Inertial_Data_Tx_Thread( void )
{
    static fifo_inertial_data_item_t *fifoItem;
    static struct bt_gatt_notify_params params = { 0 };
    static const struct bt_gatt_attr *attr;
    static uint8_t sampleCount = 0;
    static uint8_t inertialPacket[ INERTIAL_SAMPLE_PER_FRAME_BYTE_SIZE_MAX ];

    for ( int i = 0; i < remoteSrv.attr_count; i++ )
    {
        if ( bt_uuid_cmp( remoteSrv.attrs[ i ].uuid, BT_UUID_INERTIAL_DATA_TX_CHRC ) == 0 )
        {
            LOG_INF( "Found inertial arrts at %d", i );
            attr = &remoteSrv.attrs[ i ];
            break;
        }
    }

    params.attr = attr;
    params.func = Ble_Connection_Inertial_Data_Tx_On_Sent;

	for ( ;; )
    {
        fifoItem = k_fifo_get( &inertialDataTxFifo, K_FOREVER );
        memcpy( inertialPacket + ( sampleCount * INERTIAL_SAMPLE_BYTE_SIZE ), fifoItem->data, fifoItem->length );
        sampleCount++;

        if ( sampleCount >= samplePerFrame )
        {
            sampleCount = 0;

            if ( notificatioInertialDataTxEnabled == BT_NOTIFICATION_ENABLED )
            {
                params.data = inertialPacket;
                params.len = samplePerFrame * INERTIAL_SAMPLE_BYTE_SIZE;

                if ( k_sem_take( &inertialTxSemaphore, K_MSEC( 150 ) ) != 0 )
                {
                    LOG_WRN( "\n[W] DEVICE - Send inertial data timeout" );
                    continue;
                }
                
                if ( bt_gatt_notify_cb( currentConnection, &params ) != 0 )
                {
                    LOG_WRN( "\n[W] DEVICE - Gatt notify failed" );
                    k_mutex_lock( &appDataMutex, K_FOREVER );
                    appData.deviceInError = true;
                    k_mutex_unlock( &appDataMutex );
                }
            }
        }
    }
}

My doubts:

Is this delay due to the connection interval parameter? 

How should I set the interval connection? I read about to simply define MIN_CONN_INTERVAL and MAX_CONN_INTERVAL in the BLE source code. Is it the best way?

If I want to set the connection interval, I need to do it on both the devices (central and peripheral)? Which device define theese connection parameters?

Parents
  • Hi Andrea,

    Could you please give some details on how you determine that the delay is an interval of 100ms? Also, what do you mean by that interval being "minimum fixed?"

    It is known that bt_gatt_notify_cb() will block and wait if the buffer is full, which would explain the delay in various scenarios. Please refer to the following DevZone case and blog.
    bt_nus_send takes time to execute
    Building a Bluetooth application on nRF Connect SDK - Part 3 Optimizing the connection

    How should I set the interval connection? I read about to simply define MIN_CONN_INTERVAL and MAX_CONN_INTERVAL in the BLE source code. Is it the best way?

    If I want to set the connection interval, I need to do it on both the devices (central and peripheral)? Which device define theese connection parameters?

    The mentions of MIN_CONN_INTERVAL and MAX_CONN_INTERVAL are most likely about the use of those macros in the nRF5 SDK example codes. They are not applicable for the nRF Connect SDK (NCS).

    In Nordic's free online Bluetooth Low Energy Fundamentals course, you can find the method to set it in Lesson 3.

    The connection interval is negotiated between the central and the peripheral. They can have different range of supported connection interval. Both of them needs to share some common interval value for a successful negotiation. You can refer to Ole Bauck's answer here:  Questions about connection interval negotiation .

    Hieu

  • Hi Hieu,

    Could you please give some details on how you determine that the delay is an interval of 100ms? Also, what do you mean by that interval being "minimum fixed?"

    Before the bt_gatt_notify_cb() I added a function that toggle an output of nRF52840, and it toggles precisely every 100ms.

    In Nordic's free online Bluetooth Low Energy Fundamentals course, you can find the method to set it in Lesson 3.

    Meanwhile, I've already found this course and I understood how to manage the connection parameters. Thank you anyway. I found that my default connection interval was setted to 50ms, half the interval measured. So I tryed to set different values but between two call of bt_gatt_notify_cb() I measure always the double of interval choosed. Keep in mind that the fifo buffer in the worst case is filled by one sample every 1ms and the maximum of BLE packet is 12 samples, so the code has always all data available when the connection interval ends.

    It is known that bt_gatt_notify_cb() will block and wait if the buffer is full, which would explain the delay in various scenarios. Please refer to the following DevZone case and blog.

    This could be the cause. If you think to understand why about the double respect to the connection interval between bt_gatt_notify_cb() calls, let me know. Thanks for the suggestion anyway. I'll take a look to articles and I hope to understand what's going on. 

Reply
  • Hi Hieu,

    Could you please give some details on how you determine that the delay is an interval of 100ms? Also, what do you mean by that interval being "minimum fixed?"

    Before the bt_gatt_notify_cb() I added a function that toggle an output of nRF52840, and it toggles precisely every 100ms.

    In Nordic's free online Bluetooth Low Energy Fundamentals course, you can find the method to set it in Lesson 3.

    Meanwhile, I've already found this course and I understood how to manage the connection parameters. Thank you anyway. I found that my default connection interval was setted to 50ms, half the interval measured. So I tryed to set different values but between two call of bt_gatt_notify_cb() I measure always the double of interval choosed. Keep in mind that the fifo buffer in the worst case is filled by one sample every 1ms and the maximum of BLE packet is 12 samples, so the code has always all data available when the connection interval ends.

    It is known that bt_gatt_notify_cb() will block and wait if the buffer is full, which would explain the delay in various scenarios. Please refer to the following DevZone case and blog.

    This could be the cause. If you think to understand why about the double respect to the connection interval between bt_gatt_notify_cb() calls, let me know. Thanks for the suggestion anyway. I'll take a look to articles and I hope to understand what's going on. 

Children
  • Hi Andrea,

    Andrea Verdecchia said:
    Before the bt_gatt_notify_cb() I added a function that toggle an output of nRF52840, and it toggles precisely every 100ms.

    Do you mean that this output is toggle before bt_gatt_notify_cb() and toggled again in bt_gatt_notify_params.func?

    Andrea Verdecchia said:
    Keep in mind that the fifo buffer in the worst case is filled by one sample every 1ms and the maximum of BLE packet is 12 samples, so the code has always all data available when the connection interval ends.

    Am I right to understand that your system always produces more data (at least 1 sample/ms) than it can consume (at most 12 samples/50ms == 0.24 sample/ms)?

    If so, then your BT TX buffer will always be full, and this blocking wait behavior will be always there. Worse, a buffer will be overflown, or data will have to be dropped.

    Assuming your call to the API is asynchronous with the connection interval, I am surprised that the wait time is always precisely 100ms. As you can imagine, without any syncing, we shouldn't be able to be precise about how many milliseconds there are between your call of bt_gatt_notify_cb() and when a connection interval ends/begins. I suspect there is some side effect of the BT TX buffer being full and/or how threads are prioritized, but I will need to check with some development engineers about this. I will get back to you as soon as I find anything.

  • Hi Andrea,

    There are no good guesses from our development engineers either. Do you think you can get a sniffer trace of the communication?

    If you don't have a dedicated hardware, you can use a nRF51/52 series DK/Dongle to run the nRF Sniffer. We have a guide for that in the nRF Sniffer documentation, and another in Lesson 6 of our Bluetooth Low Energy Fundamentals course.

Related