This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

regarding Sleep Mode of nRF51

Hi. I'm using PCA10028, SDK10.0.0 S130.

I want to make nRF51 goes sleep mode. So I tested linked source code as below. github.com/.../main.c

It works well. But after I add this code in "ble_app_hrs_c" as below, it doesn't work.

int main(void) {

bool erase_bonds;

// Initialize.
APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, NULL);
buttons_leds_init(&erase_bonds);
uart_init();
printf("Heart rate collector example\r\n");
ble_stack_init();
device_manager_init(erase_bonds);
db_discovery_init();
hrs_c_init();
bas_c_init();

// Start scanning for peripherals and initiate connection
// with devices that advertise Heart Rate UUID.
scan_start();


// Configure BUTTON1 as a regular input 
  nrf_gpio_cfg_input(BUTTON_1, NRF_GPIO_PIN_NOPULL); 
   
  // Configure BUTTON2 with SENSE enabled  
  nrf_gpio_cfg_sense_input(BUTTON_2, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_LOW); 
   
  // Configure the LED pins as outputs 
  nrf_gpio_range_cfg_output(LED_START, LED_STOP); 
   
  nrf_gpio_pin_set(LED_1); 
   
  // If desired, change the RAM retention parameters: 
  NRF_POWER->RAMON = POWER_RAMON_ONRAM0_RAM0On	 << POWER_RAMON_ONRAM0_Pos 
				   | POWER_RAMON_ONRAM1_RAM1On	 << POWER_RAMON_ONRAM1_Pos 
				   | POWER_RAMON_OFFRAM0_RAM0Off << POWER_RAMON_OFFRAM0_Pos 
				   | POWER_RAMON_OFFRAM1_RAM1Off << POWER_RAMON_OFFRAM1_Pos; 
   
  while(1) 
  { 	 
	  // If BUTTON1 is pressed.. 
	  if(nrf_gpio_pin_read(BUTTON_1) == 0) 
	  { 
		  // Clear LED1
		  nrf_gpio_pin_clear(LED_1); 


		  // Enter system OFF. After wakeup the chip will be reset, and the MCU will run from the top  
		  NRF_POWER->SYSTEMOFF = 1; 
	  } 
  } 

Q1. It doesn't go to "nrf_gpio_pin_read(BUTTON_1) == 0", although i press the button.

Q2. If I want to use Only advertising or scanning, I can make other blocks go to sleep mode. Could you give me the way of that? Like example code or advice?

I hope your reply.

  • FormerMember
    0 FormerMember

    Q1) When the BSP library is included in the project, I would recommend you to not use the buttons used by that library, button 1 and 2. BSP is by default included in the projects in the SDK. As you can see in the BSP documentation, button 1 will put the chip to sleep. If you change the button that triggers the system OFF mode to button 3 or 4 you will see that it works.

    When using the softdevice, and want to put the chip to system OFF, you should use the function sd_power_system_off(..).

    The same would be for the RAM on/off register; use sd_power_ramon_set(..)/get(..)/clr(..).

    As you may know, the LEDs are "inverted" on the nRF51-DK. It means that nrf_gpio_pin_clear(LED) will turn the LED on.

    Q2) sd_power_system_off(..)/ NRF_POWER->SYSTEMOFF = 1 will put the chip to system OFF. When the chip wakes up, the chip will be reset, see the nRF51 Series Reference Manual, chapter 12.1.5.

    If you want the chip to sleep between the advertising/scanning events, you should use sd_app_evt_wait(..). All SDK examples do this using power_manage().

    For your reference, I have attached a modified version of your code that sets the chip in system OFF when pushing button 3:

    int main(void)
    {
        bool erase_bonds;
    		uint32_t err_code;
    
        // Initialize.
        APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, NULL);
        buttons_leds_init(&erase_bonds);
        nrf_log_init();
        APPL_LOG("Heart rate collector example\r\n");
        ble_stack_init();
        device_manager_init(erase_bonds);
        db_discovery_init();
        hrs_c_init();
        bas_c_init();
    	
    		// Configure BUTTON1 as a regular input 
        nrf_gpio_cfg_input(BUTTON_3, NRF_GPIO_PIN_PULLUP); 
      
        // Configure BUTTON2 with SENSE enabled  
        nrf_gpio_cfg_sense_input(BUTTON_4, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_LOW); 
      
        // Configure the LED pins as outputs 
        nrf_gpio_range_cfg_output(LED_START, LED_STOP); 
    
        scan_start();
     		
    		nrf_gpio_pin_clear(LED_3); // todo
    		nrf_gpio_pin_set(LED_4);
    		
        for (;; )
        {
    			// If BUTTON1 is pressed.. 
          if(nrf_gpio_pin_read(BUTTON_3) == 0) 
          { 
              // Clear LED1
              nrf_gpio_pin_toggle(LED_4); 
              // Enter system OFF. After wakeup the chip will be reset, and the MCU will run from the top 
    					err_code = sd_power_system_off();
    					APP_ERROR_CHECK(err_code);
              //NRF_POWER->SYSTEMOFF = 1; 
          } 
        }
    }
    
  • Thank you for your help.

    Q1. It's very helpful. Let me try.

    Q2. I still have problem. My goal is that it should be advertising in low power mode. That's why I'm developing BLE. As I've tested "ble_app_hrs" as peripheral. Its current cunsumption is too high. As I think, that's because "ble_app_hrs" advertising speed is very fast. So I changed source code as below. But its current consumption is still 1mA around. I think there is the other good way to save current consumption even it's advertising. Could you give me more advice? If i have to use slow advertising mode, that's no problem. I need your help.

    #define APP_ADV_INTERVAL 100000

    static void advertising_init(void) {

    uint32_t      err_code;
    ble_advdata_t advdata;
    
    // Build advertising data struct to pass into @ref ble_advertising_init.
    memset(&advdata, 0, sizeof(advdata));
    
    advdata.name_type               = BLE_ADVDATA_FULL_NAME;
    advdata.include_appearance      = true;
    advdata.flags                   = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
    advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
    advdata.uuids_complete.p_uuids  = m_adv_uuids;
    
    ble_adv_modes_config_t options = {0};
    

    #if 0 // fast mode options.ble_adv_fast_enabled = BLE_ADV_FAST_ENABLED; options.ble_adv_fast_interval = APP_ADV_INTERVAL; options.ble_adv_fast_timeout = APP_ADV_TIMEOUT_IN_SECONDS; #else // slow mode options.ble_adv_slow_enabled = BLE_ADV_SLOW_ENABLED; options.ble_adv_slow_interval = APP_ADV_INTERVAL; options.ble_adv_slow_timeout = APP_ADV_TIMEOUT_IN_SECONDS; #endif

    err_code = ble_advertising_init(&advdata, NULL, &options, on_adv_evt, NULL);
    APP_ERROR_CHECK(err_code);
    

    }

    int main(void) {

    ......

    err_code = ble_advertising_start(BLE_ADV_MODE_SLOW);
    APP_ERROR_CHECK(err_code);
    
    // Enter main loop.
    for (;;)
    {
        power_manage();
    }
    

    }

  • Please refer to my new Answer as below.

  • FormerMember
    0 FormerMember in reply to roger.k

    ble_app_hrs in the SDK has not been power optimized. There is one power optimized example in the SDK, ble_app_pwr_profiling, I would recommend you to take a look at that.

    A power consumption of approximately 1 mA could be a result of the chip being in debug mode, the chip can exit debug mode using one of the following methods:

    1. Power reset
    2. Pin reset using nrfjprog from the command line: nrfjprog --pinreset
  • Thanks a lot. It's very helpful.

Related