FRIENDz

FAILURE IS THE SIGN OF SUCCESS!!

Controlling a Matrix of LEDs: Charlieplexing

The term Charlieplexing comes from Charlie Allen (of Microchip Technology, Inc.), who published the method. The technique is based on the fact that LEDs only turn on when connected the “right way” around (with the anode more positive than the cathode). Here is the table showing the LED number that is lit for the valid combinations of the three pins. L is LOW, H is HIGH, and i is INPUT mode. Setting a pin in INPUT mode effectively disconnects it from the circuit:

Pins LEDs
2 3 4  1 2 3 4 5 6
L L L  0 0 0 0 0 0
L H i  1 0 0 0 0 0
H L i  0 1 0 0 0 0
i L H  0 0 1 0 0 0
i H L  0 0 0 1 0 0
L i H  0 0 0 0 1 0
H i L  0 0 0 0 0 1
Modify the preceding sketch by adding the extra pin to the pins array:

byte pins[] = {2,3,4,5}; // the pins that are connected to LEDs

Add the extra entries to the pairs array so that it reads as follows:

byte pairs[NUMBER_OF_LEDS/2][2] = { {0,1}, {1,2}, {0,2}, {2,3}, {1,3}, {0,3} };

Everything else can remain the same, so the loop will sequence through all 12 LEDs because the code determines the number of LEDs from the number of entries in the pins array. Because Charlieplexing works by controlling the Arduino pins so that only a single LED is turned on at a time, it is more complicated to create the impression of lighting multiple LEDs. But you can light multiple LEDs using a multiplexing technique modified for Charlieplexing. This sketch creates a bar graph by lighting a sequence of LEDs based on the value of a sensor connected to analog pin 0:


byte pins[] = {2,3,4};
const int NUMBER_OF_PINS = sizeof(pins)/ sizeof(pins[0]);
const int NUMBER_OF_LEDS = NUMBER_OF_PINS * (NUMBER_OF_PINS-1);
byte pairs[NUMBER_OF_LEDS/2][2] = { {0,1}, {1,2}, {0,2} };
int ledStates = 0; //holds states for up to 15 LEDs
int refreshedLed; // the LED that gets refreshed
void setup()
{
// nothing here

}
void loop()
{
const int analogInPin = 0; // Analog input pin connected to the variable resistor
// here is the code from the bargraph recipe
int sensorValue = analogRead(analogInPin); // read the analog in value
int ledLevel = map(sensorValue, 0, 1023, 0, NUMBER_OF_LEDS); // map to the
number of LEDs
for (int led = 0; led < NUMBER_OF_LEDS; led++)
{
if (led < ledLevel ) {
setState(led, HIGH); // turn on pins less than the level
}
else {
setState(led, LOW); // turn off pins higher than the level
}
}
ledRefresh();
}
void setState( int led, boolean state)
{
bitWrite(ledStates,led, state);
}
void ledRefresh()
{
// refresh a different LED each time this is called.
if( refreshedLed++ > NUMBER_OF_LEDS) // increment to the next LED
refreshedLed = 0; // repeat from the first LED if all have been refreshed
if( bitRead(ledStates, refreshedLed ) == HIGH)
lightLed( refreshedLed );
}
// this function is identical to the sketch above
// it lights the given LED, the first LED is 0
void lightLed(int led)
{
// the following four lines convert LED number to pin numbers
int indexA = pairs[led/2][0];
int indexB = pairs[led/2][1];
int pinA = pins[indexA];
int pinB = pins[indexB];
// turn off all pins not connected to the given LED
for(int i=0; i < NUMBER_OF_PINS; i++)
if( pins[i] != pinA && pins[i] != pinB)
{ // if this pin is not one of our pins
pinMode(pins[i], INPUT); // set the mode to input
digitalWrite(pins[i],LOW); // make sure pull-up is off
}
// now turn on the pins for the given LED
pinMode(pinA, OUTPUT);
pinMode(pinB, OUTPUT);
if( led % 2 == 0)
{
digitalWrite(pinA,LOW);
digitalWrite(pinB,HIGH);
}
else
{
digitalWrite(pinB,LOW);
digitalWrite(pinA,HIGH);
}
}
This sketch uses the value of the bits in the variable ledStates to represent the state of the LEDs (0 if off, 1 if on). The refresh function checks each bit and lights the LEDs or each bit that is set to 1. The refresh function must be called quickly and repeatedly,or the LEDs will appear to blink.

No comments:

Post a Comment