I am using an Atmel ATtiny13 which has a 6-pin I/O. I'd like to control about 15 LEDs but am unsure how to connect everything. Without multiplexing of any sort, it seems I'd only be able to control 6 LEDs at a time. Am I limited to only 6 LEDs because of the size of the microcontroller?
-
\$\begingroup\$ I had not seen. Possibly duplicated: electronics.stackexchange.com/questions/9860/… \$\endgroup\$– Daniel GrilloCommented Mar 4, 2011 at 19:36
-
3\$\begingroup\$ Don't forget to compare your options against the cost of buying a slightly pinnier microcontroller. Also pay attention to the per-port and total current limits. \$\endgroup\$– joeforkerCommented Mar 4, 2011 at 20:39
-
\$\begingroup\$ When I began working with micros a while ago, this is a question I wished had been easy to find with clear answers. I managed to learn about charlieplexing and successfully implement it, but I wanted to recreate the question here with the excellent quality of SE-community answers. \$\endgroup\$– JYeltonCommented Mar 4, 2011 at 21:47
-
1\$\begingroup\$ @joeforker You're right, the cost for a micro with more pins was pretty minimal, considering my project was a one-off. I thought at one point about using a micro with about 20 IO pins to accomplish the job, but one of my goals was a very small circuitboard footprint. Also, awesome adjective pinnier! \$\endgroup\$– JYeltonCommented Mar 4, 2011 at 21:54
-
\$\begingroup\$ Duplicate: electronics.stackexchange.com/questions/1609/… \$\endgroup\$– mjh2007Commented Mar 10, 2011 at 21:01
6 Answers
There are several methods which can be used to drive large numbers of LEDs from a few IO pins.
The simplest is standard row/column display multiplexing. With this technique, you can drive \$( n / 2 )^2\$ LEDs with \$n\$ IO pins. Mathematically, the duty cycle is:
$$\frac{1}{minimum(\text{unique row patterns, unique column patterns})}$$
This means that this technique has a duty cycle of 100% when all LEDs are lit (or all rows or all columns are identical) and a duty cycle of \$1 / n\$ when a diagonal line needs to be lit (or all the rows are different). You're only guaranteed 100% duty cycle when lighting every LED or one LED (or zero LEDs, but that doesn't really count for much).
Slightly more complex is Charlieplexing. With this technique, you can drive \$n^2 - n\$ LEDs with \$n\$ IO pins. Only \$n - 1\$ LEDs can be lit simultaneously with this technique. Mathematically, the duty cycle is:
$$\frac{1}{\text{minimum simultaneous sets}}$$
where a simultaneous set is a unique group of LEDs which has a common anode or common cathode. (This hasn't been proven, it's just what I arrived at after pondering the problem for a minute. If duty cycle is important to you, you'll want to look into this further.) This is a much more complex calculation both intellectually and computationally than the equivalent calculation for standard multiplexing. Effectively, you get a duty cycle of \$1 / n\$ when all LEDs are lit but some (only some) patterns of n-1 or fewer LEDs can have a duty cycle of 100%. You're only guaranteed 100% duty cycle when lighting 1 LED.
The last method I'll mention is to use a shift register or IO expander. With two pins (Either the raw data/clock interface, I2C, or unidirectional SPI), you can control an arbitrarily large number of LEDs. The duty cycle for any pattern is 100%, but the update rate is inversely proportional to the number of LEDs. This is the most costly method. For 15 LEDs, it will probably be cheaper to just upgrade to a micro with that many IO pins.
-
\$\begingroup\$ +1 for explaining a bit about the duty cycle aspect. In the second sentence about Charlieplexing, did you mean "drive n^2-n LED's with n IO pins? \$\endgroup\$– JYeltonCommented Mar 4, 2011 at 21:52
-
\$\begingroup\$ Charlieplexing can be done very similarly to multiplexing, if one simply omits one light from each row. Actually, it may be possible to "regain" that light by adding a diode, though unless column drivers are constant-current outputs, making it match the brightness of the others may be difficult. \$\endgroup\$– supercatCommented Mar 18, 2011 at 15:40
Using Charlieplexing you can directly drive \$n \times (n-1)\$ LEDs from \$n\$ pins.
Exemple:
Six LED's on 3 Pins:
PINS LEDS
0 1 2 1 2 3 4 5 6
0 0 0 0 0 0 0 0 0
0 1 Z 1 0 0 0 0 0
1 0 Z 0 1 0 0 0 0
Z 0 1 0 0 1 0 0 0
Z 1 0 0 0 0 1 0 0
0 Z 1 0 0 0 0 1 0
1 Z 0 0 0 0 0 0 1
0 0 1 0 0 1 0 1 0
0 1 0 1 0 0 1 0 0
0 1 1 1 0 0 0 1 0
1 0 0 0 1 0 0 0 1
1 0 1 0 1 1 0 0 0
1 1 0 0 0 0 1 0 1
1 1 1 0 0 0 0 0 0
-
\$\begingroup\$ Thank you for the output pin dataset as well as a helpful schematic. \$\endgroup\$– JYeltonCommented Mar 5, 2011 at 2:15
-
1\$\begingroup\$ Another way of drawing the schematic is as an NxN grid, but driving columns only, and replacing the primary diagonal with row-column shorts. \$\endgroup\$– supercatCommented Mar 8, 2011 at 16:10
-
\$\begingroup\$ means I cannot turn all of them on at once? Does that mean If I want to turn all of them on at once I have to do time-plexing enough to fool the eyes? \$\endgroup\$– MaNyYaCkCommented Jul 20, 2018 at 12:05
-
\$\begingroup\$ @MaNyYaCk Yes. You're right. \$\endgroup\$ Commented Jul 20, 2018 at 19:44
Without multiplexing (direct drive) you are limited to 6 LEDs.
With charlieplexing you can drive n*(n-1) LEDs from n pins.
With I/O expanders or shift registers you can drive a virtually unlimited number of LEDs.
Example: MCP23008 8-bit I2C I/O Expander
-
\$\begingroup\$ Can you elaborate on what I/O expanders would be? \$\endgroup\$– JYeltonCommented Mar 4, 2011 at 19:26
-
3\$\begingroup\$ An I/O expander is external chip that contains I/O pins and registers. You can use standard communication bus like I2C or SPI to communicate with them. \$\endgroup\$– mjh2007Commented Mar 4, 2011 at 19:32
-
\$\begingroup\$ +1 You can drive a lot of LEDs with TI's TLC594 (focus.ti.com/lit/ds/symlink/tlc5940.pdf), but it may be overkill for many jobs. search.digikey.com/scripts/DkSearch/… \$\endgroup\$– kennyCommented Mar 4, 2011 at 21:15
-
\$\begingroup\$ Thanks - I should design a project that makes use of I/O expanders to force my learning of their usage. \$\endgroup\$– JYeltonCommented Mar 4, 2011 at 21:48
As @mjh2007 suggested with an I2C expander. But there are ones specifically for driving LEDs which will avoid the need for external current-limiting resistors.
Here's an example of charlieplexing that I have built.
It's a lighthouse beam simulator and uses a series of 12 LEDs charlieplexed to 4 GPIOs to sweep a beam of light around a disc. There's a video of it here.
The project is PIC based, I use a PIC12f683 which is also an 8pin uP and could be considered comparable to the 8pin AVRs.
The LED's intensity is driven by an interupt that provides a 32 step PWM at around 60Hz. Only two LEDs are allowed to be lit at any one time giving a 50% duty for each LED as that was all I needed. It also gives a good trade off of PWM refresh rate against resolution.
The coding for using charlieplexing as actually pretty simple if you stick to the "classic" method of only lighting a single LED at any one point in time at a very fast refresh rate. I work out the required PORT and TRIS (pic specific registers) first on paper then store the results in a static array. To light LED x the PIC just has to lookup the value at the array's index[x] and write them directly to the PORT (with a bit of masking to preserve the state of the other pins not used in the charliplex)
My project only has 12 LED not 15 or the maximum 20 the 5 GPIO will allow as I wanted to keep one GPIO spare for future development.
Anyway... I just thought it might be helpfull to have a working example similar to your request.
Full source code and schematics are available on my blog.
Another option would be to use the Neopixel LEDs. They have a built-in control IC and you only need one pin to control as many LEDs as you like. Of course you will need an adequate separate LED power source then.