Make an LED Ring Light Up Smoothly?

I am working on a project that would look really cool if I was able to put a ring of LEDs (kind of like the one on the TRON Identity Discs) light up smoothly in a circle, rather than have sections of the LEDs light up one by one. I know EL wire will achieve that smooth, uniform look that I want, but I can't get EL wire to light up little by little in a loop.

Are there any ideas? I've thought about writing some script on a microcontroller that lights them up smoothly, but I'm not sure what kind of LEDs I would need for that, or if there may be an easier solution.

• Do you mean that all LEDs should light up together instantaneously (parallel them), they should light up in a visually linear increasing intensity ramp (I have an answer previously posted for that), or light up in sequence but with a smooth ramp-up profile for each consecutive one? – Anindo Ghosh Apr 28 '13 at 10:23
• I'll check out the visually linear increasing intensity ramp. I guess I couldn't find the words for it. Thanks Anindo. – M. Choi Apr 28 '13 at 10:52
• See the last part of this answer, the PWM curve you want is y = x ^ 2.5. I can write it up into an answer to this question if you like. – Anindo Ghosh Apr 28 '13 at 11:25
• I've never seen Tron but looks like Anindo has it covered – Andy aka Apr 28 '13 at 13:30
• Sparkfun sells some lightpipe that you might be able to illuminate from one side. – Eric Gunnerson Apr 29 '13 at 1:49

Breaking the problem into multiple blocks:

Hardware:

• LEDs:

The simplest implementation would involve 16 LEDs. If a smoother transition is desired, 32 or even larger numbers of LEDs could be used, with appropriate LED driver ICs.

• Constant current LED driver with built-in PWM dimming support

The Texas Instruments TLC5940 LED driver supports 16 LEDs, each with 12 bit (4096 step) PWM dimming. The PWM duty cycle for each LED is internally generated by the IC, relieving the microcontroller from intense timing and PWM generation effort. The part is controlled by a serial interface, and open source libraries exist for many common microcontrollers and development boards. Outputs are constant current sinks, so one saves on the per-LED current control resistors.

If 32 LEDs or more are desired for a smoother transition, the TLC5940 supports cascading, so a single set of control lines can program the entire array of LED drivers.

If one wants to go way over the top with a smooth track of LED illumination, then the Austria MicroSystems AS1130 132 LED driver, or even their 144 LED driver (AS1119) with its integrated charge pump for driving LEDs from a power rail lower than the forward voltage of your LED, might be of interest.

• Microcontroller:

Pretty much any microcontroller capable of driving a serial line (typically SPI) with a reasonably high data rate would suffice. An Arduino Uno, for instance, would be ample.

• Power:

Note that while individual LEDs apparently are not power hungry beasts, putting 16 or 144 of them in parallel translates to anywhere from a watt to 10 or more Watts, assuming just normal 20 mA indicator LEDs. Add to this the power consumption of the LED drivers themselves (e.g. 60 mA typical per TLC5940), and the power requirements become pretty hefty.

Software:

• Timing:

The microcontroller must be capable of transmitting the LED control packet(s) for all the LED drivers, at better than persistence of vision rates: Preferably more than 20 times per second for a static display, and 200 times per second or better for something that is intended to be moving. Also, the human eye is very sensitive to even minor glitches in a smooth light intensity transition, so the transmission of control data should ideally be driven from a stable counter interrupt, and no other microcontroller task should be allowed to preempt a LED controller refresh.

• Intensity calculation:

The computation of a reasonably linear (to the human eye) sequence of PWM duty cycles for a smooth transition involves approximately the following simplified formula: y = (x ^ 2.5) / k where y is desired intensity for step number x, k is a constant derived from available bit depth (resolution) of the PWM generator.

In simple terms: Smaller rise in duty cycle is required at low intensities, bigger jumps at high intensity, to appear linear in transition.

64 distinct intensity steps should suffice for reasonable transition smoothness, 256 if over-the-top is the flavor of the week. For 64 steps mapped to 4096 PWM values (12 bit PWM), the formula above works out to:

PWMvalue = (StepNumber ^ 2.5) x 0.125

It's not perfect but is pretty close.

For 256 steps and 12 bit PWM, the formula is PWMvalue = (StepNumber ^ 2.5) x 0.00390625

While this computation is trivial enough, for best performance it makes sense to compute the PWM values for each step in advance, and incorporate them as a static array, a lookup table (LUT) within the code. This saves precious cycles during run-time, by retrieving from an array rather than calculating exponential values.

• Implementation logic:

In each refresh cycle, update PWM duty cycles for each LED as per the LUT, leaving a gap of say 64 / 4 = 16 steps between consecutive LEDs. Thus, the first LED will smoothly transition from zero to full within 64 refresh cycles, the second LED will start on the 16th refresh cycle and, the 3rd LED on the 32nd refresh cycle, and so on. For 16 LEDs, 64 x 4 = 256 cycles will leave all LEDs full lit. Calculate the maximum time per refresh by dividing the desired transition time for the full "Tron ring" by 256, and set your refresh interrupt counter accordingly.

If you actually implement a Tron ring, please do share a video. The videos of DIY Tron disc light-up implementations currently found on YouTube are way too rudimentary.

• Could you provide some references from where did you take this formula: y = (x ^ 2.5) / k ? – m.Alin Aug 13 '13 at 12:54
• @m.Alin Please see this, and your prior query about the same subject and my responses. :-) – Anindo Ghosh Aug 13 '13 at 13:56
• Thanks Anindo and sorry, I forgot that I already asked you the same question.. :) – m.Alin Aug 13 '13 at 14:12