Today’s circuit aims to control quite a few LEDs with few pins and without using other integrated chips. The technique used is called charlieplexing and was proposed in 1994 by Charlie Allen of Maxim, having nevertheless been the subject of a patent in the late 1970s by AEG-Telefunken.

The technique used by this method reduces the number of pins needed to turn on the LEDs because the pins assume the three possible states: high, low and input (high impedance or disconnected).
To control n * (n-1) LEDs are required n pins or otherwise to control L LEDs are required (1 + sqrt (1 + 4 * L)) / 2.

PinsLEDs
10
22
36
412
520
630
742
856
972
1090
nn²-n

It should be noted that this method uses the property of persistence of vision so that we have the appearance that several LEDs are lit at once when in practice there is only one. For this trick to work it is necessary that the refresh occurs at more than 50 Hz.

On the other hand in the circuit presented it is assumed that all LEDs are identical. With different LEDs it is necessary to ensure that the “forward-voltage” of the LEDs is more or less the same.

## Schematic

Notice:
The circuit for CSEduino can be checked in this page. An Arduino can also be used.

## Bill of materials (BOM)

• 12x 5mm or 3mm LED (D1-D12)
• 4x 1K Ohms Resistors(R1-R4)

## Code

The Sketch used was as follows:

```#include "Chaplex.h"

byte ctrlpins[] = {10,11,12,13};    //Arduino pins controlling charlieplexed leds
#define PINS 4                //number of these pins

#define DELAY 500             //speed of switching leds in bar on and off

Chaplex myCharlie(ctrlpins, PINS);     //control instance

charlieLed myLeds[]  = {
{ 0 , 1 },
{ 0 , 2 },
{ 0 , 3 },
{ 1 , 0 },
{ 1 , 2 },
{ 1 , 3 },
{ 2 , 0 },
{ 2 , 1 },
{ 2 , 3 },
{ 3 , 0 },
{ 3 , 1 },
{ 3 , 2 }
};

void setup() {
// initialize timer2
noInterrupts();                 //disable all interrupts
TCCR2A = 0;
TCCR2B = 0;
TCNT2 = timer2TCNT2;
TCCR2B |= (1 << CS22) | (1 << CS21) | (1 << CS20);  //prescaler 1024 = 64 micro secs
TIMSK2 |= (1 << TOIE2);        //enable timer overflow interrupt
interrupts();                  //enable all interrupts
}

ISR(TIMER2_OVF_vect) {          //timer2 interrupt routine
myCharlie.outRow();           //output for one led row
TCNT2 = timer2TCNT2;          //preload timer for next interrupt
}

void loop() {
for (int i=0; i< PINS*PINS-PINS; i++) {
myCharlie.ledWrite(myLeds[i], ON);
delay(DELAY);
}
for (int i=0; i<PINS*PINS-PINS; i++) {
myCharlie.ledWrite(myLeds[i], OFF);
delay(DELAY);
}
}
```