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

Slow Wake-Up and Timer Start from Power Off

Hello,

I am trying to set the nRF52 to power off and wake up on a momentary button push (scope measures momentary push logic low around 50ms-100ms). However, I am struggling to have my debounce timer start up fast enough to detect the button being still pressed. If I hold the button down for a longer press, 200ms+, then I am able to read the button pin as registering a press in my debounce timer. The nRF52 tOFF2ON is stated as 16.5us, so I am thinking the timer is not starting fast enough or the button pin is not setup quick enough? Any direction would be very helpful!

First I set up my button input and debounce timer:

int
main (void)
{
  uint32_t err_code;
  uint32_t time_ticks;
  uint32_t time_ms = 1; //Time(in miliseconds) between consecutive compare

  //Initialize.
  err_code = NRF_LOG_INIT(NULL);
  APP_ERROR_CHECK(err_code);

  /*********** Manual Input Config ******************/
  err_code = nrf_drv_gpiote_init ();
  APP_ERROR_CHECK(err_code);
  //nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(true);
nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(false);
  in_config.pull = NRF_GPIO_PIN_PULLUP;
  err_code = nrf_drv_gpiote_in_init (BUTTON_1, &in_config, in_pin_handler);
  APP_ERROR_CHECK(err_code);
  nrf_drv_gpiote_in_event_enable (BUTTON_1, true);

  // Check initial button state
  if (button1_is_pressed())
    {
      btnpressed = 1;
    }

  /*********************************************/

  /*********** Timer Config ******************/
  nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
  err_code = nrf_drv_timer_init (&TIMER_LED, &timer_cfg,
				 timer_callback_handler);
  APP_ERROR_CHECK(err_code);
  time_ticks = nrf_drv_timer_ms_to_ticks (&TIMER_LED, time_ms);
  nrf_drv_timer_extended_compare (&TIMER_LED, NRF_TIMER_CC_CHANNEL0, time_ticks,
				  NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);
  nrf_drv_timer_enable (&TIMER_LED);
  /*****************************/

Here is my code to setup power off:

void
sleep_mode_enter (void)
{

  //uint32_t err_code;

  nrf_drv_gpiote_out_set (LED_1);

  //err_code = bsp_wakeup_button_enable(0);

  //err_code = nrf_gpio_cfg_sense_set( BUTTON_1, BUTTONS_ACTIVE_STATE ? NRF_GPIO_PIN_SENSE_HIGH :NRF_GPIO_PIN_SENSE_LOW );
  nrf_gpio_cfg_sense_set ( BUTTON_1, NRF_GPIO_PIN_SENSE_LOW);

  // Go to system-off mode (this function will not return; wakeup will cause a reset).
  nrf_drv_timer_compare_int_disable(&TIMER_LED,NRF_TIMER_CC_CHANNEL0);
  nrf_drv_timer_disable (&TIMER_LED);
  sd_power_system_off ();
//  err_code = sd_power_system_off ();
//  APP_ERROR_CHECK(err_code);
  while (1)
    ;
}

Here is my button debounce timer handler, after a short momentary push from wake-up, the system is seeing "state" as false, if I hold the button down for a long press it measures true.

void timer_callback_handler (nrf_timer_event_t event_type, void* p_context)
{
  static uint32_t button_debounce = 0;

  bool state;
  switch (event_type)
    {
    case NRF_TIMER_EVENT_COMPARE0:
      total_ticks++;
      state = button1_is_pressed();
      if (state && btnpressed) // Still held down
	{
  • Have you considered using a circuit to debounce the button e.g. 2 resistors and one capacitor

  • The real start up time is not 16.5us. The real start up time will also include start up of resources like flash, clocks and regulators. However it should take much less than 50 ms to from the wake-up signal to you read the button in the code.

    Why are you setting up the button as gpiote IN before you read the state of the button (using button1_is_pressed(). I assume this reads BUTTON_1 pin)? Do you have a pull-up on the button such that it doesn't float when it is not pressed? For momentary press is btnpressed ever set to '1'?

  • Roger - That is certainly possible, though many of our designs are space constrained so every hardware placement matters. Also, it just seems to be good coding practice to see a button pressed over some period of time - perhaps it is overly cautious.

    Ole - I am using the internal pull-up. I have the edge interrupt setup to activate on any edge which sets the flag "btnpressed".

    Here is my GPIO event handler:

    void
    in_pin_handler (nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
    {
    
      if (button1_is_pressed())
        {
          btnpressed = 1;
        }
      else
        {
          btnreleased = 1;
        }
    
    }
    
  • @LukeC

    What code is in your button1_is_pressed() ?

    Also. Why do you want to read the button ?

    Does the button serve more than one function, and is not just used to wake the board up ?

    Does something special happen if the system is started by this button being pressed ?

    If so, I suspect there is another solution to the problem using flags retained in RAM (albeit a small cost in the current use in power off mode)

  • Here is the code:

    #define BUTTON_1       13
    
    #define button1_is_pressed() !nrf_drv_gpiote_in_is_set(BUTTON_1)
    

    The basic functionality is part has one physical button, one press it wakes up and blasts out an advertising packet and goes back to power off. It can also do a long press which changes the advertising data, this is working perfectly. It is only the short presses that it is missing.

    It still seems like a very slow wake up time. Perhaps I need to go through and scour the data sheets to see total time it takes to get the internal oscillator and everything setup.

    I am sure if a just put a cap on it this will keep me from spurious presses, but it sure seem like I should be able to wake up quick enough to see this.

Related