adafruit / Adafruit_nRF52_Arduino

Adafruit code for the Nordic nRF52 BLE SoC on Arduino
Other
610 stars 494 forks source link

More on Power consumption #165

Open pbecchi opened 6 years ago

pbecchi commented 6 years ago

Since long time I am fighting to lower power consumption using this library to the levels reachable with Sdk examples! I have run several examples, testing the uA level in different type of code. If we don't use BLE libraries uA are very near to the one expected , normally few uA when we are in low power mode. But if we use BLE consumption get well above 1mA so about 100 times more that expected! I have used the dual role BLE uart example and these are my findings: -to enter low power mode you have to add delay() in the main loop , the longest the milliseconds the lowest the power drain. -all Ble central related functions are taking quite a bit of mA -keeping only BLE peripheral functions, with delay(100) will give about 600uA that is about what is expected (100 uA+500uA for Serial uart) -taking out all Serial.begin and Serial.print from the example INCREASE the power drain to about 2mA while should be reduced by 500uA

I think this strange behaviour may only be due to some Serial debug statement present on the BLE libraries. In theory Serial debug should be fully controlled by the Tools menu setting and with debug=0 slould not be executed!

binloan commented 4 years ago

Hi, i have read some issues related with the power consumption and i have no clear how to do a well setup to use the Adafruit with a battery. I did some tests with "standard" code but i see that the lipo batt is drained too fast, so my questions are below:

Should i send a command code from my controller device (Android phone) to set the Adafruit as some as a "standby mode"? I mean if exists something like power off and power on by BT commands. I do not if it is the called as "sleep mode" and "wake up"

Should i add delays in the loop code in order to have less consumption? I've read this thread but i do not see clear if these are good practices reccommeded by Adafruit

Exists any convenction to proceed when the lipo batt is almost empty? i mean, advice to the user when batt is under 5%

When i put the charger, the lipo batt will be recharging automatically? Or maybe i should to manage something programatically.

I am newby using this Adafruit BT device and i need some patterns to start working well with it. Thanks in advance

I think you should head over to forums.adafruit.com and ask for support there.

Despite that, have a look into the many examples provided with the library. The best way is to start there. A good way to save energy is to call suspendLoop(); at the end of your setup and then handle all further actions via Interrupts and SoftwareTimers (example code comes with the library). That will cut energy consumption by the factor of 12-15 already. Anything further is way more advanced stuff, that I would want to deal with if I was a beginner.

lefedor commented 4 years ago

Hello, I want ask participants if someone can share sample sketch runs any Beacon task idling under 10uA. I'm using Eddystone TLM beacon feature and want achieve lowest consumption possible.

I have stripped down feather board from power consuming elements, still my best result is about 300uA (280..305).

My current actual strategy roughly is :


SoftwareTimer wUpdateBeaconAdv;

void setup(){
..
Bluefruit.autoConnLed(false);
Bluefruit.begin();
// Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
Bluefruit.setTxPower(-4);    // Check bluefruit.h for supported values
Bluefruit.setName("Bluefruit52");
startAdv()
..
  wUpdateBeaconAdv.begin(wSnsMsInterval, wUpdateBeaconAdvDo);
  wUpdateBeaconAdv.start();
..
sd_power_dcdc_mode_set(NRF_POWER_DCDC_ENABLE);
sd_power_mode_set(NRF_POWER_MODE_LOWPWR);
suspendLoop();
..
}

void startAdv(void)
{
  //Define adv packet
  Bluefruit.Advertising.clearData();
  Bluefruit.Advertising.setBeacon(wEddyTlm);

  Bluefruit.ScanResponse.addName();

  Bluefruit.Advertising.setType(0x01);
  Bluefruit.Advertising.restartOnDisconnect(true);

  Bluefruit.Advertising.setInterval(160, 1800);    // in unit of 0.625 ms
  Bluefruit.Advertising.setFastTimeout(6);      // number of seconds in fast mode
  Bluefruit.Advertising.start(0);                // 0 = Don't stop advertising after n seconds

}

void wUpdateBeaconAdvDo(){

}

I have flashed sandeepmistry bootloader/core (non-RTOS) for testing and got EddystoneURL running in 4-6uA, so my Feather can run this currents. Still I want keep adafruit API.

binloan commented 4 years ago

Hello, I want ask participants if someone can share sample sketch runs any Beacon task idling under 10uA. I'm using Eddystone TLM beacon feature and want achieve lowest consumption possible.

I have stripped down feather board from power consuming elements, still my best result is about 300uA (280..305).

My current actual strategy roughly is :


SoftwareTimer wUpdateBeaconAdv;

void setup(){
..
Bluefruit.autoConnLed(false);
Bluefruit.begin();
// Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
Bluefruit.setTxPower(-4);    // Check bluefruit.h for supported values
Bluefruit.setName("Bluefruit52");
startAdv()
..
  wUpdateBeaconAdv.begin(wSnsMsInterval, wUpdateBeaconAdvDo);
  wUpdateBeaconAdv.start();
..
sd_power_dcdc_mode_set(NRF_POWER_DCDC_ENABLE);
sd_power_mode_set(NRF_POWER_MODE_LOWPWR);
suspendLoop();
..
}

void startAdv(void)
{
  //Define adv packet
  Bluefruit.Advertising.clearData();
  Bluefruit.Advertising.setBeacon(wEddyTlm);

  Bluefruit.ScanResponse.addName();

  Bluefruit.Advertising.setType(0x01);
  Bluefruit.Advertising.restartOnDisconnect(true);

  Bluefruit.Advertising.setInterval(160, 1800);    // in unit of 0.625 ms
  Bluefruit.Advertising.setFastTimeout(6);      // number of seconds in fast mode
  Bluefruit.Advertising.start(0);                // 0 = Don't stop advertising after n seconds

}

void wUpdateBeaconAdvDo(){

}

I have flashed sandeepmistry bootloader/core (non-RTOS) for testing and got EddystoneURL running in 4-6uA, so my Feather can run this currents. Still I want keep adafruit API.

As mentioned in my previous comment you're getting the best power consumption that you can get with the current API implementation. If you need to go down any lower, you should get rid of the freeRTOS. I also don't have that much idea on where else we can save energy. I know @hathach mentioned he would like to improve it, but doesn't have time. @hathach (or any one else with better understanding of the API) maybe you could point out some areas where you think power is drained most likely. Then other people like me could start working on those issues and contribute them. Power consumption is a major concern for most feather board buyers.

ericlangel commented 4 years ago

with older versions i could get arround 6µA with changig the RTOS Clock Rate down to 4 Hz

The Problem is that the RTOS Ticks (default: 1024 Hz) wakes up the MCU with every Tick. That consume around 200-300µA. it would be better to use vPortSuppressTicksAndSleep(ms) -> this stops the RTOS Ticks for x ms. But this didnt save current->on my last test with V10.

maybe its working with V15?

binloan commented 4 years ago

with older versions i could get arround 6µA with changig the RTOS Clock Rate down to 4 Hz

The Problem is that the RTOS Ticks (default: 1024 Hz) wakes up the MCU with every Tick. That consume around 200-300µA. it would be better to use vPortSuppressTicksAndSleep(ms) -> this stops the RTOS Ticks for x ms. But this didnt save current->on my last test with V10.

maybe its working with V15?

As I understood from the last commits they moved to a tickless approach which is why changing the tickrate does not improve on power consumption anymore.

lorneb commented 4 years ago

@binloan was the main aim of moving to tickless to allow RTOS to play nicer with sleep power management and hence provide better lower power consumption? I'm trying to come up to speed with the low power concerns, so also just checking in to this issue to see if anyone has made any more progress?

binloan commented 4 years ago

@lorneb yeah I think so. Tickless would allow the system to go to sleep for longer hence improving power consumption.

Nenik commented 4 years ago

Summary of my recent power tuning efforts (nRf52 0.20.0 and 0.20.1):

Using 52840, things were quite well already, with I2C sensor, no UART (USB-CDC active only when plugged to USB, thus having plenty of power) and the default FreeRTOS setup (which is already tickless), the idle consumption was significantly under 100uA and my biggest concern was #537 When I have migrated to 52832 (custom board, using Tayo Yuden EYSHSN module, which I got working well 2 years ago with 0.8.3 or so), I run into troubles, even when using limited minimal test programs:

With those few changes (together with rigorous USART disablement logic, 52832 has a real serial line and that is causing 2mA load whenever active), I am at less than 20uA idle consumption (loop inside delay() between events, such as I2C transfer from a sensor or ADC usage) on a custom 52832 board.

hathach commented 4 years ago

@Nenik could you do us a favor to submit an PR for this, this will have you listed as contributor which helps to resolve this low power issue as well.

FleshdeckTV commented 4 years ago

I have Bluefruit nRF52832. It is normal that the addition of attachInterrupt adds 350μA to the power consumption?

Nenik commented 4 years ago

@FleshdeckTV wiring interrupt alone makes no difference (it's just a pointer in flash), but if you configure some peripheral to generate that interrupt, that's where it gets more complicated. What kind of interrupt (interrupt source) is that? Since you mentioned attachInterrupt(), you seem to be talking about pin change interrupt. That one could be tricky, it depends on how are those interrupts implemented in the nRF52 port. nRF52 supports IN event or PORT event for a pin change interrupts. The former is more precise, but needs the main clock running, causing higher consumption. I'd have to check one of my older project to see how did I handle that...

Nenik commented 4 years ago

For reference, see e.g. https://devzone.nordicsemi.com/f/nordic-q-a/20195/getting-an-interrupt-when-any-of-multiple-gpio-pins-change

cchabro commented 3 years ago

Hello everyone, I searched long for an easy used BLE module with low power consumption. I read this thread and I was excited to try the Adafruit ItsyBitsy nRF52840 Express - Bluetooth LE. I started with the code example of wb8wka but the current consumption is beyond the above. In the loop: with delay(500); 1,23mA with waitForEvent(); arround 4mA

I used: Bootloader is 0.2.11 Softdevice s140 6.1.1

So my Question would be...

Do I need to have some other version of Softdevice or Bootloader? (If yes, where is the location to change it?) Is there a older Software Version which could reach the lower uA values? Is there a hardware change needed, which I didn't found until know? I tried to change configTICK_RATE_HZ to 4 but this changed nothing.

So, could anyone help me to set the current lower with some hints? Thank you.

ladyada commented 3 years ago

remove the dotstar RGB LED, that has a quiescent current

cchabro commented 3 years ago

That was a fast answer! I will try it tomorow and will write the measurments. Thank you.

cchabro commented 3 years ago

Today I could test the ItsyBitsy without the dotstar and the current with the delay drops down to ca 490uA. I checked the Schematic and looked for other components to reduce the current, but I just saw that I could replace the LDO (If=55uA), Flash-memory and the Bus Buffer are actually quite reasonable. So I don't understand why the current is so high, if other people speak about 70uA.

Is there some other code example which I could follow? Or should I check older version to drop the current consumption. I read, that there should be developed a tutorial for low power consumption. How is the status for this?

lefedor commented 3 years ago

I have tested simple sketch with recent RTOS timer patches on bare NRF52832 with ext quartz and can tell/confirm that it's idling @ 5ua as Eddystone Beacon + spikes to 1xx ua (0.1 mA) every second. LDO adds 4-60ua depends on model. If spikes prolongation to every 10..30 seconds is achievable this would be perfect.

ericlangel commented 3 years ago

@lefedor which Adafruit version did you use? which changes did you made?

the spikes could be the advertising

lefedor commented 3 years ago

https://github.com/adafruit/Adafruit_nRF52_Arduino/pull/555/commits/a5afbec143bf5cf7253a4b75e396ea2dea0aaf97 I'm on git nightly snapshot, as far I see recent tag 0.21.0 should not be different.

nicertwin commented 3 years ago

Hi,

I'm having issues with base current. I was using a really old version of this library (0.9.3) and an old version of arduino and was getting average currents of around 100uA. Unfortunately, when i updated to the newest version and updated my arduino, everything is now around 3mA after compiling the same code.

When I comment out everything (including bluefruit.begin()) and just have 2 if statements and an sd_app_evt_wait(); running in the loop, it still uses around 2mA.

I literally tried disabling every peripheral manually in my old code, so i don't know what could be causing this change.

//Disable everything to save power (except the ADC because we are using that) NRF_UARTE0->ENABLE = 0; //disable UART NRF_SAADC ->ENABLE = 0; //disable ADC NRF_PWM0 ->ENABLE = 0; //disable all pwm instance NRF_PWM1 ->ENABLE = 0; NRF_PWM2 ->ENABLE = 0; NRF_TWIM1 ->ENABLE = 0; //disable TWI Master NRF_TWIS1 ->ENABLE = 0; //disable TWI Slave NRF_TWIM0 ->ENABLE = 0; //disable TWI Master NRF_TWIS0 ->ENABLE = 0; //disable TWI Slave NRF_I2S -> ENABLE = 0; NRF_PDM -> ENABLE = 0; NRF_SPI0 -> ENABLE = 0; //disable SPI NRF_SPI1 -> ENABLE = 0; //disable SPI NRF_SPI2 -> ENABLE = 0; //disable SPI NRF_POWER -> DCDCEN = 0x00000001; //Enable low power mode sd_power_mode_set(NRF_POWER_MODE_LOWPWR);

Do you have any ideas on what else could be causing the change?

nicertwin commented 3 years ago

@hathach I'm really sorry to bother you, but I have a deadline because this device needs to be used in animal experiments and I've spent a month trying to figure out what happened. Basically with our custom board, we previously had average currents of .1uA, but now when compiling even example codes from above, it will only result in 2-3mA consumption. Do you have any idea what could result in that big of a jump? Nothing on the board has changed, and older complied versions of the code still run fine with the same consumption. Guidance would really really be appreciated.

lefedor commented 3 years ago

Sounds like cpu always busy and RF transmitting. You can try rewrite code or fall back to old codebase revision as an quick solution: https://github.com/adafruit/Adafruit_nRF52_Arduino/tags?after=0.8.0

hathach commented 3 years ago

@hathach I'm really sorry to bother you, but I have a deadline because this device needs to be used in animal experiments and I've spent a month trying to figure out what happened. Basically with our custom board, we previously had average currents of .1uA, but now when compiling even example codes from above, it will only result in 2-3mA consumption. Do you have any idea what could result in that big of a jump? Nothing on the board has changed, and older complied versions of the code still run fine with the same consumption. Guidance would really really be appreciated.

which version you are on,also what is your mcu 832 or 840. if you are using the tip of the master, there is a bug following the CryptoCell that could increase the power after the merge of #466 as mentioned here #600 . I would like to help you as well, unfortunately I have a tight schedule on esp32s2 project, and won't be switch back to nrf52 work until it is done.

nicertwin commented 3 years ago

It's the 832. With the original current, I had a my local repo was on 8cba1aae529eb044b30a477d22a15ae58e82bbb1, which i think is part of 0.10.

When i first tried updating, it was to 0.17, which is when I realized the current jump, but since my local was working, I just left it alone. More recently, I've also tried 0.20 and 0.21.

I tried just copying my old version of the repo and then giving it to others to use so that I can work around this, but they get the following error that I couldn't figure out, since the file does seem to exist in the bin folder. I can't find anything about that file anywhere online. image

selman-nus commented 3 years ago

Another way to reduce power is to go full event response aka callback and abandon the use of loop() with suspendLoop() call. ( I will take note myself for the tutorial, before I start to forget things)

https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/master/libraries/Bluefruit52Lib/examples/Peripheral/beacon/beacon.ino#L59

Also you may want to tweak the ble radio timing/parameter such adv, connection interval etc ... the full list and its affect (current save) will come later when I tested them with the bench ( we may go as far as low power profile with pre-configured parameter for user). There may be more trick, but I kind of forget, will get back to this when we are done with the nrf52840 :D

Hi @hathach , Is this aforementioned "coding guideline for low power" tutorial published and already available? If it is not available can you please suggest a list of things we can try to reduce the power consumption?

selman-nus commented 3 years ago

so, i just tested the Beacon Example from Version 10.1 the only change: i stopped Serial with Serial.end()

with Suspendloop() at the end of Setup() i get 800-900µA with waitforevent() in the loop() i get around 300µA with waitforevent() and vPortSuppressTicksAndSleep(250) in the loop() i get also 800-900µA with waitforevent() in the loop() and Tickrate = 4 i get around 130µA with waitforevent() in the loop() and Tickrate = 4 and advertiseinterval = 2sek i get around 5-7µA

finaly.....suspendloop() doesn't save current vPortSuppressTicksAndSleep(250) doesn't save current

MCU: NRF52832 Board: Custom ( Taiyo Yuden NRF52832 Module with external 32khz and external LC for DCDC)

Hi @ericlangel , I have the same board from Taiyo Yuden and it seems like it is using more current (0.5ma) than nrf52DK. I understand that some optimizations you list here don't help reducing consumption anymore because of the updates on the library.

Can you please advise me on what current optimizations/tweaks I can work on so I can reduce the power consumption on this board?

ericlangel commented 3 years ago

@selman-nus which board do you mean? i have never used a taiyo board. i only use their NRF52 Modules with custom made boards.

i think i cant advise you, because i stay on Version 0.9.3. Never tested actual versions. Had no time for that.

selman-nus commented 3 years ago

@ericlangel I thought you were using the EBSHSNZWZ board which has EYSHSNZWZ on it. However, I have already disconnected the module from the rest of the board. So I am also using the same module with you.

I can test on the current version and update here with my findings. But I don't know what should I test, I am new to this library.

ericlangel commented 3 years ago

@selman-nus Watch out: The EYSHSNZWZ is different to Adafruit default.

It has no LF 32khz Osc.

So you need to Enable the RC Osc

//#define USE_LFXO // Board uses 32khz crystal for LF

define USE_LFRC // Board uses RC for LF

its defined in variant.h of your Arduino selected Board

C:\Users\Username\AppData\Local\Arduino15\packages\adafruit\hardware\nrf52\0.9.3\variants\feather_nrf52832

selman-nus commented 3 years ago

Thanks for the tip, I will try that when I am designing a custom board with this module. But actually the current board I am using (EBSHSNZWZ) already has the 32khz crystal and the DCDC converter: (see image below)

I have a question tho, is that RC Osc increasing power consumption?

image

ericlangel commented 3 years ago

its a long time ago that i worked with....

but using rc when 32khz osc is connected was a bad idea (dont know why actual) and using 32khz osc without connected 32khz osc was also a bad idea (dont know why actual)

sorry, i think i cant help you at the moment

ajs123 commented 3 years ago

Update The nice power reduction I'm seeing may be attributable to this change in v0.23 of the core library rather than to the difference between suspendloop() and a scheduled task vs. the traditional loop(). Apologies for that - I've left the post in case the summary is useful to others but removed the part attributing the 6 mA reduction in supply current to the scheduled task approach.

Since I've consulted this tread, and things it points to, repeatedly, I thought I'd weigh in with what worked for me.

In short, replacing

void loop()
{
  //do all the stuff you need to do
  delay(LOOP_INTERVAL);
}

with

void setup()
{
  // Your normal initialization code goes here
  SuspendLoop();          // Don't use the traditional Arduino loop() function
  SoftwareTimer myLoopTimer;         // Set up a timer for the routine that replaces loop()
  myLoopTImer.begin(LOOP_INTERVAL, myLoop);      // Set it to run every LOOP_INTERVAL ms
  myLoopTimer.start();       // Start it
}

void loop     // Empty function
{
};

void myLoop(TimerHandle_t xTimerID)
{
// Things you used to do in loop()
// Do not end with delay()
}

Elsewhere (typically a callback), you can pause with myLoopTimer.stop(); and resume with myLoopTImer.start();

jpconstantineau commented 3 years ago

@ajs123 You might want to note that some things cannot be called from timers. Take for example file system access. I did try to save data to a file from a timer (update settings for future reloading in setup) and never managed to make it work. As soon as I put it in the main loop, it worked.

A constant 6mA is an indication that the CPU never sleeps. If you use BLE, actual current consumption will be very "spiky" as you can see in #600

ajs123 commented 3 years ago

Yes re the 6mA - see my update to the post. I was looking and looking for the FPU interrupt issue perhaps still lingering and most likely I was falling victim to the crypto interrupt issue that's fixed with v0.23 of the core.

Re things that cannot be called from timers, the issue I'm aware of is with things that take longer than the recurring timer interval (or, in the case of deferred callbacks from interrupts, things that take longer than the possible time between interrupts). See here for use of direct-to-task notification as a solution. The "mainline" task runs at lowest priority and blocks unless it has a notification waiting. There can be multiple notifications and it will only unblock once.

With that said - and I hope it's useful - if performance is no different with delay() then in many cases it will be simpler, and still effective, to use the regular Arduino loop(). In my application, I want to be able to go into a very low power mode. I was unable (at least with the 0.21 and 0.22 cores) to get resumeloop() to work but I was successful (with the 0.23 core) with stopping and restarting a timer. Power usage with the timer stopped is barely different from what I get using systemOff().

ericlangel commented 2 years ago

In the last Days i tried the V1.2 release.

And i could get very good results for Current consumption. i did something similar to @ajs123

suspendLoo() after Setup and in Loop itself. And with a timer i call resumeLoop(), to process what i want.

So i got around 4-6µA current consumption (with Advertising Interval Peaks). I dont changed anything in RTOS or Core.

So for me the V1.2 is a great improvement against V0.9.3

joseangeljimenez commented 2 years ago

Thanks @ericlangel for your nice report! For the sake of completeness, can you indicate,

ericlangel commented 2 years ago

oh sorry

its NRF52832 on a custom Board (without LDO, supplied by 3,6V Li-Battery) Selected Board is Adafruit Feather nRF52832 Advertising Interval = 2000ms

Siroyan commented 2 years ago

Hello!

Currently, I am having trouble with the high power consumption of Adafruit Feather nRF52840 Board. According to RAYTAC's datasheet, it should only consume a few micro-A in sleep mode, but in my environment, it was at least 700uA. Do you have any good ideas? By the way, I'm thinking of eventually making a product that transmits sensor values via BLE once every few minutes.

Following are the results of my experiment.

void setup() { suspendLoop(); }

void loop() {}


- 7.65 mA

include

void setup() { sd_power_mode_set(NRF_POWER_MODE_LOWPWR); }

void loop() { waitForEvent(); }

ajs123 commented 2 years ago

The NeoPixel on the Feather board consumes about 500uA when not lit. It’s not too hard to carefully pop it off (all at once or kind of layer by layer) with a pair of small side cutters. That should get you down to 200 uA. Recalling past forum discussion, the interface chip for the USB may be a significant contributor as well.

Siroyan commented 2 years ago

@ajs123 Thanks for the reply ! I could understand that the power consumption of the LED is the problem. I will try to remove it. As for the USB chip, I don't think it is installed on the board I am using. I am supplying power directly from the 3V pin. Here is the schematic. https://learn.adafruit.com/assets/68545

P.S. After removing the LED, the current consumption dropped to 500uA.

jpconstantineau commented 2 years ago

@Siroyan Have you tried running the "Blink_sleep" example? It blinks for 30 seconds, then it goes to deep sleep. Before going in deep sleep, it sets up 2 wake-up pins that the chip will wake up and reboot if it detects the correct transition on.

During that sleep time, you should be able to measure a truely low current consumption from the chip and anything above a couple of uA should be from any additional hardware on your board (neopixel being one hungry thing...)

That being said, are you quoting average currents? This will likely be very spiky in fact and highly dependent on the code you have.

For my BlueMicro_BLE keyboard firmware, I was able to bring the current consumption to a low level in between radio transmissions, however, you have to keep in mind that when the CPU is running, it can consume about 6mA and when the radio is running, it can generate spikes upwards of 20mA. As such, having a device that measures current consumption very rapidly is very useful to tweak and verify that your code is indeed minimizing power consumption. Have a look at my video here that's done with the PPK2 to get a hint about what that looks like.

Getting the CPU to low power mode when doing nothing is very important; otherwise, you will get that 6 mA I was mentioning above.

I haven't checked whether my code is still "low power" with the latest (1.2.0) but I use these 2 methods: 1 - add a delay at the bottom of the loop. This ensures that the loop doesn't run as soon as it's completed. Without a delay, it will restart the loop as soon as possible, making the CPU run in circles very fast (~6mA). 2 - add a vApplicationIdleHook(void) function with sd_power_mode_set and sd_app_evt_wait. I don't know if these are really needed or already done somewhere else but for my code, it seems to help. This task is the one that the RTOS uses when there are no other tasks left to do and it goes idle. Have a look here for the code I use...

Siroyan commented 2 years ago

@jpconstantineau Thanks for your reply !

When I tried the sample program, the current consumption after the LED blinks was about 500uA. I would eventually like to get the current down to a few uA during sleep, and I don't think this is quite enough.

I am using Keysight's b2900 series Source mesurement unit. It should have enough resolution and I don't think it is "average current". I tried to use sd_power_system_off() and sd_power_mode_set(NRF_POWER_MODE_LOWPWR), but they all consumed about 6~7mA, and the lowest current was when I used suspendLoop().

ericlangel commented 2 years ago

@Siroyan Your suspendLoop() Code is the right example with the V1.2 (my experience) But i have no experience with the NRF52840. Maybe the USB consumes some power?

But as the Neopixel show....dealing with µA is not just code. Every 10k Resistor matters -> 3V3/10k = 330µA So you should also have a look at the schematic.

Siroyan commented 2 years ago

@ericlangel Thank you for pointing this out. After reviewing the schematic, I thought it might be related to the power consumption of the QSPI Flash and the leakage current from the OUT side of the LDO. However, I don't think both of them are enough to reach several hundred uA, I would appreciate your opinion.

ericlangel commented 2 years ago

i dont know when QSPI is used. In idle(slepp) it should consume 25µA.

But you said you suppling the Board with the 3V Pin?

Did you checked (measured) reverse Current of the LDO?

Siroyan commented 2 years ago

@ericlangel Thanks.

But you said you suppling the Board with the 3V Pin?

Yes, and I measured current with LDO removed now, so It still consumed about 500uA.

With the nRF52840 running suspendLoop(), if there are no factors on the board that consume current, the total consumption should be only a few uA, right?

ericlangel commented 2 years ago

I have never used NRF52840 (never tested current consumption).

I just used NRF52832. And yes, with the example above you get around 2-5µA. (without BLE advertise!)

Siroyan commented 2 years ago

Thank you very much for people, for helping me !

I said "LDO removed now", but actually I removed LiPo charger chip.

After removing the LDO, the current dropped to a few µA !!! The waveform of the current is very noisy though.

ericlangel commented 2 years ago

i have a strange Bug

void clock_handle(void)
{
  Status.RTC_Flag = true;
}

attachInterrupt(PIN, clock_handle, FALLING);

causing a Current of around 410µA

without this line i have 5-6µA

jgartrel commented 2 years ago

I seem to have a similar issue that @ericlangel described above when testing with the nrf52832. When using BOTH the Wire Library (I2C) and attachInterrupt, power consumption increases dramatically from <11uA to 472uA.

I ran 4 tests and measured the idle current during the delay(10000) in loop:

  1. Baseline (No I2C, no attachInterrupt) - 2.525uA
  2. attachInterrupt only - 10.25uA
  3. I2C only - 2.525uA
  4. Both I2C and attachInterrupt - 472uA

The code snippit below seems to be the simplest way to express the issue:

#include <bluefruit.h>
#include <Wire.h> //I2C library

#define INT_PIN 15

volatile unsigned long ms = 25;

void irqHandler()
{
  #if CFG_SYSVIEW
  SEGGER_SYSVIEW_RecordEnterISR();
  #endif

  ms = 2000;

  #if CFG_SYSVIEW
  SEGGER_SYSVIEW_RecordExitISR();
  #endif
}

void setup() {
  Bluefruit.begin();
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, !LED_STATE_ON);

  Wire.begin();
  delay(100);

  Wire.beginTransmission(0x0E);
  Wire.write(0x0F);
  Wire.endTransmission();

  Wire.end();
  delay(100);

  pinMode(INT_PIN, INPUT_PULLUP);
  attachInterrupt(INT_PIN, irqHandler, FALLING);
}

void loop() 
{
  digitalWrite(LED_BUILTIN, LED_STATE_ON);
  delay(ms);
  digitalWrite(LED_BUILTIN, !LED_STATE_ON);
  delay(10000);
}

Test 1 - (2.525uA):

//  Wire.beginTransmission(0x0E);
//  Wire.write(0x0F);
//  Wire.endTransmission();
...
//  attachInterrupt(INT_PIN, irqHandler, FALLING);

Test 2 - (10.25uA):

//  Wire.beginTransmission(0x0E);
//  Wire.write(0x0F);
//  Wire.endTransmission();
...
  attachInterrupt(INT_PIN, irqHandler, FALLING);

Test 3 - (2.525uA):

  Wire.beginTransmission(0x0E);
  Wire.write(0x0F);
  Wire.endTransmission();
...
//  attachInterrupt(INT_PIN, irqHandler, FALLING);

Test 4 - (472uA):

  Wire.beginTransmission(0x0E);
  Wire.write(0x0F);
  Wire.endTransmission();
...
  attachInterrupt(INT_PIN, irqHandler, FALLING);

Should I open this as a separate issue, or should we just use this thread to discuss it?