Is there any way to wake up after a precise amount of time in the
POWER_DOWN or STAND_BY modes?
I'm afraid not. You will have to use a timer. Since the ATtiny84 does
not have an asynchronous timer, you will have to keep your timer
clocked. This means the clkIO clock domain has to stay
active. Now, take a look at the table “Active Clock Domains and Wake-up
Sources in Different Sleep Modes”, on page 33 of the ATtiny84
datasheet. It shown that “Idle” is the only sleep mode
that keeps this clock domain active.
Even with the SLEEP_MODE_IDLE, I could only get the current draw
down to around (~1.2mA).
There are ways to bring this down. First, there is a collection of
functions named power_*_disable()
in the avr-libc. You can use
these to power down every single peripheral except the one timer that
you will be using.
Most importantly, you can save power by reducing the clock speed. Since
these devices have extremely little leakage current, the current draw is
roughly proportional to the clock frequency. You can then achieve huge
power savings by drastically reducing that frequency. Obviously, your
processing power will also suffer, but this may not be an issue for a
simple binary clock.
I think the best option for you is to clock your ATtiny84 off a
32.768 kHz watch crystal. See the section
6.2.4 – Low-Frequency Crystal Oscillator in the datasheet.
These crystals can be very accurate, as they are specifically designed
for time keeping. And the frequency is so low that the current draw from
the MCU will likely be negligible compared to whatever other components
are in your clock.
Edit: answering the question in the comment.
Wouldn't waking from idle still use the watchdog timer though? Or is
there a way to wake up based on the 32.768 kHz crystal?
As the watchdog timer is way too inaccurate, it is of no use to you.
Instead, you would use either Timer 0 or Timer 1, and configure it to
deliver an interrupt every 32,768 CPU cycles. This interrupt will
be your 1 Hz wakeup source.
You can do this with either timer, in either CTC or fast PWM mode. You
have to configure the prescaler and the TOP value such that
prescaler_factor × (TOP + 1) = 32,768
Then, enable the relevant interrupt, and define the corresponding ISR
that will advance your clock by one second.