Press "Enter" to skip to content

How to simulate candlelight with an Arduino

Here in Scandinavian countries we really enjoy the dark nights in the winter – we put up all kinds of decorations for Halloween and Christmas. Traditionally we have used ordinary candles in our various decorations, although candles posed some major drawbacks. The burntime is rather limited and we have to light them manually when wind gusts blows them out.

I have tried to buy LED candles from China but in all honesty they look just that – very fake and nothing like a real candle. So what to do?

Luckily it is possible to create a very realistic candle flicker effect using an Arduino or any other MCU – hardcore makers have even used the pic12f675 chip.

Candle simulator circuit

Parts I have used for this LED candle simulation

  • 1x 5mm Red LED
  • 2x 5mm Yellow LED
  • 3x resistors – be sure to match LED specifications
  • Photoresistor, Light dependent resistor
  • Arduino Pro mini
Measuring the light with a LDR
Light Dependent Resistor
66% yellow light 33% red light
Two yellow led and a red led

Step 1 – Soldering the LEDs and LDR

In order to create a realistic candle effect it is vital that we both simulate the colors and the flickering. This is possible with 3 leds where 66% of the light is yellow and the rest 33% is red – just like a real flame where most of the light is yellow.

Moreover we will need the light to be flickering and fading up and down randomly – this is something that the cheap chinese fake candles could never achieve since they give a much more mechanical effect.
But I will show you how to create a much realistic flame simulation.

Arduinos can fade LEDs using the inbuilt PWM pins – in this tutorial I am using the Arduino Pro Mini 328 – 5V/16MHz which has a total of 6 PWM pins.

I soldered the 3 LEDs to the corresponding PWM pins 3, 6 and 9. Remember to calculate the right resistor for the leds.

One of the goals with this project is that I don’t want to turn on and off the electric candle – the LED candle will sleep in daylight and only flicker in the nighttime. A light dependant resistor is simple device that changes its resistance when light shines upon it. I soldered the LDR to the ground pin and the analog A3 pin – measuring the light is simply done by the command analogRead(A3).

For practical reasons I added an on/switch that I have salvage from an old HP laser printer. The LED candle is driven by a battery box with 3×1,5V AA batteries.

Step 2 – The code

The Arduino will sleep in daylight and this is done by using the AVR libraries

#include <avr/sleep.h>
#include <avr/power.h>

The little Atmel MCU will sleep for 30 seconds and then wake up to see whether it is dark enough to wake up and start flickering the LEDs.

Arduino deep sleep
AVR deep sleep code example

The Arduino code

Download Arduino INO file (Save-As)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include &lt;avr/sleep.h&gt;
#include &lt;avr/power.h&gt;
// This variable is made volatile because it is changed inside an interrupt function
//volatile int sleep_count = 0; // Keep track of how many sleep cycles have been completed.

int thresHold = 300;

// LED Fire Effect

int ledPin1 = 3;
int ledPin2 = 9;
int ledPin3 = 6;

void setup()
{
//clock_prescale_set (clock_div_2);

watchdogOn(); // Turn on the watch dog timer.

// The following saves some extra power by disabling some
// peripherals I am not using.

// Disable the ADC by setting the ADEN bit (bit 7) to zero.
//ADCSRA = ADCSRA &amp; B01111111;

// Disable the analog comparator by setting the ACD bit
// (bit 7) to one.
//ACSR = B10000000;

// Disable digital input buffers on all analog input pins
// by setting bits 0-5 to one.
//DIDR0 = DIDR0 | B00111111;

pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);
pinMode(ledPin3, OUTPUT);

}

bool daylight = false;
long lastMeasured = -290000;

void loop()
{

if(daylight || abs(millis()-lastMeasured)&gt;300000)
{
// sleep_count is used - because we can't trust millis after sleeping
analogWrite(ledPin1, LOW);
analogWrite(ledPin2, LOW);
analogWrite(ledPin3, LOW);
delay(100);

if(analogRead(A3)&lt;thresHold)
daylight = false;
else
daylight = true;

lastMeasured = millis();

//sleep_count = 0;
}

if(daylight==false)
{
// CODE TO BE EXECUTED PERIODICALLY
analogWrite(ledPin1, random(120) + 135);
analogWrite(ledPin2, random(120) + 135);
analogWrite(ledPin3, random(120) + 135);
delay(random(100));

}
else
{
// Sleep again
goToSleep();
}
}

void goToSleep()
{
// The ATmega328 has five different sleep states.
// See the ATmega 328 datasheet for more information.
// SLEEP_MODE_IDLE -the least power savings
// SLEEP_MODE_ADC
// SLEEP_MODE_PWR_SAVE
// SLEEP_MODE_STANDBY
// SLEEP_MODE_PWR_DOWN -the most power savings
// I am using the deepest sleep mode from which a
// watchdog timer interrupt can wake the ATMega328

set_sleep_mode(SLEEP_MODE_PWR_DOWN);//SLEEP_MODE_PWR_DOWN); // Set sleep mode.
sleep_enable(); // Enable sleep mode.
sleep_mode(); // Enter sleep mode.
// After waking from watchdog interrupt the code continues
// to execute from this point.

sleep_disable(); // Disable sleep mode after waking.

}

void watchdogOn() {

// Clear the reset flag, the WDRF bit (bit 3) of MCUSR.
MCUSR = MCUSR &amp; B11110111;

// Set the WDCE bit (bit 4) and the WDE bit (bit 3)
// of WDTCSR. The WDCE bit must be set in order to
// change WDE or the watchdog prescalers. Setting the
// WDCE bit will allow updtaes to the prescalers and
// WDE for 4 clock cycles then it will be reset by
// hardware.
WDTCSR = WDTCSR | B00011000;

// Set the watchdog timeout prescaler value to 1024 K
// which will yeild a time-out interval of about 8.0 s.
WDTCSR = B00100001;

// Enable the watchdog timer interupt.
WDTCSR = WDTCSR | B01000000;
MCUSR = MCUSR &amp; B11110111;

}

ISR(WDT_vect)
{
//sleep_count ++; // keep track of how many sleep cycles have been completed.
}

Conclusion

Well, I think I succeed creation a pretty good illusion of a real candle flicking in the wind. Even my wife seemed pleased with the result and have asked me to create more of these candles.

Luckily it is now possible to get clone Arduinos for a fraction of the price of an original Pro Mini.

Planning to create your own LED candles – leave a comment below or subscribe to our YouTube channel.
You might even show your own creations.

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *