The
ATtiny has several subsystems which can be separately turned on and
off. The datasheet describes all of these systems but we just want to
find out how to turn them off! Thankfully, you can skip straight to
looking at power.h. This header exposes some methods which make
power management more straightforward. From this header file you can
quickly find all the subsystems on the ATTiny85 which can be switched
off.
- power_adc_disable()
- power_timer0_disable()
- power_timer1_disable()
- power_usi_disable()
In practice, I can't actually switch all of these off in my project.
- Timer1 - used by Manchester lib. The datasheet says that timer1 is always stopped while we are asleep
- ADC - used to read analog value from sensor. ATTINYWATCHDOG already explicitly turns off the ADC when we sleep.
The
ATtiny datasheet has a section on power saving. This recommends that
when not in use, pins should be set to input mode so that they are not
driving anything.
The
wiring of my project currently connects the VCC of my TX module to the
battery VCC line. However, I can improve power use by connecting TX VCC
to a pin on the ATtiny. This allows me to power down the TX while the
ATtiny sleeps.
There
is one change which I should make which will actually consume more
power. I am planning to run an ATtiny from battery power for long
periods of time. At some point the battery will start to run out and the
battery voltage will drop. The ATtiny can operate over a fairly wide
range of voltages. However, but the voltage drops too low the ATtiny can
actually be damaged. To avoid this happening, we can enable a Brown Out
Detection (BOD) circuit. This is enabled by setting a fuse on the
ATtiny.
The details about how to set the fuse are listed on this page. I used the command line approach which involved the following steps.
- Open a command line in: \path\to\arduino-0022\hardware\tools\avr
- Run the following command to read the current fuses
avrdude -C "\path\to\arduino-0022\hardware\tools\avr\etc\avrdude.conf" -p ATtiny85 -c stk500v1 -b 19200 -p COM3 -v
Note that the stk500v1 works fine when using the Arduino as an ISP. Also note that the fuse values get output twice. For example:
avrdude: Device signature = 0x1e930b
avrdude: safemode: lfuse reads as E2
avrdude: safemode: hfuse reads as DD
avrdude: safemode: efuse reads as FF
avrdude: safemode: lfuse reads as E2
avrdude: safemode: hfuse reads as DD
avrdude: safemode: efuse reads as FF
avrdude: safemode: Fuses OK - Use this site to work out your new fuse values. Select "ATtiny85", the default features value is correct. The "current settings" section will likely show fuse values matching what you read from your chip.
- To enable BOD, select your desired level, in my case "Brown-out detection level at VCC=2.7 V; [BODLEVEL=101]". Click "Apply feature settings". The updated fuse settings are shown in the "Current settings" section. In my case, the default of DF changed to DD. In binary this means 0b11011111 changes to 0b11011101.
- To apply this change, run the following command:
avrdude -C "\path\to\arduino-0022\hardware\tools\avr\etc\avrdude.conf" -p ATtiny85 -c stk500v1 -b 19200 -p COM3 -U hfuse:w:0xDD:m
The output of this command should include the following lines:
avrdude: 1 bytes of hfuse written
avrdude: 1 bytes of hfuse verified
avrdude: safemode: Fuses OK
avrdude done. Thank you.
The results after making all of these changes are as follows.
- Sleep current - 0.025mA (up from 0.006mA). This makes it clear how much current the Brown Out Detection support requires.
- Wake current - 7.8mA (down from 8.5mA). This is a rough figure - the reading on the multimeter jumps around as the RF TX happens and the ATtiny sleeps between transmits. 7.8mA is about the highest reading I saw so I am going to use that for now.
Finally,
there is one mode thing which I could do in software to improve power
usage. This would be to rewrite my code to be interrupt driven. This
would allow the ATtiny to spend more time asleep. However, the resulting
code would be more complex and I don't need the extra power savings at
the moment.