Path: Home => AVR-EN => Applications => Eggtimer RGB m8515   Diese Seite in Deutsch: Flag DE Logo
RGB display of time 15:39:13 AVR applications

Eggtimer RGB with ATmega8515
Hardware, Mounting, Application and Software for a 11 minute eggtimer

Eggtimer RGB with ATmega8515

  1. Properties
  2. Hardware
  3. mounting
  4. Software
  5. Conclusions
This describes a timer, that operates with 11 RGB LEDs. It can be used to control the cooking process of eggs.

1 Properties of the eggtimer with ATmega8515

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 website.

Page top Properties Hardware mounting Software Conclusions

2 Hardware

2.1 Selecting the AVR device type

Selecting the ATmega8515 Accessing 10 or 11 RGB LEDs requires at least four 8-bit ports (32 I/O pins). Additional pins should allow to
  1. play music over an OCR pin, to which a speaker could be attached,
  2. attach a key to stop and restart the timer.
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
==> 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 driven.

2.2 Schematic

Schematic of the eggtimer 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.

Crystal frequencies for that task 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).

Internal RC clocking 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 source code.

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:
  1. 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.
  2. 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.
  3. 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 light.
  4. 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 Libre Office calculation sheet measured for the factually measured voltages and LED currents of the final device.
  5. 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.
  6. The resistors are
    RLED = (Vop - VLED - Vsink) / ILED
  7. I chose the nearest values from the resistor row E24, which are available by my electronics dealer.

Resistors at different operating voltages The table provides the blue, green and red resistors for three operating voltages:
  1. for 3.7 V, which is the minimum and provided e. g. by larger Li cells,
  2. for 4.5 V, which come out of three cascaded AA(A) battery cells, and
  3. for 5.0 V, if you want to use an USB plug or an external power supply.
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.

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.

See the Libre Office calculation sheet for more details.

Page top Properties Hardware mounting Software Conclusions

3 Mounting

3.1 PCB

PCB for the eggtimer For convenient mouting a single-sided PCB layout was designed. It covers half of a euro format (100-by-80 mm).

Component placement on the eggtimer PCB 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.

3.2 Final

After the hardware is complete, the different components can be tested. See the Software section for a test program.

Top view The PCB is covered with an acrylic glass cover in 10 mm distance, for which holes for the LEDs, the key and the switch are screwed.

Side view 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.

Page top Properties Hardware mounting Software Conclusions

4 Software


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.

4.2 Assembling

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.

4.3 Fuses

Fuses of the ATmega8515 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:
  1. Port I/O test: tests the speaker output pin via SBI and CBI instructions,
  2. Timer 1 IO: tests the speaker via OC1B toggling of timer 1,
  3. 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,
  4. LedRot: rotates all 11 LEDs by switching them to blue, green and red in a row,
  5. 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,
  6. Key: if the key is not pressed, LED1 is blue, if pressed: green,
  7. Key toggle: advances the color resp. the LED each time the key is pressed, enables counting of toggle events on the key input.
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.

4.5 How the PWM works

First of all: all functions, such as
  1. the LED PWM,
  2. key interrupts, and
  3. starting and stopping sounds,
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.

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 following:
  1. 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 long.
  2. So the TC0-CTC has to be adjusted to divide the clock by 240.
  3. The colors have to count from 0 to 511 in two phases of 256 steps each,
  4. The PWM step counter counts up from 0 to 0 (256).
  5. A PWM cycle counter counts down from 8 to 0.
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.

The timing of the PWM works as follows:
  1. The clock frequency of 4.194304 MHz is advancing the timer (prescaler = 1).
  2. 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 57.22046 µs.
  3. 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).
  4. 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.
  5. 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 30 seconds.
  6. 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.
After that the minute increases and the cycle repeats with the next LED, and so on until 11 minutes are over.

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.

I/O ports and register organization 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:
  1. 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.
  2. 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

Flow diagram normal PWM cycle 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 source code):

  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

The access to the work register set is a bit different:

  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

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.

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 working register.

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

PWM repeat 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

Flow 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
  1. green value decreases and the blue increases in phase 1, or
  2. the blue value decreases and the red incraeses in phase 2.
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).

If in phase 1 and both the green and the blue value reach zero, the
  1. the phase 2 flag is set, and
  2. 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
  3. the rBB is shifted back to its original position.
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.

4.5.7 The next LED

Flow to 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. Example for preparing the next LED The steps are as follows:
  1. first the phase 2 flag is cleared, because the next color combination is phase 1,
  2. 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,
  3. 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
  4. 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 register set.
  5. 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 copy routines.
  6. 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 next.
  7. 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.

Page top Properties Hardware mounting Software Conclusions

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 reaches zero,
  1. the flag bSound is cleared,
  2. the OCR1B pin is set to clear, and
  3. the TC1 compare match A interrupt is disabled.
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.

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 this mode,
  1. TC1 interrupts on compare match B every 1 ms,
  2. downcounts the counter that is preset to the desired check frequency,
  3. if zero checks for a set bit in the flag register to start the next tone, and
  4. starts the sound generation with the tone that register pair ZH:ZL points to in the gamut table.
Following the tone generation, when the tone duration has counted to zero, this mode is entered again.

5 Conclusions

This project demonstrates that 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.

Page top Properties Hardware mounting Software Conclusions

Praise, error reports, scolding and spam please via the
comment page to me.

©2019 by