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

Enhanced ShockBurst NRF_ESB_EVENT_TX_SUCCESS in PRX

Hi, we have been experimenting with the ESB PRX and PTX examples and have integrated them into our code. We are using the PTX to continuously stream data to the PRX side and we sometimes want to send data from the PRX side to the PTX. We can do this by queuing payloads to be sent with the ACK, and are able to successfully receive these payloads on the RTX side. But we don't get the NRF_ESB_EVENT_TX_SUCCESS (or NRF_ESB_EVENT_TX_FAILED for that matter) in the PRX afterwards.

It is my understanding that we should receive this event on the PRX side after the payload was transferred. According to the docs:

If the node is a PRX:

  1. Handle NRF_ESB_EVENT_RX_RECEIVED events as packets are coming in. Multiple packets might arrive in the RX FIFO between each event.
  2. To attach payloads to acknowledgment packets, add them to the TX FIFO using nrf_esb_write_payload. The payload must be queued before a packet is received. After a queued payload is sent with an acknowledgment, it is assumed that it reaches the other device. Therefore, an NRF_ESB_EVENT_TX_SUCCESS event is queued.

Is there something obvious that I'm missing?

  • Hi,

     

    Q1: What SDK is being used?

    Q2: Is it nRF52832 in both PRX and PTX side?

    Q3: How is ESB initialized and configured?

    Kind regards,

    Håkon

  • Hi Hakon. We are using SDK v15.0.0 and yes, nrf52832 on both sides.

    The ESB TX is set-up like this:

    static void Init(TOwner* o)
            {
                assert(o != nullptr);
                assert(owner == nullptr);
    
                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   = 600;
                nrf_esb_config.bitrate            = NRF_ESB_BITRATE_2MBPS;
                nrf_esb_config.event_handler      = event_handler;
                nrf_esb_config.mode               = NRF_ESB_MODE_PTX;
                nrf_esb_config.selective_auto_ack = false;
                nrf_esb_config.tx_output_power    = NRF_ESB_TX_POWER_4DBM;
    
                ret_code_t err_code = nrf_esb_init(&nrf_esb_config);
                APP_ERROR_CHECK(err_code);
    
                err_code = nrf_esb_set_base_address_0(o->getAddresses().base_addr_0.data());
                APP_ERROR_CHECK(err_code);
    
                err_code = nrf_esb_set_base_address_1(o->getAddresses().base_addr_1.data());
                APP_ERROR_CHECK(err_code);
    
                err_code = nrf_esb_set_prefixes(o->getAddresses().addr_prefix.data(), o->getAddresses().num_pipes);
                APP_ERROR_CHECK(err_code);
    
                owner = o;
            }

    and the RX side is set-up like this:

    static void Init(TOwner* o, Esb::Addresses addr)
            {
                ASSERT(o);
                ASSERT(owner == nullptr);
    
                owner = o;
    
                ret_code_t ret = nrf_drv_clock_init();
                if (ret != NRF_ERROR_MODULE_ALREADY_INITIALIZED) {
                    APP_ERROR_CHECK(ret);
                }
    
                ret = nrf_drv_power_init(nullptr);
                if (ret != NRF_ERROR_MODULE_ALREADY_INITIALIZED) {
                    APP_ERROR_CHECK(ret);
                }
    
                nrf_drv_clock_lfclk_request(nullptr);
                ret = app_timer_init();
                APP_ERROR_CHECK(ret);
    
                hfclk_start();
                
                //==============================================================
                nrf_esb_config_t nrf_esb_config = NRF_ESB_DEFAULT_CONFIG;
                nrf_esb_config.payload_length     = 8;
                nrf_esb_config.protocol           = NRF_ESB_PROTOCOL_ESB_DPL;
                nrf_esb_config.bitrate            = NRF_ESB_BITRATE_2MBPS;
                nrf_esb_config.mode               = NRF_ESB_MODE_PRX;
                nrf_esb_config.event_handler      = nrf_esb_event_handler;
                nrf_esb_config.selective_auto_ack = false;
                nrf_esb_config.tx_output_power    = NRF_ESB_TX_POWER_4DBM;
    
                ret_code_t err_code = nrf_esb_init(&nrf_esb_config);
                APP_ERROR_CHECK(err_code);
    
                err_code = nrf_esb_set_base_address_0(addr.base_addr_0.data());
                APP_ERROR_CHECK(err_code);
    
                err_code = nrf_esb_set_base_address_1(addr.base_addr_1.data());
                APP_ERROR_CHECK(err_code);
    
                err_code = nrf_esb_set_prefixes(addr.addr_prefix.data(), addr.num_pipes);
                APP_ERROR_CHECK(err_code);
    
                //==============================================================
                ret = nrf_esb_start_rx();
                APP_ERROR_CHECK(ret);
            }

  • Hi,

     

    I checked the esb_ptx and esb_prx from SDK v15.2, which has similar configuration as you have, where I only modified the esb_prx example to send ACK, and it gives the event "NRF_ESB_EVENT_TX_SUCCESS" one payload after the event "NRF_ESB_EVENT_RX_RECEIVED" has occurred.

    This is because the PRX does not know if the ack payload was successfully received before it gets a new payload.

    Here's the modified esb_prx I used for testing:

    /**
     * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA
     *
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     *
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     *
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     *
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     *
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     *
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */
    #include "nrf_esb.h"
    
    #include <stdbool.h>
    #include <stdint.h>
    #include "sdk_common.h"
    #include "nrf.h"
    #include "nrf_esb_error_codes.h"
    #include "nrf_delay.h"
    #include "nrf_gpio.h"
    #include "nrf_error.h"
    #include "boards.h"
    
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    uint8_t led_nr;
    
    nrf_esb_payload_t rx_payload;
    
    /*lint -save -esym(40, BUTTON_1) -esym(40, BUTTON_2) -esym(40, BUTTON_3) -esym(40, BUTTON_4) -esym(40, LED_1) -esym(40, LED_2) -esym(40, LED_3) -esym(40, LED_4) */
    
    void nrf_esb_event_handler(nrf_esb_evt_t const * p_event)
    {
        switch (p_event->evt_id)
        {
            case NRF_ESB_EVENT_TX_SUCCESS:
                NRF_LOG_DEBUG("TX SUCCESS EVENT");
                nrf_gpio_pin_write(LED_1, !(rx_payload.data[1]%8>0 && rx_payload.data[1]%8<=4));
                break;
            case NRF_ESB_EVENT_TX_FAILED:
                NRF_LOG_DEBUG("TX FAILED EVENT");
                nrf_gpio_pin_write(LED_2, !(rx_payload.data[1]%8>1 && rx_payload.data[1]%8<=5));
                break;
            case NRF_ESB_EVENT_RX_RECEIVED:
                NRF_LOG_DEBUG("RX RECEIVED EVENT");
                if (nrf_esb_read_rx_payload(&rx_payload) == NRF_SUCCESS)
                {
                    // Set LEDs identical to the ones on the PTX.
                    //nrf_gpio_pin_write(LED_1, !(rx_payload.data[1]%8>0 && rx_payload.data[1]%8<=4));
                    //nrf_gpio_pin_write(LED_2, !(rx_payload.data[1]%8>1 && rx_payload.data[1]%8<=5));
                    //nrf_gpio_pin_write(LED_3, !(rx_payload.data[1]%8>2 && rx_payload.data[1]%8<=6));
                    nrf_gpio_pin_write(LED_4, !(rx_payload.data[1]%8>3));
    
                    NRF_LOG_DEBUG("Receiving packet: %02x", rx_payload.data[1]);
                    if (nrf_esb_write_payload(&rx_payload) == NRF_SUCCESS) {
                        nrf_gpio_pin_write(LED_3, !(rx_payload.data[1]%8>2 && rx_payload.data[1]%8<=6));
                        NRF_LOG_DEBUG("ACK Payload sent");
                    }
                }
                break;
        }
    }
    
    
    void clocks_start( void )
    {
        NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
        NRF_CLOCK->TASKS_HFCLKSTART = 1;
    
        while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);
    }
    
    
    void gpio_init( void )
    {
        bsp_board_init(BSP_INIT_LEDS);
    }
    
    
    uint32_t esb_init( void )
    {
        uint32_t err_code;
        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 };
        nrf_esb_config_t nrf_esb_config         = NRF_ESB_DEFAULT_CONFIG;
        nrf_esb_config.payload_length           = 8;
        nrf_esb_config.protocol                 = NRF_ESB_PROTOCOL_ESB_DPL;
        nrf_esb_config.bitrate                  = NRF_ESB_BITRATE_2MBPS;
        nrf_esb_config.mode                     = NRF_ESB_MODE_PRX;
        nrf_esb_config.event_handler            = nrf_esb_event_handler;
        nrf_esb_config.selective_auto_ack       = false;
    
        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);
    
        return err_code;
    }
    
    
    int main(void)
    {
        uint32_t err_code;
    
        gpio_init();
    
        err_code = NRF_LOG_INIT(NULL);
        APP_ERROR_CHECK(err_code);
    
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
        clocks_start();
    
        err_code = esb_init();
        APP_ERROR_CHECK(err_code);
    
        NRF_LOG_DEBUG("Enhanced ShockBurst Receiver Example started.");
    
        err_code = nrf_esb_start_rx();
        APP_ERROR_CHECK(err_code);
    
        while (true)
        {
            if (NRF_LOG_PROCESS() == false)
            {
                __WFE();
            }
        }
    }
    /*lint -restore */
    

     

    Could you try this and see if you get the event then?

     

    Kind regards,

    Håkon

Related