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

My ESB PTX receives delayed duplicate ACK packets from my PRX

Hello!

My problem is that I am getting duplicates of the ACK packets I send from my PRX device to my PTX device.

To debug this problem, I configured my PTX to continuously stream data at 100hz. In my PRX device, I receive the packets, handle them, and then I send an ack packet on ever 100th sample.

So from my PRX I am sending (one uint32 number at a time) 0,1,2,3,4,5,6,7,8,9,10, 11, 12, 13, 14, ...

But on my PTX I receive (one uint32 number  at a time)           0,1,2,3,4,5,6,7,0,8,1,9,2,10,3,11,4,12,5,13,6,14, ...

The pattern is always consistent - the first 8 packets come through without any problem, and then I start getting current data interleaved with duplicate data that is always 8 packets old. 

I suspect that I must be doing something wrong, but I have tried a lot of things and the only thing that I have found that gets rid of the duplicate packets is to flush the tx_fifo buffer on the PRX inside my esb event handler when I receive my NRF_ESB_EVENT_TX_SUCCESS event. I have to completely flush it. calling nrf_esb_pop_tx() has no effect. The really crazy thing is that if I run nrf_esb_pop_tx() I get NRF_ERROR_BUFFER_EMPTY,  but if I don't flush the (apparently empty) buffer, My PRX will send duplicate packets!

At first I assumed that the packets were lingering in the fifo buffer. The documentation is clear about when packets are removed from the tx_buffer of the PTX device, but it is somewhat vague about when packets get removed from the tx_fifo on the PRX. That doesn't seem to be the issue though - if it were, then nrf_pop_tx() would not return NRF_ERROR_BUFFER_EMPTY.

Is this a common problem? Should I have to call nrf_esb_flush_tx() in my NRF_ESB_EVENT_TX_SUCCESS handler? It seems like a very bad idea - If multiple tx packets get loaded before the PRX receives an incoming message to attach them to, then all but one will be lost. Is it common to address this problem on the PTX side somehow? Am I doing something else wrong?

Both of the devices I used for this test were nrf52 dev boards. I am using sdk version 15.2.0.

Here is my PRX setup

nrf_esb_config_t nrf_esb_config 	= NRF_ESB_DEFAULT_CONFIG;
nrf_esb_config.protocol 			= NRF_ESB_PROTOCOL_ESB_DPL;
nrf_esb_config.retransmit_delay 	= 1000;
nrf_esb_config.retransmit_count 	= 0; // not sure what this even means on PRX
nrf_esb_config.bitrate 				= NRF_ESB_BITRATE_2MBPS;
nrf_esb_config.event_handler 		= nrf_esb_event_handler;
nrf_esb_config.mode 				= NRF_ESB_MODE_PRX;
nrf_esb_config.selective_auto_ack	= false;
nrf_esb_config.payload_length       = 4;
nrf_esb_config.tx_output_power      = RADIO_TXPOWER_TXPOWER_Pos4dBm;

err_code = nrf_esb_init(&nrf_esb_config);
VERIFY_SUCCESS(err_code);

err_code = nrf_esb_set_base_address_0(base_addr_0);
VERIFY_SUCCESS(err_code);

err_code = nrf_esb_set_base_address_1(base_addr_1);
VERIFY_SUCCESS(err_code);

err_code = nrf_esb_set_prefixes(addr_prefix, 8);
VERIFY_SUCCESS(err_code);

err_code = nrf_esb_set_rf_channel(s_data_channel);
VERIFY_SUCCESS(err_code);

err_code = nrf_esb_start_rx();
VERIFY_SUCCESS(err_code);

and here is my PTX setup

nrf_esb_config_t nrf_esb_config         = NRF_ESB_DEFAULT_CONFIG;
nrf_esb_config.retransmit_delay			= 600;
nrf_esb_config.retransmit_count         = 2;
nrf_esb_config.selective_auto_ack       = false;
nrf_esb_config.protocol                 = NRF_ESB_PROTOCOL_ESB_DPL;
nrf_esb_config.bitrate              	= NRF_ESB_BITRATE_2MBPS;
nrf_esb_config.event_handler            = nrf_esb_event_handler;
nrf_esb_config.mode                     = NRF_ESB_MODE_PTX;
//    nrf_esb_config.payload_length			= 30;
nrf_esb_config.tx_output_power          = RADIO_TXPOWER_TXPOWER_Pos4dBm;

err_code = nrf_esb_init(&nrf_esb_config);
VERIFY_SUCCESS(err_code);

err_code = nrf_esb_set_base_address_0(base_addr_0);
VERIFY_SUCCESS(err_code);

err_code = nrf_esb_set_base_address_1(base_addr_1);
VERIFY_SUCCESS(err_code);

err_code = nrf_esb_set_prefixes(addr_prefix, 8);
VERIFY_SUCCESS(err_code);

err_code = nrf_esb_set_rf_channel(s_data_channel);
VERIFY_SUCCESS(err_code);

This is the function I use to send ack packets from the PRX to the PTX

void esb_send_ack_packet(uint8_t pipe, uint8_t * ackpack, uint8_t nbytes)
{
	//tx_payload.noack = false;
	nrf_esb_payload_t tx_payload = {0};

	memcpy(tx_payload.data, ackpack, nbytes);
	tx_payload.length = nbytes;
	tx_payload.pipe = pipe;
	tx_payload.noack = false;

	uint32_t err_code = nrf_esb_write_payload(&tx_payload);
	if (err_code == NRF_SUCCESS) {
		NRF_LOG_INFO("SENDING ACK PACK to pipe %d - %d %d %d %d", pipe, ackpack[0], ackpack[1], ackpack[2], ackpack[3]);
	}
	else if (err_code == NRF_ERROR_NO_MEM) {
		nrf_esb_flush_tx();
		NRF_LOG_INFO("esb buff full - flushing");
	}else {
		NRF_LOG_INFO("Sending packet failed\r\n");
	}
}

If any else would be useful, let me know

Parents Reply
  • Hi Justin

    I am happy to hear that the modified implementation solved your issue Slight smile

    Can you confirm whether or not you use one or multiple pipes?

    The changes in the nrf52-esb-buffer-improvements repo were merged in SDK v17.0.0, but unfortunately there was an issue with the merge and some lines of code were not included. As such the current implementation in SDK v17.0.x also has some issues. 

    This has been reported internally, and I am hoping the proper implementation will be included in a future update to the SDK. 

    Best regards
    Torbjørn

Children
  • Hi Torbjørn,

    The design does normally use multiple pipes, but for the test case that I setup to debug the problem I only had one PTX device actually transmitting. The PRX was still configured to receive on multiple pipes though.

    Also, I forgot to mention in my original post that I did make one small change to the nrf_esb implementation. 

    I changed

    #define ESB_EVT_IRQ SWI0_IRQn 
    #define ESB_EVT_IRQHandler SWI0_IRQHandler 

    to

    #define ESB_EVT_IRQ QDEC_IRQn 
    #define ESB_EVT_IRQHandler QDEC_IRQHandler

    because I use SWIO for the app_timer.

  • Hi Justin

    Thanks for the confirmation, interesting to know that you can also get issues with a single pipe using the older code. 

    Changing the SWI0 interrupt to the QDEC interrupt should not have an impact on execution, as long as you don't use the QDEC peripheral obviously. 

    Best regards
    Torbjørn

Related