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

nRF51 wrong sequence in received packets

I'm using nRF51822_xxAA , with SDK12.3.0 and Softdevice S130 v2.0.1 on Keil V5.29.0.0. And as a central I use Redmi 7A phone with Android V10.
I want to sample ADC @ 200Hz, and send the sample as 2 bytes inside a packet of 20 bytes (10 ADC values) at real-time. To make sure all the packets have been successfully received, I've simulated the process to generate a sawtooth signal every time ADC interrupt has been triggered, then when a 20Bytes packet is full it'll be sent over BLE, then received on the phone then saved to a file.

The problem is when I drew the data I've saved, I found there was a wrong sequence in receiving packets, for example, when I send 3 packets of data, I send them as follow:
[Packet_1][Packet_2][Packet_3]...
but when when I receive them, sometimes, I receive them as follow:
[Packet_1][Packet_3][Packet_2]...
since :
1- I've added TX_COMPLETE_EVT to the characteristic I use, and check it before sending a new packet, and that didn't help.
2- I'm creating the data packet inside adc_event_handler() and when the packet is full I set a flag, then the packet will be sent inside the main function, for (;;) loop (not app_scheduler).
3- MIN_CONN_INTERVAL = MSEC_TO_UNITS(8, UNIT_1_25_MS) = 10ms.
4- MAX_CONN_INTERVAL = MSEC_TO_UNITS(10, UNIT_1_25_MS) = 12.5ms.
5- Other connection parameters are as default.
6- my for (;;) loop, doesn't have any delay function.
7- I'm using 3 ADC channels together, all of them is being sampled with the same frequency, but I'm sending only one channel's value.
8- The phone app I use I've written it on android studio 4.1

The question is where does the problem exist? in the peripheral or central side? and how to fix it?

Thanks in advance!

Parents
  • example, when I send 3 packets of data, I send them as follow:
    [Packet_1][Packet_2][Packet_3]...
    but when when I receive them, sometimes, I receive them as follow:
    [Packet_1][Packet_3][Packet_2]...

     I think this should not be possible to receive the swapped packets since BLE in its core have sequence numbers for packets so that the receiving controller layer will not accept a packet in wrong sequence order. It seems that there is something wrong in the way you are interpreting the data.

    It would help us if you show us some code snippets on how you are sending data on the TX side and how you are pulling data on the receiver side.

Reply
  • example, when I send 3 packets of data, I send them as follow:
    [Packet_1][Packet_2][Packet_3]...
    but when when I receive them, sometimes, I receive them as follow:
    [Packet_1][Packet_3][Packet_2]...

     I think this should not be possible to receive the swapped packets since BLE in its core have sequence numbers for packets so that the receiving controller layer will not accept a packet in wrong sequence order. It seems that there is something wrong in the way you are interpreting the data.

    It would help us if you show us some code snippets on how you are sending data on the TX side and how you are pulling data on the receiver side.

Children
  • this code is to generate the signal, it's done inside the adc_event_handler:

    if(sawtooth_cntr<100)
    	sawtooth_cntr++;
    else
    	sawtooth_cntr=0;
    	
    if(ble_samples_cntr <10)
    {	
    	hr_buffer[ble_samples_cntr *2] = (uint8_t)(sawtooth_cntr>>8);
    	hr_buffer[ble_samples_cntr *2 + 1] = (uint8_t)(sawtooth_cntr);
    	ble_samples_cntr++;
    }
    if(ble_samples_cntr>=10)
    {
    	ble_samples_cntr=0;
    	ble_packet_ready_to_send = true;
    }

    this is where to send the packet:

    for( ;;)
    {
    	.
    	.
    	.	
    	
    	if(hr_packet_ready_to_send && m_nlrs.is_notification_enabled )
    	{
    		if(my_data_tx_complete)
    		{
    			my_ble_characteristic_update(&m_nlrs,hr_buffer);
    			ble_packet_ready_to_send = false;
    			my_data_tx_complete = false;
    		}
    		
    	}
    }

    this is how to update the characteristic value:

    uint32_t my_ble_characteristic_update(ble_nlhrs_t * p_nlrhrs, uint8_t * p_data)
    {
        uint32_t err_code;
        if((p_nlrhrs->conn_handle != BLE_CONN_HANDLE_INVALID) || (!m_nlrhrs->is_notification_enabled))            //ensure that ther's a connection, otherwise softdevice will result in error
        {
            uint16_t                    len = MY_DATA_LENGTH;
            ble_gatts_hvx_params_t      hvx_params;		//20 bytes
            memset(&hvx_params,0,sizeof(hvx_params));
            
            hvx_params.handle   = p_nlrhrs->char_handles.value_handle;
            hvx_params.type     = BLE_GATT_HVX_NOTIFICATION;
            hvx_params.offset   = 0;
            hvx_params.p_len    = &len;
            hvx_params.p_data   = (uint8_t*) p_data;
            err_code = sd_ble_gatts_hvx(p_nlrhrs->conn_handle,&hvx_params);       
        }
        else
            err_code = NRF_ERROR_NOT_FOUND;
    		
        return err_code;       
    }

    and this is how I implemented tx_complete:

    bool my_data_tx_complete=true;
    static void on_tx_complete(ble_nlhrs_t * p_nlhrs, ble_evt_t * p_ble_evt)
    {
        my_data_tx_complete=true;
        if(m_send_complete_para.callback) {
            m_send_complete_para.callback(m_send_complete_para.context,m_send_complete_para.task_type);
        }
    }
    

  • for central side:

    1-When using Bluetooth Low Energy on nRfconnect for pc, there were no problems, I can send my data over BLE @200hz, and get them as correct as I sent.

    2- When using nRFconnect for mobile phone (android), there was no wrong sequence order in data packets, but when my phone had no enough RAM (i.e. there are other APPs are working together at the same time), in this case there was missed BLE packets, when I checked the log file, I've found that packet is missed there too 

      

    where P1 and P2 are the received packets, but there must be another packet between them because the mcu is generating a sequence of numbers between 0 and 100.

  • There are few things that are of concern.

    hvx_params.p_data   = (uint8_t*) p_data;

    Is this p_data word aligned?

    What is the value of MY_DATA_LENGTH?

    The code below

    if(sawtooth_cntr<100)
    	sawtooth_cntr++;
    else
    	sawtooth_cntr=0;
    	
    if(ble_samples_cntr <10)
    {	
    	hr_buffer[ble_samples_cntr *2] = (uint8_t)(sawtooth_cntr>>8);
    	hr_buffer[ble_samples_cntr *2 + 1] = (uint8_t)(sawtooth_cntr);
    	ble_samples_cntr++;
    }
    if(ble_samples_cntr>=10)
    {
    	ble_samples_cntr=0;
    	ble_packet_ready_to_send = true;
    }

    is hr_buffer memory  being accessed both by ADC and BLE notification modules? if yes, then you need to have it under critical section

    Are you using ble_samples_cntr anywhere else apart from the code you showed?

    I think what you are seeing is a conflict or race condition in your code, which is a general programming issue that you need to debug. I am quite confident that this is not related to the Nordic solution. But if you can provide me a stripped version of this code that is ready to compile and flash, i can attempt to debug this a bit and try to see where you might have a race condition.

  • Is this p_data word aligned?

    yes it's an array of 20 bytes

    What is the value of MY_DATA_LENGTH?

    20 bytes

    is hr_buffer memory  being accessed both by ADC and BLE notification modules?

    when ADC fills out the array, it'll set a flag "ble_packet_ready_to_send", so the array will be available for the BLE notification module, otherwise there's no any other possibility for BLE module to get access to it. anyway, I'll re-check if there's any conflict or race-condition there.

    Are you using ble_samples_cntr anywhere else apart from the code you showed?

    no, only inside adc_event_handler, it's a static variable inside the handler, and it might affect the bytes order into the array, but I don't have such a case.

    Is it possible that the problem exists in the central side?, because by using nRFconnect for pc the problem didn't appear. 

  • Rami AM said:
    Is it possible that the problem exists in the central side?, because by using nRFconnect for pc the problem didn't appear. 

    It is possible, please take a look at how it is unpacking data, like the code you showed me here. 

    I am quite confident that the BLE side does not have a problem since i have not heard of this issue within BLE before 

Related