Another Arduino tutorial today - Charlieplexing!
Charlieplexing is a technique proposed in early 1995 by Charlie Allen at Maxim Integrated Products for driving a multiplexed display in which relatively few I/O pins on a microcontroller are used to drive an array of LEDs.
Basically, it allows you to take a number of pins n, and drive n(n-1) LEDs from them. Using this formula, you can see that as the number of pins increases, the number of LEDs also increases, but exponentially. For example:
- 2 pins will drive 2(2-1) pins (2)
- 3 pins will drive 3(3-1) pins (6)
- 4 pins will drive 4(4-1) pins (12)
- 5 pins will drive 5(5-1) pins (20)
- 6 pins will drive 6(6-1) pins (30)
In more detail, the way charlieplexing works is thanks to a microcontroller's ability to put its pins into high impedance mode (on the Arduino, this is INPUT mode), effectively detaching that pin from the circuit completely. Other than the pin(s) set to INPUT mode, there will be two others, both set to OUTPUT. One of these will be set to LOW (the current sink), and the other will either be set to HIGH or a PWM value (the current source). Each combination of two different pins will cause one of two LEDs in the matrix to be lit, depending on which is the source and which is the sink. Today, I'm going to explain in explicit detail how to charlieplex 6 LEDs via 3 pins, as this is the point at which charlieplexing becomes useful, and before it gets horribly complicated.
To start with, you will need:
- 6 LEDs
- 3 220Ohm resistors
- A bunch of jumper wires
First of all, here's a schematic for the circuit we are going to create:
And here's one for another circuit, to show you how it can be implemented in a much larger fashion.
Here's a picture of my circuit, made in Fritzing. I've done my best to simplify the wiring as much as I can, by using a bunch of different colours. I've also used SVG format, so you can zoom as close as you like.
Once you have your hardware set up, you will want to start thinking about the code. This is, needless to say, quite a lot more complex than the wiring. I've written a basic charlieplexing program, which should be usable on any size of charlieplexed matrix, as long as it fits within the driving device's specifications.
The essence of the code is permutation theory. The details are outside the scope of this article, but there are many resources online to get to grips with it.
Here's my code:
/*
* Arrays containing the pin numbers used in
* each charlieplexed matrix. In this case, both
* matrices are the same size, and this code will
* not work properly if this is not the case.
*/
int charlie1[3] = { 9, 10, 11 };
int numPins = sizeof(charlie1)/sizeof(int);
// Basic LED control functions
void allOff(int pinArray[], int del) {
/*
* Turn off all LEDs in the array
* pinArray = Array of pins to turn off
* del = Delay before next action
*/
for(int pin = 0; pin 0) {
for(int fadeVal = 0; fadeVal = 0; fadeVal--) {
analogWrite(pinArray[source], fadeVal);
delayMicroseconds(del);
}
}
}
void setup() {
// Set all pins to output-
for(int i = 0; i 0) {
allOn(pinArray, del);
allOff(pinArray, del);
reps--;
}
}
This code is easily extensible to allow it to control multiple matrices, just by adding a new pin array at the top. The Arduino has 6 PWM capable pins, so you could theoretically have up to 30 LEDs driven by it. Whether the Arduino would be up to the task is another matter, as even on this example, when all LEDs appear to be lit, the duty cycle is sufficiently reduced for them to be significantly less bright.
To close, here's a video of the code above being used on a charlieplexed matrix from 4 pins on the Arduino. As I just mentioned, all which needs changing is the pin array at the top. All I did to make it work was add pin 6 to its initialisers, and changed the array size to 4. Other than that I messed with some of the timings, but that's unrelated.
I look forward to finding out how my imminently due TLC5940 PWM capable LED driver ICs respond to charlieplexing next week, so expect a post on my findings!
If you'd like any help with your own charlieplexed circuits, feel free to give me a shout either in the comments or personally, via the contact form.
n00b