Two years ago, I spent some time analyzing the algorithm used in a candle flicker LED as commonly found in cheap artificial candles. I reverse engineered the algorithm from the flickering pattern and recreated the algorithm in software. Turns out this is of interest for many people who are searching for artificial candle algorithms – there is a surge of traffic every year around December. However, I just reverse engineered one of the controller ICs – this does not mean that this is a good approximation of a real candle.
But how to get there? First, we need to understand how a real candle behaves. In a recent comment, Gary made the excellent suggestion to record a real candle on video and analyze the data. I noticed something similar could be done in a very quick-and-dirty way, by connecting a photodiode to a digital storage oscilloscope.
My five-minute experimental set up is shown above. I used a large area (~7 mm²) photodiode and connected it to a 10 kOhm sense resistor. The distance between photodiode and flame was around 4-5 cm. The candle generated enough photocurrent to cause a voltage of ~100 mV across the sense resistor. This can be fed directly into an oscilloscope without additional amplifier. I used the deep sampling mode of a DS1052E oscilloscope and decimated the sampled data by a factor of 100 to get better sampling resolution. This allowed me to capture around one minute of light intensity data at an effective sampling rate of 175 Hz.
The figure above shows a measurement of the undisturbed candle in motionless air. The lower plot displays the variation of intensity over time. The heat map above shows the autocorrellation of 1500 ms slices along the same time axis.
Interestingly, even without any outside interference, there is a steady change in brightness. This is almost invisible to the eye, as it is a change of around only 5% on a scale of seconds. The autocorrelation shows that there is no long-range order in this pattern (red is the maximum in the heat map and shows only up for zero lag). Further statistical analysis shows that the distribution is symmetric and normal.
The physical origin of this effect is not clear to me. However the pattern could possibly be simulated with a constrained random walk (here are some examples). Although, this slow variation is hardly visible due to its low magnitude, and exact reproduction may not be crucial to emulate the appearance of a real candle.
Things get much more interesting, if the candle is disturbed by gusts of air. The figure above shows an experiment where I disturbed the candle by carefully, but completely unscientifically, administering a pulse of air by blowing at the candle.
Each pulse leads to a quickly varying change in brightness (“flicker”) above the base level – the candle actually gets brighter. Interestingly, the flicker has periodic characteristics (“oscillations”), as evident from the autocorrelation plot. The frequency of these oscillations seems to be around 5 Hz, drifting up, and seems to be a fundamental parameter of the flame since it appears to be relatively constant in all observations.
The trace above shows the details of a single, representative, event. There are three distinct features, marked with A, B and C.
- A) Initial drop in brightness: This seems to be associated with the arrival of the air pulse. Possibly the candle is depleted of flammable gasses here?
- B) Chaotic oscillations: This could be due to turbulence of the in rushing air, which exerts varying force on the candle.
- C) Harmonic oscillations: This seems to be an intrinsic process of the candle that was initiated by the external pulse. At this point, there is probably no additional external force acting on the flame. The oscillations are damped and die off after around 3 seconds.
This behavior is quite complex and even a purely empirical model is not easy to derive. Is there a chaotic oscillator that can be easily parametrized to behave in a similar way? Alternatively, one could simply ignore the chaotic oscillation in region B). Then the flickering could be simulated using a damped harmonic oscillator. It is quite possible that the visual difference is negligible.
Alternatively, a much more pragmatic solution would be to use snippets of recorded temporal brightness variations and rearrange them randomly.
To test this approach, I generated animated gifs of the recorded data.
31 thoughts on ““Reverse engineering” a real candle”
I did this exact same thing because I’m generally unsatisfied with most commercial LED candles. I haven’t codified the results into a hacked candle yet, but looking forward to doing it.
I’d love to see an artificial candle with a mic that flickers when it detects air :P. Great work
With a threshold that, once crossed, powers off the candle?
They already have some that do the power on/off by blowing on them.
I recall seeing it done in a electronics magazine a few decades ago – it also included a photosensitive element so you could not only “blow it out” with air but also “light it” with an actual flame – the artificial flicker was probably rubbish compared to this though…
I’m certain I’ve seen these commercially available
Nice! You can use CFD software like Comsol to create a very accurate model of a flame and directional forces acting upon it (blowing air). After you understand how the hot gases of the flame behave you could probably feed your simulation results into a custom Matlab program that would estimate light emission given temperature readings at many points in space around the flame. You could simply take those temperature readings and map that into a voltage range for a single LED. Could probably be done in a single weekend!
P.S. There’s many simplifications I made but this should yield a more accurate model.
“Check out my realistic LED candle. It uses an array of mass air flow sensors to approximate the airflow around the candle. The DAQ is connected to that server sitting over there that’s is running the realtime fluid dynamics simulation on a quad GPU setup to simulate the flame. Best part is, I didn’t have to use my heater all winter!”
The temporal intensity signature is only half of it. The flame of a real candle also bobs around in space. This is particularly noticeable if any objects near the candle are casting shadows. I’d love to see you extend your research to mapping the x/y/z motion of the flame. (Flame size is probably also significant, but I’m guessing less noticeable than centroid position and intensity.)
Do you think the ‘steady change in brightness’ that he observed in the undisturbed candle might have just been the changing distance from the photodiode?
Maybe so. Although if the flame is moving in space, that must be due to air disturbance, which would (I think) also affect the intensity.
Perhaps this would be a good setup for capturing the x/y coordinates and intensity of the flame: tripod mounted CCD looking directly down at the flame (i.e. on the z-axis). A long focal length to minimize any effect of z position on observed intensity.
Nice post, Tim.
A while I made an LED candle using a photodiode to “record” a real candle then “play” it back on an LED. The result is significantly more realistic than some of the E-Candles I have seen.
Put a low mass thermistor near the LED set so the current thru it induces a self-heating effect [like in a mass air flow sensor], measure the resistance changes of air drafts or puffs of air, and you could mimic the flicker effects of air blowing on a real candle. Also, a cluster of 3 or 4 LEDs slowly shifting in individual intensity, modulated by the main brightness modulation could mimic the ‘bobbing’ effect of the candle flame.
You could use a simple autoregressive model fed with random noise to simulate the candle.
Did you gamma correct the animations btw?
An autoregressive model requires constructing a polynomial that models the physical behavior right? I’m really interesting in how exactly you’d derive such a polynomial?
Most simply? An LPC analysis, just that.
In 1996 I did something similar, using triangle-wave LFOs and a pair of 7W AC bulbs to mimic the movement of flame on a gas mantle. LEDs in place of the AC hardware would probably do the same, though some bias to compensate for the froward voltage drops would be needed. http://www.phantasmechanics.com/alf.html
They have a new style now that’s totally incredible using (I believe) a small magnet and a light that reflects off of a dancing plastic piece. I saw these at a party once and was just amazed because from a distance of about 10 feet, you couldn’t even tell it wasn’t real. I’ve been looking around for an extremely high-quality solution to candles that light on a timer, and so far, these were the best I’d ever seen. They take “D” sized batteries, though, which is crazy.
Just saw this on learn.adafruit.com, made using a video of a real candle:
That one looks pretty nice. It is probably inspired by this one:
So, I finally have been able to replicate a candle in a very very very realistic way with some Gaussian distribution using the numbers given on your study of the candle light, so here are the numbers
Probability Random LED Brightness
50% 77% – 80% (its barely noticeable)
30% 80% – 100% (very noticeable, sim. air flicker)
5% 50% – 80% (very noticeable, blown out flame)
5% 40% – 50% (very noticeable, blown out flame)
10% 30% – 40% (very noticeable, blown out flame)
all of this with a Gaussian actualization time.
Probability Random Time
90% 20 ms
3% 20 – 30 ms
3% 10 – 20 ms
4% 0 – 10 ms
To avoid a pattern that runs too tight, in general my 20 ms are there to create a 5 hz noticeable “flickering” because of the probabilities of the first step, as there is a huge probability of having a nominal state a few times followed of a spike, yet as there is a 20% chance of getting selected a low state, it’s very likely to happen a nominal-high-low pattern overtime, but like in a real candle it’s not gonna happen every single time and not at the exact time, so overall due to my clock speed I ended looking at 20 ms for a 5 hz pattern to appear, if your microprocessor its not an arduino uno just play with the 20 ms, eventually you’ll get it
Interesting, thank you for your feedback!
If I understand correctly, you simply varied brightness and duration according to a weighted gaussian distribution? So there is no “memory” of the previous state?
exactly, there’s no need, as this its the pattern most likely to happen anyway, sure, sometimes it will not happen exactly like that but that’s exactly why it works so well, just as in nature, there is a slight chance of something “random” to happen, sometimes it looks undisturbed, and some times its very disturbed, some times the flicker its just crazy, sometimes its kinda slow and that makes it look realistic, but if you take a median pattern it will be nominal-high-low at 5 hz over time with a maximum variation of relative 50% of nominal luminosity
Any chance you are making your code public? Sounds like a very nice library to be hosted on github 🙂
Interesting! I am going to try this!
Are your brightness numbers percentages of the duty cycle, or true apparent brightness? like here: https://learn.adafruit.com/led-tricks-gamma-correction/the-quick-fix
Interesting! I am going to use this!
Are the numbers calculated as percent of the duty cycle, or true apparent brightness?
Like here: https://learn.adafruit.com/led-tricks-gamma-correction/the-quick-fix
I have also been generally unhappy with the results of commercial flame/candle simulators, and even my own LFSR based designs aren’t truly satisfactory, despite all sorts of filtering. I stumbled upon this blog while searching for better algorithms, and I must say, the idea of using recorded samples is a good one. I have downloaded the two CSV files to see what I can gin up in an FPGA as far as using it as prerecorded brightness data to drive an existing color palette map and associated RGB LED.
As an aside, have you considered recording data from multiple angles around the flame to get spatial data as well? Playback would be to a LED board with LEDs placed at the same angles. I remember a commercial “luminary” box that had three LEDs in it that worked fairly well, so recording at 120 degrees would work a treat.
You could build a Markov chain from the sampled data, that should produce a very convincing simulation of candle flicker without any need to understand a physical model. I suppose that’s basically what you did by taking snippets of the actual recorded flickering and then randomly rearrange them.