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:
- PWM=OFF, BLE= OFF -> 1.5uA
- PWM=OFF, BLE=ON -> 1.8uA
- PWM=ON, BLE=OFF -> 1.8uA
- 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();
}
}