11

I've noticed most example snippets always have a delay in the loop even if it's not needed for proper execution of the program.

I can only assume this is added because people copy and paste without understanding what's going on but it got me thinking if adding a delay could possible save power too.

If I have a loop that checks some inputs for changes could it be possible that adding a delay(10) saves some cycles and thus power?

4
  • 4
    No. Even a delay "uses" cycles.
    – Majenko
    Feb 14 '18 at 15:51
  • 2
    Obligatory Nick Gammon reference: gammon.com.au/forum/?id=11497. All about energy.
    – user31481
    Feb 14 '18 at 15:52
  • @MarkLakata. What about yield()
    – user31481
    Feb 15 '18 at 10:10
  • 2
    @MarkLakata Multithreaded? In Arduino? 99.99% of the time there is no real scheduler, and in any case in the other 0.01% of cases the delay function does not "free" the calling thread (the delay implementation is just like a for loop doing nothing)
    – frarugi87
    Feb 15 '18 at 13:32
16

No, it burns energy by doing nothing.

You definitively should send your MCU to sleep and wake up on events or use the watchdog timer to wake up after a predefined period of time.

8

The delay function doesn't do anything special. It basically just counts down milliseconds inside a while loop and times it with micros().

void delay(unsigned long ms)
{
    uint32_t start = micros();

    while (ms > 0) {
        yield();
        while ( ms > 0 && (micros() - start) >= 1000) {
            ms--;
            start += 1000;
        }
    }
}
3
  • 1
    Calling yield() is somewhat special, but yeah it's still a busy wait that spends most of the time running instructions. Feb 14 '18 at 22:49
  • 2
    @PeterCordes Calling yield() is nothing special. That is just a (weakly defined) function that does nothing. It's there to allow other libraries or code to override it and implement some kind of cooperative threads, but the default code doesn't, so it does nothing. It's not like calling yield() in something like VB where it releases the program flow back to the OS...
    – Majenko
    Feb 15 '18 at 10:35
  • @Majenko: Thanks, I assumed that yield implied a multi-tasking OS, not just a stub in case there was multi-tasking. (And yeah, I was thinking it literally was POSIX sched_yield(2), and that this implied Arduino ran a full OS like Linux. Hard to keep track of which dev boards (RPi / Arduino / whatever) run what when I don't use any of them myself. >.<) Feb 15 '18 at 10:58
5

No, a short delay (up to 100 millis) is usually inserted in a void loop() when you are attached to an external sensor, in order to stabilize the readings. But it has nothing to do with power consumption. As an example, here are lines 49-52 from the example sketch "AnalogInSerialOut":

      // wait 2 milliseconds before the next loop
      // for the analog-to-digital converter to settle
      // after the last reading:
      delay(2);
2

The answers above are wrong, at least for NodeMCU 0.9 (ESP-12 board) ESP8266 and I also tested with Firebeetle ESP8266 board. Since I have a USB tester I can check that if the loop method is empty, the boards consume about 70mA-80mA but during delay(ms) they consume about 20mA-30mA.

This is the delay function for the boards commented:

void __delay(unsigned long ms) {
    if(ms) {
        os_timer_setfn(&delay_timer, (os_timer_func_t*) &delay_end, 0);
        os_timer_arm(&delay_timer, ms, ONCE);
    } else {
        esp_schedule();
    }
    esp_yield();
    if(ms) {
        os_timer_disarm(&delay_timer);
    }
}

I have not investigate further why delay function saves so much power consumption.

1

could it be possible that adding a delay(10) saves some cycles and thus power?

No, the delay() function just pauses the code for the time specified. It's stil running and consuming energy for counting the time and waiting it to finish.

If you need to conserve power, you could adjust your circuit components in a fashion that will save energy, or if you want to save energy on your Arduino, you could use a breadboard setup(Instructions here and here) or make use of the internal watchdog timer to sleep and wake at certain time intervals. More tutorial about watchdog timer is explained here.

Cheers!

0

I suspect the answer depends on the kind of Arduino you're using.

The ESP8266 is ARM based, and I believe ARM chips include power management circuits, where subsystems are automatically put in low power state when they are not being used. An ARM-based Arduino will likely use a lot less power while executing a delay than while doing other things.

I don't think AVR chips have any sort of power management, so they have all their silicon "lit up" at all times. That said, CMOS logic circuits do use more power when switching states than when idle, so even an AVR-based Arduino will probably use slightly less power while in a delay() function that it will when it's running instructions that use the arithmetic unit, UARTs, and other subsystems of the chip.

You'll get much better power savings by putting your Arduino into sleep mode.

2
  • On AVR delay() uses the ALU. Jul 17 '20 at 8:19
  • Yeah, I guess it would use the ALU to see if enough time had passed. I meant that more as an example of the different subsystems of the chip than an accurate list, but point taken.
    – Duncan C
    Jul 17 '20 at 17:04
0

As stated in previous answers, at least on the AVR version of the Arduino core, delay() is a busy wait that keeps the CPU running. In his answer, Duncan C correctly states that “CMOS logic circuits do use more power when switching states than when idle”. It is then expected that instructions that switch a large number of gates or flip-flops consume more power than instructions that only switch a few ones.

Out of curiosity, I disassembled a call to delay() to see what kind of instructions it executes. I found that the “hot path” is a loop that executes 44 instructions per iteration:

  • 23 of them do arithmetic or logic (add, subtract, compare, XOR)
  • 13 move data around (register load, register copy, I/O, read RAM)
  • 7 alter the program flow (function call, return, jump, conditional branches, conditional skip)
  • 1 alters a bit in a status register

I do not know how this compares with “typical” code, but the large proportion of instructions that do arithmetic and logic computations suggests that delay() should be way more energy hungry than, say, a long sequence of nop instructions. In the end, the only way to know for sure whether delay() changes anything to the power consumption of a specific program would be to measure it.

As a side note, an easy way to save some power on AVR boards is to #include <avr/sleep.h> and insert a call to sleep_mode() at the end of loop(). The sleep with not last for long though, as the Arduino core sets Timer 0 to interrupt the CPU every 1024 µs.

Not the answer you're looking for? Browse other questions tagged or ask your own question.