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

How to disable radio notification after enabling it

Hi,

In my application I need radio notification only during connection. When connection is dropped the peripheral goes to advertising mode and here i disable the radio notification. But it looks like the notification is not disabled since I see the current consumption is high. Is there something that I shud keep in mind regarding enabling and disabling radio notifications. The reason I know high current consumption is caused by radio notification is that this happens only when transitioning from connection->advertisement mode. whereas if the device starts in advertisement mode straight away then current consumption is in right ball park. Please see the code below on how I enable and disable notification. I am using s110 softdevice. Any help is appreciated. Thanks in advance.

 void radio_enable_notif(uint32_t type, uint32_t distance){
  uint32_t err_code;

  err_code = sd_nvic_ClearPendingIRQ(SWI1_IRQn);
  APP_ERROR_CHECK(err_code);

  err_code = sd_nvic_SetPriority(SWI1_IRQn, APP_IRQ_PRIORITY_LOW);
  APP_ERROR_CHECK(err_code);

  err_code = sd_nvic_EnableIRQ(SWI1_IRQn);
  APP_ERROR_CHECK(err_code);

  err_code = sd_radio_notification_cfg_set(type, distance);
  APP_ERROR_CHECK(err_code);
}

void radio_disable_notif(void){
  uint32_t err_code = sd_radio_notification_cfg_set(
      NRF_RADIO_NOTIFICATION_TYPE_NONE, NRF_RADIO_NOTIFICATION_DISTANCE_NONE);
  APP_ERROR_CHECK(err_code);

  err_code = sd_nvic_DisableIRQ(SWI1_IRQn);
  APP_ERROR_CHECK(err_code);
}

Update 1: I used timeslot APIs from here to disable/enable radio notifications only when Softdevice is idle. This worked for S110 softdevice. But would not work for S130 which is used in our master devices.

Update 2: I have attached an example Radio_notification_Example.zip to reproduce the bug I have been talking about. The example builds for PCA10028 boards. The example compiles with all necessary files including softdevice. On development kit I could reproduce the bug for the s110 softdevice(used by slave) and not on s130(used by master). After running slave_example we can notice advertisement consuming low current on bootup, but after it connects and goes back to advertisement the current consumption is high. Please feel free to ask if any questions. The example I have provided is a bare minimum version of what we are trying to do on our custom boards. PS: In my set up i use GCC 5.3.1. I'm using Linux machine. Example usage -

make GCC_INSTALL_ROOT=/usr/local/gcc-arm-none-eabi-5_3-2016q1 GCC_VERSION=5.3.1 JLINK_DIR=/opt/SEGGER/JLink SLNO=682844601 clean all upload

Update 3: radio_notif.c attached as mentioned in the comment to the answer.

  • There are several methods in that tutorial, which one are you using and what equipment?

  • Øyvind, We are using Ampere meter method for measurement. That is sufficient for us to observe the problem. In order to observe with more accuracy one can increase advertising interval or decrease scan window. In the slave example(where the bug is) we can easily see the current falling to uA range even with simple multimeter on bootup. But after a connection-disconnection sequence it does not.

  • Hi,

    Firstly NRF_RADIO_SIGNAL_CALLBACK_ACTION_END ends the ongoing timeslot, but not the timeslot session (timeslot events occur in the context of a timeslot session, please refer to the SoftDevice Specification), this means that you will not get an NRF_EVT_SESSION_CLOSED. If you at some point call sd_radio_session_close() you must call sd_radio_session_open(handler) again to be able to open a timeslot event.

    I am not able to reproduce your issue, I have modified a version of the ble_app_template example to use radio notification and timeslots. Please refer to my code below. In order to see correct current draw I made sure to sleep by calling

    __SEV();
    __WFE();
    __WFE();
    

    Instead of sd_app_evt_wait();. Please see this thread. I measured the current using a N6705B DC Power Analyzer.

    I set a flag using GPIO to enable/disable radio notifications on the next timeslot, which I also trigger by GPIO. I've also made some simplifications to the example given in the answer above

    int main(void)
    {
        uint32_t err_code;
        bool erase_bonds;
    
        // Initialize.
        timers_init();
        buttons_leds_init(&erase_bonds);
        ble_stack_init();
        device_manager_init(erase_bonds);
        gap_params_init();
        advertising_init();
        services_init();
        conn_params_init();
        
        enable_radio_notification = false; // Set Radio Notification enable flag to false
        err_code = sd_radio_notification_cfg_set(NRF_RADIO_NOTIFICATION_TYPE_INT_ON_ACTIVE, NRF_RADIO_NOTIFICATION_DISTANCE_800US);   //Configure only once
        APP_ERROR_CHECK(err_code);
            
        application_timers_start();
        
        err_code = ble_advertising_start(BLE_ADV_MODE_FAST); // Start execution.
        APP_ERROR_CHECK(err_code);
        
        err_code = sd_radio_session_open(timeslot_callback); // Create timeslot session
        APP_ERROR_CHECK(err_code);
        
        // Enter main loop.
        for (;;)
        {
            __SEV();
            __WFE();
            __WFE();
        }
    }
    
    
    nrf_radio_signal_callback_return_param_t * timeslot_callback(uint8_t signal_type)
    {
        static nrf_radio_signal_callback_return_param_t signal_callback_return_param;
    
        switch(signal_type)
        {
          case NRF_RADIO_CALLBACK_SIGNAL_TYPE_START:
             signal_callback_return_param.params.request.p_next = NULL;           // End timeslot
             signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_END;
    
                
             nrf_gpio_pin_toggle(20); // For signal analyzer verification
            
             if(enable_radio_notification)                                                                                                               //Boolean flag to enable/disable radio notification
             {
                 NVIC_ClearPendingIRQ(SWI1_IRQn);
                 NVIC_EnableIRQ(SWI1_IRQn);
             } 
             else 
             {
                 NVIC_ClearPendingIRQ(SWI1_IRQn);
                 NVIC_DisableIRQ(SWI1_IRQn);
             }
                
             nrf_gpio_pin_toggle(20);
             break;
    
           default:
             break;
        }    
        return (&signal_callback_return_param);
    }
    

    Please find attached in the main answer a folder containing images of the different current test cases. Note that the 800µA draw is due to the application not being power optimized, HFCLK is running, etc.

  • This was with S132 using SDK 11, what version of SD110, SD130 and SDK are you using? The current draw is due to the chip not being able to sleep, likely due to a pending interrupt.

Related