Dropped packets with bt_nus_send

Greetings,


I am using the peripheral_uart Bluetooth nrf sample as a base for my custom application.

I have a ble_write_thread that just receives data on a message queue and calls the bt_nus_send function the same as the sample. And I also have a thread that produces the data and loads it to the ble message queue for transmission.

Recently because of a new requirement we need to send a lot more data via BLE than previously( to the central which is a mobile phone with the nRF Connect app). This has created issues with the integrity of the data packets we are sending. When the device is close to the edge of the Bluetooth range the device starts dropping packets.

As other members have previously informed me on the Zephyr discord this could be because while trying to resend the data (because of a poor connection on the edge of the range) new data are being queued in the BLE stack's buffers and the older ones that have still not been sent are overwritten thus they are never sent ( and appear as if they were dropped ) This only happens when the device is on the edge of the Bluetooth range & the issue is that the BLE stack is still trying to resend older packets.

I have increased the CONFIG_BT_BUF_ACL_TX_COUNT=200 & CONFIG_BT_BUF_ACL_TX_SIZE=251 (which is the maximum if I am not mistaken). I have also decreased the Supervision Timeout to the minimum (100 ms) so that the device disconnects for any transmission that takes more than 100 ms but this also seems not to solve the problem. I have also decreased the rate with which we queue new data to the ble_write_thread.

Is there something I am missing on the BLE operation or anything else I could do to eliminate this issue?

Thank you in advance!

Best regards,

Stavros

  • purging a message queue might cause data loss in your case, when the message queue buffer is not empty. Why do you want to purge the message queue? I would suggest something like below

    void ble_transmit_data( ble_data_t ble_data )
    {
        uint8_t retry_count = 0;
        
    	while ((k_msgq_put(&ble_msgq, &ble_data, K_NO_WAIT) != 0) && (retry_count++ < 10)) {
    		/* Sleep for sometime. How long, is application specific */
    		k_msleep(10);
    	}
    	
    	if(retry_count == 10) { LOG_WRN("Failed to add data to message queue"); }
    }

  • Because the Zephyr documentation suggests this implementation and also I do not want to make the producer threads wait.
    I will try this though.

    Wouldnt this result in an endless loop if the device disconnects while the producer thread is stuck in this loop? Something like this would also cause the watchdog of the producer thread to trigger.

    I just tried it and it makes the device unresponsive when it is on the edge of the Bluetooth range and it just freezes and stops transmitting, and after disconnecting the ble_write_thread and producer thread report 60 - 120 seconds of execution ( I am profiling the execution of the bt_nus_send and the producer thread )

  • Actually, after a few modifications I have implemented this in my application and it seems to eliminate any further dropped packets.

    Thnk you very much for the support if you have any other comments for improvements or any other thoughts you have on this it would be greatly appreciated, otherwise I will be closing this ticket on Monday that I will have finalized my implementation

  • I didn't read this whole thread but something which might assist your basic lost packet issue: When a BLE disconnect/reconnect event occurs the data successfully sent to the Softdevice by the uart service handler but not yet physically transmitted in full via BLE using the uart code is simply discarded by the Nordic Softdevice without notification to the uart code. In our case this produces a single lost packet (we transmit in packets) for each disconnect followed by a connect, This happens more often near the edge of the BLE range.

    The only workaround we know is to query Central for any missing packets (or Central simply informs Peripheral of any missing packets using an embedded packet sequence number) and re-transmit those missing packets. This is a pain; if you find a simpler solution we would be happy to hear of it.

  • Hugh, yes, that is one possible scenario where the uart data can be lost when you have a disconnect/connect sequence happening at the end of BLE range, but I did not think that this was the case as the description made me think that the data loss happens even without disconnect. Not sure how to handle such scenario when the softdevice just discards the packets. Seems like there is no error handling we can do here.

Related