Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs

ESB PRX problem with sending ACK payload

Hello. I can't normally use USB for two-way communication.

The problem is sending the PRX payload in ACK packets.

After conducting a simple test: PPTX sends a packet once a second and displays its serial number on the screen, then receives a packet from PRX and outputs its serial number. There are a lot of omissions.

I noticed the following incomprehensible point in the code: the tx fifo buffer is decremented before it is used in the condition, as a result, in the presence of one payload, it will not be transmitted. If you move the decrement after the condition, then there are no confirmation packets missing.

// Pipe stays in ACK with payload until TX FIFO is empty
                        // Do not report TX success on first ack payload or retransmit
                        if (p_pipe_info->ack_payload == true && !retransmit_payload)
                        {
                            uint32_t pipe = NRF_RADIO->RXMATCH;
                            m_ack_pl_container_entry_point_pr_pipe[pipe]->in_use = false;
                            m_ack_pl_container_entry_point_pr_pipe[pipe] = (nrf_esb_payload_random_access_buf_wrapper_t *)m_ack_pl_container_entry_point_pr_pipe[pipe]->p_next;
                            
                            //--- original code -------
                            
                            //m_tx_fifo.count--;
                            
                            //----------
                            
                            if (m_tx_fifo.count > 0 && m_ack_pl_container_entry_point_pr_pipe[pipe] != 0)
                            {
                                 mp_current_payload = m_ack_pl_container_entry_point_pr_pipe[pipe]->p_payload;
                            }
                            else mp_current_payload = 0;
                            
                            //----- my code ------
                            
                            m_tx_fifo.count--;
                            
                            //---------------
                            
                            // ACK payloads also require TX_DS
                            // (page 40 of the 'nRF24LE1_Product_Specification_rev1_6.pdf').
                            m_interrupt_flags |= NRF_ESB_INT_TX_SUCCESS_MSK;
                        }
I did the right thing by transferring this line of code, will it affect other parts of the ESB?

It is also unclear how to reset the TX FIFO for PRX, since m_acc_pl_container.in_use remain busy, as a result, the entire connection collapses when working with multiple PIPES.

Parents
  • Hi 

    I will help you out with this case, since I have worked a lot with the ESB library. 

    Can you first let me know which SDK type and version you are using?

    What is your retransmit_count configuration set to? 

    By default it is only set to 3, which means you only have 3 attempts at retransmitting the payload in case of packet loss. Could you try to increase this to a larger value and see if the problem persists?

    Best regards
    Torbjørn

  • Hello.

    SDK version: nRF5_SDK_17.0.2_d674dde. Device NRF52840.

    I have a slightly non-standard complex scenario of working on ESB.

    If in short: 1 receiver and many transmitters. Data is exchanged between the receiver and one transmitter on channel 1, receiving connection requests and sending responses to them on channel 0.

    The transmitter on pipe 0 requests permission to connect to the receiver. If the transmitter accepts the permission confirmation, it switches to pipe 1 and further data exchange between the connected receiver and the transmitter is carried out on pipe 1 (the address of pipe 1 is unique for each transmitter). The transmitter is switched off either by command or by timeout. 

    The data length is up to 252 bytes, the speed is 2 Mbit, the ACK timeout is 2 ms, the resend is 2. If the transfer is not successful, the PTX TX FIFO is collected.

    The receiver, when accepting a connection request and deciding to connect, sets the unique address of the transmitter on its pipe 1 and is thus able to exchange data with it. In addition, the receiver also remains capable of receiving and responding on pipe 0. When the receiver is disconnected, it stops receiving data on pipe 1 and reconfigures the address on it, and also resets the PRX TX FIFO using its own function.

    Of course, the whole mechanism of interaction is more complicated, but the main point is exactly this.

    I can personally give you the code of the corrected ESB library, the code of all functions related to working with ESB.

    In fact, the problem in question does not depend on the implementation of the ESB algorithm, I see that there is a problem with resetting PRX TX FOFO. More precisely, one of the obvious problems is that when switching from work on one pipe to another, and always with a different address, there is a need to reset the PRX TX FIFO, otherwise if we started working on another pipe and there will be no more calls from the transmitter on the previous pipe, then the PRX TX FIFO remains filled forever, which ultimately leads to the inability of the receiver to send anything to the transmitter - two-way communication is broken.it just does not always affect the work, but in my scenario it turned out to be critical. I am also interested in your opinion about the change in the ESB library code that I took above, after this change everything seems to have worked stably for me.

    Maybe my description is a little confusing, but I hope the meaning will be clear.

    Since you asked about the settings:

    uint8_t base_addr_0[4] = {0xE7, 0xE7, 0xE7, 0xE7};
    uint8_t base_addr_1[4] = {0xC2, 0xC2, 0xC2, 0xC2};
    uint8_t addr_prefix[8] = {0xE7, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8};
    
    uint32_t esb_init (void)
    {
        uint32_t err_code;
    
        nrf_esb_set_rf_channel(device.settings.rf_frequency);
    
        nrf_esb_config_t nrf_esb_config         = NRF_ESB_DEFAULT_CONFIG;
    
        nrf_esb_config.retransmit_count         = 2;
        nrf_esb_config.tx_output_power          = NRF_ESB_TX_POWER_8DBM;
        nrf_esb_config.selective_auto_ack       = true;
        nrf_esb_config.protocol                 = NRF_ESB_PROTOCOL_ESB_DPL;
        nrf_esb_config.bitrate                  = NRF_ESB_BITRATE_2MBPS;
        nrf_esb_config.payload_length           = NRF_ESB_MAX_PAYLOAD_LENGTH;
        nrf_esb_config.event_handler            = nrf_esb_event_handler;
        nrf_esb_config.retransmit_delay         = 2000;
        
    #ifdef MODE_PRX 
        nrf_esb_config.mode = NRF_ESB_MODE_PRX;
    #else
        nrf_esb_config.mode = NRF_ESB_MODE_PTX;
    #endif
    
        nrf_esb_init(&nrf_esb_config);
    
        nrf_esb_set_base_address_0(base_addr_0);
    
        nrf_esb_set_base_address_1(base_addr_1);
    
        nrf_esb_set_prefixes(addr_prefix, 8);
    
        NRF_RADIO->MODECNF0 = (NRF_RADIO->MODECNF0 & ~RADIO_MODECNF0_RU_Msk) | (RADIO_MODECNF0_RU_Fast << RADIO_MODECNF0_RU_Pos);
    
    #ifdef MODE_PRX 
        nrf_esb_start_rx();
    #endif
    
        return NRF_SUCCESS;
    }

Reply
  • Hello.

    SDK version: nRF5_SDK_17.0.2_d674dde. Device NRF52840.

    I have a slightly non-standard complex scenario of working on ESB.

    If in short: 1 receiver and many transmitters. Data is exchanged between the receiver and one transmitter on channel 1, receiving connection requests and sending responses to them on channel 0.

    The transmitter on pipe 0 requests permission to connect to the receiver. If the transmitter accepts the permission confirmation, it switches to pipe 1 and further data exchange between the connected receiver and the transmitter is carried out on pipe 1 (the address of pipe 1 is unique for each transmitter). The transmitter is switched off either by command or by timeout. 

    The data length is up to 252 bytes, the speed is 2 Mbit, the ACK timeout is 2 ms, the resend is 2. If the transfer is not successful, the PTX TX FIFO is collected.

    The receiver, when accepting a connection request and deciding to connect, sets the unique address of the transmitter on its pipe 1 and is thus able to exchange data with it. In addition, the receiver also remains capable of receiving and responding on pipe 0. When the receiver is disconnected, it stops receiving data on pipe 1 and reconfigures the address on it, and also resets the PRX TX FIFO using its own function.

    Of course, the whole mechanism of interaction is more complicated, but the main point is exactly this.

    I can personally give you the code of the corrected ESB library, the code of all functions related to working with ESB.

    In fact, the problem in question does not depend on the implementation of the ESB algorithm, I see that there is a problem with resetting PRX TX FOFO. More precisely, one of the obvious problems is that when switching from work on one pipe to another, and always with a different address, there is a need to reset the PRX TX FIFO, otherwise if we started working on another pipe and there will be no more calls from the transmitter on the previous pipe, then the PRX TX FIFO remains filled forever, which ultimately leads to the inability of the receiver to send anything to the transmitter - two-way communication is broken.it just does not always affect the work, but in my scenario it turned out to be critical. I am also interested in your opinion about the change in the ESB library code that I took above, after this change everything seems to have worked stably for me.

    Maybe my description is a little confusing, but I hope the meaning will be clear.

    Since you asked about the settings:

    uint8_t base_addr_0[4] = {0xE7, 0xE7, 0xE7, 0xE7};
    uint8_t base_addr_1[4] = {0xC2, 0xC2, 0xC2, 0xC2};
    uint8_t addr_prefix[8] = {0xE7, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8};
    
    uint32_t esb_init (void)
    {
        uint32_t err_code;
    
        nrf_esb_set_rf_channel(device.settings.rf_frequency);
    
        nrf_esb_config_t nrf_esb_config         = NRF_ESB_DEFAULT_CONFIG;
    
        nrf_esb_config.retransmit_count         = 2;
        nrf_esb_config.tx_output_power          = NRF_ESB_TX_POWER_8DBM;
        nrf_esb_config.selective_auto_ack       = true;
        nrf_esb_config.protocol                 = NRF_ESB_PROTOCOL_ESB_DPL;
        nrf_esb_config.bitrate                  = NRF_ESB_BITRATE_2MBPS;
        nrf_esb_config.payload_length           = NRF_ESB_MAX_PAYLOAD_LENGTH;
        nrf_esb_config.event_handler            = nrf_esb_event_handler;
        nrf_esb_config.retransmit_delay         = 2000;
        
    #ifdef MODE_PRX 
        nrf_esb_config.mode = NRF_ESB_MODE_PRX;
    #else
        nrf_esb_config.mode = NRF_ESB_MODE_PTX;
    #endif
    
        nrf_esb_init(&nrf_esb_config);
    
        nrf_esb_set_base_address_0(base_addr_0);
    
        nrf_esb_set_base_address_1(base_addr_1);
    
        nrf_esb_set_prefixes(addr_prefix, 8);
    
        NRF_RADIO->MODECNF0 = (NRF_RADIO->MODECNF0 & ~RADIO_MODECNF0_RU_Msk) | (RADIO_MODECNF0_RU_Fast << RADIO_MODECNF0_RU_Pos);
    
    #ifdef MODE_PRX 
        nrf_esb_start_rx();
    #endif
    
        return NRF_SUCCESS;
    }

Children
  • Hi 

    For the longest time there was a problem with the ACK payload mechanism in the ESB library, which would cause issues when uploading ACK payloads for multiple pipes at once as you describe. Essentially the library would only check the oldest packet in the FIFO, regardless of which pipe it received a packet on. 

    I made a patch to the library to fix this which I shared here

    In the nRF Connect SDK version of the ESB library this patch is applied, but it was never fixed in the nRF5 SDK implementation unfortunately. 

    Could you give the patched library a go and see if it works better, and if not which issues are still remaining?

    Best regards
    Torbjørn

Related