Date: March 13, 2009 | Comment

If you’ve visited my web site on backyard railroad illumination, you know about my fixation with creating light that flickers as though it were a fire (either from candle or a fireplace).

Schematic of circuit to fade, flicker single LED (click to download PDF)

Schematic of circuit to fade, flicker single LED (click to download PDF)

The first solution to that problem was to modify LED tea candles — readily available at crafts stores and even Walgreens — so that they would work off of standard 12-volt garden lighting (aka: Malibu lighting).

The dirty little secret of that method is that all the tea candles flicker at the same time. I’m not quite sure why this is so — perhaps the proprietary microcontroller used in those devices is time based and since they all start at the same time, they seem to work in synch? In any event, it does make looking at all the “fires” on my layout pulse at the same time.

So, in the back of my mind, I knew I wanted something besides tea lights to make flickering light on the layout. I kept looking around the net, and in January a reader of the backyard illumination site pointed me to an Instructables that showed a circuit to increase the current that could pass through a tea light, allowing up to four LEDs to be driven in the circuit.

The Instructables site provides a “related” window in the right-rail and along with the increased current circuit there were a couple of other “LED candles” that caught my fancy.

One, which by March seems to have been removed from the site, used the concept of the linear feedback shift register to control the flickering. Unfortunately, it was written for a Pic12F675, not an AVR (reading the datasheets, I decided that an ATTiny13 would be the equivalent controller).

What I liked about this idea was that it utilized seven of the eight pins of the microcontroller — it drove five LEDs (which is five of the pins and one each for power and ground). There were other circuits on the ’Net and Instructables that used just one LED, but none used all five (this was in January).

So, I bought a handful of ATTiny13s at Jameco and set about to build the circuit and convert the code.

I didn’t really get anywhere. So, I started writing my own code. For the first shot, I decided to control just a single LED (crawl before walking).

The circuit illustrated above and the code below do that. What’s different (it turns out) from what I’ve done here and what others around the ’Net have done is that I’m fading the LED from dark to bright in a random manner.

I do this without using hardware pulse width modulation (PWM); I chose to skip hardware PWM because of the way the ATTiny13 is configured: the PWM pins are also the pins that are used for programming. To use hardware PWM I would have had to program the chip, power down the circuit, connect the LEDs, run the program and to debug, do the steps in the opposite order.

Easier to write my own PWM code, I thought ;-)

The code makes (to my eye, at least) a more realistic candlelight flicker. But, it is just one LED and while that might be enough for somebody else, I’ve got four more pins to use in this project and I’m going to figure out how to use them.

I’m working with another developer over at Ladyada forums and I hope to have a five-LED version of fading code work on an ATTiny13 shortly.

For now, though, here’s Version 1, the single LED fading digital candle:

/*
* DigitalCandle -- Version 1
* -----------
* Use random numbers to emulate a flickering candle on a single LED without hardware PWM 
* 
* David M. Cole <cole@dmcole.net>
* License: 2009 Creative Commons Attribution-Noncommercial-Share Alike 3.0 U.S.
* Target: ATTiny13
* Compiler: AVR-GCC
*/
 
#include <avr/io.h>														// Defines pins, po
 
//	Declare variables
//	==============================================
	uint8_t x, y, z, i, j;
//	==============================================
 
	int main(void)
		{
			DDRB = 0b11111111;										// PortB all outputs
 			for(;;)												// loop forever
 				{
		 			x = 4;
					y = rand(1,255);
					z = rand(63,255);
					for (i = z; i < y; i++)								// the fading in loop
						{ 
							PORTB = 1 << x; 						// light on 
							for (j=0; j < y; j++)
								{
									if (j > i)
										{
											PORTB = 0 << x;	 		// light off 
										}
								}
							}								// end fade in 
					y = rand(1,255);
					z = rand(63,255);
					for (i = y; i > z; i--)								// the fading out loop
						{
							PORTB = 1 << x;							// light on 
							for (j=0; j < y; j++)
								{
									if (j > i)
										{
											PORTB = 0 << x;			// light off
										}
								}
						}									// end fade out
				}
		}

Leave a reply