Projects

How Low Can You Go?

Working with ATtiny Low Power Modes

Rob Bell & Mike Hansell

Issue 15, September 2018

This article includes additional downloadable resources.
Please log in to access.

Log in

Ultra-low power modes for the ATtiny microcontroller make it a perfect candidate for some tasks where ultra-low-power consumption is required.

BUILD TIME: 60 MINUTES
DIFFICULTY RATING: Intermediate

When it comes to the Internet of Things or even just remote data logging, one problem that often crops up is the power requirements. Power is easy to find in the average house, but if you’re trying to keep things light and compact for remote deployment, powering your project can be a real burden. In this project, we’ll experiment with ultra-low power modes with the ATtiny85, providing you with ways to power your next IoT project.

THE BROAD OVERVIEW

Microcontrollers obviously require some degree of power to operate. If you are trying to use your project where mains power is not available then you likely need to use battery power. But even the largest of batteries will run flat eventually, and modest current demands can turn into very large demands over an extended time.

The ATtiny range of microcontrollers lend themselves to some exceptionally versatile low-power functionality. This is in part due to the flexible voltage input requirements, as well as internal functions which can put the microcontroller into various types of sleep.

SUITABILITY

Before running straight to low power, it’s important to understand how the low power operation comes about.

If you’re running computationally heavy tasks, constantly calculating /reading /writing, then low power operation won’t really help you as they still take power to perform. Where the low power consumption comes from is in the methods for replacing idle time with sleep.

If you think about how many delays you have put into certain sketches, you may realise that your Arduino sits there simply passing time until it needs to do something again. These are precisely the times when you could sleep the circuit to save power.

TRIMMING DOWN

The ATtiny can be configured in various ways to reduce power consumption, by adjusting operating parameters and removing features you may not be using. We'll take a look at some of these.

It’s worth noting that when measuring such fine current, there are a whole host of factors which can influence the results. Your own test results may vary a little based on temperature, test equipment, and more.

Operating Voltage

The ATtiny can run on a wide range of voltages, though the maximum clock speed does decrease with the voltage too - but that’s fine for most low power applications anyway!

If we run the same perpetual-loop sketch on an ATtiny at two different voltages (5V and 3.3V), and measure the current draw, we can determine which is the most efficient.

VccCurrentPower
5v 14.67mA 73.35mW
3.3v 8.12mA 26.80mW

From the results above, it seems a no-brainer to say that supplying the ATtiny85 from 3.3V is the correct choice with dramatically lower current consumption, but a very important point needs to be considered. Does your project need to interface with 5V devices? Inputs are easily handled with a resistive voltage divider, but outputs are different.

Batteries can easily supply 3V. This makes a lot of projects easier as long as you’re not dependent on sensors and modules that require higher voltages. You may need to retain 5V operation in such cases - it all depends on your application.

With the exception of our clock-speed test below, we’ll run all tests at 3.3V based on these results.

Clock Frequency

Slower clock = lower power, correct? Sort of...

To get a baseline, we uploaded a fairly basic sketch (a counter in setup() and nothing in loop()) to an ATtiny85 set to run at 8MHz then 1MHz. Results are shown in the table that follows:

Vcc8mhz1MHz
5v 14.67mA 14.62mA
3.3v 8.12mA 7.91mA

While lower clock frequency reduces current consumption, it is not a massive leap. However, the drop in current is measurable and repeatable, so we feel comfortable suggesting that 1MHz is the better option providing you don’t need the faster processing. It also gives you a lower minimum operating voltage for the ATtiny which is an important consideration. Of course, this is just a baseline and it’ll vary with the workload too.

From now on we’ll run all tests at 1MHz.

GPIO States

It makes sense to theorise that the GPIO state will affect the current draw, even when unused. We ran the tests to confirm this theory.

To do this a sketch was loaded with an empty setup() and an empty loop().

STateCurrent
UNASSIGNED8.64mA
INPUTS7.72mA
OUTPUT LOW7.82mA
OUTPUT HIGH7.88mA

As we expected, setting all of the GPIO to outputs draws a little more current, and setting them as a high output results in a little more current being drawn. It is worth noting that we have nothing connected to the outputs. If you’re driving an LED, sensor or anything else from one or more outputs, that device’s current draw must be factored in also.

What we can take from this is, you can likely see a marginal reduction in current by setting unused GPIO to an input state.

Disabling the ADC

It’s actually possible to entirely disable the Analogue to Digital converter (ADC) on the ATtiny to save around 300µA too. That may not sound like a lot, but could be just the extra time you require from a battery pack. Similar to the GPIO, if you need the ADC for your project, then this isn’t an option. However, if you’re working with purely digital signals, you may as well shut it down and take the savings!

SLEEP MODES

You have trimmed and checked everything you can possibly wrangle from your code and been frugal with the use of hardware. Now what? Sleep of course!

This is where we start to make the major leaps into low power consumption, and when the real fun starts. You see, you can have your microcontroller go to sleep! Just like most laptop computers will go to sleep when the lid is closed or when your computer goes into power saving mode, only to be woken at the touch of a button without a full boot. All of these actions are one form or another of sleep modes. While not all will actually put the processor to sleep, the overall consideration is fairly similar.

Unlike idle, where your current consumption is constant and low, sleep modes take things to a whole new level. You can’t perform computation or other complex functions while in a sleep mode, but they’re the perfect way to save power when sitting idle.

There are several modes of sleep for the ATtiny:

  • SLEEP_MODE_IDLE
  • SLEEP_MODE_ADC
  • SLEEP_MODE_PWR_SAVE
  • SLEEP_MODE_EXT_STANDBY
  • SLEEP_MODE_STANDBY
  • SLEEP_MODE_PWR_DOWN

These sleep modes are also available for many regular Arduino projects too, so can easily be experimented with. Let's take a look at the differences:

THE WAKEUP CALL

If we put the Arduino or ATtiny85 to sleep, how do we wake it again? This can be done in a couple of ways. Depending on your application, you’ll find various methods suitable.

Reset

We can of course, simply reset it. Physical pin 1 of the ATtiny85 is assigned the reset function. A simple switch to ground would do the job (standard reset configuration). The ATtiny would then do a full power on sequence and run the sketch. This may or may not suit your application.

Interrupt

We could assign a pin (physical pin 6 would be a good choice) to cause an interrupt via a switch to ground. This could wake the ATtiny allowing it to do various actions as necessary then either continue or go back to sleep again. This is on-demand, great for user-input or sensor-triggered applications.

Watchdog Timer

We could use the watchdog timer to wake after a pre-defined time has elapsed. The watchdog option provides a very reliable timer interface to create timer-driven actions / wake periods. It’s not useful for projects which respond to human interaction (if immediate action is required), however, it's great for repetitive actions at a required interval.

THE WATCHDOG TIMER

Based on the ATtiny85 datasheet, the watchdog timer can be set to timeout and wake the ATtiny after multiples of 16ms up to 8 seconds. So that’s 16ms, 32ms, 64ms, 125ms, 250ms, 500ms, 1 second, 2 seconds, 4 seconds and 8 seconds timeouts. If you need longer timeouts you could increment a counter each time the watchdog times out. When the watchdog timer times out, the sketch will continue directly after the instruction that put it to sleep.

In our next test, we’ll illuminate an LED every 4 seconds, with all of the power saving features we’ve looked into enabled. The result is a current drain of just 4.6µA in sleep mode. The current drain jumps to 8.7mA when the LED illuminates, but remember, this is for just 30ms every 4 seconds.

IS IT ALL WORTH IT?

Absolutely! Using the example provided above, we can look at how much our sleep cycle affects current draw across a duration of time. In our blinking LED example the system draws 4.6µA for 3.97 seconds, and 8.7mA for 30ms of each 4-second cycle.

Blink current - 8.7mA x 0.03s (0.75% of the time) = 65.25µAh.

Sleep current - 4.6µA x 3.97s (99.25% of the time) = 4.6µAh.

If we add those together, we get a mere 69.85µAh. That’s less than 1mAh! Compare that to an idle processor, with some of the other power-saving methods applied. Let’s conservatively say the idle current draw is around 7.5mA at idle, and apply that to our maths.

Blink current - 8.7mA x 0.03s (0.75% of the time) = 65.25µAh.

Idle current - 7.5mA x 3.97s (99.25% of the time) = 7,444µAh (that’s a comma, not a decimal point, i.e. 7.444mAh)!

If we add those together, we get a 7.501mAh. That’s a 100 times increase in power consumption!!! Both current figures are fairly small, sure. But when we apply this sort of theory to a battery, the difference becomes clearer.

A CR2032 lithium battery is rated at (conservatively) 200mAh. To estimate the duration the circuit could run from a battery, we divide that by the current usage.

Sleep circuit (converted from µA to mA for clarity): 200mAh / 0.06985mAh = 2,862 hours or 119 days!

Compare that to our idle-only circuit: 200mAh / 7.501mAh = 26.7 hours - or just over a single day!

As you can see. sleep makes a BIG difference in this context, and should definitely be explored for low power solutions.

But that’s enough theory - let’s build something!

Build 1:

The Sleepy Blink

Parts Required:JaycarAltronicsCore Electronics
1 × ATtiny85 MicrocontrollerZZ8721Z5105COM-09378
1 × 3mm Red LEDZD0100Z0700POLOLU-1070
1 × 4.7kΩ ¼W Resistor*RR0588R7574-

Parts Required:

* Quantity shown, may be sold in packs. You’ll also need a breadboard and prototyping hardware.

This tongue-in-cheek project name refers to the Arduino “Blink” sketch which is what just about everyone starts with when experimenting with Arduino. It is effectively an emulation of the blink circuit we have described in the preceding text, so you can actually put it into practice.

A great experiment is to vary the sleep cycles, running from a coin battery, to see the difference in duration before the battery goes flat.

You’ll notice that we’ve been VERY conservative with the current-limiting resistor for the LED also. This is deliberate and is designed to reduce the current to the LED so it is only just visible. If you prefer you can replace with a 200Ω resistor for a much brighter LED illumination, however, it will come at the cost of longevity.

These parameters are fun to adjust and experiment with while you observe the resulting effects in terms of battery life!

THE CODE

Load up the sketch sleepy_blink.ino onto your ATtiny. Being an ATtiny, you’ll need a programmer, ISP connection from an Arduino, or our ATDEV programmer project described in issue #014.

You’ll notice within the sketch that you can adjust the blink duration by changing the int period, which is currently set to option 8.

// 0 = 16ms, 1 = 32ms, 2 = 64ms, 3 = 128ms, 
// 4 = 250ms, 5 = 500ms, 6 = 1 sec, 7 = 2 sec, 
// 8 = 4 sec, 9 = 8 sec
int period = 8;
// This = 4 second timeout. Refer to table above

The sketch has a few lines of comments above this that specifies the values for 16ms to 8 seconds. The relevant values are provided in the code comments, so you can experiment with the selection and see the results for yourself.

IMPORTANT NOTE: The sketches supplied will NOT "verify/compile" if the IDE is not set up for an ATtiny85. They will fail if the IDE is left at say, an UNO.

Build 2:

The Sleepy Datalogger

Parts Required: JaycarAltronicsCore Electronics
1 × ATtiny85 MicrocontrollerZZ8721Z5105COM-09378
1 × 3mm Red LEDZD0100Z0700POLOLU-1070
1 × Light Dependent Resistor (LDR)RD3485Z1621SEN-09088
1 × 10kΩ ¼W Resistor*RR0596R7582PRT-14491
1 × 4.7kΩ ¼W Resistor*RR0588R7574-

Parts Required:

* Quantity shown, may be sold in packs. You’ll also need a breadboard and prototyping hardware.

This build is fairly straightforward and still only requires a few connections. An SD card adaptor can use SPI for simple communication without using all the available GPIO. The SD libraries are a bit heavy for an ATtiny, there are lightweight versions that will fit, allowing you to expand the storage. While you can store a little data in the EEPROM and variables, retrieval becomes something of a challenge, and the external storage would resolve this issue - especially if you need to store more than a handful of values over time.

In its current form, this is just a demonstration for a long-time duration, which can really be as long as you want it.

This basic code can be used for any standard GPIO sensors, however, it’s worth noting - your sensor must be voltage-compatible with your supply.

While we have demonstrated the ATtiny is more efficient at 3V, it may not be acceptable for the peripherals you require. In this case, operating the ATtiny at 5V may be the only option. You can use voltage dividers and such, but it may be pointless. If you’re sleeping most of the time, the operating voltage becomes largely irrelevant.

THE CODE

Load up the sketch sleepy_datalogger.ino. This is an example sketch only, demonstrating how we would approach the data logging functionality with sleep modes.

This is effectively a hack for the watchdog timer functionality. Due to its limit of 8 seconds, we run into problems with longer durations.

Fortunately, the workaround for this is rather easy. We simply use a counter on each watchdog wake. If the counter hasn’t reached our threshold yet, we increment and go back to sleep. If it has, we perform our required functions, reset the counter and go back to sleep. While it’s not millisecond-accurate, it doesn’t really need to be, and can provide reasonable accuracy for a once-per-hour, once-per-day, or even once-per-month read from some type of sensor.

The only major requirement is calculating the current draw to ensure your battery supply has enough grunt to take the reads for you.

Build 3:

Intelligent Peripheral Power

Parts Required:JaycarAltronicsCore Electronics
1 × ATtiny85 MicrocontrollerZZ8721Z5105COM-09378
1 × BC547 TransistorRD3485Z1621SEN-09088
1 × 3mm Red LEDZD0100Z0700POLOLU-1070
1 × 1kΩ ¼W Resistor*RR0572R7558PRT-14492
1 × 4.7kΩ ¼W Resistor*RR0588R7574-
1 × DHT11 SensorXC5420Z6320CE05172

Parts Required:

* Quantity shown, may be sold in packs. You’ll also need a breadboard and prototyping hardware.

If you’ve just gone through Build 2, you may be wondering “what about active sensors?”. Indeed - when we use active sensors such as a DHT11, we power them directly from the supply. This means that every time the microcontroller is put to sleep, the sensors are still running - even if no readings are being taken.

We can easily circumvent this issue, however, by using a transistor to supply power to the sensor. This transistor is switched on and off by the microcontroller. This gives us a method to digitally power-down any peripherals from the GPIO, thereby providing them with sleep functionality too!

Now there is one caveat to this method - some sensors have a delay on startup, and we’re effectively cold-starting them each time we initialise our read. For this reason, it would be necessary to wake, wait the required time to get a steady reading from the sensor, record the result, then sleep again.

Obviously, this is going to negatively impact on your overall current consumption, but your sleep current is still the same as it would be otherwise and there is still a substantial improvement in the total current draw.

We have added an LED into the sensor supply power, purely for observational purposes. In a final build, you would likely remove this as it’s just using power for no gain - however, for our experimental observations here, it’s worthwhile.

THE CODE

Load sleepy_peripherals.ino sketch onto your ATtiny. This is fairly straightforward. The pin from the ATtiny is set to switch the transistor on and off depending on the overall microcontroller state.

WHERE TO FROM HERE?

See how far you can push things! Now you know how to run a microcontroller using the ultra-energy-efficient sleep modes!

We're only scratching the surface, but see what else you can do to reduce power consumption in your projects! Even if you're mains-powered, you'll be doing your part to reduce energy consumption and emissions!