System_ON_Sleep of XIAO BLE

System_OFF_Sleep (Deep Sleep) is used to significantly reduce current consumption, but requires an external trigger for wake-up. On the other hand, System_ON_Sleep can easily woken up using the built-in RTC interrupt. In a project that periodically sends data from a peripheral to the central, I experimented with System_On_Sleep to see how much current consumption of a peripheral XIAO could be reduced.

In System_ON_Sleep, the CPU sleeps by the WFI() command, but during sleep, it seems to repeatedly exit the idle state every 1mS, check the requests of modules, supply current to the necessary modules for the necessary time, and return to the idle state. When the RTC interrupt occurs, the CPU wakes up and performs the defined task, then sleeps again by the WFI() command.

The example sketch is "(1)sleep for 10 seconds, (2)wake up by RTC interrupt, (3)send 8 bytes of data to the central, (4)after 100mS delay, (5)sleep again”.
3.3V was applied to the 3V3 pin of XIAO and the current consumption was measured using PPK2.

As a result, it was found that 53% of the current can be reduced when using “mbed 2.9.1” and 90% when using “non mbed 1.1.1”.
The reasons why “mbed 2.9.1” is not able to reduce the current are: (1) the radio module is probably powered every 7~8mS even during sleep, (2) the communication frequency with the central is 10mS (“non mbed” 20mS), and (3) the idle current is 1100uA (“non mbed” 5uA).
Reading and verifying these reasons from the source code is unfortunately beyond my capabilities.

The current reduction effect of “non mbed 1.1.1” is expected to be significant for my project, which involves periodic data transfers.

Here is the sketch used for the measurement. (310.0 KB)

The following documents were used for reference.
Lesson 14 – nRF5x Power Management Tutorial – Embedded Centric
nRF52840 Product Specification v1.1 5.3 POWER — Power supply, 6.22 RTC — Real-time-counter
GitHub - tigoe/BluetoothLE-Examples: BluetoothLE Examples of various platfoms


Another impressive experiment by msfujino, much appreciated.

It seems Adafruit core (based on Free RTOS) performs much better in terms of power efficiency. To what I saw on Adafruit Github, the number of peripheral connection is also higher than Mbed core.

Perhaps it is time to permanently switch to Adafruit core. Thanks again for your sharing.

I’ve been using “mbed” because the “ArduinoBLE” library was easier for me to understand than “bluefruit”. “mbed” still has a battery voltage reading bug that has not been resolved, and I’ve found it has poor sleep performance. I am beginning to think that this might be a good time to move away from “mbed”.

Nice work!

There are additional tricks that might help in other situations. If you don’t need a main loop at all, you can call suspend_loop() at the end of setup. FreeRTOS will automatically put the system in System_ON_Sleep when possible.

Also, if you have an event based device (e.g. button press) with heavy main loop processing, you can use a FreeRTOS semaphore in the main loop. FreeRTOS will automatically put the system in System_ON_Sleep while it is blocked on the semaphore. Examples here: Getting lower power consumption on Seeed XIAO nRF52840

It seems the power efficiency can be further improved by enabling the on-chip DC-DC converter.

// Enable DC-DC converter

// RTC initialization
initRTC(32768 * SLEEP_TIME); // SLEEP_MTIME [sec]

// Initialization of Bruefruit class

The average current of my peripheral improves from 0.57mA to 0.35mA. The peak current seems to be lower, from 25mA to 15mA. I do not have tools on hand to see if the transmit power stays the same. Perhaps I can use a sketch to scan the RSSI of the broadcast packets although this method is not very precise.

Thank you all for the helpful information.
According to the schematic of XIAO_nRF52840, it looks like the inductor is implemented, so I can use DC/DC mode!

When I tried DC/DC mode, the average current decreased from 700uA to 560uA with every 10 seconds of wake-up and data transfer.

Do you use source mode or ammeter mode on your PPK2? My measurement waveform is not entirely similar to your posted diagrams.

In source mode, 3299mV is applied to the 3V3 pin.
Transmit power is “setTxPower(4);”.

My measurement feeds 3.7V from PPK2 to the battery pins.

If 3.7V is fed to the battery bads, it passes through the LDO and a large capacitor is also connected, so the current behavior may be different.

Yes this could be the reason. If I understand correctly, the chip has a VDDH pin which allows direct battery connection and saves the external LDO.

Unfortunately we have to live with the external LDO on Seeed board since VDD only tolerates up to 3.6V. We may connect non-rechargeable Lithium battery directly to VDD but we cannot avoid, if it exists, reverse leakage to the LDO.

I got information from hobbya and daCoder about the on-chip DCDC converter and on-board flash memory. I have tried to find out how effective they are together with System_ON_Sleep.

I was able to reduce the current by about half just to get the system into DCDC mode without sleep. Used in conjunction with System_ON_Sleep, I was able to reduce the current by 94% on “non-mbed” and 71% on “mbed”. As expected, using “non-mbed” reduces the current by far. Flash memory OFF was not significantly more effective than the other two, so it was omitted from the data.

Here is the sketch used for the measurement. (10.5 KB)