ATtiny Ultra Low Power: How to
reduce battery current consumption by 93% so it lasts 14.6 times longer.
Find out exactly how to do it here.
Oh Nooooooo! not another page on:
"ATtiny ultra low power operation".
Most pages all say the same thing:
Use a 1MHz burst clock;
but the question
is...
...Can you do any better?
Burst clock 1MHz or 128kHz - Which is better?
Find out which one you should use; a slow (internal 128kHz) or fast
(internal 1MHz) for the burst clock; also avoid a 'gotcha' if using the 128kHz
clock.
See real current use for different processor
modes and usage here.
What you want to know is:
How exactly do I achieve that lowest possible current use?
Can I do any better with a slower clock and if so how much better?
Exactly what current is used in different modes (clocks and voltages).
How to solve the 128kHz code problem.
This page explores different settings and modes and
shows the current consumed for an ATtiny85.
Note: Operating the ATtiny85 in 128kHz mode is not shown anywhere else.
We'll also test the ATtiny85 in
128kHz mode which is not done anywhere else because there are a few details that can trip you up!
Programming the ATtiny85 bare chip
So for ATtiny ultra low power operation, we're going to program the ATtiny85 on a bare board
using an Arduino as the programmer. The ATtiny85 is a very popular
ATtiny device and is readily available, not to mention that it also
comes in a very breadboard friendly 8 pin DIP chip. Other chips will
need a surface mount solder connection.
A slow clock reduces the current used - the slower the better. You need an AVRISP programmer to set the fuses to allow 128kHz operation.
Extra components on breakout boards use current - lets keep it
simple as possible.
Note: Even an LED will drain the battery faster than the
ATtiny85 (in sleep mode) - its capable of extremely low sleep current - less than 0.5uA
Internal peripherals use current; peripherals such as the ADC consume
current even when you are not using them! (but you can turn them off
within your program).
Four factors that affect current consumed are:
Supply voltage,
Clock speed.
Internal peripherals (e.g. ADC).
Processor sleep mode.
Whether or not you forgot to enable all pull-ups!
Note: It is important to enable pull-ups as not doing so will
increase power consumption as a floating input can cause current draw if
it floats to mid rail (likely as noise received on the pin will charge
the pin capacitance).
Of course, putting the processor to sleep does not achieve much; it
has to wake up for a while and do useful work. But, as long as the active time (or burst)
is short compared to the sleep time then you save a lot of power (by lowering the average current).
Slow Clock or Burst Clock
For battery powered ATtiny ultra low power operation, you will want to save power and for
that you need a burst clock...(maybe). There's two (or three) ways of thinking
about this either:
BURST: You get all the processing out of the way using a high speed clock and sleep
the rest of the time, resulting in low average power consumption.
ALWAYS ON: You do all the processing at low speed taking longer but using less current.
SLOW BURST: Use the slow clock in the burst portion and sleep the rest.
It depends entirely on your design i.e. if you have a fair mount to
do, then option 1 would be appropriate. But on the other hand
if you have to keep the processor running, option 2 would be best.
Alternatively use option 3 for low processor intensity tasks.
ATtiny ultra low power: Clock Speed
Many
other low power designs use the 1MHz clock (right side of figure below).
You can see that far more current is required than a slower clock (left side of figure below).
[Source ATtiny85 datasheet: Figure 22-1]
For example with a 5V5 system the maximum current drawn
is 1.1mA compared to 200uA at 100kHz (the top graph line) - a difference of 5 times between maximum
and minimum current used!
If you want ATtiny ultra low power then reduce the clock speed.
ATtiny ultra low power: Supply Voltage
Note: The supply voltage also plays a big part in reducing the current used.
The supply voltage is important in reducing current used
especially for higher clock frequencies - see the right of the diagram
above. When using a 1MHz clock reducing the supply voltage from 5.5V to
1.8V reduces the current usage from 1.1mA to 0.3mA i.e. by nearly 75%!
((1.1e-3 - 0.3e-3)/1.1e-3)*100 = 72%.
If you want ATtiny ultra low power then reduce the supply voltage.
TIP: If you must use 1MHz clock, reduce the supply to save 72% current.
Supply Voltage at 128kHz
When using the internal 128kHz oscillator, you can save even more
current by reducing the supply voltage as shown below - this is when
using the 128kHz internal clock (from 200uA @ 5V5 to ~100uA @ 2V):
[Source ATtiny85 datasheet: Figure 22-5]
Supply Voltage De-rating
Lower voltage means lower current, but there are
limits (higher clock frequencies do not work at low
voltage!).
Graphs show minimum voltage for operation at the chosen frequency.
[Source ATtiny85 datasheet: Figure 21-1, 21-2]
The minimum voltage for 10MHz is 2.7V,
falling to 1.8V for 4Mhz (and lower).
Note: Minimum operational voltage is 1.8V (For f<=4MHz).
Setting the 128kHz oscillator
A feature that is not talked about very much is:
The ATtiny85 has an Internal 128kHz oscillator.
The reason that it is not talked about at all, is that when you choose this clock, using Spence Konde's ATtiny library, it seems like you have bricked the chip! In fact you have not. This page explains how to use the 128kHz oscillator - the chip is not bricked at all.
LiPo battery Considerations
The voltage from a LiPo battery is ideal for low power operation of a
microcontroller as its voltage output ranges from 4.2V to 3V (an
average of 3.7V which is why this value is often quoted). It means you
don't need any voltage regulator to use the microcontroller. but you do need... a 3V minimum limit.
3V Minimum Limit
The problem with a LiPo battery is that it must not be discharged
below 3V as permanent damage to the battery can occur. It means you need
to turn off all circuitry attached to the battery when that voltage is
reached!
To stop that event it is common practice to attach a battery
protector chip that shuts off current drain below 3V. One example is the
DW01A chip found on the TP4056 boards.
ATtiny85 Current Measurements
The following tests are performed with a empty loop() function and 5V power supply. The
processor is not stopped just continually jumps to the same location
(back 1 address). So the processor is running and using current. The
various tests can be made by uncommenting parts of the program below and programming in different clock rates (Burn bootloader).
#include <avr/sleep.h>
voidsetup(){
pinMode(0,INPUT_PULLUP);
pinMode(1,INPUT_PULLUP);
pinMode(2,INPUT_PULLUP);
pinMode(3,INPUT_PULLUP);
pinMode(4,INPUT_PULLUP);
pinMode(5,INPUT_PULLUP);
ADCSRA&=~(1<<ADEN);// Disable ADC
// set_sleep_mode(SLEEP_MODE_IDLE);
// set_sleep_mode(SLEEP_MODE_ADC);
// X set_sleep_mode(SLEEP_MODE_PWR_SAVE); // not ATtiny85
// X set_sleep_mode(SLEEP_MODE_STANDBY); // not ATtiny85
//set_sleep_mode(SLEEP_MODE_PWR_DOWN);
//
// sleep_enable();
// sleep_cpu();
}
voidloop(){
}
There are also tests with the sleep power down mode - in this case the
clock is switched off during sleep so the clock setting does not matter.
Clock and Sleep mode Tests
Note I/O Setup as all INPUT_PULLUP for all except test 1 and all at 5V supply.
[*] - Input pins were not set to using input pull up resistors.
You can see that if the processor only sleeps then current draw is
extremely low 414nA (but its not doing anything!). It is obviously the
best mode for saving battery power and getting the best ATtiny ultra low power operation.
Test Notes
(click to show)
1. Initial test 128kHz:
Current drawn varies from 770uA to 2400uA. Even using an inactive loop there's a problem!
2. Better Test 128kHz ADC disabled:
Setting all pins as input with pull-ups, the current drawn is
158uA which matches the expected current consumption for a 5V power
supply, operating at 128kHz.
For consistency all inputs must be set as INPUT_PULLUP. Floating inputs cause random current draw up to 2mA!
The ADC is also disabled.
3 Better Test with ADC enabled:
Same as test 2 with the ADC is enabled.
4. Test 1MHz ADC disabled:
The capacitor measurement method just about works:
Vmeasure=4.37: higher I pulls cap low fast.
5. Test 8MHz ADC disabled:
Same setup as 3.
6. Test 16MHz ADC disabled:
Same setup as 3.
7. Sleep Test - Sleep with ADC Disabled:
Additional code :
Header :
#include <avr/sleep.h>
In setup():
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_cpu();
Note: The ADC is disabled.
8. Sleep Test - Sleep with ADC enabled:
Additional code : As for test 7.
Note the higher the current consumption with the ADC enabled; 299uA
compared to 0.4uA when not using the ADC (both in sleep mode)!
9. Sleep Test - ADC SLEEP mode enabled:
Using this power down code:
set_sleep_mode(SLEEP_MODE_ADC);
This is an ADC noise reduction mode.
End of ATtiny ultra low power test notes.
Power Saving modes (ATtiny85)
There are three power saving sleep modes for the ATtiny85 whereas there
are six in an Arduno Uno/Nano (ATMega328). The table shows 5V operation and descending order of power usage:
Active mode clock with ADC disabled
Current used @5V (no action loop just repeats around loop)
16MHz
12mA
8MHz
6.2mA
1MHz
1.08mA
128kHz
166uA
Sleep Mode
(Clock ignored in sleep)
Current used @5V
(no action loop just repeats around loop)
SLEEP_MODE_IDLE
1071uA
SLEEP_MODE_ADC
640uA (ADC noise reduction mode)
SLEEP_MODE_PWR_SAVE
N/A [1]
SLEEP_MODE_STANDBY
N/A [1]
EXTENDED_STANDBY
N/A [1]
SLEEP_MODE_PWR_DOWN
414nA
[1] Available in ATmega328p but not ATtiny85.
ATtiny Ultra Low Power: Calculations
First of all measure the static currents (without burst operation)
then calculate the average current used (unless you have a expensive
current meter that can measure current bursts of less than 1ms period!).
You can easily calculate the average current used if you know the following:
Ip - Active static processor current (Set by clock and supply voltage).
Ic - Active static circuit current (depends on what you are driving).
Is - Inactive processor current (sleep mode).
Trep - Repeat period time.
Tburst - Burst period time.
Using:
Ton_ratio = (Tburst / Trep)
Toff_ratio = (Trep - Tburst) / Trep
Then the average current is
Iavg = (Ic+Ip) * Ton_ratio + Is * Toff_ratio
Does 128kHz make a difference?
After all that the question is:
Is it even worth using a 128kHz clock for ATTiny Ultra Low Power operation?
The idea is to see whether using the 128kHz clock makes any difference
at all to power consumption in a practical circuit. In this test the
processor will operate for a very short time and sleep for a
longer time i.e. burst mode.
To test this out you need a practical example. Lets choose a simple one:
A flashing LED - that is used only as a indicator i.e. not a lamp.
For the lowest current use an Ultra Bright LED.
Lets make the LED flash every half second. Since it is an ultra
Bright LED lets turn it on for 1ms (1ms in every 500ms) and drive it
with ~2mA. The Voltage drop across an LED varies with the current
through it, and at 2mA the voltage drop is about 2.3V (1k resistor used
as RLED).
Flashing Night light
LED Flash Example Sketch
// Low power LED flash / POV light.
// Use Spence Konde library:
// Chip Attiny85 (no bootloader).
// Clock source WDT 128kHz
// Disable millis()/micros().
// BOD disabled.
#include "Arduino.h"
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>
#define LED_PIN 4
// WDT Interrupt Need some code for coming out of sleep.
// but is does not need to do anything! (just exist).
ISR(WDT_vect){
}
// Enters the arduino into sleep mode.
voidenterSleep(void)
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_mode();// Start sleep mode
// Hang here until WDT timeout
sleep_disable();
power_all_enable();
}
// Setup the Watch Dog Timer (WDT)
voidsetupWDT(){
MCUSR&=~(1<<WDRF);// Clear the WDRF (Reset Flag).
// Setting WDCE allows updates for 4 clock cycles end is needed to
// change WDE or the watchdog pre-scalers.
WDTCR|=(1<<WDCE)|(1<<WDE);
//0.5s Good for cat light WDTCR=(0<<WDP3)|(1<<WDP2)|(0<<WDP0)|(1<<WDP0); // 16ms Good for POV light.
//32ms, 64ms no good flicker using 1ms on time
// WDTCR = (0<<WDP3) | (0<<WDP2) | (0<<WDP1) | (0<<WDP0);
WDTCR|=_BV(WDIE);// Enable the WDT interrupt.
}
voidsetup(){
pinMode(1,INPUT_PULLUP);
pinMode(2,INPUT_PULLUP);
pinMode(3,INPUT_PULLUP);
pinMode(LED_PIN,OUTPUT);// 4
pinMode(5,INPUT_PULLUP);
pinMode(6,INPUT_PULLUP);
ADCSRA&=~(1<<ADEN);// Disable ADC
setupWDT();
}
volatilestaticint_delValue;// Set volatile to keep.
voiddelayLoop(intdel){// 1
if(del<=0)return0;
_delValue=del;
#undef _MORENOP_
#define _MORENOP_ " nop \n\t nop \n\t"
while(_delValue--);// _MORENOP_ ;
}
void_loop(){
// Re-enter sleep mode.
enterSleep();
}
voidloop(){
// Toggle the LED on
digitalWrite(LED_PIN,1);
delayLoop(7);// output = 1.012ms every 500ms.
// Toggle the LED off
digitalWrite(LED_PIN,0);
enterSleep();
}
[File:low_power_led_flash_wdt.ino - except changed the WDT period in setup to 500ms]
TIP: Measure the LED voltage as this will change for different ILED values.
128kHz Burst Calculations
Vled
: 2.3V
LED current:
: 1.83mA
Processor Active current (128kHz) : 166uA
Processor Sleep Current: : 414nA
Burst time
: 1ms
Repeat Period
: 500ms
Burst current = (1.83e-3 + 166e-6) = 1.996mA
Average Burst current @ 128kHz =
(1.83e-3 + 166e-6)*(1.0/500)+0.414e-9*(499.0/500)
= 3.99241uA
Comparing this to no sleep (but still using the 128kHz clock and turning the LED on for 1ms in every 500ms) gives:
No sleep current 128kHz (burst is active):
(1.83e-3 + 166e-6)*(1.0/500)+166e-6*(499.0/500) = 169.66uA
Without sleep 169.66uA is used compared to 3.99uA when sleep is active, saving 165.67uA.
Sleep current is
negligible (~0.4nA) compared to the burst current (1.99mA) so
you can really just use the burst current for the average and get a
reasonable current consumption value.
Average current = (1.996e-3)*(1.0/500) = 3.992uA
Compared to 169.66uA without using sleep mode.
C.F. Assumed value Results
Assuming the following:
Vsup = 5V
Vled = 3V
Rled = 1k
Isleep = ??? [ The datasheet Table 21-1 quotes a maximum of 10uA at 3V
(the only reference to power-down current values and min and typ values are not specified) - in reality it is far
lower than 10uA ]. From measurements it is
shown to be negligible (414nA) so ignore it (see above calculations).
Ip = 175uA [from graph here @ 5V]
The difference is mostly due to the assumed (inaccurate) LED voltage and Vsup.
1MHz Burst Calculations
Vled
: 2.3V
LED current:
: 1.83mA
Processor Active current (128kHz) : 1.08mA
Processor Sleep Current: : 414nA
Burst time
: 1ms
Repeat Period
: 500ms
Burst current = (1.83e-3 + 1.08e-3) = 2.910mA
Burst Average current 1MHz =
(1.83e-3
+ 1.08e-3)*(1.0/500)+0.414e-9*(499.0/500) = 5.82041uA
Comparing this to no sleep (but still using the 128kHz clock and turning the LED on for 1ms in every 500ms) gives:
No sleep current 1MHz (burst is active)::
(1.83e-3 + 1.08e-3)*(1.0/500)+166e-6*(499.0/500) = 171.48uA
Without sleep 171.48uA is used compared to 5.82uA when sleep is active, saving 165.66uA!
Again, sleep current is
negligible (~0.4nA) compared to the burst current 2.91mA so
you can really just use the burst current for the average and get a
reasonable current consumption value.
Average current = (2.91e-3)*(1.0/500) = 5.820uA
Compared to 171.48uA without using sleep mode.
Conclusion for 128kHz c.f. 1MHz
128kHz average current: 3.99uA
1MHz average current: 5.82uA
Roughly using 128kHz compared to 1MHz saves 30% average current - in this circuit. In a battery powered system that is a lot!
Note however, if your circuit (active current) uses
significantly more than the processor current (166uA) then the 128kHz
saving has less effect. In other words the active burst current and
processor burst current must be fairly similar for you to save
significant current using the 128kHz clock (see POV light High and Low Current).
Persistence of Vision night light
The same circuit is used and the original program is adjusted
slightly, but now using POV to make it appear that the
light is continuously on; all that changes is the repeat rate used. POV
requires a repeat rate better than 20ms and 16ms is the best we can do.
In the code, un comment the 16ms repeat rate and comment out the 0.5s
to get the POV operation (there are two programs below that do this for
you - the first shows a flicker problem when using interrupts, and the
second solves that new problem).
//0.5s Good for cat light WDTCR=(0<<WDP3)|(1<<WDP2)|(0<<WDP0)|(1<<WDP0); // 16ms Good for POV light.
// 32ms, 64ms no good flicker using 1ms on time // WDTCR = (0<<WDP3) | (0<<WDP2) | (0<<WDP1) | (0<<WDP0);
So
the question is, what are the current savings?
128kHz POV light: Calculations Low I
Vled
: 2.3V
LED current:
: 1.83mA (11 times processor current)
Processor Active current (128kHz) : 166uA
Processor Sleep Current: : 414nA
Burst time
: 1ms
Repeat Period
: 16ms
Burst current = (1.83e-3 + 166e-6) = 1.996mA
Average Burst current @ 128kHz =
(1.83e-3 + 166e-6)*(1.0/16)+0.414e-9*(15.0/16)
= 124.75uA
Comparing this to no sleep (but still using the 128kHz clock and turning the LED on for 1ms in every 500ms) gives:
No sleep current 128kHz (burst is active):
(1.83e-3 + 166e-6)*(1.0/16)+166e-6*(15.0/16) = 280.38uA
Without sleep 280.38uA is used compared to 124.75uA with sleep, saving 55%.
So instead of 1.83mA (with no processor) you get an
average current of 125uA. This is a 93% current saving! [ ((1830e-6 -
125e-6) / (1830e-6))*100 ]. This means the battery will last 14.6 times longer [ 1.83e-3 / 125e-6 ].
128kHz POV light: Calculations High I
This example shows the effect of using the 128kHz slow clock is lower due to:
circuit current >> sleep current.
Here set Rled = 100Ohm
Vled
: 2.92V
Vsup
: 4.4V
LED current:
: 14.8mA (90 times processor current)
Processor Active current (128kHz) : 166uA
Processor Sleep Current: : 414nA
Burst time
: 1ms
Repeat Period
: 16ms
Burst current = (14.8e-3 + 166e-6) = 14.966mA
Average Burst current @ 128kHz =
(14.8e-3 + 166e-6)*(1.0/16)+0.414e-9*(15.0/16)
= 935.37uA
Comparing this to no sleep (but still using the 128kHz clock and turning the LED on for 1ms in every 500ms) gives:
No sleep current 128kHz (burst is active):
(14.8e-3 + 166e-6)*(1.0/16)+166e-6*(15.0/16) = 1091.00uA
Without sleep 1091.00uA is used compared to 935.37uA with sleep, saving 14%.
TIP: You could use a 1MHz clock here since the saving in current is only 14% (or instead, as below, reduce the on-time burst).
So instead of 14.8mA (with no processor) you get an
average current of 935uA. This is a 93% current saving [ ((14.8e-3 -
935e-6) / (14.8e-3))*100 ].This means the battery will last 15.8 times longer [ 14.8e-3 / 935e-6 ].
The percentage saving is the same as the Low I mode, but the current is higher.
Reducing the Burst time
Reducing the on-time burst period restores savings. This is
often done with higher currents as very high brightness LEDs are allow a
greater pulse current than the steady state current.
The LED may be too bright so reducing the on time allows the saving again
On-time = 0.150ms
Without sleep 304.75uA compared to 140.31uA with sleep, saving 54%.
Gotcha at 128kHz
Essentially, when using interrupts at low clock speeds. if the time spent
in doing the interrupt is of the same time order of the operation you
are trying to perform then there will be a problem i.e. noticeable timing errors.
Why interrupts are problem at 128kHz
When you use the 128kHz clock and want to precisely time LED
operation the millis() and micros() functions, you should disable them.
If you look at the source code for these functions they state that they
are only reliable at clock frequencies >= 1MHz.
The problem:
The interrupt service
routine for millis()/micros() uses a lot of instructions and when using a
slow clock there are fewer available processing instructions per
second. There is not enough time to process the interrupt and have
accurate timing - the processor is running out of time to execute both
the interrupt code and the main code.
The interrupt, while always affecting main code timing, is supposed
to be executed fast so it is not noticed! At high speed (16MHz clock),
interrupting
the main loop is not a problem (since the interrupt execution time is
small compared to main code time) but when you use a slower clock, if
interrupt execution time is comparable to the main loop code time, then
there's a problem.
It can cause a major timing error as in the example below.
Sketch POV light flickering
In the example below the millis() function is used and, as described
above, this causes timing problems when using the 128kHz clock.
// Low power LED flash / POV light. BAD Flickering.
// Use Spence Konde library:
// Chip Attiny85 (no bootloader).
// Clock source WDT 128kHz
// ***Enabled*** millis()/micros(). *** causes flicker.
// BOD disabled.
#include "Arduino.h"
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>
#define LED_PIN 4
// WDT Interrupt Need some code for coming out of sleep.
// but is does not need to do anything! (just exist).
ISR(WDT_vect){
}
// Enters the arduino into sleep mode.
voidenterSleep(void)
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_mode();// Start sleep mode
// Hang here until WDT timeout
sleep_disable();
power_all_enable();
}
// Setup the Watch Dog Timer (WDT)
voidsetupWDT(){
MCUSR&=~(1<<WDRF);// Clear the WDRF (Reset Flag).
// Setting WDCE allows updates for 4 clock cycles end is needed to
// change WDE or the watchdog pre-scalers.
WDTCR|=(1<<WDCE)|(1<<WDE);
//0.5s Good for cat light
// WDTCR = (0<<WDP3) | (1<<WDP2) | (0<<WDP1) | (1<<WDP0);
// 16ms Good for POV light.
WDTCR=(0<<WDP3)|(0<<WDP2)|(0<<WDP0)|(0<<WDP0);//32ms, 64ms no good flicker using 1ms on time
WDTCR|=_BV(WDIE);// Enable the WDT interrupt.
}
voidsetup(){
pinMode(1,INPUT_PULLUP);
pinMode(2,INPUT_PULLUP);
pinMode(3,INPUT_PULLUP);
pinMode(LED_PIN,OUTPUT);// 4
pinMode(5,INPUT_PULLUP);
pinMode(6,INPUT_PULLUP);
ADCSRA&=~(1<<ADEN);// Disable ADC
setupWDT();
}
void_loop(){
// Re-enter sleep mode.
enterSleep();
}
voidloop(){
// Toggle the LED on
digitalWrite(LED_PIN,1);
delay(1);
// Toggle the LED off
digitalWrite(LED_PIN,0);
enterSleep();
}
[File:low_power_led_flash_wdt_flicker.ino]
Solving the problem
You can disable millis() and micros() when using the Spence Konde library (See 'Programming options' in that link).
TIP: Disable millis() and micros() at clock frequencies below 1MHz.
The two programs show the problem - the one above shows flicker,
while the one below shows no flicker. They both try to do the same
thing which is to turn on a high brightness LED once (for 1ms) every
16ms. This allows your eye to merge the flashes so you don't see
flashing (16ms is the closest WDT timer interval to 20ms - the preferred
repeat rate).
In fact the first program will show LED flicker as the millis() and
micros() interrupt interfere with the LED turn on time (or repeat time).
This is due to there being 128 instructions within 1ms (1e-3/128e-3) so
if the ISR takes 100 instructions then it will change the 1ms timing
causing flicker (when the millis() interrupt occurs within the 1ms
period).
Once you disable
millis() and micros() you'll probably want some delay code and the
easiest way is to create a loop function that you time yourself.
To get the delay time for the LED 'on' period just create a loop
construct (as below) that you timed using an oscilloscope (or work out the
number of clock cycles required for 1ms at 128kHz and delay that number
of instructions).
Warning: The watchdog timer clock is not that accurate.
Your timings will probably be different unless you calibrate the watchdog timer clock.
Sketch POV light no flicker
In the program below millis()and micros() are disabled (by
setting fuses using the Spence Konde library) and a self timed delay
function gives the delay operation.
// Low power LED flash / POV light.
// Use Spence Konde library:
// Chip Attiny85 (no bootloader).
// Clock source WDT 128kHz
// Disable millis()/micros().
// BOD disabled.
#include "Arduino.h"
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>
#define LED_PIN 4
// WDT Interrupt Need some code for coming out of sleep.
// but is does not need to do anything! (just exist).
ISR(WDT_vect){
}
// Enters the arduino into sleep mode.
voidenterSleep(void)
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_mode();// Start sleep mode
// Hang here until WDT timeout
sleep_disable();
power_all_enable();
}
// Setup the Watch Dog Timer (WDT)
voidsetupWDT(){
MCUSR&=~(1<<WDRF);// Clear the WDRF (Reset Flag).
// Setting WDCE allows updates for 4 clock cycles end is needed to
// change WDE or the watchdog pre-scalers.
WDTCR|=(1<<WDCE)|(1<<WDE);
//0.5s Good for cat light
// WDTCR = (0<<WDP3) | (1<<WDP2) | (0<<WDP1) | (1<<WDP0);
// 16ms Good for POV light.
WDTCR=(0<<WDP3)|(0<<WDP2)|(0<<WDP0)|(0<<WDP0);//32ms, 64ms no good flicker using 1ms on time
WDTCR|=_BV(WDIE);// Enable the WDT interrupt.
}
voidsetup(){
pinMode(0,INPUT_PULLUP);pinMode(1,INPUT_PULLUP);
pinMode(2,INPUT_PULLUP);
pinMode(3,INPUT_PULLUP);
pinMode(LED_PIN,OUTPUT);// 4
pinMode(5,INPUT_PULLUP);ADCSRA&=~(1<<ADEN);// Disable ADC
setupWDT();
}
volatilestaticint_delValue;// Set volatile to keep.
voiddelayLoop(intdel){// 1
if(del<=0)return0;
_delValue=del;
#undef _MORENOP_
#define _MORENOP_ " nop \n\t nop \n\t"
while(_delValue--);// _MORENOP_ ;
}
void_loop(){
// Re-enter sleep mode.
enterSleep();
}
voidloop(){
// Toggle the LED on
digitalWrite(LED_PIN,1);
delayLoop(7);// output = 1.012ms 2k2 dim ish, 470R bright (leaves eye impression)
// Toggle the LED off
digitalWrite(LED_PIN,0);
enterSleep();
}
[File:low_power_led_flash_wdt.ino]
ATtiny Ultra Low Power Conclusions
Maximum Current reduction
For minimum current usage, use the 128kHz clock in burst mode with
processor sleep for the inactive period.
At 128kHz the processor current is 166uA (Ip128kHz).
At 1MHz the processor current is 1080uA (Ip1MHz).
The greatest effect of using the 128kHz clock is when the current
consumed by the rest of the circuit (Ic) is of a similar order. If the
circuit current Ic is much greater than the processor current (Ip), then
the savings made using the 128kHz clock are proportionally lower.
TIP: Use a 128kHz clock if Ic is ~10 times Ip128kHz (or less).
TIP: Use a 1MHz clock if Ic is >> 10 times Ip128kHz (or greater).
Using a 1MHz clock is easier since you can use normal millis() and
micros() functions. Also programming it is easier (the normal AVRISP
program works without modifying the AVRISP code).
For a 128kHz clock, don't use millis()/micros() functions
- turn them off in Spence Konde library as they use too much processing
time and affect normal code (use your own delay time code instead).
TIP: Disable millis()/micros() functions
when using 128kHz .
Supply Voltage
If you must use a 1MHz clock then reduce the supply to save 72% of current (this will work at any clock frequency (not the same percent) but you must maintain minimum voltage for the chosen clock rate).
The minimum voltage for operation at 4MHz and below is 1.8V.
Make sure all unused I/O are set to INPUT_PULLUP. It is easy to
forget this and draw a lot more current than you expect. So examine your
own code and any other code that you expect to use low current.
Warning: It is easy to forget to set the I/O to input pullups.
Peripherals
The ADC uses current when not in use so turn it off: if you don't need it!.
Conclusion
Using the sleep mode of the ATtiny allows almost negligible current
flow. If you turn on the chip for a short burst to do some work, then...
...you can get a circuit to run for ages using a small battery!
NOTE: You get the best ATtiny ultra low power operation by reducing clock speed and reducing supply voltage, in addition to using burst mode.
The 128kHz clock is useful for low current designs, but is a little harder to use.
Unlock the secrets of Arduino scrolling displays! This beginner-friendly guide shows you how to create real-time, dynamic graphics using an SSD1306 OLED, perfect for tracking sensor data and building…
Comments
Have your say about what you just read! Leave me a comment in the box below.
Don’t see the comments box? Log in to your Facebook account, give Facebook consent, then return to this page and refresh it.