I’ve been wondering for some time whether the power consumption of an ATmega varies depending on the code it is running. Obviously, sleep modes and clock rate changes have a major impact – but how about plain loops?
To test this, I uploaded the following sketch into a JeeNode:
Interrupts were turned off to prevent the normal 1024 µs timer tick from firing and running in between. And I’m using “volatile” variables to make sure the compiler doesn’t optimize these calculations away (as they’re not used).
The result is that the code pattern does indeed show up in the chip’s total current consumption:
The value displayed is the voltage measured over a 10 Ω resistor in series with VCC (the JeeNode I used had no regulator, and was running directly off a 3x AA battery pack @ 3.95V).
What you can see is that the power consumption cycles between about 8.4 mA and 8.8 mA, just by being in different parts of the code. Surprising perhaps, but it’s clearly visible!
The shifts in the second loop are very slow – due to the fact that the ATmega has no barrel shifter. It has to use a little loop to shift by N bits. To get a nice picture, those shifts are performed only 5,000 times instead of 50,000.
The high power consumption is during the multiplication loop, the low consumption is during the shift loop.
In the end, I had to use a lot of tricks to create the above oscilloscope capture, because there was a substantial amount of 50 Hz hum on the measured input signal. Since the repetition rate of the signal I was interested in was not locked to that 50 Hz AC mains signal, most of the “noise” went away by averaging the signal over 128 triggers.
The other trick was to use the scope’s “DC offset” facility to lower the signal by 80 mV. This allows bumping the input sensitivity all the way up to 2 mV/div without the trace running off the screen. An alternative would be to use AC coupling on the input, but then I’d lose the information about the actual DC levels being measured.
What else can we deduce from the above screen shot?
- loop 1 takes 93.48 ms for 50,000 iterations, so one cycle runs in ≈ 1.8 µs
- loop 2 takes 108.52 ms for 5,000 iterations, so one cycle runs in ≈ 21.8 µs
As you can see, shifts by a variable number of bits do take quite a lot of time on an ATmega, relatively speaking!
Update – As noted in the comments, a shift by “321″ ends up being done modulo 256, i.e. 65 times. If I change the shift to 3, the run times drop to being comparable to a multiply. The power consumption effect remains.