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

Using same pin for sleep and wake up

I am using SDK 15.2 with Segger Studio 4.10

I am trying to use the same button for sleep mode and wake up. I am doing a long press for sleep and sense wake up.

I am able to put it into sleep mode, but as soon as I let go it wakes up, is there something I can do to delay it, or lacth it for when it goes to sleep?

Here is the snippet for what I am doing.

void button_timerout_handler(void * p_context) {
  uint32_t err_code;
  static uint32_t cnt;

  if(app_button_is_pushed(0)) {
    cnt++;
    if(cnt >= LONG_PRESS(LONG_PRESS_WAIT)) {
      cnt = 0;
      NRF_LOG_INFO("Long Press");
      
      // prepare wake up button
      nrf_gpio_cfg_sense_input(BUTTON_PIN_4, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);

      // Go to system-off mode (this function will not return; wakeup will cause a reset).
      err_code = sd_power_system_off();
      APP_ERROR_CHECK(err_code);

    }
    else {
      err_code = app_timer_start(m_button_action, 
                                 APP_TIMER_TICKS(BUTTON_STATE_POLL_INTERVAL_MS),
                                 NULL);
      APP_ERROR_CHECK(err_code);
    }
  }
  else {
    cnt = 0;
    NRF_LOG_INFO("Short Press");
  }
}

static void button_event_handler(uint8_t pin_no, uint8_t action) {
  uint32_t err_code;
  if((pin_no == BUTTON_PIN_4) && (action == APP_BUTTON_PUSH)) {
    err_code = app_timer_start(m_button_action,
                             APP_TIMER_TICKS(BUTTON_STATE_POLL_INTERVAL_MS),
                             NULL);
    APP_ERROR_CHECK(err_code);
    NRF_LOG_INFO("Button Pressed!");
  }

}

static const app_button_cfg_t buttons[NUM_BUTTONS] = {
  {BUTTON_PIN_4, APP_BUTTON_ACTIVE_HIGH, NRF_GPIO_PIN_PULLUP, button_event_handler},
};

static void button_init(void){
  uint32_t err_code;

  err_code = app_button_init((app_button_cfg_t *)buttons, NUM_BUTTONS, BUTTON_DELAY);

  APP_ERROR_CHECK(err_code);

  err_code = app_button_enable();

  APP_ERROR_CHECK(err_code);

  // Enable timer for long button press detect
  err_code =  app_timer_create(&m_button_action, APP_TIMER_MODE_SINGLE_SHOT, button_timerout_handler);
  
  APP_ERROR_CHECK(err_code);
}

Thank you for the help.

  • Instead of immediately going to system off, start another timer for 250 ms and put your sleep code in the timeout handler for that timer. That's just to wait for the button to stop bouncing - when it stops (should have definitely stopped after 250 ms), you can enable input sensing and go to system off mode safely.

    void debounce_timeout_handler(void * p_context) {
        // Prepare wake up button
        nrf_gpio_cfg_sense_input(BUTTON_PIN_4, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
        
        // Go to system-off mode (this function will not return; wakeup will cause a reset).
        err_code = sd_power_system_off();
        APP_ERROR_CHECK(err_code);
    }

  • Thank you very much Andy, this is a very nice way to do it. I ended up doing a flag for a LONG PRESS and then checked the action APP_BUTTON_RELEASE and the flag to be true.

    like so,

    /*######################### SLEEP AND WAKE UP ####################################*/
    bool isLongPress = false;
    
    void button_timeout_handler(void * p_context) {
      uint32_t err_code;
      // Counter to detect long press
      static uint32_t cnt;
    
      if(app_button_is_pushed(SLEEP_WAKE_ID)) {
        cnt++;
        if(cnt >= LONG_PRESS(LONG_PRESS_TIME)) {
          cnt = 0;
          NRF_LOG_INFO("Long Press!");
          isLongPress = true;
        }
        else {
          err_code = app_timer_start(m_button_action, APP_TIMER_TICKS(BUTTON_STATE_POLL_INTERVAL_MS), NULL);
          APP_ERROR_CHECK(err_code);
        }
      }
      else {
        cnt = 0;
        NRF_LOG_INFO("Short Press!");
        isLongPress = false;
      }
    }
    
    static void button_event_handler(uint8_t pin_no, uint8_t action) {
      uint32_t err_code;
      if(action == APP_BUTTON_PUSH) {
        switch(pin_no) {
          case BUTTON_WAKE_SLEEP:
            NRF_LOG_INFO("Button Pressed!");
    
            err_code = app_timer_start(m_button_action, BUTTON_STATE_POLL_INTERVAL_MS, NULL);
            APP_ERROR_CHECK(err_code);
            break;
        }
      }
      else if ((action == APP_BUTTON_RELEASE) && isLongPress) {
        switch(pin_no) {
          case BUTTON_WAKE_SLEEP:
          NRF_LOG_INFO("Button Released!");
    
          
          // Prepare wake up button
          nrf_gpio_cfg_sense_input(BUTTON_WAKE_SLEEP, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
    
          // Go to system-off mode (this function will not return; wakeup will cause a reset).
          err_code = sd_power_system_off();
          APP_ERROR_CHECK(err_code);
        }
      }
    }
    
    static const app_button_cfg_t buttons[NUM_BUTTONS] = {
      {BUTTON_WAKE_SLEEP, APP_BUTTON_ACTIVE_HIGH, NRF_GPIO_PIN_PULLUP, button_event_handler},
    };
    
    static void button_init(void){
      uint32_t err_code;
    
      err_code = app_button_init((app_button_cfg_t *)buttons, NUM_BUTTONS, BUTTON_DELAY);
    
      APP_ERROR_CHECK(err_code);
    
      err_code = app_button_enable();
    
      APP_ERROR_CHECK(err_code);
    
      // Enable timer for long button press detect
      err_code =  app_timer_create(&m_button_action, APP_TIMER_MODE_SINGLE_SHOT, button_timeout_handler);
      
      APP_ERROR_CHECK(err_code);
    }

    Thanks again for your help.

Related