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

Zephyr nrf52832 BLE peripheral, I want to reduce power when not connected

I have a battery powered iOT device using BLE, I2C, and GPIO.  I am focused on reducing the power consumption. When BLE is not connected, I want to have as little power usage as possible.

1. I advertise at a "slow" interval

#define BT_LE_ADV_CONN_NAME_SLOW BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE | \
BT_LE_ADV_OPT_USE_NAME, \
BT_GAP_ADV_SLOW_INT_MIN, \
BT_GAP_ADV_SLOW_INT_MAX, NULL)

2. When BLE is not connected, I power off

device_set_power_state(i2c_dev, DEVICE_PM_OFF_STATE, NULL, NULL);
device_set_power_state(gpio_dev, DEVICE_PM_OFF_STATE, NULL, NULL);

3. When BLE is connected, I go active

device_set_power_state(i2c_dev, DEVICE_PM_ACTIVE_STATE, NULL, NULL);
device_set_power_state(gpio_dev, DEVICE_PM_ACTIVE_STATE, NULL, NULL);

My questions:

1. Are there any other default devices/services I should disable such as UART or console, some logging?

2. I read about power management and tickless idle.  I have some questions on tickless idle. When not connected, the device is advertising BLE, and in the main function has a loop and this is the pseudo code:

loop forever {

if connected to BLE {

do some stuff

}

k_break_wait(1000000)

}

I was thinking the main function (main thread) could be suspended until BLE is connected.  When BLE is disconnected, the only thread working would be the BLE advertising at 1-1.2 second intervals

Will that help with power management because of tickless idle?  If so, how do I suspend and wake the main thread?

3. Is there anything else I could do for power reduction?

4. I have read on the forums people have measured the microamps being used from their devices.  What equipment do they use for this?  Could someone give an example?

Parents
  • 1. Are there any other default devices/services I should disable such as UART or console, some logging?

     If logging is enabled with UART as backend, then you need to look at disabling UART before going to sleep.

     

    Will that help with power management because of tickless idle?  If so, how do I suspend and wake the main thread?

    The Zephyr idle task is responsible for trigger any sleep related triggers. And for the idle task to run, the other threads must be in either suspended/blocked/waiting states. The BLE thread might do some preprocessing and sends/receives data and the BLE controller does some processing on that data. Normally the radio activity (+pre and post processing of those packets in the link layer) are high priority and are handled with highest NVIC priority. They normally takes couple of milliseconds to configure the radio and process the received data. The time when radio is actually transmitting is the time that the CPU is available to the application and hence the threads/scheduler can run during BLE packets transfer. Tickless idle here is a special type of sleep where it disables the RTC interrupt while in sleep and when the system wakes up it fixes the missing internal ticks. 

    If you have to use the power management API depends if you want to have total control on the power transition states in your system and if you want to have a power management policy that the rest of the system needs to obey. The system will still go to low power states even without using these high level power management.

     

    3. Is there anything else I could do for power reduction?

     Enabling tickless idle, making sure that the threads yield when in idle and not doing busy loops should normally be enough for the threads to behave in such a way that the inactivity causes the idle thread to run and there forth make the system go to sleep.

     

    4. I have read on the forums people have measured the microamps being used from their devices.  What equipment do they use for this?  Could someone give an example?

     You can achieve such low power in deep sleep (Systemoff) very easily and also in systemidle(WFE) when most of the clocks/and regulators are turned off. Normally if your device goes to systemidle sleep then it has a timer or other wakeup sources that keep some clock on. If you want to keep the power low then try to keep these wakeup sources to be GPIO or NFC or a bit more expensive (in terms of power) peripherals which use LFCLK. Avoid using peripherals that use HFCLK based peripherals as wakeup sources as these peripherals normally keep the clock on in sleep.

  • Hi Susheel,

    You said, "The system will still go to low power states even without using these high level power management."  Is this different than tickless idle?  Please explain?

    You said, "And for the idle task to run, the other threads must be in either suspended/blocked/waiting states. ", and also  " Enabling tickless idle, making sure that the threads yield when in idle and not doing busy loops "

    So, for example, could I call k_thread_suspend from the main thread, to suspend that thread on a BLE disconnect event and then wake up the main thread on a BLE connect event?  When the main thread is suspended only the BLE thread is running to advertise

  • yayembedded said:
    You said, "The system will still go to low power states even without using these high level power management."  Is this different than tickless idle?  Please explain?

    By high level power management, I meant the additional  power management features other than the basic sleep and tickless sleep that your application can include. Idle/Tickless idle is pretty basic sleep related to idle thread.

     

    yayembedded said:
    You said, "And for the idle task to run, the other threads must be in either suspended/blocked/waiting states. ", and also  " Enabling tickless idle, making sure that the threads yield when in idle and not doing busy loops "

    All the tasks/threads that are created by your application need to yield instead of busy looping/waiting. The threads created inside the BLE stack and other libraries will yield as required. You should make sure that your application specific threads are suspendinig/yielding when they do no need any processing time and the scheduler will remove that specific thread from run/ready queues making it one way closer for the idle thread to become runnable if no other protocol or library related threads are not running.

     

    yayembedded said:
    So, for example, could I call k_thread_suspend from the main thread, to suspend that thread on a BLE disconnect event and then wake up the main thread on a BLE connect event?  When the main thread is suspended only the BLE thread is running to advertise

     Yes, There are many ways for the thread to be removed from ready/runnable state. You can wait/poll on any other zephyr native semaphore/mutex/pipe/queue etc waiting for some other condition to happen and until then the scheduler will remove that waiting thread from the runnable queue putting it in waiting state. Waiting state in this way will also let the idle thread run. So basically idle thread runs when there are no runnable threads to schedule.

Reply
  • yayembedded said:
    You said, "The system will still go to low power states even without using these high level power management."  Is this different than tickless idle?  Please explain?

    By high level power management, I meant the additional  power management features other than the basic sleep and tickless sleep that your application can include. Idle/Tickless idle is pretty basic sleep related to idle thread.

     

    yayembedded said:
    You said, "And for the idle task to run, the other threads must be in either suspended/blocked/waiting states. ", and also  " Enabling tickless idle, making sure that the threads yield when in idle and not doing busy loops "

    All the tasks/threads that are created by your application need to yield instead of busy looping/waiting. The threads created inside the BLE stack and other libraries will yield as required. You should make sure that your application specific threads are suspendinig/yielding when they do no need any processing time and the scheduler will remove that specific thread from run/ready queues making it one way closer for the idle thread to become runnable if no other protocol or library related threads are not running.

     

    yayembedded said:
    So, for example, could I call k_thread_suspend from the main thread, to suspend that thread on a BLE disconnect event and then wake up the main thread on a BLE connect event?  When the main thread is suspended only the BLE thread is running to advertise

     Yes, There are many ways for the thread to be removed from ready/runnable state. You can wait/poll on any other zephyr native semaphore/mutex/pipe/queue etc waiting for some other condition to happen and until then the scheduler will remove that waiting thread from the runnable queue putting it in waiting state. Waiting state in this way will also let the idle thread run. So basically idle thread runs when there are no runnable threads to schedule.

Children
No Data
Related