Applications => Eggtimer RGB m8515
Diese Seite in Deutsch:
Eggtimer RGB with ATmega8515
Hardware, Mounting, Application and Software for a 11 minute eggtimer
Eggtimer RGB with ATmega8515
This describes a timer, that operates with 11 RGB LEDs. It can be
used to control the cooking process of eggs.
The hardware properties of the described eggtimer:
Sorry: I tried to take a video with the eggtimer, but the
timer's 60 Hz multiplexing and the video camera produced
a horrible video and sound. Nothing that can be shown on a
- Maximum time measurable 11 minutes,
- can be built to operate at 3.7 or 4.5 or 5.0 V by
- previous full minute displayed in red, configurable to
leave all red LEDs of previous minutes on,
- current minute first green, with slowly increasing blue
share, then decreasing blue and increasing red share, 512
different colors with 8 bit PWM resolution,
- exact timing with a crystal clock, works with three
different crystals as well as with an internal RC
oscillator of 2 or 4 MHz (with small time differences
- low power consumption by switching unneeded previous LEDs
off, average consumption approx. 30 mA, battery
operation mode by default,
- can be configured to leave all red LEDs of previous
minutes on in case of an external power supply providing
200 mA max.,
- plays selectable gamut tones at the end of each minute,
- widely configurable source code for many purposes and
variations, with intensive documentation, flow charts,
and timing values,
- hardware test routines provided as configurable source
code for convenient separate testing of all hardware
2.1 Selecting the AVR device type
Accessing 10 or 11 RGB LEDs requires at least four 8-bit ports (32 I/O pins).
Additional pins should allow to
To find out which of the AVR device types fits these reequirements best,
I used the device selector in the AVR simulator
avr_sim. To ease hardware
and software design it was simpler to have all LEDs in a row of four
complete 8-bit I/O ports. Only the following types
- play music over an OCR pin, to which a speaker could be attached,
- attach a key to stop and restart the timer.
==> ATmega <==
ATmega16 - PDIP40
ATmega16A - PDIP40
ATmega32 - PDIP40
ATmega32A - PDIP40
ATmega83 - PDIP40
ATmega161 - PDIP40
ATmega162 - PDIP40
ATmega163 - PDIP40
ATmega323 - PDIP40
ATmega8515 - PDIP40
ATmega8535 - PDIP40
provide such complete 8-bit ports in a 40-pin PDIP package. Adding the
external interrupt pin for the key shrinks the type list down to:
==> ATmega <==
ATmega161 - PDIP40
ATmega162 - PDIP40
ATmega8515 - PDIP40
When ticking on an OC pin, the list empties, because most of the OC
pins are in the middle of an I/O port. The only possible selection
was OC1B, which left over the above three device types. As the
ATmega161 is out of production, only ATmega162 and ATmega8515 come
into question. I selected the 8515 for my project.
The avr_sim device selector to the right shows the pinning of the
ATmega8515. There is only one pin left (PE1), if 11 LEDs shall be
This shows how to attach the 11 RGB LEDs to the 32 I/O ports of the
AVR device. The three colors blue, green and red are always attached
in that row, each with a resistor to limit the current through the
LEDs. The LEDs are of the common-anode type, so all anodes are
connected to the positive operating voltage. If you want to use
common cathode types, you'll have to tie the cathodes to ground
and change the software slightly.
The speaker is attached via an electrolytic capacitor of 47µF.
The key is attached to the INT2 pin directly, the software switches
the internal pull-up resistor on.
The crystal that drives the clock of the ATmega8515 is of a
frequency of 4.194304 MHz, which is chosen for an 8-bit PWM.
If you use a 4 MHz crystal or the internal RC at 4 MHz
instead, your minute will be longer by 3 seconds, an acceptable
inaccuracy for an eggtimer.
If you want to use a different crystal: only the listed ones work
exactly, if you adjust the CTC-divider accordingly. The
2.097 MHz already provides enough speed for the lengthy minute
change and can also be used. This was the result of an assembler
code optimization: in the first version the code needed 138 clock
cycles for a minute change, but the current version remains below
the 120 clock cycles (that is what the extensive cycle counting in
the software section was made for).
You don't need the accuracy of a crystal for your boiling eggs?
Fine, use an internal RC and leave the two crystal inputs open.
The internal RC oscillator can work on 1, 2, 4 and 8 MHz.
The version with 1 MHz is too slow for this application,
so either use 2 or 4 Mhz. The difference to the exact
timing of 60 seconds is small. Configure the fuses of the
ATmega8515 accordingly, and do not forget to adjust the assembler
The version with 8 Mhz clock would require to set the prescaler
of TC0 to eight. As such high speed does not provide advantages
(in the contrary: current consumption increases in battery operations)
this version is not taken into account.
All other xtal frequencies have a more or less large difference to
the 60 s rhythm. See the
Libre Office calculation sheet
xtals for more details on the differences.
Not shown in the scheme is a six-pin-ISP plug, which serves to program
the ATmega8515 within the system. The pins needed for that are marked
as secondary function in the ATmega8515.
The resistors Rblue, Rgreen and Rred
were selected with the following parameters:
- A maximum of twelve LEDs have to be driven if you'll leave
one LEDs for all previous minutes on (e. g. red), makes
10 LEDs, plus the two LEDs of the current minute. The two
LEDs are only on during the beginning of a PWM clock cycle,
switching them off during the PWM cycle reduces average
consumption to 11 LEDs.
- The ATmega8515 can drive 200 mA max. from its VCC or
GND pin. So the maximum current for each of the 12 LEDs on
is 16.7 mA.
- To leave enough current for the device in idle mode and for
the operation of the speaker, the LED current was therefore
chosen to be 15 mA, which is large enough for lots of
- At 15 mA the forward voltages of the LEDs are: blue =
2.92 V, green = 3.09 V, red = 2.09 V, with
slight differences for each exemplar. See the
calculation sheet measured for the factually measured
voltages and LED currents of the final device.
- At 15 mA the pin voltage in sink direction is
approximately 0.4 V. Factually an average of 358 mV
was measured, with a range from 319 to 410 mV.
- The resistors are
RLED = (Vop - VLED -
Vsink) / ILED
- I chose the nearest values from the resistor row E24, which
are available by my electronics dealer.
The table provides the blue, green and red resistors
for three operating voltages:
If you use an external source and not battery operation, you can
leave all LEDs for previous minutes at red, which consumes
150 mA at the end and can be sourced from an USB plug or an
external power supply, but is not recommended for battery
operation. Just switch that on (or off, which is the default) in
the source code. If you want mixed operation, use the free pin
PE1 for a jumper, which enables to keep all previous LEDs on.
- for 3.7 V, which is the minimum and provided e. g.
by larger Li cells,
- for 4.5 V, which come out of three cascaded AA(A)
battery cells, and
- for 5.0 V, if you want to use an USB plug or an external
I built my exemplar with three 1.5 V batteries. And measured
the voltages of all 32 LEDs. The average sink voltage at roughly
4.2 V operating voltage was 0.358 V, the average current
per LED was 14,19 mA. The average forward voltage for the
blue LEDs was 2.798 V, for the greens 2.777 V and for
the reds 2.023 V. The average currents were 13.11 mA for
the blue, 15.31 mA for the green and 14.04 mA for the
red LEDs. Such small differences in the LED currents are invisible.
Libre Office calculation sheet
for more details.
For convenient mouting a single-sided PCB layout was designed. It
covers half of a euro format (100-by-80 mm).
These are the components on the PCB. All holes to be drilled are
0.8 mm, only those for the speaker and battery pins as well
as for the ISP6 pins are 1 mm. One bridge was unavoidable.
After the hardware is complete, the different components can be
tested. See the Software section for a
The PCB is covered with an acrylic glass cover in 10 mm
distance, for which holes for the LEDs, the key and the switch
This is the view from the side. The lowest layer is an acrylic
glass plate holding the batteries and the speaker. The speaker
has small 3 mm holes for the noise and is fixed with glue.
The distance of the plate to the PCB is 25 mm.
The software is available as assembler source code is available
here or can be viewed
in the browser here.
For testing all components of the board separately, I wrote
the test software here.
See chapter 4.4 for details.
Before you assemble make sure you have the correct settings
selected. The default works with a 4.194304 MHz crystal.
I cannot be made responsible if you cooked your egg for six
minutes instead of three, just because your eggtimer runs on
2 Mhz clock instead of the above rate and you missed
changing the constant clock in the source code.
For simulation of the source code some switches are included,
those accelerate execution. Make sure all those switches are
on zero before assembling the final version.
When programming the flash the fuses have to be altered once.
To switch the external crystal on, the oscillator fuse has to
be set. After that the ATmega8515 runs with 4.194304 MHz.
4.4 Hardware diagnosis
For testing the hardware of the eggtimer, I have written a
number of routines that check the hardware components. The
software is available as assembler source code
here. It has to
be edited to configure it, then re-assemble and burn the hex
file to the flash memory.
It includes the following routines:
All the routines can be activated by setting the respective
constants to one. Only one of the seven routines should be
set to one, only the first one switched on is executed.
- Port I/O test: tests the speaker output pin via SBI and
- Timer 1 IO: tests the speaker via OC1B toggling of timer
- Led: switches the LED to white by turning all three LEDs
on, the LED can be selected by setting dbgLedNr to a number
between 1 and 11,
- LedRot: rotates all 11 LEDs by switching them to blue,
green and red in a row,
- LedPwm: mixes the color of dbgLedNmbr (1..11) with the
blue portion dbgPwmBlue (0 ... 255), the green portion in
dbgPwmGreen and the red portion in dbgPwmRed, a delay
(between 0 and 255) can be added and reduces execution speed,
- Key: if the key is not pressed, LED1 is blue, if pressed:
- Key toggle: advances the color resp. the LED each time
the key is pressed, enables counting of toggle events on the
4.5 How the PWM works
First of all: all functions, such as
are performed inside the respective interrupt service routines.
There is nothing to do outside the ISRs, so it isn't necessary
to save and restore SREG.
- the LED PWM,
- key interrupts, and
- starting and stopping sounds,
4.5.1 Timing of the PWM
Secondly: you'll miss seconds and minutes counters. It is not
organized like this, as a second is not exactly to be defined
with a 4.194304 MHz clock. The time counters are behind the
No matter what this means per second, within 60 seconds the whole
counting mechanism provides one minute duration. So better forget
the seconds, they are of no use here.
- 240 (CTC-Divider) * 512 (colors) * 256 (PWM cycle length) * 8
(PWM repetitions per color) is exactly 251,658,240 clock cycles,
at a clock frequency of 4.194304 MHz exactly 60 seconds
- So the TC0-CTC has to be adjusted to divide the clock by
- The colors have to count from 0 to 511 in two phases of 256
- The PWM step counter counts up from 0 to 0 (256).
- A PWM cycle counter counts down from 8 to 0.
The timing of the PWM works as follows:
After that the minute increases and the cycle repeats with
the next LED, and so on until 11 minutes are over.
- The clock frequency of 4.194304 MHz is advancing the
timer (prescaler = 1).
- TC0 works in CTC mode, with compare port A set to 239.
This divides the clock frequency by 240 and triggers an
interrupt with a frequency of 17.476,26 kHz, every
- The PWM cycle increases the rPwm register, compares
if the blue, green and red compare values are reached
(and clears the respective LEDs if equal).
- Every 256 times the rPWM reaches zero again (every
14.65 ms). If the rPCnt, that was previously set to
eight, does not reach zero, the PWM cycle start condition
repeats, so that each PWM cycle repeats eight times. That
means 117.19 ms for eight repetitions.
- In PWM phase 1, the PWM values of the green LED
decreases by one and the blue LED increases by one. If
the green LED reaches zero, phase 2 starts, which turns
the blue LED off and the red one on. Phase 1 lasts exactly
- In PWM phase 2, the blue PWM value decreases by one
and the red value increases by one. This phase also lasts
exactly 30 seconds.
4.5.2 Organization of the PWM bits
The following organisation optimizes the software.
The 32 LEDs (10 * 3 + 2) are attached to
the I/O ports as shown here. During the PWM cycles the driver
direction for active LEDs is written to 1, for inactive LEDs
it is at 0. This allows to work with common anode as well as
with common cathode LEDs.
The organization of the register sets was chosen to avoid having
to write 22 different different rotines: two for each minute.
Two register sets are used during the operation:
- R3:R0 hold the start condition at each PWM cycle. That
is necessary because each PWM cycle is repeated eight
times, so that the start condition is needed each time
the PWM restarts. These registers are copied to the
second set each time the PWM cycle starts. In the first
cycle, the first green LED is fully on (PWM compare
value = 0, never reaches equality), the first blue and
the first red LED are switched off. The blue LED is
only switched on after its PWM value is larger than zero.
- R7:R4 hold the current condition at each PWM step.
Whenever the blue compare value reaches the current PWM
value, the blue bit in the respective register is written
to zero. The same for the green and the red bits. Following
the comparison, the content of all four registers R7:R4
is written to the I/O direction ports.
4.5.3 CTC access to PWM bits
Access to these bits in the different phases is organized as
follows. The pointer Y points to R0, the blue bit, located in
the register, is at 0x01 and points to the blue bit of
LED1. rBB is used all over the following procedures and always
points to the blue LED of the current minute.
Setting that blue bit in the start register set works like this
(r is a temporary working register, named rmp in the assembler
The access to the work register set is a bit different:
ld r,Y ; Read content of register R0 to r
or r,rBB ; OR with the blue bit
st Y,r ; Copy result to register R0
If a set bit shall be cleared (e. g. if the PWM cyle
counter matches the blue compare value, just replace the OR
by EOR, which clears the previously set bit.
ldd r,Y+4 ; Read content of register R4 to r
or r,rBB ; OR with the blue bit
std Y+4,r ; Copy result to register R4
The advantage of that is that Y can point to any of the four
registers in the start register set as well as to the four
working registers, too, by use of the displacement. If the
green bit shall be set, just shift rBB once left. But: if
the seventh bit is concerned, shifting means that the one
is shifted to carry. In that case the address in Y has to
be increased (by INC YL) and the one in the carry has to be
rotated into bit 0 of rBB.
Going from the first LED to the second is therefore simple:
just shift rBB three times to the left (and increase YL
plus rotate rBB again whenever a carry is shifted out of
rBB). But: it isn't that simple (see below for an example
moving from LED3 to LED4):
A lot of things to do. And we do have to take care that the
Interrupt Service Routine doesn't last longer and the next
CTC interrupt comes in before we finished that one.
Fortunately that lengthy routine occurs only once a minute,
so sending the controller to sleep to reduce power consumption
makes in any case sense. The sleep share in the final version
is at 89%, so it really makes sense to use that feature.
Of course, all four work bytes have to be written to the
four direction ports, because each step can change two of
those registers (if the red or green bit is located one
address higher, like in the example case above). I decided
to perform the output of the working register set to the
four direction ports prior to any further calculations in
the ISR routine. That ensures that the LED switching does
not depend from the duration of the further processes and
is always performed exactly in clock cycle 7 to 10 after
the timer reached its interrupt condition, no matter how
lengthy the ISR operations last.
4.5.4 A normal CTC cycle: comparing colors
With that a normal PWM cycle in the interrupt service
routine of the compare A interrupt of TC0 looks like shown
here (to the right). It starts with the output of the
working register set to the direction ports. Then the SREG
is read and the PWM cycle counter rPwm is increased. If
that reaches zero, a different path is followed (see below).
If not at zero, the three colors of the current LED have
to be checked if they reached their compare values and are
to be switched off.
First, the blue compare value is compared with the PWM
counter. If equal (Z flag is set after compare), the blue
bit is cleared with the EOR and written back to the
The pointer rBB is then shifted left to point to the green
bit. If the carry flag is set after shifting, Y is increased
and the carry flag is rotated back into rBB. Y and rBB now
point to the green color of the LED.
The green compare value is now compared with the PWM step
counter rPwm. If equal, the green bit of this LED is cleared.
Now again rBB is shifted to point to the red bit. If the
red compare value equals rPwm, the red bit is cleared.
At the end, the rBB and Y values have to move back to where
they started from.
The flow diagram has added the number of clock cycles following
the interrupt condition of TC0 has occurred. If all conditions
take the longest path (which cannot be the case) a total of
57 clock cycles would be consumed. At minimum (no switching of
LEDs, no carries when shifting) the duration is 41 clock cycles.
As the next CTC interrupt comes 240 clock cycles after the
previous one, this load is between 17 and 24% and in no case
exceeds the CTC cyle length of TC0.
4.5.5 Repetition of the PWM cycle
As described above, the PWM cycle is repeated eight times at the
same color. So this routine performs these repetitions: it counts
the counter down, if that does not set the Z flag, the start
value in the start register set is simply copied over the work
register set and after restoring SREG it returns from the
interrupt. When the next CTC interrupt comes in, the working
register set is written to the DDR ports and becomes active.
This part is even shorter than the compare run, but it appears
only once in 256 cases, so does not have much influence on
overall execution times.
4.5.6 The next color
If eight PWM cycles, with the same blue, green and red compare
values, have been performed, both rPwm and rPCnt reach zero.
That means that depending from the phase the
If in phase 1, both the green and blue LEDs are activated in the
start registers by ORing the register content at Y with rBB
and the once left-shifted rBB (of course with address
increase if carry occurs).
- green value decreases and the blue increases in phase 1,
- the blue value decreases and the red incraeses in phase 2.
If in phase 1 and both the green and the blue value reach zero,
If in phase 2, both the red LED is activated in the start
register by shifting rBB twice left and ORing the register
content at Y with rBB.
- the phase 2 flag is set, and
- rBB is shifted to the green LED, which is switched off
in the start register, the blue LED is switched off, but the
red LED is not yet on because rRed is still at zero. This
will be switched on in the next color cycle, and
- the rBB is shifted back to its original position.
4.5.7 The next LED
If in phase 2 and both the blue and the red value reach zero,
the minute is over and the next LED has to be activated.
Here, as an example, switching from LED3 to LED4 is shown.
LED3 is, with its blue and green diode, the leftmost part
of register R0, its red bit is at bit 0 of register R1.
The steps are as follows:
- first the phase 2 flag is cleared, because the next
color combination is phase 1,
- then the current blue bit is cleared by exclusive
ORing it with the bitpointer rBB, the current red bit
is not cleared but left active to signal the last
full minute when the next LED changes its colors,
- then it is checked if the last phase (LED 11) is
currently active, by checking
If both conditions are true, the active counting is
switched off by
- if Y is at 3, and
- if rBB is at 32 (= bit 5).
- switching the LED11 to red only,
- stopping the timer TC0 and its interrupts,
- writing the restart condition (Y=0, rBB=1) to
the start register set, and
- setting the Stopped flag.
- If Y=3 and LED10 is active (rBB is at 8 resp. has
bit 3 set), then
This finally jumps to the copy routine that copies the
values of the start registers R0 to R3 to the work
- LED11's rBB is set to the red bit of LED10 (LED11
has no blue LED attached), and
- the green bit of LED11 is turned on.
- If Y=3 and neither LED10 nor LED11 are active, then
the next green LED is activated directly by shifting
rBB four times left and performing the rest of the
- If Y is not yet 3, it is checked whether Y=0 and rBB=1,
because in that case clearing of the last LED is not
performed. If LED1 is active, the same shifting routine
(four times left to the next green LED) is performed
- If Y is not 0 or rBB is not 1, rBB is shifted right
to the red bit of the previous LED, which is turned off.
In that case five left shifts position rBB to the next
green LED. The next green LED is switched on and rBB is
shifted once right to point to the blue bit of the next
LED. Finally, the start values are copied to the work
register set and the routines end with RETI.
4.5.8 Common cathode LEDs?
Another hint: If you use common cathode LEDs only the
following change has to be made: at start-up set all PORTx
to all ones and not to zero. All other things remain the
same. The 50 kΩ of the internal pull-up resistors,
which are switched on when the DDR bits are off, causes
a current of less than 60 µA through the LEDs,
which is small and in any case invisible.
4.6 How the sound works
4.6.1 TC1 as sound generator
To generate sound, TC1 is set to CTC mode, with the compare
A port as CTC match. Compare B is set to 0 and drives the
OCR1B output pin: if the sound is on, the pin toggles, if
it is off, the output pin is cleared.
The duration over which the tone is activated is handled in
register pair R25:R24. This pair is counted down. If it
At the highest tone, a6 with 14.080 kHz,
the maximum tone duration is 2.3 s, at the lowest,
A1minor with 55 Hz, duration can be as long
as 596 s.
- the flag bSound is cleared,
- the OCR1B pin is set to clear, and
- the TC1 compare match A interrupt is disabled.
4.6.2 The gamut table
To enable a sound tone frequency the gamut is integrated as
a table in the source code. The gamutTable consists of
two words for every tone: the first is the CTC value (with
the MSB first when readout with LPM) and the tone duration
counter value for one second duration. All octaves from
A1minor over Aminor and a0
to g7 are in the table.
In the source code, the constant cOctave determines the
octave from which the 11 tones are taken from. cOctave can
range from -2 to +6. -2 starts with A1minor or
55 Hz and spans to e (165 Hz), -1 starts with
Aminor with 110 Hz and spans to
e1 (330 Hz). a2 with 880 Hz
should be a good selection (cOctave=2). Each minute plays
the next higher tone in the gamut for one second long.
The register pair ZH:ZL points to the current gamut position.
If the flag bPlay is set, the tone starts.
4.6.3 TC1 as sound checker
If no tone is active, TC1 serves as a sound flag checker. In
Following the tone generation, when the tone duration has
counted to zero, this mode is entered again.
This project demonstrates that
- TC1 interrupts on compare match B every 1 ms,
- downcounts the counter that is preset to the desired
- if zero checks for a set bit in the flag register to
start the next tone, and
- starts the sound generation with the tone that register
pair ZH:ZL points to in the gamut table.
This again demonstrates the extended opportunities that
programming in assembler offers. Not any other language
provides the opportunity for that kind of exact timing.
Do not try that in C, you'll end with lots of gray hair.
- it is possible to construct a three-channel PWM by
software, with 8 bits resolution on all three PWM
- the PWM works with a frequency of 68 Hz, and
outputs eight complete PWM cycles before advancing
to the next color, enough speed for tricking men's
eye and to avoid any flickering effects,
- unlike PWMs that are constructed with timers, the
output channels can be on any of the available I/O
pins (here: 32 pins) and are not limited to one pin
per channel, so we have a 32-channel-wide PWM here,
something that neither a MEGA nor any XMEGA provides
- it is possible to do that with controller clock
frequencies of less than 2 MHz and up,
- it is exact, and the switching point of the LEDs
every 57 µs does not depend on the different
tasks to be done within the CTC interrupt by placing
the output instructions of the PWM channels on top of
the interrupt service routine,
- with the use of AVR-specific instructions, such as
LD/ST as well as LDD/STD, the tasks can be optimally
solved, so that the programming structure is simple
and remains straight-forward, even considering the
complexity of the tasks.
Praise, error reports, scolding and spam please via the
©2019 by http://www.avr-asm-tutorial.net