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

BLE UART losing packets

Hi all,

I am using PCA10040 with nRF5_SDK_13.0.0 and using the ble_perpheral -> ble_app_uart example.

I am trying to stream data from UART to an android phone and the data is coming from an external MCU with its TX/RX pin connected to the RX/TX pin on the NRF52DK. Every 40ms, I am sending a line of characters up to 49 bytes (max), terminating with a new line character.

Somehow, the android app is not able to receive the data and it only able to receive 1 out of every 3 lines of characters, and this is very consistent. Here is the log file from the app:

10:12:52.531 "4 111 222 333 211564 212372 212076 999999 0" received I 10:12:52.550 Notification received from 6e400003-b5a3-f393-e0a9-e50e24dcca9e, value: (0x) 37-09-31-31-31-09-32-32-32-09-33-33-33-09-32-31-31-35-30-37-09-32-31-32-34-30-33-09-32-31-32-30-36-34-09-33-32-36-34-35-09-30-0D-0A

10:12:52.572 "7 111 222 333 211507 212403 212064 32645 0" received I 10:12:52.596 Notification received from 6e400003-b5a3-f393-e0a9-e50e24dcca9e, value: (0x) 31-30-09-31-31-31-09-32-32-32-09-33-33-33-09-32-31-31-35-31-35-09-32-31-32-33-33-31-09-32-31-32-30-38-31-09-33-32-33-30-30-09-30-0D-0A

10:12:52.621 "10 111 222 333 211515 212331 212081 32300 0" received I 10:12:52.643 Notification received from 6e400003-b5a3-f393-e0a9-e50e24dcca9e, value: (0x) 31-33-09-31-31-31-09-32-32-32-09-33-33-33-09-32-31-31-35-32-30-09-32-31-32-33-36-36-09-32-31-32-30-34-34-09-33-32-33-31-31-09-30-0D-0A
A 10:12:52.662 "13 111 222 333 211520 212366 212044 32311 0

It basically receiving the 4th, 7th, 10th line etc, and losing the 5th, 6th, 8th, 9th etc lines. Can anyone advise on how this problem can be solved?

Thanks in advance!

  • Are you checking the returned error code of ble_nus_string_send()? Is it always NRF_SUCCESS (0x00000000)?

  • Hi Petter,

    The default codes does the following:

            case APP_UART_DATA_READY:
                UNUSED_VARIABLE(app_uart_get(&data_array[index]));
                index++;
    
                if ((data_array[index - 1] == '\n') || (index >= (m_ble_nus_max_data_len)))
                {
                    NRF_LOG_DEBUG("Ready to send data over BLE NUS\r\n");
                    NRF_LOG_HEXDUMP_DEBUG(data_array, index);
    
                    do
                    {
                        err_code = ble_nus_string_send(&m_nus, data_array, index);
                        if ( (err_code != NRF_ERROR_INVALID_STATE) && (err_code != NRF_ERROR_BUSY) )
                        {
                            APP_ERROR_CHECK(err_code);
                        }
                    } while (err_code == NRF_ERROR_BUSY);
    								
    							
                    index = 0;
                }
                break;

    The do-while loop is constantly checking for NRF_ERROR_BUSY. I presume its constantly trying to send the string until successful then it breaks out of the do-while loop. Perhaps this is taking too much time and hence its losing packets inbetween?

    If so, is there anyway to rectify the problem? I think it should be able to transfer much faster than that!

  • Seems you are checking the error code, if err_code was something else than NRF_ERROR_INVALID_STATE or NRF_ERROR_BUSY you would enter the error handler and reset the device (if you haven't defined DEBUG).

    If ble_nus_string_send() is called successfully the notification should be buffered, so then the issue may be on the Android side, but it is a but difficult to say without debugging some more. The easiest way to find out is to do a sniffer trace of the connection, you can use the nRF Sniffer. If that is not possible, I would add some more printfs, to see that you don't get disconnected or something like that.

    You could also try to do a test by connecting to another DK, running the ble_app_uart_c example, see if you are able to receive everything there.

  • Hi Petter,

    Just realised that its actually working fine now. I made a mistake in encoding the sequence number to send. Now I am getting all the data transmitted via UART and receiving on the android phone.

    However, now I am facing a different problem with buffering. Not sure if I should post a new thread on it. I will just explain the problem here.

    What is happening how is that even though all the data is transmitted successfully, there seems to be a lag. I am transmitting 25 strings per second. So after 10 seconds, I would have transmitted the 250th string. On the NRF logger, the first string is received at 09:42:56.450 and the 250th string (suppose to be received 10 seconds later) is received at 09:43:07.684. There is a slight delay and this builds up over time. The 1500th string (should be received 1 minute after the first packed received) is only received at 09:44:17.516. 

    Another observation I have is that on the nRF Toolbox UART app, after I click on the DISCONNECT button, it is still buffering data that is lagging behind. And it actually waits for a long time for the buffing to complete before it really disconnects.

    Is it possible to achieve real time data transmitting and receiving without any lag? My hardware is continuously transmitting for hours and I can't possibly have the lag building up over time. I suspect it would probably have a buffer overrun error after sometime.

  • That is great Slight smile

    You should add a new question, but I'll try to give a quick answer.

    It seems to me that you are trying to push more data than you have bandwidth for, then you will have a lag.

    If that is the case, you have two options, push less data, or increase bandwidth. Pushing less data may not be an option, but you can increase bandwidth by:

    -Sending fewer, larger packets, reducing overhead. Increasing the ATT MTU and enabling DLE.

    -Use the high speed 2 Mbps mode introduced in Bluetooth 5

    -Your other observation is probably because event though you disconnect in the app, you will still be connected at the Android system level. And since you are using notifications the packet don't have to be acked at the application level.

    Hope this helps. If not, I think you should add a new question.

Related