ATmega48 Timer
I originally built a thermostat in this project case until it was decommissioned in favor of this one.
The unit lay around for months, challenging me to think of something I
could use it for. Appearances to the contrary, a good deal of
craftsmanship went into that project, fitting all the components in. I
am neither a carpenter or a metalworker, and all of my tools are
crude, cheap and unforgiving. In addition, I can't measure very
well, and my eyesight is poor.
Anyway to
make a long story short, I decided to build a timer such as that used
in the kitchen, and since the project had four pushbuttons, that was
what I had to work with. Of course we already have a kitchen timer, but
I never liked it, partly because it implements too many (mostly useless) functions, and it is not user friendly.
The
real challenge for this project was to use battery power only with no
on-off switch. The power supply is 3 alkakline "AA" batteries. For the
first time I was going to try out the power-down sleep mode of an AVR
microprocessor. In hindsight is was a bit of a trial but the results
are well worth it. When "off", the project consumes 1/2 microamp, and
wakes up when pushbutton 1 is pressed. (Powered up it draws
5.5 mA.)

You may wonder what the purpose of Q1 is. I wanted to measure
and display the battery voltage on start-up. The only ADC reference in the ATmega48 was 1.1V, so a resistive divider was
required. Q1 acts as a switch, allowing current to flow through the
divider only when required.
The LCD is powered from
I/O port PD7, so it can be turned off under program control during
power down. A backlight is shown connected to port PB2, but in my
project I have disconnected it, reasoning that the unit will not often
be used in the dark. If you need a backlight, a pushbutton would be the best
way to go.


When first powered up, a version message is displayed on the
LCD line 1, and the battery voltage (in tenths) on line 2. After a
short delay the prompt comes up to set the hours. You can press the
up/down buttons, then OK. Then you set the minutes, and press OK again.
(If you press the Stop button, the unit turns off.) The timer starts
counting down from the time you set. You can then press the Stop button
to pause the countdown and Start (same button) to resume the countdown.
When (if) countdown reaches 5 minutes, the alarm sounds briefly. At
zero, the alarm sounds continuously for about 90 seconds or until the
Stop or Reset button is pressed. After the countdown reaches zero, the
LCD displays "Expired" and the time starts to count up. After 5 minutes
of waiting for user input the unit powers itself down. After counting
up for 15 minutes it also powers down. These intervals are all
parameters in the code which you can change if you like.
Placing
the unit into power down mode is straightforward enough, but getting
the current to drop to the minimum level was not that simple. When I
first tried it, the current actually jumped to around 75 mA! Writing
zero to the PORTD register made it drop drastically; once the LCD was
powered off, any PORTD output pins that were high caused a large
current draw. However the current was still 175 uA, much too high for a
unit that was "off". It took me a while to realize that setting the
PRADC bit of the PRR register to high did not cut power to the ADC. The
solution was to also set the ADEN bit of ADCSRA to low. Then the
current dropped to 1/2 uA.
The
project uses the internal clock in the ATmega48, running at 4 mHz.
Since time intervals are being measured, leaving the AVR to run its
internal clock as supplied may result in considerable error. There are
two ways to improve the accuracy. The best way is probably to use a
crystal or resonator, and the XTAL1/2 pins are free if you choose to do
so. What I did was to set the CKOUT fuse and use PB0's CLKO function. I
connected a frequency counter and adjusted OSCCAL until the frequency
was very close to 4.0 mHz. This should be fine for this
application.
Download C
source code for the timer
Back
to VE3LNY's AVR Project Page