Reducing power consumption during wake-up

Hello, I am working with a Seeed XIAO nRF52840.

I'm able to get an average of 500 uA in SYSTEM OFF mode. However, for this application, the current consumption during wake-up is quite high (6mA plateau and then an 8 mA peak).

I would like to know if there is a way to reduce this consumption, right now I'm doing the programming in Arduino IDE using Bluefurit and AdafruitSPIFlash libraries. This is my code:

#include <bluefruit.h> // Necessary for Bluetooth communication
#include <Adafruit_SPIFlash.h>  // Necessary for FLASH memory management

Adafruit_FlashTransport_QSPI flashTransport; // Initialize flash communication device
Adafruit_SPIFlash flash(&flashTransport);

// Manufacturer IDs
#define XIAOMI_ID   0x0038F
#define APPLE_ID    0x004C

// Pin for sequential wake-up
#define WAKE_UP 2

// UUID for Beacon (fictional)
uint8_t beaconUuid[16] =
{
  0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78,
  0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0
};

// Beacon creation for advertising
BLEBeacon beacon(beaconUuid, 0x0102, 0x0304, -54);

// Optimized function for advertising
void start_advertising(void) {
  Bluefruit.Advertising.setBeacon(beacon);
  Bluefruit.ScanResponse.addName();

  // Increase interval for power savings
  Bluefruit.Advertising.setType(BLE_GAP_ADV_TYPE_NONCONNECTABLE_SCANNABLE_UNDIRECTED); // No connection allowed
  Bluefruit.Advertising.setInterval(160, 160); // Higher interval for power saving (units of 0.625ms)
  Bluefruit.Advertising.setFastTimeout(1);
  Bluefruit.Advertising.start(0); // Continuous advertising
}

// Optimized function for configuring clocks
void configure_clocks(void) {
  NRF_CLOCK->LFCLKSRC = CLOCK_LFCLKSRC_SRC_RC; // Use internal oscillator directly
  NRF_CLOCK->TASKS_LFCLKSTART = 1; // Start low-frequency clock
}

void setup() {

  // Enable DC/DC converters
  NRF_POWER->DCDCEN = 1;
  NRF_POWER->DCDCEN0 = 1;

  // Start low-frequency clock directly
  configure_clocks();

  // Initialize and put flash memory into deep sleep
  flashTransport.begin();
  flashTransport.runCommand(0xB9);  // Enter deep sleep mode
  flashTransport.end(); // End flash transport communication

  // Initialize Bluefruit library
  Bluefruit.begin();
  Bluefruit.setTxPower(0); // Keep TX power at -20dBm
  Bluefruit.autoConnLed(false); // Disable auto-connect LED

  // Low-power temperature reading
  int32_t temp = 0;
  sd_temp_get(&temp);
  int32_t real_temp = temp / 4;

  // Set manufacturer ID and populate beacon with temperature reading
  beacon.setMajorMinor(real_temp, 0);

  // Start advertising
  start_advertising();

  delay(20);

  // Configure GPIO for wake-up
  nrf_gpio_cfg_sense_input(WAKE_UP, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
  // Enter system-off mode for deep sleep

  NRF_POWER->SYSTEMOFF=1;
}

void loop() {
  // Empty loop
}

And this is the profile I see using the Power Profiler Kit 2 as source meter at 2200 mV:

Parents
  • Hello,

    It looks like it doesn't go to sleep properly. I am not familiar with the Arduino implementation for the nRF52840. But I believe that if you want it to be properly low power, you should use the nRF Connect SDK. It is a bit more complex than Arduino, but in that case you will use our SoftDevice Controller (Bluetooth Low Energy stack), and you will see a better current consumption.

    Best regards,

    Edvin

  • Hello,

    When I put it to sleep, I see this in the power profiler application both when entering system off using the register and using

      sd_power_system_off();
    

    Can I use the SDK and softdevice with the Seeed Studio XIAO nrf52840 or do I need the Development Kit for this?

  • Hello,

    Sorry, I should have specified. There are two types of sleep. System on and system off. sd_power_system_off() and NRF_POWER->SYSTEMOFF=1; is basically the same thing, and it puts the chip in system off, which is the deepest level of sleep. This mode, however, does require an external source for wakeup. That could be a button press (GPIO interrupt) or a power on reset (turning the device off and on).

    Then we have the system on sleep, which is a "lighter sleep". We use this between e.g. advertisement packets, or radio events when you are in a connection, or whenever you run out of things to do. 

    This is what the current consumption looks like when you are using the system on sleep when advertising:

    You can see that the 3 spikes that occurs 3 times in this screenshot are 3 advertising events, advertising on 3 channels every advertising interval. Also you can see the average current consumption in this case is 615.39µA (measured from the start of one advertising event to the start of the next).

    The CPU is barely being used apart from the advertising events, so the base current is almost nothing (there are some spikes charging up some capacitors, which is creating some smaller spikes on ~3mA, and there is some added base current because there is a timer going that  keeps track of the timing between the advertising events). The spikes in your screenshot is the same, but you can see that it is much lower. only around 10µA, This is only the capacitors being charged, in order to make sure it can wake up on an external event.

    But from the current measurements in your first post, it looks like there is about 0.5 secons with a constant current consumption of 6mA. This makes me think that it doesn't go to system on mode sleep. So while the Arduino IDE is nice and easy to get started, it is not intended for professional use, and has some obvious disadvantages.

    Juan Lopez said:
    Can I use the SDK and softdevice with the Seeed Studio XIAO nrf52840 or do I need the Development Kit for this?

    You can use it. According to this site:

    https://docs.zephyrproject.org/latest/boards/seeed/xiao_ble/doc/index.html

    You need to select your target board "xiao_ble/nrf52840":

    Just tested one sample now, and it built "without" any warnings. (it had some warnings that you need to configure some USB device (P)ID before production.

    I do not, however, know anything about the experience using this board. The fact that it mentions USB when I built the peripheral_uart sample tells me that it probably doesn't have a debugger, and uses the USB as a transport to a bootloader, and it uses USB for serial communication. In a perfect world, this works fine, but as soon as the app crashes, it means that the USB also crashes, and the logging will stop. So it may cause some challenges, and you can't properly debug, but you can give it a go.

    If you are in serious business, however, I can really recommend that you get hold of a Development Kit. The debugger makes debugging and logging a lot more reliable. And if you are using the seeed device for it's form factor, then you can port the application to run on this after you are done with the application development.

    Please note the programming and debugging section:

    https://docs.zephyrproject.org/latest/boards/seeed/xiao_ble/doc/index.html#programming-and-debugging

    So it looks like you should be able to flash directly from nRF Connect SDK (in VS Code) because it is familiar with the bootloader. If you buy a Nordic Development kit, it comes with an on-board debugger, which you can also use to flash and debug external devices. So depending on how much you struggle with the seeed device directly, you may consider this.

    Let me know if you encounter any issues during startup with NCS (nRF Connect SDK). I can really recommend the "nRF Connect SDK Fundamentals" course that we have on DevAcademy:

    https://academy.nordicsemi.com/courses/nrf-connect-sdk-fundamentals/

    The SDK is a mouthful, so perhaps you can avoid some pitfalls by following this course to get familiar with the SDK and it's environment.

    Best regards,

    Edvin

  • Hello, no problem haha

    Right now, I'm waking up from SYSTEM OFF by pulling a pin LOW.

    If I understood your post correctly, the system should wake up from SYSTEM OFF to SYSTEM ON Sleep?

    I just installed the nrf SDK for VSCode and flashed this code into the board:

    #include <zephyr/kernel.h>
    #include <zephyr/drivers/gpio.h>
    #include <nrfx_power.h>
    
    
    int main(void) {
        NRF_POWER->DCDCEN0 = 1;
        NRF_POWER->DCDCEN = 1;
    
        // Configure the wakeup pin
        //configure_wakeup_pin();
    	NRF_POWER->SYSTEMOFF = 1;
    	while(1);
    
        return 0;
    }
    

    But I see this power consumption in the profiler:

    Am I doing something wrong/missing something in my code?

  • Juan Lopez said:
    Right now, I'm waking up from SYSTEM OFF by pulling a pin LOW.

    Yes, that would be the same as a button press. A button press is just a GPIO change interrupt, so this is your "external event". 

    Juan Lopez said:
    If I understood your post correctly, the system should wake up from SYSTEM OFF to SYSTEM ON Sleep?

    Well, preferably you would want your application to do something before going to sleep. The application will "automatically" go to sleep (system on) whenever it can. And if your application detects that it hasn't been connected to for the last 1 minute, 10 minutes or one hour (that is up to you), then you can enter system off. Or just advertise forever, until someone connects to it again.

    Juan Lopez said:
    Am I doing something wrong/missing something in my code?

    Well, it is probably working as intended, but the application is not doing anything. It just powers itself off (system off mode) immediately after starting. So the last while(1); and return 0; are never reached. 

    I suggest you check out some of the sample applications. I like the NCS\nrf\samples\bluetooth\peripheral_uart. Try building that, and see if you can see any advertisements using the nRF Connect for Android/iOS app. 

    Best regards,

    Edvin

Reply
  • Juan Lopez said:
    Right now, I'm waking up from SYSTEM OFF by pulling a pin LOW.

    Yes, that would be the same as a button press. A button press is just a GPIO change interrupt, so this is your "external event". 

    Juan Lopez said:
    If I understood your post correctly, the system should wake up from SYSTEM OFF to SYSTEM ON Sleep?

    Well, preferably you would want your application to do something before going to sleep. The application will "automatically" go to sleep (system on) whenever it can. And if your application detects that it hasn't been connected to for the last 1 minute, 10 minutes or one hour (that is up to you), then you can enter system off. Or just advertise forever, until someone connects to it again.

    Juan Lopez said:
    Am I doing something wrong/missing something in my code?

    Well, it is probably working as intended, but the application is not doing anything. It just powers itself off (system off mode) immediately after starting. So the last while(1); and return 0; are never reached. 

    I suggest you check out some of the sample applications. I like the NCS\nrf\samples\bluetooth\peripheral_uart. Try building that, and see if you can see any advertisements using the nRF Connect for Android/iOS app. 

    Best regards,

    Edvin

Children
  • Well, it is probably working as intended, but the application is not doing anything. It just powers itself off (system off mode) immediately after starting. So the last while(1); and return 0; are never reached

    Okay, I will look into the SDK examples that use SYSTEM OFF and check if they work as intended. I'll report back with the results.

    I suggest you check out some of the sample applications. I like the NCS\nrf\samples\bluetooth\peripheral_uart. Try building that, and see if you can see any advertisements using the nRF Connect for Android/iOS app. 

    I ran "multiple_adv_sets" not long after trying that SYSTEM OFF code I sent in the last reply, and received the data in both Android and iOS, so the BLE Stack is working alright.

    Thank you for your help, have a good weekend.

Related