What is Chaplex

Chaplex is a library to easy control charlieplexed leds with more than one led switched ON at one time without any limit i.e. as a maximum all leds can be ON. Of course this cannot be done without multiplexing - so my library inherits an easy method to control the Arduino pins connected to the leds.

More you can find here.

How to describe the led structure?

To understand how this works let us look at the example of controlling six leds connected to the Arduino pins 2 (via R1), 3 (via R2) and 4 (via R3).

Chaplex uses some ideas of Alexander Brevigs library Charlieplex.

With the following statements an instance of Chaplex is created:

byte ctrlpins[] = {2,3,4};         //Arduino pins

#define PINS 3                     //number of these pins

Chaplex myCharlie(ctrlpins, PINS);  

With the defined array ctrlpins[] it is now possible to describe the controlled leds.

This is done in the same way as in the Charlieplex library of Alexander Brevig. A typedef in Chaplex.h defines a pair of indexes in ctrlpins[] where anode and cathode of the led are connected to.

This defined type is called charlieLed in Chaplex. You can create single variables of type charlieLed for every led.

But if you want to control the leds in the same way it can be a better idea to use an array. The order of the leds as elements in the array should follow the mechanical order.

Let us assume that the leds shown in the plan above are mechanical side by side in this way:


Array declaration for this is:

charlieLed myLeds[6]={{0,1},  //controlled in sorted order
                      {0,2},  // every element is one led with
                      {1,2},  // {anode-pin,cathode-pin}
                      {2,1},  // "pin" means here - index in
                      {2,0},  // ctrlpins array
                      {1,0}}; // defined above

If a charlieplexed structure with more leds would be in a square then there is nothing against creating a two dimensional array of type charlieLed.

How Chaplex works

Let us assume, Arduino pin 2 is set to OUTPUT/HIGH. Now pin 3 and pin 4 control LED1 and LED3 in this way:

pin 3pin 4 LED1LED3

So in one cycle all (two in our example) leds with the anode connected to the pin set to HIGH are controlled. Let us call this a row of leds.

The next cycle sets pin 3 to OUTPUT/HIGH and selects so the next row. Now pin 2 and pin 4 can control LED2 and LED5.

Third cycle sets pin 4 to OUTPUT/HIGH and selects the third and last row. Now pin 2 and pin 3 can control LED4 and LED6.

And now we are round. We only need these three cycles and when this is done in a loop fast enough you can light on all leds without flickering.

But it is necessary that there is an information how all leds should be switched, ON or OFF.

Chaplex divides setting of leds ON or OFF and output to the hardware. Methods for setting single leds ON or OFF and clearing all leds to OFF only write informations into a private 2-dimensional array of Chaplex:

 pin 2 - column 0pin 3 - column 1pin 4 - column 2
pin 2 - row 0OFF (constant)ON or OFFON or OFF
pin 3 - row 1ON or OFFOFF (constant)ON or OFF
pin 4 - row 2ON or OFFON or OFFOFF (constant)

A method for driving the leds takes the informations from this array and controls the Arduino pins - only one row. The next call of this method does the next row. Next call - the third and last row.

And again the next call of the output method starts again with the first row (in this example with three pins). It's your task of making the calling program this way that the output method is called fast enough again and again in a loop or via interrupt.

But you do not have to take care for the round going cycles over the rows, this is done in the method with a private counter.


Here you can download a .zip-file with the library.

Public methods

void ledWrite(charlieLed led, byte state)

Sets the given led (described by a single variable or an array element) to state OFF or ON in a private array of the instance. No real hardware output is caused. ON and OFF are defined in Chaplex.h as 1 and 0.

void allClear()

Sets for all leds the value in the private array to OFF. No real hardware output is caused.

void outRow()

Controls the Arduino pins with the values in the private array. The method makes the hardware output for one cycle and sets private counters so that next call of the method will do the next cycle (or the first).

void Chaplex(byte* pins, byte numerOfPins)

The constructor of an instance also creates the private 2-dimensional array for the led values and the private loop counter variable for outRow(). At the end of the creator the funtion allClear() ist called to set all leds in the private array to OFF and function outRow() is called for hardware output of the first row (may be this is unnecessary).

There is no limit to create more instances of Chaplex to control different groups of charlieplexed leds connected to different Arduino pins. You have to secure that outRow() methods of all instances are called often enough to avoid flickering of controlled leds.


There are two examples:

  • FlickeringLeds is a sketch where in main loop all leds are set randomly (every 100 ms controlled by millis() function) and outRow() method is called every round in main loop. In this way you can make programs if the work to do in main loop is not too much and no waiting (delay) is used. outRow() at the end of every round in main loop has to be called often enough that no unwanted flickering occurs.

  • InterruptControl is a sketch where outRow() method is called in an ISR using timer2. So you can be sure that outRow() is called frequently enough to avoid flickering of the charlieplex controlled leds even if delay() in main loop is used. If you use timer2 for own interrupt you cannot use tone() function (uses timer2 too).


  • A call of outRow() method can switch ON all leds with anodes connected to the same Arduino pin. In a structure of leds controlled by 3 Arduino pins these are 2 leds. With 4 Arduino pins 3 leds can be ON - in general always one led less than the number of used Arduino pins.

    Current of all leds ON is added together and goes over the Arduino pin set to HIGH. You have to calculate this and use resistors with the right values. That's your problem, but you find many suggestions - Google "charlieplexing". You have also to take into account the brightness of the leds.

  • Some tests of example FlickeringLeds using a self made ATTiny85 board showed a strange effect. The method outRow() at the end of the main loop was called very often and some leds were glowing a little also in OFF state. Adding an if-statement so that the method outRow() was only called once every millisecond ended this effect. I have no oscilloscope and I could not find out the reason.

Further development

I used work with the library Chaplex for learning how to create Arduino libraries. I have no project with charlieplexing so I will not develop this library further on. You are free to do it.

For example you could create a new public method which sets a limits for leds really switched to ON during hardware output in outRow(). If your project only needs much less then all leds in a row switched to ON you could take smaller resistors for more brightness and nevertheless be secure that in error case not too many leds can be really switched ON in outRow(). So an Arduino pin would be save during set to HIGH.