ESB "Hiccup"

I am currently working on a project in which I want to transmit audio wirelessly from one nRF chip to another. Currently I am using the nRF Dongle to act as the transmitter and a nRF-DK board as the receiver. I have finally gotten them to talk to each other through ESB, and the transmitter is currently sending a digital sine wave table out to the receiver which is then using SPI to interface with an external DAC. The problem lies in these "hiccups" that occur periodically, and while the frequency of the wave is something I can control, I can't seem to get rid of these hiccups. I am new to the Nordic development environment and I don't have much experience in the ESB protocol, and so I'm not sure if it's a hardware limitation, an acknowledgement issue, or something that I've overlooked in my code. At some point, the transmission will live in an SAADC callback function. That version works in terms of the signal path, but is experiencing the same problem that is outlined here. The problem is shown below, and here is my initialization of ESB, along with the transmission. Any help is greatly appreciated!

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.protocol                 = NRF_ESB_PROTOCOL_ESB_DPL;
    nrf_esb_config.retransmit_delay         = 100;
    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.selective_auto_ack       = true;
    nrf_esb_config.payload_length           = 2;
    nrf_esb_config.retransmit_count         = 1;

    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, NRF_ESB_PIPE_COUNT);
    VERIFY_SUCCESS(err_code);

    return err_code;
}

int i = 0;

    while (true)
    {
        tx_payload.data[0] = SineWave[i] & 0xFF;
        tx_payload.data[1] = SineWave[i] >> 8;
        tx_payload.noack = true;
        nrf_esb_write_payload(&tx_payload);

        i++;

        if (i >= 80)
        {
            i = 0;
        }

        nrf_delay_ms(50);
    }

 

Parents
  • Hi 

    As a general rule I would suggest using longer packets, and a higher number of retransmits, to ensure more efficient and reliable communication. 

    Still, if you are only sending a packet every 50ms, and experiencing regular repeated interruptions, then it points to a more critical issue. 

    Are you logging the ESB callbacks on the TX side to see if you are receiving TX failed interrupts or not?

    Do you have any interrupts in the system running at the highest priority, other than the ESB library?
    The ESB library is not designed to allow other interrupt at priority 0, and unfortunately this is the default priority if you don't change it to something else. 

    Could you try to add a sequence counter to the ESB payload? 
    This could be as simple as an 8-bit counter that you increment for every packet. 

    Then it is very easy to spot reception issues on the RX side, such as dropped or repeated packets. 

    Best regards
    Torbjørn

  • Thank you for your quick response! 

    I have tried to initialize the logger, but for some reason, I cannot seem to get it working on this project (only in other project files). I have tried adding a sample counter to the payload, but since I cannot print it out to the log, I cannot see the sample number in real time. 

    For the transmitter, is it possible to use the log even though it is just the nRF Dongle? I figured I would only be able to use it on the DK board for the reception side. 

    On the reception side, currently the SPI interrupt priority is at 0, and the ESB is at default, so I will go ahead and change that. 

  • Hi

    It sounds odd that more than 3Hz would be a problem, if you are sampling at 1000Hz. 

    Have you checked on the receiving end that you are getting all the samples? 
    If you count the samples over time you can check if you receive the expected 1000 samples pr second. 

    Are you doing any buffering on the receiving side to handle any inconsistency in timing or minor delays that could happen over the wireless link?

    Also, is the DAC set up to play a 1000 Hz samplerate signal properly? 
    If the output appears digitized it could just be that the appropriate filtering is not applied, to remove any frequency components above 500 Hz (half the sampling frequency, as per the Nyquist theorem). 

    Best regards
    Torbjørn

  • I ended up fixing the speed issue (it was slowed down due to logging, so taking all unnecessary code out drastically improved the output waveform), but now we are faced with noise on the output. While I can hear the tone that is being transmitted, there is underlying noise that seems to get even worse when I connect ground to the ADC of the transmitter side (ideally no sound at all). I currently have the ADC resolution set to 14 bit and I am removing the bottom 4 bits in order to combat ADC noise. Is there anything else that you think could be causing the problem or that I should look into?

  • Hi

    I assume you have tested that this noise has nothing to do with the radio transmission, and is actually present on the sampled signal before it is transmitted over the air?

    Have you tried to measure the analog signal with an oscilloscope to see if the noise is present on the input, or if it is somehow added by the sampling process itself? 

    There are various external and internal factors that could affect noise on the input. Since this is more of a hardware question I would recommend opening a new ticket, explain the problem, and include the schematic design of your board so we can check if it looks good. 

    The complete ADC configuration could also be helpful. One way to check if the noise is caused by the ADC itself is to enable oversampling on the ADC, and see if the noise is reduced. 

    Best regards
    Torbjørn

  • So the noise is not being injected at the input, as this is also happening with a function generated wave going through the ADC. I can post the ADC config here however, to see if there is something I can change in that. 

    void saadc_init(void)
    {
        ret_code_t err_code;
        nrf_saadc_channel_config_t channel_config =
            NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);
    
        err_code = nrf_drv_saadc_init(NULL, saadc_callback);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_saadc_channel_init(0, &channel_config);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1], SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);
    
    }
    
    void saadc_sampling_event_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_drv_ppi_init();
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
        timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
        err_code = nrf_drv_timer_init(&m_timer, &timer_cfg, timer_handler);
        APP_ERROR_CHECK(err_code);
    
        /* setup m_timer for compare event every 20us */
        uint32_t ticks = nrf_drv_timer_us_to_ticks(&m_timer, 40);
        nrf_drv_timer_extended_compare(&m_timer,
                                       NRF_TIMER_CC_CHANNEL0,
                                       ticks,
                                       NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                                       false);
        nrf_drv_timer_enable(&m_timer);
    
        uint32_t timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&m_timer,
                                                                                    NRF_TIMER_CC_CHANNEL0);
        uint32_t saadc_sample_task_addr   = nrf_drv_saadc_sample_task_get();
    
        /* setup ppi channel so that timer compare event is triggering sample task in SAADC */
        err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_ppi_channel_assign(m_ppi_channel,
                                              timer_compare_event_addr,
                                              saadc_sample_task_addr);
        APP_ERROR_CHECK(err_code);
    }
    
    void saadc_sampling_event_enable(void)
    {
        ret_code_t err_code = nrf_drv_ppi_channel_enable(m_ppi_channel);
    
        APP_ERROR_CHECK(err_code);
    }

  • Hi 

    Sorry for the slow response, I have been out of office for the last couple of weeks. 

    In order to check if the noise is caused by the ADC itself you could try to enable oversampling, and see if the noise is reduced?

    Theoretically every doubling of the oversampling (corresponding to increasing the oversampling setting by 1) should reduce the ADC noise by half a LSB. 

    You can change the oversampling setting through the NRFX_SAADC_CONFIG_OVERSAMPLE parameter in sdk_config.h. Try a value of 4 for instance, and you should see a reduction of noise of about 2 LSB compared to an oversample setting of 0. 

    Best regards
    Torbjørn

Reply
  • Hi 

    Sorry for the slow response, I have been out of office for the last couple of weeks. 

    In order to check if the noise is caused by the ADC itself you could try to enable oversampling, and see if the noise is reduced?

    Theoretically every doubling of the oversampling (corresponding to increasing the oversampling setting by 1) should reduce the ADC noise by half a LSB. 

    You can change the oversampling setting through the NRFX_SAADC_CONFIG_OVERSAMPLE parameter in sdk_config.h. Try a value of 4 for instance, and you should see a reduction of noise of about 2 LSB compared to an oversample setting of 0. 

    Best regards
    Torbjørn

Children
No Data
Related