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

Reading the RSSISAMPLE register is very time-consuming using the ESB in nRF52833 (approximately 400-500ms each time).

When I used the code to get the RSSI values for different channels, I found that it was very time-consuming, about 400-500ms, and most of the time was spent waiting (NRF_RADIO->EVENTS_RSSIEND = 1. May I ask why this is? Is there a way to optimize it?

static uint8_t esb_get_rf_channel_rssi(uint8_t ch)
{
    nrf_esb_set_rf_channel(ch);
    nrf_esb_start_rx();
    nrf_delay_us(150);
    NRF_RADIO->EVENTS_RSSIEND = 0;
    while(NRF_RADIO->EVENTS_RSSIEND == 0);
    NRF_RADIO->TASKS_RSSISTART = 0;
    uint8_t rssi_reading = NRF_RADIO->RSSISAMPLE;
    nrf_esb_stop_rx();
    return rssi_reading;
}

Parents Reply Children
  • Yes, I have tried to remove the "NRF_RADIO->TASKS_RSSISTART = 0" and the problem still arises. The way to measure the time is to obtain the system time before and after the "while(NRF_RADIO->EVENTS_RSSIEND == 0)", and find that the interval is about 400ms. Before each wireless connection, the function esb_get_rf_channel_rssi is repeatedly called to obtain the RSSI for each channel.

  • Why is "while(NRF_RADIO->EVENTS_RSSIEND == 0);" so time-consuming? Is it inherently so time-consuming in theory or is there an issue with my code somewhere? 

  • #include <stdbool.h>
    #include <stdint.h>
    #include "boards.h"
    #include "bsp.h"
    #include "app_timer.h"
    #include "nordic_common.h"
    #include "nrf_error.h"
    
    #include "nrf_gpio.h"
    
    #define max_channel      80   
    static uint32_t scan_repeat_times = 1;
    
    #define RSSI_NO_SIGNAL              127    /**< Minimum value of RSSISAMPLE */
    
    #define PIN_GPIO  (4UL)
    
    void rssi_measurer_configure_radio(void)
    {
    	NRF_RADIO->POWER  = 1;
    	NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_DISABLE_Msk;
    	NVIC_EnableIRQ(RADIO_IRQn);
    
    	NRF_CLOCK->TASKS_HFCLKSTART = 1;
    	while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);
    }
    
    #define WAIT_FOR( m ) do { while (!m); m = 0; } while(0)
    
    uint8_t rssi_measurer_scan_channel(uint8_t channel_number)
    {
    	uint8_t sample;
    
    	NRF_RADIO->FREQUENCY  = channel_number;
    	NRF_RADIO->TASKS_RXEN = 1;
    
    	WAIT_FOR(NRF_RADIO->EVENTS_READY);
    	NRF_RADIO->TASKS_RSSISTART = 1;
    	WAIT_FOR(NRF_RADIO->EVENTS_RSSIEND);
    
    	sample = 127 & NRF_RADIO->RSSISAMPLE;
    
    	NRF_RADIO->TASKS_DISABLE = 1;
    	WAIT_FOR(NRF_RADIO->EVENTS_DISABLED);
    
    	return sample;
    }
    
    uint8_t rssi_measurer_scan_channel_repeat(uint8_t channel_number)
    {
    	uint8_t sample;
    	uint8_t max = RSSI_NO_SIGNAL;
    	for (int i = 0; i <= scan_repeat_times; ++i) {
    		sample = rssi_measurer_scan_channel(channel_number);
    		// taking minimum since sample = -dBm.
    		max = MIN(sample, max);
    	}
    	return max;
    }
    
    
    
    /**
     * @brief Function for application main entry.
     */
    int main(void)
    {
    
        static uint8_t sample[max_channel];
    
        nrf_gpio_cfg_output(PIN_GPIO);
    
    
       rssi_measurer_configure_radio();
    
     
     nrf_gpio_pin_toggle(PIN_GPIO);
    
      for (uint8_t i = min_channel; i <= max_channel; ++i)
      {
              sample[i] = rssi_measurer_scan_channel_repeat(i);
      }
       nrf_gpio_pin_toggle(PIN_GPIO);
    
    
    
        while (true)
        {
            __SEV();
            __WFE();
            __WFE();
          
        }
    }
    
    
    /** @} */
    

    This takes ~20ms to scan 80 channels (time measured with gpio toggling).

  • Hi!

    Thank you very much for your reply. I still have a few questions I would like to ask you.

    Why is it still time-consuming when I use the code you provided, and why does it easily trigger a watchdog reset? Additionally, the RSSI obtained through the method you provided differs greatly from the RSSI after an actual connection is established, with a difference of about 30-40 in value. I noticed that you did not stop RX before setting the Frequency, and you did not restart RX after setting it. Is it that the RX reception during broadcasting is measuring the RSSI of the noise in the environment?

  • Hi!

    langzou said:
    Why is it still time-consuming when I use the code you provided

    What time are you measuring with the code I provided? If you run it on top of ESB, then I guess you have configured the radio to a specific addresses, etc, and only receive packets from specific devices. So the time it takes to get the RSSI measurement will depend on how often these devices transmit.

    langzou said:
    Additionally, the RSSI obtained through the method you provided differs greatly from the RSSI after an actual connection is established

    You are only interesting the RSSI for the device you are connected to?

    langzou said:
    I noticed that you did not stop RX before setting the Frequency, and you did not restart RX after setting it.

    The RX is started in the beginning of rssi_measurer_scan_channel(). At the end of that function, the RX is disabled.

    langzou said:
    Is it that the RX reception during broadcasting is measuring the RSSI of the noise in the environment?

    It's measuring RSSI of noise in the environment.

Related