Charlieplexing is an ingenius method for controlling many LEDs without using many microcontroller pins. You can turn on or off one LED at a time. To light more than one LED at a time, you can scan the LEDs by turning a sequence of them on and off really fast. The number of LEDs you can control is determined by this formula: N pins * (N pins – 1). For example, if you have 4 pins, you can control 12 LEDs (4 pins * 3 pins). If you have 2 pins, you can control two LEDs, which makes it a little silly to employ Charlieplexing, since you could simply connect each LED to an MCU pin and then to ground. Charlieplexing makes more sense for more than two LEDs. Nine pins will get you 72 LEDs!

Here is an ATmega328 on a custom PCB controlling 20 LEDs (the 21st is on its own pins) with just 5 pins:

Charlieplexing takes advantage of the fact that LEDs are diodes: Current flows in only one direction through an LED. Connect two LEDs in parallel with each but with opposite polarity so that only one conducts (lights up) at a time and that is the basis of Charlieplexing.

The ATmega328 pins can source upwards of 40 mA. The grand total of current from Vcc to GND in an ATmega328, however, is capped at 200 mA. Keep that in mind when pumping electrons through your Arduino or ATmega328. In this project, we’ll only ever have a single LED turned on at a time, so no more than roughly 20 mA will be running through the microcontroller’s pins at any time (not including what the MCU takes itself, of course).

In this project, we’ll set up a simple Charlieplexing circuit with 12 LEDs controlled by an Arduino that will look like this:

I’ll walk you through connecting 12 LEDs to four pins on your Arduino. The Arduino sketch will make the LEDs “chase” in a circle(ish). The breadboard set up for this gets nuttier and nuttier the more LEDs and pins you add. I’m going to stop at four pins, mostly because the breadboard starts to look crazy and four pins will get you going on your own quite easily.

I wrote the Arduino code to make it easy to add or remove LEDs. There is a simple function to call to turn on any given LED. You can nab the Arduino code for this project right here:

On a side note, the Arduino digitalWrite() and maybe even the pinMode() calls are heavyweights compared to the standard AVR C register macros for directly manipulating bits in the DDRx and PORTx registers of the ATmega328 (or any AVR chip, for that matter). The Arduino calls gobble up a quite a lot of clock cycles when you call them, whereas the DDRx and PORTx macros translate to one or maybe two assembly instructions (WAY faster). When it comes to scanning over the LEDs rapidly to make more than one at a time appear to be on, the fewer clock cycles in between each LED during each refresh (or, “frame” of animation), the brighter and less flickery the LEDs will appear to be. The optimum way to scan these LEDs, especially when there are many of them, is to use direct register manipulation calls, NOT digitalWrite() or pinMode(). There is a great replacement for the Arduino calls out on Google Code that provides digitalWriteFast() and others to help speed up those common calls. Here is a link to the Google Code page for that library.

On a side note to the above side note… Here is a gist showing code that directly manipulates the DDRx and PORTx registers to save on cycles when switching between LEDs:

This project will assume you know how a breadboard works, how to calculate the proper current limiting resistance for an LED running on 5 volts and what the cathode (ground/negative) and anode (positive) leads are on your LEDs.



Step #1: Schematic

Charlieplexing LEDs with an AVR ATmega328 (or Arduino)Charlieplexing LEDs with an AVR ATmega328 (or Arduino)Charlieplexing LEDs with an AVR ATmega328 (or Arduino)Charlieplexing LEDs with an AVR ATmega328 (or Arduino)
  • I've labeled the schematic to match the photos used to build the project. The Arduino pins 9, 10, 11 and 12 are used to control the LEDs and I've labeled them from 12 down to 9 as A, B, C and D.
  • The second image shows the current path when pin A is HIGH, B is LOW and C and D are set to INPUT.
  • The third image shows the current path when pin B is HIGH, A is LOW and C and D are set to INPUT.
  • When I map out Charlieplexing LEDs, I use the A/B/C labeling to make it easier to keep track of what's going on. For instance, LED "AB" is the LED that's lit when current goes from A to B. LED "DA" is the LED that's lit when D is HIGH, A is LOW and the other pins are set as INPUT.

Step #2: Breadboard Setup - Jumpers/Wiring

Charlieplexing LEDs with an AVR ATmega328 (or Arduino)
  • The little breadboard I'm using has only 5 holes in each row on each side of the board. I jumpered the two sides together with the shorter (orange) jumper wires.
  • I had to extend each row (A, B, C) down to another set of rows to give us more holes to plug LEDs into. I used longer (green) jumper wires to do this.
  • The second set of rows has a row for pin D.

Step #3: Plug In LEDs - AB, BA, BC, CB, CA and AC

Charlieplexing LEDs with an AVR ATmega328 (or Arduino)Charlieplexing LEDs with an AVR ATmega328 (or Arduino)Charlieplexing LEDs with an AVR ATmega328 (or Arduino)Charlieplexing LEDs with an AVR ATmega328 (or Arduino)
  • Pairs of LEDs will go into the same rows together, but their leads will be opposite of each other.
  • For the first 3 pair, I'll label them and point out what's positive and what's negative on the LEDs. The next step won't have the polarity marked. However, you'll still have the LED labels and you'll know by that (i.e., "DA") which way it goes in and to what pins it should be connected.

Step #4: Plug in LEDs - AD, DA, BD, DB, CD and DC

Charlieplexing LEDs with an AVR ATmega328 (or Arduino)Charlieplexing LEDs with an AVR ATmega328 (or Arduino)Charlieplexing LEDs with an AVR ATmega328 (or Arduino)Charlieplexing LEDs with an AVR ATmega328 (or Arduino)
  • When plugging in the LEDs here, follow their labels to know which lead goes where in the breadboard holes: For instance, for LED "AD," you will put the LED's anode (positive) lead into row A of the bottom rows and its cathode (negative) lead into row D. LED "DA," then, would go in the same rows but backwards.
  • On this row of LEDs, we're going back the other way (left to right). The pattern will chase from the AB LED going left to CA, down to AD, then right to DC, then start over again.

Step #5: Plug In Limiting Resistors

Charlieplexing LEDs with an AVR ATmega328 (or Arduino)Charlieplexing LEDs with an AVR ATmega328 (or Arduino)Charlieplexing LEDs with an AVR ATmega328 (or Arduino)Charlieplexing LEDs with an AVR ATmega328 (or Arduino)
  • The LEDs I'm using are rated for roughly 3 volts. The Arduino is pushing out 5 volts. Using Ohm's Law, I figure I have to use a 100Ω resistor to limit the current through the LEDs to 20 mA: (5 volts from Arduino - 3 volts for LED) ÷ 0.02 Amps for LED = 100Ω
  • For typical red or green LEDs that work on 2 volts and draw 20 mA, 150Ω resistors will work just fine: (5 volts from Arduino - 2 volts for LED) ÷ 0.02 Amps for LED = 150Ω
  • Notice the spots we plug the resistors into. The rows will match up with the A, B, C and D rows and will be connected to the Arduino's digital pins 12, 11, 10 and 9 respectively. In the source code provided in the next step, those pins will be defined as constants to match that A/B/C/D labeling.
  • The last photo shows TWO resistors being added: C and D. By now I think you get the idea.

Step #6: Connect the Arduino

Charlieplexing LEDs with an AVR ATmega328 (or Arduino)

Just about the easiest step: Connect wires from the rows on the breadboard for the resistors to the appropriate pins on the Arduino.

Step #7: Upload the Code

Charlieplexing LEDs with an AVR ATmega328 (or Arduino)
  • The source code for this is located in the body of the project above. Copy-n-paste it into your Arduino IDE.
  • Upload the code to your Arduino using the Upload command from the File menu and if everything is hooked up correctly, you should see the LEDs chasing around your breadboard.

25-year IT veteran by day, maker by night and weekend. Love little fiddly electronic bits and making useful AND useless things for fun and relaxation.

blog comments powered by Disqus

Related Supplies at Maker Shed


Get every new post delivered to your Inbox.

Join 28,391 other followers