How do I put nRF52805 into low-power sleep mode with the ability to wake up to a button press (GPIOs going low to create interrupt)?

I am writing software for a battery-powered device that needs to go into the lowest power possible sleep mode when not in use and be able to wake up with one of 8 buttons are pressed so that it can transmit a Bluetooth BLE transmission to a receiver and then go back to sleep when complete.

Currently, I am using the function k_cpu_idle(), which seems to be mostly working as I measure 8uA sleep current when the MCU is asleep, but approximately every 5 seconds, I see a blip increase in the current up to 20uA followed by another larger blip of 40uA the following 5 seconds. Is this correct or is there a better way to perform this? 
(Note that I am using the latest version, 2.8, of the toolchain and built the project to use Zephyr.)

main.c Code
* Initialize all GPIOs with configure_gpio_wakeup function.
* In my infinite while(1) loop, I call k_cpu_idle() to put the MCU into sleep mode.

prj.conf File Contents

# Enable GPIO
CONFIG_GPIO=y

# Clock configuration
CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y  # Use RC oscillator for LFCLK
CONFIG_SYS_CLOCK_EXISTS=y  # Ensure low-power idle mode

# Configure power management
CONFIG_PM=y
CONFIG_PM_DEVICE=y
CONFIG_PM_DEVICE_RUNTIME=y
CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE=y

# Enable Bluetooth for BLE operations
CONFIG_BT=n
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_LL_SW_SPLIT=y
CONFIG_BT_CTLR=y
CONFIG_BT_HCI=y

CONFIG_TICKLESS_KERNEL=y

# Basic stack sizes
CONFIG_IDLE_STACK_SIZE=256
CONFIG_MAIN_STACK_SIZE=1024


# Logging and Debugging
# Disable logging and UART to reduce periodic activity
CONFIG_LOG_BACKEND_RTT=n
CONFIG_USE_SEGGER_RTT=n
CONFIG_LOG_BACKEND_UART=n
CONFIG_SERIAL=n
CONFIG_UART_CONSOLE=n
CONFIG_LOG=n
CONFIG_PRINTK=y  # Minimal runtime print support

CONFIG_WATCHDOG=n # Ensure no unnecessary peripherals are active.


# Debugging Optimizations
CONFIG_DEBUG_OPTIMIZATIONS=y
CONFIG_DEBUG_THREAD_INFO=y
# Enable Debugging for Power Management
CONFIG_PM_LOG_LEVEL_DBG=y

# Default tick rate (compatible with BLE and Nordic platforms)
#CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000  # Avoids conflicts
  • Hi Jason

    Just a few question to start off with.

    1. I see that you have both 

    CONFIG_BT=n and CONFIG_BT_LL_SW_SPLIT. The CONFIG_BT_LL_SW_SPLIT depends on CONFIG_BT so it seems a bit strange to me. What is reason behind this?
    2. CONFIG_PM=y should give you a warning as it has been deprecated for over a year
    3. k_cpu_idle should not be used unless absolutely necessary. In normal system the idle thread will take care of power management including idling 
    4. If you want the system to go as low as possible I would suggest having a look at the system_off sample where the device is put into system off and awaken with external input(button press)
    Regards
    Runar
  • Hi Runar. Thanks for the prompt response. I was using Chat GPT for debugging to save time and only included CONFIG_BT_LL_SW_SPLIT, per the AI's suggestion. 
    Q1) What do you recommend I change in my prj.conf file?
    Q2) How do I use the system_off sample function, and does it require any prerequisite setups? When I try to use this function, I get a build error. Do I need to include a header file to use it?
    Q3) Could you point me to an example program that goes to sleep until a button is pressed and then wakes up to transmit a BLE signal?

    Thanks,
    JasonS

  • Integrity Circuits said:
    Hi Runar. Thanks for the prompt response. I was using Chat GPT for debugging to save time and only included CONFIG_BT_LL_SW_SPLIT, per the AI's suggestion. 

    Aha

    Integrity Circuits said:
    Q1) What do you recommend I change in my prj.conf file?

    I think I would change it to something like this

    prj.conf File Contents
    
    # Enable GPIO
    CONFIG_GPIO=y
    
    # Clock configuration
    CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y  # Use RC oscillator for LFCLK
    CONFIG_SYS_CLOCK_EXISTS=y  # Ensure low-power idle mode
    
    # Configure power management
    CONFIG_PM_DEVICE=y
    CONFIG_PM_DEVICE_RUNTIME=y
    CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE=y
    
    # Enable Bluetooth for BLE operations
    CONFIG_BT=y
    #CONFIG_BT_SETTINGS=y #if you want to store the bt connection settings
    
    CONFIG_TICKLESS_KERNEL=y
    
    # Basic stack sizes
    CONFIG_IDLE_STACK_SIZE=256
    CONFIG_MAIN_STACK_SIZE=1024
    
    
    # Logging and Debugging
    # Disable logging and UART to reduce periodic activity
    CONFIG_LOG_BACKEND_RTT=y
    CONFIG_USE_SEGGER_RTT=y
    CONFIG_SERIAL=n
    CONFIG_UART_CONSOLE=n
    CONFIG_LOG=y #I am a big fan of logging during development and debugging
    CONFIG_PRINTK=y  # Minimal runtime print support
    
    CONFIG_WATCHDOG=n # Ensure no unnecessary peripherals are active.
    
    
    # Debugging Optimizations
    CONFIG_DEBUG_OPTIMIZATIONS=y
    CONFIG_DEBUG_THREAD_INFO=y
    # Enable Debugging for Power Management
    CONFIG_PM_LOG_LEVEL_DBG=y

    The Konfig will of course need to be adjusted to the behavior of your application. If you are not to familiar with our BLE stack I would suggest take a look at our BLE course  

    Integrity Circuits said:
    How do I use the system_off sample function, and does it require any prerequisite setups? When I try to use this function, I get a build error. Do I need to include a header file to use it?

    The system off sample should work straight of the box. Are you developing on a DK(like the nrf52832 emulating 52805) then it should compile straight out of the box. Can you upload the errors you see?

    Integrity Circuits said:

    Q3) Could you point me to an example program that goes to sleep until a button is pressed and then wakes up to transmit a BLE signal?

    system_off_advertising.zip

    I don't think there is a specific sample for it. But you can have a look at this project. I have just added advertisement to the system off sample 

    Regards

    Runar

  • Thanks Runar. Using your "system_off_advertising" example code on the nRF52-DK evaluation board along with the "nRF52 Connect for Desktop" dongle tool to monitor the BLE activity, the advertisement shows up on the "nRF52 Connect for Desktop", but when I select "Connect" from the "nRF52 Connect for Desktop" too, it fails to connect and times out.

    Any ideas why it will not connect? If you have a nRF52-DK board, could you try to replicate this issue on your side?

  • I hired an experienced firmware engineer to debug the BLE connection issue. He found the following fix, and now the BLE connection works. I've included the corrected code in the attached zip file.

    1) In main.c, replace bt_le_adv_start (line 58) with this err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));

    2) In the pro.conf file, this parameter was added: CONFIG_BT_PERIPHERAL=y
    system_off_advertising_Solved.zip

Related