26
\$\begingroup\$

I'm considering taking on a project that would involve individually addressing 500 LEDs, optimally with PWM support for each.

I'm planning on using an Arduino since I already have one, but I'm open to suggestions if anyone thinks a different platform would be a better match.

Shift registers would need to be employed. What is a good shift register to use in this situation? If PWM makes this project a lot more expensive, I'm alright to do without it. I want to try to spend less than $100. I'd bulk buy 500 LEDs off ebay.

What is your opinion on the best way to control such a large number of LEDs? Also, how would I go about providing the power? I'd appreciate any help. I'm fairly experienced with electronics, I've just never done anything on such a large scale.

\$\endgroup\$

15 Answers 15

16
\$\begingroup\$

I am the author of the ShiftPWM library and I just updated the documentation to include schematics and a lot more general info for normal LED's, LED strips and high power LED's.

You probably already started your project, but since this page gets a lot of visitors, I'd still like to provide a detailed answer.

If you want to control 500 LED's with ShiftPWM, you can get about 64 brightness levels per LED at 60 Hz. You would use 64 shift registers. Dedicated hardware PWM drivers will give you more brightness levels, but will be a bit more expensive. I think the main advantage of my library is ease of use, because it includes RGB and HSV functions and a lot of examples.

I would personally go for the TLC5916 of TLC5917 instead of normal shift registers, because they have a built in constant current LED driver. This will save you a lot of soldering, because you don't need resistors.

On my website ( http://www.elcojacobs.com/shiftpwm ) I have more info on how to connect the LED's and how to deal with driving the long signal wires with the Arduino at high speeds.

If you have any more questions, please ask.

\$\endgroup\$
4
  • \$\begingroup\$ Have you looked at my answer below? Although the technique I describe uses extra hardware, the same approach could probably be used to vastly improve the speed of your library. I've not programmed the Arduino, so I'm not familiar with its instruction timings, but in simplest form you could reduce your CPU loading to whatever would be required to simply blast bits out the SPI (if you're presently at 5 cycles per bit and your SPI takes 16 cycles per byte, that would be a 2.5x speedup). You might even be able to do some more sophisticated things while still running at that speed. \$\endgroup\$
    – supercat
    Aug 9, 2012 at 23:08
  • \$\begingroup\$ For example, suppose you want to have eight brightness levels representing full-on, 1/2, 1/4, 1/8, 1/16, 1/32, 1/64, and 1/128. If the Arduino can perform an "AND" or "OR" operation on a value fetched from a pointer and increment that pointer in less than four cycles, you could probably use three bits per pixel to store your brightness information and still achieve a transfer speed of 16 cycles per 8 LEDs. \$\endgroup\$
    – supercat
    Aug 9, 2012 at 23:11
  • \$\begingroup\$ Calculating the PWM values overlaps the SPI output in my library. I run the SPI at 4MHz and the calculations take just a bit longer than the SPI output. It takes 43 clock cycles per byte, so per 8 outputs. This is fast enough for most setups. You can get more speed by using bit code modulation, where you have 8 update periods, each next period half the duration of the previous. I have written a BCM version, but it is more sensitive to the moment when you update the brightness setting. It can cause flickering when it is misaligned. I will probably use it in the matrix version though. \$\endgroup\$
    – ElcoJacobs
    Aug 11, 2012 at 13:53
  • \$\begingroup\$ BCM has the advantage of your approach that you can make use of the 1/2,1/4... timing, but still takes only one pin per LED. If you have a computer science background, you might find it interesting how the SPI bytes are calculated. I receive the duty cycle from memory (2 clocks) and do a compare(1 clock). The compare result is stored in the carry, so I can shift it into the byte with a rotate over carry (1 clock). Doing it 8 times puts all the compare results in one byte which is ready to send to the SPI. \$\endgroup\$
    – ElcoJacobs
    Aug 11, 2012 at 14:02
14
\$\begingroup\$

Just copy :-)

http://www.evilmadscientist.com/article.php/peggy2

Today we’re releasing an update to our “Peggy” open-source LED Pegboard project. Peggy version 2 has been redesigned from the ground up. And it looks… almost exactly the same. The changes under the hood are substantial, though, and we think that it’s a big improvement in many ways.

First and foremost, Peggy 2.0 still does the same darn thing: it provides efficient power to a 25 x 25 array of LED locations. Peggy is designed to take some of the sting, complexity, and mess out of playing with LEDs. It’s a versatile and powerful light-emitting pegboard that lets you efficiently drive hundreds of LEDs in whatever configuration you like, without so much as calculating a single load resistor. You can install anywhere from one to 625 LEDs, and Peggy will light them up for you.


Peggy 2.0 is now also Arduino compatible: it supports programming through a USB-TTL cable, using the popular Arduino software environment.

\$\endgroup\$
3
  • \$\begingroup\$ Wonderful link! Bookmarked. I was not planning to work on a project like this, but I have to make it now I saw that little video :-) \$\endgroup\$ Jun 30, 2010 at 14:22
  • \$\begingroup\$ @NicolaeSurdu Not broken. I opened it just now. \$\endgroup\$
    – Axeman
    Oct 20, 2012 at 11:49
  • 3
    \$\begingroup\$ Whilst this may theoretically answer the question, it would be preferable to include the essential parts of the answer here, and provide the link for reference. \$\endgroup\$
    – user17592
    Jun 21, 2013 at 10:24
7
\$\begingroup\$

What layout do you want the LEDs in? You can save a lot of work if you buy some LED matrixes, you can get single-color 8x8 LED matrixes (64 LEDs) for a buck or two.

You're not gonna get real PWM with an AVR and shift registers on this many LEDs, but you may be able to squeeze 2-4 levels of brightness. You'd have to run the numbers and see what's possible.

Allegro makes some handy constant current sink shift registers specifically designed for controlling arrays of LEDs, so that you don't need the extra resistors, that will make things simpler as well. You might not be able to drive the LEDs directly from the AVR output if it can't provide enough power, so you'll need to use transistors. You can get them in arrays in a single IC, that saves some work too.

\$\endgroup\$
1
  • \$\begingroup\$ all very good points! \$\endgroup\$
    – Jason S
    Dec 21, 2009 at 12:43
6
\$\begingroup\$

I've no idea of the range of PWM you need for an LED but I've been working on a 64 channel PWM controller for a servo control application that can give me pulses of between 600us and 2.4ms. This uses CD74HCT238E's (3-8 line demultiplexors) to generate 64 channels from 8 I/O pins on an ATMega168 and is controllable via simple serial commands. I guess you could chain multiple versions of a modified version this controller together on a serial line and address all 500 LEDs... You could probably use the ATTiny2313 version of the controller as your firmware requirements would be simpler.

My blog contains the assembly source and schematics and details of the design process.

\$\endgroup\$
6
\$\begingroup\$

Check out "LED driver" ICs on mouser/digikey. TI, for example, makes a bunch of drivers with a variety of interfaces (I2C, SPI) that would certainly meet your needs. Most of these drivers are designed to be daisy chained so the serial out from one is fed into the serial in of another.

For example, something like the TLC5940 offers 16 channel PWM control. So, basically it's a constant current 16-bit shift register with 12-bit grayscale PWM control. I can recommend that particular IC as I helped design an 80x16 display with it.

\$\endgroup\$
5
\$\begingroup\$

Mondomatrix makes some serial (rs-485) addressable LED driver boards, and is based on the Arduino platform: http://www.displayduino.com/ You might be able to put together a system using that hardware fairly easily

\$\endgroup\$
4
\$\begingroup\$

If you don't want too many bits of PWM control for each LED, and you want to avoid having to have a processor fumble with 500 LED's every PWM cycle, you can control 8 LEDs with N bits of brightness using N 74HC595 or equivalent chips. Wire the outputs of all N chips together, and wire the enables to some circuitry which will only enable one at a time with suitable timing. Arrange so the first chip will be enabled half the time, the second will be enabled for half the remainder, etc.

Any reload of the shift registers should be synchronized with the PWM rate, so as to minimize aliasing effects (e.g. if a brightness level was switching rapidly between 0111 and 1000, the point in the PWM cycle when the switch occurred could momentarily change the apparent brightness).

While having to use multiple 74HC595 outputs for each LED may be annoying, this approach is probably the simplest one that could maintain different brightness levels without ongoing CPU intervention.

\$\endgroup\$
3
\$\begingroup\$

This does not directly answer the question, but another aspect you may need to consider is the possible brighness variability among LEDs in your 500 batch. That is particularly important if these LEDs are mounted near each other, like in a matrix or in 7-segment displays. See this answer for more details about how to address this issue, in particular, using dot correction to compensate for variations in LED brightness.

I've experienced this problem when I got 200 1mm red LEDs for a set of large 7-segment displays I was building. My cheap solution to solve the problem entailed the following:

  1. I built a LED tester in a breadboard to classify sets of leds in various brighness categories
  2. I mounted each segment using LEDs in the same category (in my design, each segment consisted of 5 LEDs mounted in series)
  3. I compensated for the difference in each segment brightness using different current limiting resistors. For example, for a segment with brighter LEDs, I would use a 100 ohm resistor, while, for another segment with dimmer LEDs, I would use 120 ohm resistors.
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Valid point, but doesn't answer the question. \$\endgroup\$
    – Matt Young
    Dec 12, 2013 at 13:04
  • 1
    \$\begingroup\$ @MattYoung Agreed. The question is largely answered by all the other answers. I just wanted to complement those answers, addressing a side issue that may affect the OP's design. \$\endgroup\$
    – Ricardo
    Dec 12, 2013 at 13:11
2
\$\begingroup\$

Dedicated driver chips with serial interfaces will indeed probably be the best route. Dealing with individual shift registers will probably mean a very complex circuit. At least Maxim and TI make some. I don't remember if either has a model particularly suited for that much.

It will still take a lot of hardware.

As for power, programming, and buses, the datasheet for each driver will probably have most information you'll need.

\$\endgroup\$
2
\$\begingroup\$

Within the software realm, if the number of distinct brightness settings one needs isn't too large, it may be helpful to store the data in "bit-planar" format (as described in my other hardware-based answer) and then have the output routines use Boolean operators to act on 8 pixels at once. For maximum efficiency, this will require having multiple separate output routines, used for different parts of the PWM cycle; for example, if one wishes to use 4-bit brightness values, one would use eight routines of the form:

  movf  bit0Comp,w  ; Should be 00 or FF depending upon bit 0 of comparand (FF if clear)
  iorwf POSTINCF,w  ; Bit 0 of data; always use IORWF
  andwf POSTINCF,w  ; Bit 1 of data; use IORWF if bit 1 of comparand is set; ANDWF if clear
  andwf POSTINCF,w  ; Bit 2 of data; Use IORWF if bit 1 of comparand is set; ANDWF if clear
  andwf POSTINCF,w  ; Bit 2 of data; Use IORWF if bit 1 of comparand is set; ANDWF if clear
  movwf SPIREG      ; Store resulting byte (bits set if >= comparand)

One would use different combinations of IORWF and ANDWF, depending upon the value of the comparand. Note that using this approach as illustrated, one may update pixel brightness values at any point in the PWM cycle without flicker provided that all four bits are written between calls to the display-shift routine, or by having the pixel-update routine determine whether the next shift will output a "1" or a "0" for the pixel, and either setting or clearing all bits of the pixel (whichever operation would make it do whatever it was going to do anyway) and then writing any bits whose value should be opposite. Note also that one may achieve arbitrary non-linear brightness scales by varying the timing of the display updates, or by using some comparand values more than once in a PWM cycle. Non-linear brightness scales are often useful with LEDs, since the difference in brightness between 1/128 duty and 2/128 duty is generally far more visible than the difference between 127/128 and 128/128 (or even between 7/8 and 8/8).

\$\endgroup\$
2
\$\begingroup\$

You can almost certainly do this easily using a PSoC3 or PSoC5.

The PSoC chips are microcontrollers that contain re-configurable digital hardware, a bit like an FPGA or CPLD. This means you can make complex circuitry for doing unusual things like driving 500 LEDs with PWM. What's more, you can probably implement the whole thing using the re-configurable digital blocks, meaning that the CPU part of the chip only needs to write the desired LED brightnesses into an array.

504 LEDs fit in a rectangle 21 x 24. If you had 24 PWM channels, and 21 GPIO, then you could get this working. Guess what? The PSoC has more than that.

You can set up 24 PWM channels easily on a PSoC, and configure 21 other pins to be part of a shift register. Next, configure some DMA channels to pump bytes from memory into the PWM outputs, and you're laughing. All the CPU needs to do now is generate the graphics. The PSoC3 has an 8-bit 8051 core, while the PSoC5 has a 32-bit ARM. Take your pick. The only external ICs you will need are some ULN2803s to provide the high drive current for the rows. The PWM outputs should have enough current drive for single LEDs.

\$\endgroup\$
2
  • \$\begingroup\$ This is total overkill for driving LED's. There are dedicated, cheap, pre-designed LED drivers made for chaining up large amounts like this that are used for gigantic displays all the time. No need to re-invent all that and for greater cost. \$\endgroup\$
    – nemik
    Aug 16, 2012 at 2:11
  • \$\begingroup\$ @nemik - Actually, total cost of the chips (from expensive Farnell) is only £6.80. \$\endgroup\$ Aug 16, 2012 at 10:25
2
\$\begingroup\$

I suggest using Binary Angle Modulation technique described in this article http://www.artisticlicence.com/WebSiteMaster/App%20Notes/appnote011.pdf

Or check ShiftPWM library http://www.elcojacobs.com/shiftpwm/

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Whilst this may theoretically answer the question, it would be preferable to include the essential parts of the answer here, and provide the link for reference. \$\endgroup\$
    – user17592
    Jun 21, 2013 at 9:36
1
\$\begingroup\$

XMOS uses the Macroblock MBI5026 with their LED tile kits. I think that they are used in most other professional systems.

Leon

\$\endgroup\$
1
\$\begingroup\$

FPGAs or CPLDs can be good for such tasks since they offer many I/O pins. Go for the simplest and cheapest. If one is not enough, use a couple.

\$\endgroup\$
2
  • \$\begingroup\$ Can you give us a few more details about why this is a good option, right now I know about it, but I know what the options are and what the suggested technologies you list are, the Origial Poster(OP) probably does not have such a background. \$\endgroup\$
    – Kortuk
    Sep 27, 2012 at 22:01
  • \$\begingroup\$ I'm not sure it's the best option but wanted it to be mentioned for completeness. If controlling 500 LEDs with PWMs, in one way or another, in the end 500 individually controllable wires are needed. It's hard to find a microcontroller with so many output pins. There are a lot of ways around this still using microcontrollers, but one or a couple of cheap CPLDs/FPGAs could easily give those output pins. \$\endgroup\$
    – Carl
    Sep 28, 2012 at 7:49
1
\$\begingroup\$

Make use of economies of scale. Chinese sites like Aliexpress sell WS2811-based LED strands for ~$15 per 50 LEDs. They are individually addressable, bright, usually waterproof, and have PWM for brightness. No soldering or shift registers to mess with either. Doing all this yourself I bet will cost you more, take much more time and be very frustrating. Plus you're in Oz so shipping from China won't be too expensive.

These are made for making giant LED displays so they tend to be pretty cheap. Just make sure to re-inject power about every 50 LEDs or so for best performance.

There are also Arduino libraries to make them easy to use.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ $15 per 50 LEDs? So for 500 LEDs, this comes to $150? And you have the nerve to tell me my solution is expensive? -1 \$\endgroup\$ Aug 16, 2012 at 10:21
  • \$\begingroup\$ Also, please can you provide a link to this. WS801 doesn't Google well, and nor does it turn up on a search of Aliexpress \$\endgroup\$ Aug 16, 2012 at 10:22
  • \$\begingroup\$ Sorry, I meant WS2811, like these aliexpress.com/store/product/… or, without PWM dimming, these aliexpress.com/store/product/… \$\endgroup\$
    – nemik
    Aug 16, 2012 at 17:25
  • \$\begingroup\$ One serial signal to drive 50 LEDs with PWM dimming. Thanks, this is exactly what I'm after. But a standard shift register provides a "latch" pin to copy buffered data to the outputs after the full frame is transmitted. There's no latch here so I expect noticeable noise at high refresh rates. The chips support 400 Kbps data with 15 bits per pixel, so the screen will display nonsense for 1.9 milliseconds while the frame updates. \$\endgroup\$
    – nialsh
    Aug 10, 2014 at 20:07

Not the answer you're looking for? Browse other questions tagged or ask your own question.