ATtiny Ultra Low Power

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.

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!

So for ATtiny ultra low power operation, we're going to program the ATtiny85 on a bare board using an Arduino as the programmer.

There are two reasons for using a stand alone ATtiny chip:

  1. A slow clock reduces the current used - the slower the better. You need an AVRISP programmer to set the fuses to allow 128kHz operation.
  2. 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.

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:

  1. 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.
  2. ALWAYS ON: You do all the processing at low speed taking longer but using less current.
  3. 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.

Clock Speed for ATtiny ultra low power

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).

attiny85 current vs frequency of operation
[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.

Supply Voltage for ATtiny ultra low power

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):

Current vs Supply voltage at 128kHz

[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.

ATtiny85 safe operating area freqneucy vs voltageATtiny85 safe operating area freqneucy vs voltage 10~20MHz

[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>

void setup() {

  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();
}

void loop() {

}

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.

Test
Clock
Current Used
@5V Supply
ADC state
Measurement
method
1
128kHz 770~2400uA Active Cap. discharge.
2
128kHz
158uA
Disabled
Cap.discharge.
3
128kHz 443uA
Active Cap.discharge.
4
1MHz
1.08mA
Disabled Cap.discharge.
5
8MHz
6.2mA
Disabled INA219 chip
6
16MHz
12mA
Disabled INA219 chip
7
SLEEP
414nA
Disabled Cap.discharge.
8
SLEEP
299uA Active Cap.discharge.
9
ADC_SLP
640uA
Active Cap.discharge.

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 0.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.
void enterSleep(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)
void setupWDT() {

   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. } void setup() { 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(); } volatile static int _delValue; // Set volatile to keep. void delayLoop(int del) { // 1 if(del<=0) return 0; _delValue = del; #undef _MORENOP_ #define _MORENOP_ " nop \n\t nop \n\t" while(_delValue--) ;// _MORENOP_ ; } void _loop() { // Re-enter sleep mode. enterSleep(); } void loop() { // 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.

Comparing to 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]
then
Iled = (Vsup-Vled) / Rled = (5-3)/1e3 = 2mA

Iburst_avg = (2e-3 + 175e-6)*(1.0/500)+ ??? *(499.0/500).

Ignoring negligible power down current gives:
Iburst_avg = (2e-3 + 175e-6)*(1.0/500) = 4.35uA
This is close to measured 3.9924uA.

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 but now using POV to make it appear that the light is continuously on; all that changes is the repeat rate used. 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 ].

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 ].

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

    Avg_sleep    
        =  (14.8e-3 + 166e-6)*(0.15/16)+0.414e-9*((16-0.15)/16) = 140.31uA

    Avg_noSleep 
        = (14.8e-3 + 166e-6)*(0.15/16)+166e-6*((16-0.15)/16) = 304.75uA

Without sleep 304.75uA compared to 140.31uA with sleep, saving 54%.

Gotcha at 128kHz

Essentially, when using interrupts at low clock speeds. if 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.
void enterSleep(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)
void setupWDT() {

   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.
}

void setup() {

  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();
}

void loop() {

   // 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 (below) show the problem. 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 it  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.
void enterSleep(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)
void setupWDT() {

   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.
}

void setup() {

  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();
}

volatile static int _delValue; // Set volatile to keep.

void delayLoop(int del) { // 1

  if(del<=0) return 0;

  _delValue = del;
  #undef  _MORENOP_
  #define _MORENOP_ " nop \n\t  nop \n\t"

  while(_delValue--) ;// _MORENOP_ ;
}

void _loop() {
  // Re-enter sleep mode.
  enterSleep();
}

void loop() {

   // 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.

  • Reducing the supply voltage reduces current usage even for the 128kHz clock (~50%).

Clock

I/O Ports

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.



New! Comments

Have your say about what you just read! Leave me a comment in the box below.



Privacy Policy | Contact | About Me

Site Map | Terms of Use