I've been having a play with this project. I made up a similar thing to what was described. A thermistor, an LED to flash, and some upper and lower temperature limits. Code here:
// Temperature monitoring system
// Author: Nick Gammon
// Date: 16 March 2013
// Thermistor calculation adapted from: http://learn.adafruit.com/thermistor/using-a-thermistor
#include <avr/sleep.h>
#include <avr/wdt.h>
// Flash LED if temperature outside this range:
const float lowTemp = 22.0; // degrees C
const float highTemp = 26.0; // degrees C
// the bigger this is, the less power we consume
const int timeBetweenReadings = 30; // seconds
const byte warningLED = 8; // which LED to flash
#define DEBUGGING false
// Wiring: Gnd <----> 5K Thermistor <----> | <----->> 4.7K resistor <-----> AREF
// |
// v
// A0
// which analog pin to connect
const byte THERMISTORPIN = A0;
// temp. for nominal resistance (almost always 25 C)
const int TEMPERATURENOMINAL = 25;
// resistance at TEMPERATURENOMINAL (above)
const int THERMISTORNOMINAL = 5000;
// how many samples to take and average, more takes longer but is more 'smooth'
const int NUMSAMPLES = 5;
// The beta coefficient of the thermistor (usually 3000-4000)
const int BCOEFFICIENT = 3960;
// the value of the 'other' resistor (measure to make sure)
const int SERIESRESISTOR = 4640;
// how many Kelvin 0 degrees Celsius is
const float KELVIN = 273.15;
// what was our last reading
float lastReading; // degrees
// how many seconds till we take another reading (updated as we enter sleep mode)
float nextReadingTime = 0; // seconds
// watchdog intervals
// sleep bit patterns for WDTCSR
enum
{
wdt_16_mS = 0b000000,
wdt_32_mS = 0b000001,
wdt_64_mS = 0b000010,
wdt_128_mS = 0b000011,
wdt_256_mS = 0b000100,
wdt_512_mS = 0b000101,
wdt_1_sec = 0b000110,
wdt_2_sec = 0b000111,
wdt_4_sec = 0b100000,
wdt_8_sec = 0b100001,
};
void setup (void)
{
#if DEBUGGING
Serial.begin(115200);
#endif // DEBUGGING
pinMode (warningLED, OUTPUT);
digitalWrite (warningLED, LOW);
lastReading = getTemperature ();
} // end of setup
// watchdog interrupt
ISR (WDT_vect)
{
wdt_disable(); // disable watchdog
}
void myWatchdogEnable (const byte interval)
{
// clear various "reset" flags
MCUSR = 0;
// allow changes, disable reset
WDTCSR = _BV (WDCE) | _BV (WDE);
// set interrupt mode and an interval
WDTCSR = _BV (WDIE) | interval; // set WDIE, and requested delay
wdt_reset(); // pat the dog
// disable ADC
byte old_ADCSRA = ADCSRA;
ADCSRA = 0;
// turn off various modules
byte old_PRR = PRR;
PRR = 0xFF;
// timed sequence coming up
noInterrupts ();
// ready to sleep
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
sleep_enable();
// turn off brown-out enable in software
MCUCR = _BV (BODS) | _BV (BODSE);
MCUCR = _BV (BODS);
interrupts ();
sleep_cpu ();
// cancel sleep as a precaution
sleep_disable();
PRR = old_PRR;
ADCSRA = old_ADCSRA;
} // end of myWatchdogEnable
float getTemperature ()
{
byte i;
float average = 0.0;
analogReference (INTERNAL);
// take N samples in a rowy
for (i = 0; i < NUMSAMPLES; i++)
average += analogRead (THERMISTORPIN);
average /= NUMSAMPLES;
// convert the value to resistance
average = 1023 / average - 1;
average = SERIESRESISTOR / average;
float steinhart = average / THERMISTORNOMINAL;
steinhart = log (steinhart);
steinhart /= BCOEFFICIENT;
steinhart += 1.0 / (TEMPERATURENOMINAL + KELVIN);
steinhart = 1.0 / steinhart;
steinhart -= KELVIN; // back to celsius
return steinhart;
} // end of getTemperature
void takeReading ()
{
lastReading = getTemperature ();
#if DEBUGGING
Serial.print ("Temperature = ");
Serial.print (lastReading);
Serial.println (" *C");
#endif // DEBUGGING
if ((lastReading < lowTemp) || (lastReading > highTemp))
nextReadingTime = 5; // if out of range, read again in 5 seconds
else
nextReadingTime = timeBetweenReadings; // when to take another reading
} // end of takeReading
void loop (void)
{
if (nextReadingTime <= 0)
takeReading ();
byte waitTime;
if (lastReading < lowTemp)
{
waitTime = wdt_512_mS;
nextReadingTime -= 0.5;
digitalWrite (warningLED, ! digitalRead (warningLED));
#if DEBUGGING
Serial.println ("Too low!");
#endif // DEBUGGING
}
else if (lastReading > highTemp)
{
waitTime = wdt_256_mS;
nextReadingTime -= 0.25;
digitalWrite (warningLED, ! digitalRead (warningLED));
#if DEBUGGING
Serial.println ("Too HIGH!");
#endif // DEBUGGING
}
else
{
// temperature OK - sleep for 8 seconds
waitTime = wdt_8_sec;
nextReadingTime -= 8;
digitalWrite (warningLED, LOW);
}
#if DEBUGGING
// force serial data out, wait for UART to empty
Serial.flush ();
#endif // DEBUGGING
myWatchdogEnable (waitTime);
} // end of loop
I am setting the flash rates for the LED by simply choosing different watchdog timer intervals. It checks the temperature every 32 seconds or so (3 x 8-second watchdog intervals). If OK, it sleeps for 8 seconds. If not, it sleeps for 0.25 or 0.5 seconds to give a slow flash (cold) or a fast flash (hot).
This is written for the Atmega328P chip! I haven't tried to convert to the Attiny85.
I was interested in the power consumption. Whilst asleep (most of the time) it uses about 4.2 uA when running at 2.6V using the 8 MHz internal oscillator. This can almost entirely be accounted for by the documented overhead of the watchdog timer itself, so I doubt it can go any lower.
The figure of 4.2 uA is also substantially less than what I believe is the self-discharge rate of AA batteries anyway, so your major issue is not what the circuit is using, but that the battery will self-discharge anyway.
A bit of measuring shows that the time taken to wake up, and go back to sleep is around 150 uS. The time to take a reading (it is taking 5 temperature measurements) is 2.2 mS, during which it consumes (I think) around 2 mA.
By my calculations that averages out at another 4.4 uA.
To take a reading over 2.2e-3 seconds means you can take 454 readings (1/2.2e-3 = 454)
Effectively rather than using 2 mA per second you are using 2/454 mA, that is 4.4 uA (2/454 = 0.0044)
I attempted to self-calculate the Vcc voltage but found that it wasn't a success with the thermistor there. Not sure if that is a programming issue or a hardware one.