Button config for wake up from deep sleep (not waking up 'sometimes')

Hello,

So, I have a working BLE project on the nRF52840 Dongle and I developed and debugged everything on the DevKit, using Zephyr/nRF Connect for VS Code. From there, I attempted to set up a separate thread that times-out after x seconds of advertising (if no connection is established) and turns off the device, as in the "system_off" sample:

pm_power_state_force((struct pm_state_info){PM_STATE_SOFT_OFF, 0, 0});

I also configured one of the DevKit's buttons to wake up / turn on the device (as in the "system_off" sample):

#include <hal/nrf_gpio.h>

/* Configure to generate PORT event (wakeup) on button 1 press. */
nrf_gpio_cfg_input(DT_GPIO_PIN(DT_NODELABEL(button0), gpios),
		   NRF_GPIO_PIN_PULLUP);
nrf_gpio_cfg_sense_set(DT_GPIO_PIN(DT_NODELABEL(button0), gpios),
		   NRF_GPIO_PIN_SENSE_LOW);

When I flashed and tested the functionality on the DevKit it worked perfectly fine, however, when I flashed and tried on the Dongle, pressing the button would not wake up the device. I figured out it might have to do with the library used for some reason, hal/nrf_gpio library does not seem to work on the Dongle ?? I managed to solve the problem configuring the button with the following code (regular drivers/gpio library):

#include <drivers/gpio.h>

#define WAKEUP_BTN_ALIAS sw0
#define SW_NODE DT_ALIAS(WAKEUP_BTN_ALIAS)

static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET_OR(SW_NODE, gpios, {0});

// Configure to generate PORT event (wakeup) on button press.
gpio_pin_configure_dt(&button, GPIO_INPUT);
gpio_pin_interrupt_configure_dt(&button, GPIO_INT_LOW_0);

This way it does work on both the DevKit AND the Dongle, however, I realized after a couple of days that the button was not waking up the device. I thought the battery was dead or that maybe I had a faulty connection. I troubleshooted without any success, only after disconnecting and reconnecting the battery, the device then turns on normally, and after timing-out (turning off), and pressing the button, the device wakes up normally.

I have now been using the device / testing my project for the past 2 weeks and have encountered this issue at least 6 times already (on Dongle), for no apparent reason, the press of the button will not wake up the device, and I'd have to open my project enclosure, disconnect and reconnect the battery to start using it again. This problem also happened twice on the DevKit.

I really have no idea how to troubleshoot this, since the device is in deep sleep mode if I understand correctly, although the GPIO module stays on... The only reason I can think of is that maybe I am missing some power management or gpio configuration. The weird thing is that 99% of the time, time-out/turn-off and wake-up button work fine. I did add these lines on the prj.conf file.

CONFIG_GPIO=y
# Power Management Config
CONFIG_PM=y
CONFIG_PM_DEVICE=y

I would really like to try configuring the button using the hal/nrf_gpio library and using the cfg_sense_set() function, but, as mentioned, the same code properly compiles and works on the DevKit, I am able to also flash it on the Dongle but the button does not work. Am I missing something Dongle-specific in order to be able to use the system_off sample on it?

Thank you in advance.

Kind regards,

Alex Fernandez.

  • Hi Alex,

    This seems strange. The GPIO sense mechanism is quite simple, and as long as you enable it and enter system off it should just work. Could it be a mechanical/electrical problem, so you don't always get the expected pulse on the GPIO input when you press the button? It could be interesting to check with an oscilloscope or similar to see if there is something fishy with the input signal when the button press does not cause wakeup from system off.

  • Hello Einar,

    I will check the signal on the button the next time this happens, thank you for suggesting that. What's strange is that it even happens on the DevKit as well, while plugged in through USB.

    Also, any idea why the button configured through the nrf_gpio library does not work on the Dongle? Is there any way you could test the "system_off" sample on it (specifically the wake up btn functionality)?

    Thank you for your response.

    Kind regards,

    Alex.

  • Einar,

    I also forgot to mention, on that system_off sample, there is this bit of code, although I am not sure what it means or does. What is the default behavior? Honestly, I omitted it since it was working without it, I figure it was necessary in case one would want to enable the app retention functionality.

    /* Prevent deep sleep (system off) from being entered on long timeouts
     * or `K_FOREVER` due to the default residency policy.
     *
     * This has to be done before anything tries to sleep, which means
     * before the threading system starts up between PRE_KERNEL_2 and
     * POST_KERNEL.  Do it at the start of PRE_KERNEL_2.
     */
    static int disable_ds_1(const struct device *dev)
    {
    	ARG_UNUSED(dev);
    
    	pm_constraint_set(PM_STATE_SOFT_OFF);
    	return 0;
    }
    
    SYS_INIT(disable_ds_1, PRE_KERNEL_2, 0);

    Regards, Alex.

  • Alex Fernandez said:
    Also, any idea why the button configured through the nrf_gpio library does not work on the Dongle?

    No, it should work regardless. These functions are from the HAL, and is quite low level works regardless of board. (This is basically helper functions that write to registers in a more convenient way). Could it be other parts that is wrong here, like the device tree? You could try to simplify further to test (less elegant, more direct):

    nrf_gpio_cfg_input(38, NRF_GPIO_PIN_PULLUP); // Button 1 is P1.06 which is 38
    nrf_gpio_cfg_sense_set(38, NRF_GPIO_PIN_SENSE_LOW);

  • Hi Einar,

    I finally had the chance to try this out and it worked. So in reality the reason this doesn't work is because of the pin value returned by default from the dongle's device tree.

    For the record, what I ended up doing to keep compatibility with the Dev Kit (using the button0 label/alias) was to add this override on the .overlay file:

    / {
        buttons {
            compatible = "gpio-keys";
            button0: button_0 {
                gpios = <&gpio1 38 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
    			label = "Push button switch 0";
            };
        };
    };

    So now I'm able to configure the wake up button using the sense_set funnction from nrf_gpio.

    I'll see if this strange behaviour of the board not waking up 'sometimes' is still an issue and reply back.

    Kind regards,

    Alex.

Related