This was an interesting challenge, so I did an experiment. Using the idea above, I connected a 32.768 crystal to pins 9 and 10 of the chip (the XTAL1/XTAL2 pins), set it to run on the 8 MHz oscillator, and uploaded this sketch:
#include <avr/sleep.h>
#include <avr/power.h>
const byte TICK = 9; // PB1
volatile unsigned long seconds = 0;
unsigned long oldSeconds = 0;
volatile unsigned long ticks = 0;
// interrupt on Timer 2 compare "A" completion g
ISR (TIMER2_COMPA_vect)
{
seconds++;
}
ISR (INT0_vect)
{
ticks++;
}
void activateInterrupt0 ()
{
EICRA &= ~(bit(ISC00) | bit (ISC01)); // clear existing flags
EICRA |= bit (ISC01); // set wanted flags (falling level interrupt)
EIFR = bit (INTF0); // clear flag for interrupt 0
EIMSK |= bit (INT0); // enable it
} // end of activateInterrupt0
void setup()
{
pinMode (TICK, OUTPUT);
activateInterrupt0();
TCCR2A = 0;
TCCR2B = 0;
// clock input to timer 2 from XTAL1/XTAL2
ASSR = bit (AS2);
// set up timer 2 to count up to 32 * 1024 (32768)
TCCR2A = bit (WGM21); // CTC
TCCR2B = bit (CS20) | bit (CS21) | bit (CS22); // Prescaler of 1024
OCR2A = 31; // count to 32 (zero-relative)
// enable timer interrupts
TIMSK2 |= bit (OCIE2A);
// stop timers 0 and 1
TCCR0A = 0;
TCCR0B = 0;
TCCR1A = 0;
TCCR1B = 0;
// disable ADC
ADCSRA = 0;
// turn off everything we can
power_adc_disable ();
power_spi_disable();
power_twi_disable();
power_timer0_disable();
power_timer1_disable();
// full power-down doesn't respond to Timer 2
set_sleep_mode (SLEEP_MODE_PWR_SAVE);
} // end of setup
void loop()
{
sleep_mode ();
if (seconds != oldSeconds)
{
oldSeconds = seconds;
// we awoke! pulse the clock hand
digitalWrite (TICK, ! digitalRead (TICK));
power_usart0_enable();
Serial.begin (115200);
Serial.println ();
Serial.print ("ticks = ");
Serial.println (ticks);
Serial.print ("seconds = ");
Serial.println (seconds);
Serial.flush ();
Serial.end ();
power_usart0_disable();
ticks = 0;
}
} // end of loop
The Serial stuff was to see how accurate the count was. Feeding in 100 kHz I got this:
ticks = 99361
seconds = 226
ticks = 99355
seconds = 227
ticks = 99356
seconds = 228
ticks = 99355
seconds = 229
ticks = 99355
seconds = 230
ticks = 99355
seconds = 231
So the results seem to be within 1% of the correct reading.
The processor sleeps in a fairly deep sleep between interrupts, which are caused by either the Timer 2 overflowing (and thus a second is up) or an external interrupt on pin 2 (the Geiger counter pin). Clearly the more interrupts the more current is used, as that turns the clock on. I measured:
- 100 Hz : 700 µA
- 1 kHz : 800 µA
- 100 kHz : 5.8 mA
So, under 1 mA for up to 1 kHz of pulses, rising somewhat for 100 kHz, but at that stage I think the processor would be awake most of the time. This was measured running from 4V supply, to keep power consumption down.
I tried to get a more accurate count by fiddling with the fuses. I changed the clock fuse to wake up after 6 clock cycles plus 0 mS (LOW = 0x82) which gave a higher count at 100 kHz:
ticks = 99399
seconds = 50
ticks = 99409
seconds = 51
ticks = 99410
seconds = 52
ticks = 99403
seconds = 53
ticks = 99412
seconds = 54
Experimentation shows that you can’t count much higher than 100 kHz, which isn’t that surprising as that would be one interrupt every 10 µS, which at 8 MHz clock doesn’t give it much time. To count higher rates you would need to feed the counter into a timer input, which would then mean the processor clock would have to be running (I think, I might be wrong). You might need to consider alternative approaches if this isn’t good enough, for example a larger battery, or maybe a dedicated counting chip.