Introduction: Chalieplexing 4 RGB-LEDs With 4 Wires on Arduino

Did you every need many LEDs, but only few wires? Then Charlieplexing is a great thing to try. With only 4 wires you can drive 12 LED with only 4 resistors as an optional protection and without any "intelligen" component like a 74595 or similar. - This example will show how to use 4 RGB LEDs to test this very nice concept. The generic code allows to control any number of lines very easy:


  // A 4 wire setup
  #define CHARLIE_PINS  4

  // Arduino Pins 9 - 12 control the LEDs
  #define CHARLIE_FIRST 9

  //
  // Sample 1: First LED(0,1) "On"
  //
  charlieClear();                                  // Clear all LED levels 
  charlieWrite(0,1,CHARLIE_MAX); // Set LED(0->1) to maximal level
  charliePlex();                                     // Generate the output pattern

Step 1: Materials and Tools

The example will use 4 RGB LEDs which happend to lay in my drawer, but you may use any spare LEDs you want to sacrify.

Required Materials
- 4 RGB LEDs (or 12 single Color LEDs)
- Arduino whatever you have

Recommended Materials
- 4 Resistors, e.g. 3k3
- Small piece of perforated circuit board (or breadboard)
- 4 PIN male headers

Recommended Tools
- Boardmarker
- Grippers
- Wire cutter
- Soldering iron

Step 2: Prepare the Stripboard

We will add a resistor to each strip, so just leave two rows in the beginning of the strips empty: One for the headers, one for the start of the resistor, cut (= isolate) on the third row of holes, the LED will be plugged starting from the forth row (sorry, the picture is after soldering).

Step 3: Bend & Plug It Like Charlie

To simplify the bending, we mark the Stripboard distance on every pin all LEDs. This way it is very easy to bend the pin the required strip. Please be aware to keep always the same "orientation" of your LEDs. In this case Pin 3 is always the anode.

So the bending pattern is:

  1. LED
    • Pin 1, Strip 1
    • Pin 2, Strip 2
    • Pin 3, Strip 3
    • Pin 4, Strip 4
  2. LED
    • Pin 1, Strip 2
    • Pin 2, Strip 3
    • Pin 3, Strip 4
    • Pin 4, Strip 1
  3. LED
    • Pin 1, Strip 3
    • Pin 2, Strip 4
    • Pin 3, Strip 1
    • Pin 4, Strip 2
  4. LED
    • Pin 1, Strip 4
    • Pin 2, Strip 1
    • Pin 3, Strip 2
    • Pin 4, Strip 3
Then plug the LEDs in the stripboard.

Step 4: Solder 28 Times

Now comes the easy part: Just solder all the LED-PINs, then the 4 resistors (I first used 3k3 throughholes and then 0k5 SMDs) and the 4 header pins. Keep a sharp eye on any shortcircuit on the front and back side of the board.

Step 5: Plug and Play With the Software

Now everything is ready to test the system. Take out your beloved Arduino (or if you're scard your Ruggduino), copy-paste the code in your Arduino sketch and modify it as required. Any improvements are welcome


/*
  CharliePlexing Library
  (c) by Olivier Chatelain 2014

  This code is CC-BY-SA-3.0
*/

#define CHARLIE_PINS  4
#define CHARLIE_FIRST 9

// Setup the memory
#define CHARLIE_COUNT CHARLIE_PINS*(CHARLIE_PINS-1)

// Charlie Level (0 = off, 255 = max)
#define CHARLIE_LOW    0
#define CHARLIE_HIGH 255

#define CHARLIE_OFF     0
#define CHARLIE_MAX   255

// Charlie Levels for anode/cathode pin-pairs
uint8_t charliePins[CHARLIE_PINS][CHARLIE_PINS];

#define CHARLIE_GREEN 0
#define CHARLIE_BLUE  1
#define CHARLIE_RED   2

int charlieRGB[CHARLIE_PINS][3] = {{1, 2, 3}, {2, 3, 0}, {3, 0, 1}, {0, 1, 2}};

void charlieClear() {
  for(int i = 0; i < CHARLIE_PINS; i++) {
    for(int j = 0; j < CHARLIE_PINS; j++) {
      charliePins[i][j] = CHARLIE_OFF;
    }
  } 
}

void charlieSetAll() {
  for(int i = 0; i < CHARLIE_PINS; i++) {
    for(int j = 0; j < CHARLIE_PINS; j++) {
      charliePins[i][j] = CHARLIE_MAX;
    }
  } 
}

void charlieSetAllLevel(uint8_t level) {
  for(int i = 0; i < CHARLIE_PINS; i++) {
    for(int j = 0; j < CHARLIE_PINS; j++) {
      charliePins[i][j] = level;
    }
  } 
}

void charlieWrite(int src, int dst, uint8_t level) {

  charliePins[src%CHARLIE_PINS][dst%CHARLIE_PINS] = level;

}

// current line displayed
int charlie_line = CHARLIE_PINS-1;

void charliePlexLine(uint8_t level) {

  // Disable last line displayed
  pinMode(CHARLIE_FIRST+charlie_line, INPUT);

  if(++charlie_line >= CHARLIE_PINS) charlie_line = 0; 
  int i = charlie_line;
  int MasterPin = CHARLIE_FIRST+i;

  // Use others as follow pins (HIGH or INPUT)
  for(int j = 0; j < CHARLIE_PINS; j++) {
    int SlavePin = CHARLIE_FIRST+j;

    if(MasterPin != SlavePin) {
      if(charliePins[i][j] > level) {
        pinMode(SlavePin, OUTPUT);
        digitalWrite(SlavePin, LOW);
      } else {
        pinMode(SlavePin, INPUT);
      }
    }
  }
  pinMode(MasterPin, OUTPUT);
  digitalWrite(MasterPin, HIGH);   
}

void charliePlex() {

  // Set one leadpin (LOW)
  for(int i = 0; i < CHARLIE_PINS; i++) {
    for(int j = 0; j < CHARLIE_MAX; j++) {
      charliePlexLine(j);
      delayMicroseconds(10);
    }
  }
}

// the setup routine runs once when you press reset:
void setup() {

}

void loop() {

  //*
  // Sample 1: First LED(0,1) "On"
  //
  charlieClear();
  charlieWrite(0,1,CHARLIE_MAX);
  charliePlex();
  //*/

  /*
  // Sample 2: Dimm White
  for(int i = 0; i < 8; i++) {
    charlieSetAllLevel(1<<i);
    charliePlex();
  }
  for(int i = 7; i > -1; i--) {
    CHARLIE_PINS(1<<i);
    charliePlex();
  }
  //*/

  /*
  // Sample 3: Alternate the COLORS
  charlieClear();
  for(int i = 0; i < CHARLIE_PINS; i++) {
    charlieWrite(i, charlieRGB[i][CHARLIE_RED], CHARLIE_MAX);
  }
  charliePlex();

  charlieClear();
  for(int i = 0; i < CHARLIE_PINS; i++) {
    charlieWrite(i, charlieRGB[i][CHARLIE_GREEN], CHARLIE_MAX);
  }
  charliePlex();

  charlieClear();
  for(int i = 0; i < CHARLIE_PINS; i++) {
    charlieWrite(i, charlieRGB[i][CHARLIE_BLUE], CHARLIE_MAX);
  }
  charliePlex();
  //*/

}


Enjoy it!
Arduino Contest

Participated in the
Arduino Contest