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

nrf52 ble + pwm huge power consumption

Hi guys, we are developing firmware for nrf52832 SoC based on the mbed platform. The firmware uses BLE and few peripherals (timers and pwms). Since our goal is to build ultra low power consumption device, our focus is to turn off all peripherals we do not use in sleep mode. For sleep mode, we use arm cortex M4 __WFI() function. And that works great, power consumption drops down to 1.8uA (as official datasheet says). The problem occurs when we combine BLE and peripherals. More exactly, we use BLE and PWM and for that configuration, in sleep mode we use both __WFI() and ble.waitForEvent() functions. In that way, power consumption is 800uA. That's way more than expected. Please find attached simple example of our problem. In the example, we tried to turn off the PWM manually. Here're four scenarios we tried:

  1. PWM=OFF, BLE= OFF -> 1.5uA
  2. PWM=OFF, BLE=ON -> 1.8uA
  3. PWM=ON, BLE=OFF -> 1.8uA
  4. PWM=ON, BLE=ON -> 800uA

The official SoftDevice documentation says that SD uses PWM0 instance. Maybe the problem is in usage confliction between SD and our pwm (since we can not choose the pwm instance within mbed platform for PwmOut). Is that right? What do you think?

Thank you.

#include "mbed.h"
#include "acd52832_bsp.h"
#include "ble/BLE.h"
#include "GapAdvertisingData.h"

#define USE_PWM         (0)
#define USE_BLE         (0)

#if USE_BLE
    BLE &ble = BLE::Instance();
#endif

Ticker WakeSleepT;
Ticker turnBuzzOffT;
Ticker sleepChanger;
PwmOut buzzer(p31);

#if USE_BLE
void bleInitComplete(BLE::InitializationCompleteCallbackContext *params){
    BLE&        ble   = params->ble;
    /* Ensure that it is the default instance of BLE */
    if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
        return;
    }
    uint8_t MSD = 0x23;
    /* setup advertising */
    ble.gap().setAdvertisingInterval(100);  // --> Has to be at least 100ms!
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, &MSD, 1);
    ble.gap().stopAdvertising();
}
#endif


int main(){
    #if USE_BLE
        ble.init(bleInitComplete);
        /* SpinWait for initialization to complete. This is necessary because the BLE object is used in the main loop below. */
        while (ble.hasInitialized()  == false){}
    #endif
    
    #if USE_PWM    
        buzzer.period(0.0F);
        buzzer.write(0.0F);
    #endif
    
    // Disconnect and stop PWM0
    NRF_PWM0->PSEL.OUT[0] = 0x80000000;
    NRF_PWM0->PSEL.OUT[1] = 0x80000000;
    NRF_PWM0->PSEL.OUT[2] = 0x80000000;
    NRF_PWM0->PSEL.OUT[3] = 0x80000000;
    NRF_PWM0->TASKS_STOP = 1;
    
    // Disconnect and stop PWM1
    NRF_PWM1->PSEL.OUT[0] = 0x80000000;
    NRF_PWM1->PSEL.OUT[1] = 0x80000000;
    NRF_PWM1->PSEL.OUT[2] = 0x80000000;
    NRF_PWM1->PSEL.OUT[3] = 0x80000000;
    NRF_PWM1->TASKS_STOP = 1;
    
    // Disconnect and stop PWM2
    NRF_PWM2->PSEL.OUT[0] = 0x80000000;
    NRF_PWM2->PSEL.OUT[1] = 0x80000000;
    NRF_PWM2->PSEL.OUT[2] = 0x80000000;
    NRF_PWM2->PSEL.OUT[3] = 0x80000000;
    NRF_PWM2->TASKS_STOP = 1;
    
    while(1){
        #if USE_BLE
            ble.waitForEvent();
        #endif
        __WFI();
    }
}
Related