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

GPIOTE won't sleep after first button press drawing too much current

I tested the code below to make the board go to sleep and wake up on each button press. When I start, it draws 30ua, but when I press the button it shoots up to 200ua (a clear sign that it is awake) and it stays on. It does not seem to sleep drawing current even though I am asking it on the code.

I have tried this with ALL last 5 SDks and the results are exactly the same. I am using DK PCA10056 1.1.0 2019.19 683309915. I tried 2 different boards with the same results. I am using the power profiler software and board to measure current (jumper off, set to DK, etc). My current profiler board is PCA63511 1.1.0 4EB01DE5. I am using the button on the board.

See pictures below. How can I make the chip sleep after first button press so less current is drawn?

#include <stdbool.h>
#include "nrf.h"
#include "nrf_drv_gpiote.h"
#include "app_error.h"
#include "boards.h"
#include "nrf_delay.h"

#ifdef BSP_BUTTON_0
    #define PIN_IN BSP_BUTTON_0
#endif
#ifndef PIN_IN
    #error "Please indicate input pin"
#endif

#ifdef BSP_LED_0
    #define PIN_OUT BSP_LED_0
#endif
#ifndef PIN_OUT
    #error "Please indicate output pin"
#endif

int buttonPressed = 0;
int buttonReleased = 0;

void in_pin_handlerlow(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
     
		ret_code_t err_code;
	
		if(pin == PIN_IN)
		{
                                if(buttonPressed==0) {
                                  buttonPressed = 1;
                                  buttonReleased = 0;
                                } else {
                                  if(buttonReleased == 0) {
                                      buttonReleased = 1;
                                      buttonPressed = 0;
                                  }
                                }
                              

				//Turn off LED to indicate the nRF5x is in System-off mode
				nrf_drv_gpiote_out_toggle(PIN_OUT);
			
				NRF_POWER->SYSTEMOFF = 1;
                           

		}

}
/**
 * @brief Function for configuring: PIN_IN pin for input, PIN_OUT pin for output,
 * and configures GPIOTE to give an interrupt on pin change.
 */
static void gpio_init(void)
{
    ret_code_t err_code;

    err_code = nrf_drv_gpiote_init();
    APP_ERROR_CHECK(err_code);

    nrf_drv_gpiote_out_config_t out_config = GPIOTE_CONFIG_OUT_SIMPLE(false);

    err_code = nrf_drv_gpiote_out_init(PIN_OUT, &out_config);
    APP_ERROR_CHECK(err_code);

    nrf_drv_gpiote_out_clear(PIN_OUT);

    nrf_drv_gpiote_in_config_t in_configlow = NRFX_GPIOTE_CONFIG_IN_SENSE_TOGGLE(false);
    in_configlow.pull = NRF_GPIO_PIN_PULLUP;

    err_code = nrf_drv_gpiote_in_init(PIN_IN, &in_configlow, in_pin_handlerlow);
    APP_ERROR_CHECK(err_code);

    nrf_drv_gpiote_in_event_enable(PIN_IN, true);

}

/**
 * @brief Function for application main entry.
 */
int main(void)
{
    gpio_init();

    while (true)
    {
        // Do nothing.
        __WFE();
        __SEV();
        __WFE();
    }
}

See below for output from Power profiler before and after button press

Parents
  • The NRF_POWER->SYSTEMOFF = 1; seems a bit odd, since it will go to system OFF, which means the chip will reset on wakeup. I would have placed some 10ms delay and led toggling in beginning of main() just to make sure you have control over what state it is in. This should also make it easier to measure in your power profiler.

    That said, make sure you have full control over the logic level on your input pin, since a floating input pin may draw anything from 30-200uA (or more), in other word connect it to GND or VDD though a pull-resistor or similiar, not leve it unconnected.

    Also, 30uA is also too high if you are only doing _WFE() and some GPIO's, is it possible that you are sourcing any current through the output pin (e.g. driving any LED or similar).

  • I removed the NRF_POWER->SYSTEMOFF = 1; and added the 10ms delay. In addition, I am using the buttons of the DK board which in my understanding have a pull up resistor which I am activating with the in_configlow.pull = NRF_GPIO_PIN_PULLUP; line. Would this cause it to NOT be floating?

    Having done all of this, I STILL get 200ua+ on the first button press. This happens with 2 DKs. I can't possibly imagine that I have 2 defective DK boards? 

    What else can I do? Nothing seems to bring this down.

  • - _WFE only: 6.6ua

    add input pin sense, see that it wakeup and measure current - wakes up. 7ua. When button clicked 200ua

    - add pin handler callback, see that it wakeup and measure current - 7ua. When button clicked 200ua

    - add output pins, see that it wakeup and measure current - 25ua. When button clicked 200ua

    No matter what I do, as soon as I press the button it spikes up to 200ua. Something is very wrong. What do you get if you run this code?

  • is it possible that I have a faulty power profiler? Can someone tell me what do you get when you run this code in the DK?

  • I was thinking that 200uA could be close to the current through a pull-up resistor that is pulled low: U = R * I = ~13kohm * ~200uA = ~2.6V (which I expect is close to VDD on the board?).

  • if you are right, does that mean that by pulling a pin low I cannot physically simply create a button with a battery that lasts 2 years? If I can have a current pull of 30ua or less I can. So creating a button operated by battery with less than 200ua is impossible? Unless I reduce the input voltage? If I reduce the input voltage to 1.7v then I = U / R = I = 1.7 * 13 = 100ua. So impossible to have a simple button that consumes less than 100ua?

  • You have enabled internal pull up (in_configlow.pull = NRF_GPIO_PIN_PULLUP;), if you expect customers will be pushing this button for a long period of time, I instead suggest use an external pull-up of 1Mohm instead.

Reply Children
Related