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

Lower power in sleep of GPIO as outputs?

Hi Nordic,

In my application, I want to consume as less power as I can. In the initialization I have this functions:

static void utils_setup(void)
{
    APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, false);
}

static void softdevice_setup(void)
{
    uint32_t err_code;

    err_code = softdevice_ant_evt_handler_set(ant_evt_dispatch);
    APP_ERROR_CHECK(err_code);
    //angel start
    err_code = softdevice_sys_evt_handler_set(sys_evt_dispatch); // start the interrupt sys controller
    APP_ERROR_CHECK(err_code);
    //angel end

    err_code = softdevice_handler_init(NRF_CLOCK_LFCLKSRC, NULL, 0, NULL);
    APP_ERROR_CHECK(err_code);

    err_code = ant_stack_static_config();
    APP_ERROR_CHECK(err_code);
}

void configure_pins_input()
{
    ret_code_t err_code;

    err_code = nrf_drv_gpiote_init();
    APP_ERROR_CHECK(err_code);
    nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(true);


    in_config.pull = NRF_GPIO_PIN_NOPULL;


    // down_pin
    err_code = nrf_drv_gpiote_in_init(buttons.up.input_pin, &in_config, in_up_pin_handler);
    APP_ERROR_CHECK(err_code);
    nrf_drv_gpiote_in_event_enable(buttons.up.input_pin, true);

    // down pin
    err_code = nrf_drv_gpiote_in_init(buttons.down.input_pin, &in_config, in_down_pin_handler);
    APP_ERROR_CHECK(err_code);
    nrf_drv_gpiote_in_event_enable(buttons.down.input_pin, true);

    // left_pin
    err_code = nrf_drv_gpiote_in_init(buttons.left.input_pin, &in_config, in_left_pin_handler);
    APP_ERROR_CHECK(err_code);
    nrf_drv_gpiote_in_event_enable(buttons.left.input_pin, true);

    // left_pin
    err_code = nrf_drv_gpiote_in_init(buttons.right.input_pin, &in_config, in_right_pin_handler);
    APP_ERROR_CHECK(err_code);
    nrf_drv_gpiote_in_event_enable(buttons.right.input_pin, true);
}

void configure_pins_output(void)
{
    nrf_gpio_cfg_output(LED_UP);
    nrf_gpio_cfg_output(LED_LEFT);
    nrf_gpio_cfg_output(LED_RIGHT);
    nrf_gpio_cfg_output(LED_DOWN);

    nrf_gpio_pin_set(LED_UP);
    nrf_gpio_pin_set(LED_LEFT);
    nrf_gpio_pin_set(LED_RIGHT);
    nrf_gpio_pin_set(LED_DOWN);
}

static void timer2_init()
{
    NVIC_EnableIRQ(TIMER2_IRQn);
    NVIC_SetPriority(TIMER2_IRQn, NRF_APP_PRIORITY_LOW);
    NRF_TIMER2->TASKS_STOP = 1;
    NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer;
    NRF_TIMER2->PRESCALER = 4;  // Fhck / 2^4
    const uint32_t PRESCALER_VALUE = 100;
    NRF_TIMER2->CC[0] = PRESCALER_VALUE & 0xFFFF;  // 10000 - 10ms
    NRF_TIMER2->BITMODE = (TIMER_BITMODE_BITMODE_16Bit << TIMER_BITMODE_BITMODE_Pos);

    NRF_TIMER2->TASKS_CLEAR = 1;
    NRF_TIMER2->INTENSET = (TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos);

    NRF_TIMER2->EVENTS_COMPARE[0] = 0;
    // start timer
    NRF_TIMER2->TASKS_START = 1;
}

After this, I open a channel, start doing things and after a while, go to sleep. To go to sleep, what I do is: I close the channel I just opened, I turn OFF the timer and I turn OFF the LEDs. Still the power consumption is around 1 mA, which is totally too much. I think that the main problem comes from the fact that the pins are set as output, and they are letting some current go out. Do you know in which set up I should put the pins before going to sleep?

Thanks!

PS: nRF51422, ANT, S210 v5.0.0

  • Hi,

    You should configure the GPIO's as input and disconnect the input buffer before going to sleep, this way the pins will be floating and no current will go through them.

  • Hi Stian,

    This is what I have been testing and I still get current consumption of 1 mA

    void do_to_sleeping(instance_data_t* data)
    {
        timer2_stop();
        close_channel(&channel_0);
        nrf_gpio_cfg_default(LED_UP);
        nrf_gpio_cfg_default(LED_DOWN);
        nrf_gpio_cfg_default(LED_LEFT);
        nrf_gpio_cfg_default(LED_RIGHT);
    
        nrf_gpio_pin_clear(LED_UP);
        nrf_gpio_pin_clear(LED_DOWN);
        nrf_gpio_pin_clear(LED_LEFT);
        nrf_gpio_pin_clear(LED_RIGHT);
    }
    

    This nrf_gpio_cfg_default() function is supposed to do what you told me, but I still get high power consumption.

    Should I set as input and disconnect in another way?

    Thanks!

  • I have tried this:

    nrf_gpio_cfg_input(LED_UP, NRF_GPIO_PIN_NOPULL);
    nrf_gpio_cfg_input(LED_DOWN, NRF_GPIO_PIN_NOPULL);
    nrf_gpio_cfg_input(LED_LEFT, NRF_GPIO_PIN_NOPULL);
    nrf_gpio_cfg_input(LED_RIGHT, NRF_GPIO_PIN_NOPULL);
    
    nrf_gpio_input_disconnect(LED_UP);
    nrf_gpio_input_disconnect(LED_DOWN);
    nrf_gpio_input_disconnect(LED_LEFT);
    nrf_gpio_input_disconnect(LED_RIGHT);
    

    Didnt make any difference...

    I also have changed the function timer stop from:

    void timer2_stop()
    {
        NRF_TIMER2->TASKS_STOP = 1;
    }
    

    to:

    void timer2_stop()
    {
        NRF_TIMER2->TASKS_SHUTDOWN = 1;
        NRF_TIMER2->TASKS_STOP = 1;
    }
    

    but it made no difference :(

  • I found out the problem: I was configuring the input pins as high accuracy (which I certainly do not need). I fixed it changing this line:

    nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(true);
    

    to

    nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(false);
    
Related