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.

  • 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);
        }
    }
    

  • 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.

Reply
  • 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.

Children
No Data
Related