This eggtimer has eight red/green LEDs, of which maximum two are active, to save
battery. The first one displays the last full minute in red, the second the
current minute in green with an increasing red share. When a minute is over,
it plays a programmable tune on the speaker.
As always I provide the following files that belong to this project:
The schematic (here in Libre-Office format)
shows the eight red-green duo LEDs are attached to ports B and D of the ATmega8.
Two portbits drive one LED. The resistors RL limit the LED current to
less than 10 mA. Their values depend from the operating voltage, the table
provides values for most of the possible operating voltages.
At start-up and after every full minute a melody is played. This is done via the
speaker that is attached to portpin PC0, via an electrolytic capacitor.
In order to use both ports B and D fully for the LED outputs, the LED control and
the speaker control are not connected with timer output pins. The program controls
both via interrupt-service-routines. See the software section on how this is
For the egg timer I develloped a PCB of the size 40-by-50 mm, which is available
here as high-resolution gif with its component placement plan (right-click on the two
All LEDs have to be mounted in the same direction, the longer LED pin to the lower hole.
The layout is single-sided, with only one bridge to be mounted. The single small line
inside the ISP6 plug is a bit risky, but with my laser printer, my UV-LED exposer,
with diluted sodium hydroxide and Iron-III-Chloride it worked fine.
Those who do not want to program the ATmega8 inside the PCB, do not need the ISP6 plug.
At 3 V operating voltage the timer needs the following supply currents:
Number of LEDs
First LED green, increasing red share
One LED green, tone playing
One LED red, next LED green with increasing red share
The source code in assembler format is available here,
the source code in the browser click here.
Assembling works with any modern AVR assembler.
During programming no fuses need to changed.
The LED control
Controlling the LEDs is complicated because the previous LED is to turn red, while
the next is PWM controlled.
The picture shows the attached eight LEDs on the two ports. On the shon bit combination
the respective LEDs turn red or green. The line Hex shows the bit combination
to be written to the ports B and D.
To turn the previous LED also to red, the LED from number 2 on have to add their
previous red state. This leads to the hexadecimal codes for PB and PD. When LED 5
is active in the PWM state, both PB and PD combinations are not zero.
Here the combinations of the LEDs 1 to 3 and 8 are shown, as located in the SRAM.
To relieve the interrupt-service-routine from unnecessary and time-intensive
decisions, those bit combinations are once generated in SRAM.
During operation the register pair Y points to the currently active LED. When
the minute ends, four are added to Y. The software uses the ability of AVRs to
temporarily add an offset to Y when accessing the bytes +1, +2 and +3 of the
current combination (ldd r,Y+n): at PWM phase start-up Y and Y+1 are written
to ports B and D, at PWM compare match Y+2 and Y+3 are written to these ports.
The time control
The time control is organized in PWM cycles. At start-up of each inner PWM cycle
the actual LED turns red, by setting the low portbit and clearing the next higher
portbit. When compare match occurs, these two portbits are reversed.
If this inner PWM cycle is over, it is repeated for 14 times.
After that the next compare match value is selected and the whole inner and outer
PWM cycles are repeated. If the compare match value finally reaches 256, a minute
To reach this timing, the timer TC2 runs as CTC, with a compare match value of 60.
This ensures a perfect repetition frequency: 1,000,000 / 1 / 61 / 256 = 64.037 Hz.
That means 15.616 ms per outer PWM cycle. 256 outer PWM cycles with increasing
compare match values yield nearly four seconds. The repetition of the inner PWM cycle
has theoretically to be be 15 to reach one minute. Practically I measured too long
times, so I reduced that repetition value to 14 instead. Note that on other operating
voltages the internal RC has different frequencies, so either increase or decrease
When the ATmega8 starts timer/counter TC2 is inited: the compare match value is
adjusted to 60, the repetition counter in X is set to 14 and the timer is brought
to CTC mode with a prescaler of 1. Anyting that follows is done within the ISR
of this timer.
The compare match value of 60 means additionally, that all ISR activities have to be
finished within this time, to ensure that no interrupts are missed. Within the
source code as well as in the flow diagrams the clock cycles needed are listed.
It is not necessary to clock the ATmega8 with an elevated frequency to achieve
Flow diagram of the timing with the OC2-ISR
This is the complete TC2-OC routine. It starts with comparing the register
rPwmCnt with the compare match value in register rPwmCmp. If both
are equal, the LED is switched to green.
Then the PWM counter in register rPwmCnt is increased. If that does not
yield zero, the ISR returns from the interrupt.
If rPwmCnt reaches zero, the PWM repetition counter in X is decreased.
If that does not reach zero, the next inner cycle PWM cycle is started by
switching the LED to red (Restart with Y and Y+1).
If the PWM repetition counter reaches zero, he is restarted with 14 and the
compare match value in register rPwmCmp is increased. Again the next
cycle starts with a red LED.
If the compare match register X reaches zero, the pointer Y to SRAM is increased
by four. If this does not reach the end of the SRAM table, the next melody is
started (see OC1A-ISR) and the cycle starts with a red LED again, to which
Y now points.
If the end of the table in SRAM is reached, the Timer TC2 is switched off,
along with its interrupt enable bit. The OCIE1A-bit remains on to allow
the speaker to play the last tune.
Playing tunes uses the 16-bit-timer TC1 in CTC mode. The ISR switches the
speaker output pin PC0 high and low.
To adjust the divider rate of TC1 for a certain tone, the software holds
a gamut table of constants behind the label gamut:. Here the gamut
frequencies between 27 Hz and up to 18.794 kHz, more than 9 1/2
octaves, are assigned to constants. For chamber tone A4 a compare match
value of 1,136 for Compare A is listed. This yields 1,000,000 / 1 / 1,136 / 2 =
440.14 Hz. The 2 results from the fact that a complete wave consists
of two cycles, one high and one low.
Two "tones" are remarkable:
cPs: This "tone" is a pause, the resulting frequency
is generated, but the output on the speaker pin is suppressed by setting
the bit bQuiet in the flag register rFlag. This
"tone" is recognized by its LSB finger print, because it is the
only one with that LSB (see the table for that check).
cEnd: This "tone" switches the music play off. The next
tune is played when the miinute is over. The pointer Z points to the next
tone following cEnd. cEnd is also recognized by its LSB, because no other
tone has this LSB (see the table).
Because each tone needs a specific number of waves to reach the same duration
(called frequency), these durations are give for all tones as constants with
n behind the label Durations:. So for A4 the compare match value of
cA4 is associated with the duration nA4. All those durations
are derived from four seconds (musicians know why). Full notes are divided
by four, half notes by 8, quarters by 16 and sixteenth by 32. By multiplying
those durations with three before dividing by eight also 3/8 durations can be
programmed. Make sure that your dividing does not reach zero, because that
yields a very long instead of a very short tone.
Another limit concerns the maximum frequency that can be generated. As you can
see from the flow diagram the OC1A-ISR needs at maximum 40 clock cycles. That
would limit the maximum frequency to be generated to cX8 tones. Fortunately
half of the interrupts just reverse the output pin and need only 18 cycles.
All repetitions of the wave need only 21 cycles, so there is lots of time
left for the OC2-ISR and the OC1A-ISR to perform. There is only ONE case
where the 40 are needed, so 14 (cE9), 16 (cC9) or even 17 kHz (cD9) can
well be generated. I never tried cE9, so I cannot guarantee that it works.
And: my speaker does not sound tones above 12 Hz, so I can not verify
With these constants melodies can be incoded into tables in the flash memory.
Here is the Internationale as table:
; Völ- ker
.dw cH3,nH3*3/16, cPs,nPs/16, cA3,nA3/16, cPs,nPs/16
; hört die Sig na- le
.dw cG2,nG2/2, cPs,nPs/16, cD2,nG2*3/8, cPs,nPs/16, cH1,nH1/8, cPs,nPs/16, cE2,nE2/2, cPs,nPs/16, cC2,nC2/4,cPs,nPs/8
; Auf zum letz- ten Ge- fecht!
.dw cA3,nA3*3/16, cPs,nPs/16, cG2,nG2/16, cPs,nPs/16, cF2,nF2/2, cPs,nPs/16, cE2,nE2*3/8, cPs,nPs/16, cD2,nD2/8, cPs,nPs/16, cD2,nD2/2,cPs,nPs/8
; Die In- ter- na- tio- na- le
.dw cD2,nD2/4, cPs,nPs/16, cH3,nH3*3/8, cPs,nPs/16, cH3,nH3/8, cPs,nPs/16, cA3,nH3/4, cPs,nPs/16, cD2,nD2/4, cPs,nPs/16, cG2,nG2/2, cF2,nF2*3/8,cPs,nPs/8
; er- kämpft das Men- schen- recht.
.dw cF2,nF2*3/16, cPs,nPs/16, cE2,nE2/8, cPs,nPs/16, cD2,nD2/8, cPs,nPs/16, cE2,nE2/4, cPs,nPs/16, cA3,nA3/4, cPs,nPs/16, cA3,nA3/2
Each note consists of two words: the first cXn determines the tone's height,
the second the tone's duration nXn in packages of four seconds. If the
next tone is to be separated by a pause, use cPs and nPs to determine the
length of the pause. With instruments you can encode any melody.
If the pause is missing between two notes, both tones are following each other.
With that you can program powerful asian music as well as motor and buzz saws.
In the flash there is enough space left for extensive programming.
cEnd closes the output of the melody. It is restarted each minute.
To the right you see the complete algorithm of the tone output.