Introduction: Charlieplexed Arduino 8x8 LED Grid Display Shield Made and Simulated in 123D Circuits

About: I'm a Dutch guy doing things with music and technology. At the moment I'm finishing my MSc in Industrial Design. Not limiting myself to any genre or discipline, I like to work on anything related to music, des…
edit: Wow, this won an awesome prize! Very many thanks guys!

Charlieplexing (http://wealoneonearth.blogspot.nl/2013/03/design-note-charlieplexing-led-matrices.html) is a powerful method for driving a large number of LEDs from a relatively small amount of IO pin and without using any extra components. The technique makes use of the fact that a LED will only let current through in one direction. So if you connect two LEDs to two IO pins, both reversed in direction, you can make the first LED light up by making one pin low and the other high. To make to other LED light, make the pin low which was high first and vice versa. Adding more LEDs to the system, you will be able to drive x2-x LEDs, where x is the number of IO pins you are using. So using 3 pins, you can use (32-3=9-3=) 6 LEDs, and using 9 pins, this increases to (92-9=81-9=) 72 LEDs.
Wanting to figure out how this method worked, but not having the parts around, I used the 123D Circuit  website to make a simulation. Added bonus is that I could easily turn the simulation into a PCB for the production of an Arduino shield. The shield can be used as a simple display with 8x8 pixels. I wrote the software so that you can animate the frames yourself in binary code. Check it out in the following video. The blinking of the LEDs unfortunately is very faint in the software, but you’ll see it if you look closely.

See the schematics and simulation here: http://123d.circuits.io/circuits/102918-charlieplexed-arduino-8x8-led-grid-display-shield


Step 1: Make the (breadboardless) Circuit

As described in the charlieplexing article  a specific wiring is needed to get the right effect. First Arduino pin goes to all the – pins of the LEDS on the first row, the + pins of these LEDs go to Arduino pin 2, 3, 4 etc. The second Arduino pin goes to all the – pins of the LEDS on the second row, the + pins of these LEDs go to Arduino pin 1, 3, 4 etc. And so on for all the other pins.

First add the nine current limiting resistors at the pins of the Arduino. In the software I gave them a value of 100 Ohm, but in reality, 10 Ohm or even no resistor is preferred. This is because each LED will flash only very shortly, so it isn’t at much risk for burning up.

The work in 123D is very tedious, so after the resistors start with duplicating a whole lot of LEDs in a grid. I started with red LEDs, but later on I found that the blinking of green was more visible in the software, so I changed them all.

With the leds in place, start wiring. This needs to be done very neatly, or else you will lose track of everything. I started with all the direct connections of each resistor horizontally, followed by the connections vertically.

With this done, we can work on the code!

Step 2: Code

The code has four main parts:
  1. The animation frames
  2. The charlieplexing mapping
  3. The loop
  4. The led handler
1 The animation frames

To make it easy to program what is shown on our little display, I've made the code so you can just type in whatever you want displayed like what is shown in the next lines. 1 means that the light is on and 0 off. The B character is meant to Arduino knows it is binary code instead of one thousand hunder etc. etc.
{
    B10101010,
    B10101010,
    B10101010,
    B10101010,
    B10101010,
    B10101010,
    B10101010,
    B10101010
  },
    {
    B11111111,
    B00000000,
    B11111111,
    B00000000,
    B11111111,
    B00000000,
    B11111111,
    B00000000
}

2 The charlieplexing mapping

This is an array indicating which pins need to be connected to each other. The beauty of this table is that you can still make this same device work, even if you have made mistakes in wiring or have some other IO pins in use. If so, just change the values in the array!

3 The loop

The loop does nothing more than changing the frame number after a set amount of time. It calls the led handler as often as possible as to avoid flicker. You could easily combine the program with something else by just adding it here.

4 The led handler

This is where the magic happens. Basically, it steps through every LED, and checks if the current animation frame wants it on or off. Something which was hard to grasp for me earlier, was the bitlogic used to do this check. If you don't get the explanation at the comments, try this tutorial: http://arduino.cc/en/Tutorial/BitMask





Code:

int limiter = 100000;//us (this allows you to delay the action of charlieplexing,
  //allowing to tweak the speed or see the effect in simulation)

int animationDelay = 200;//ms ( 1/(animationDelay/1000)=fps => 5fps )
	//this does not really work if the charlieplexing is limited

char animationLength = 4;//match this number to the number of frames you've used


//this array is filled with all the frames you want to animate, 1 is on and 0 is off
char animation[4][8]={
  {
    B10101010,
    B10101010,
    B10101010,
    B10101010,
    B10101010,
    B10101010,
    B10101010,
    B10101010
  },
    {
    B01010101,
    B01010101,
    B01010101,
    B01010101,
    B01010101,
    B01010101,
    B01010101,
    B01010101
  },
    {
    B00000000,
    B11111111,
    B00000000,
    B11111111,
    B00000000,
    B11111111,
    B00000000,
    B11111111
  },
    {
    B11111111,
    B00000000,
    B11111111,
    B00000000,
    B11111111,
    B00000000,
    B11111111,
    B00000000
  }
};
const int UPPERPIN = 13;    //upmost pin
const int LOWERPIN = 5;     //lowest pin

//this is the charlieplexing mapping, see for more info:
//http://wealoneonearth.blogspot.nl/2013/03/design-note-charlieplexing-led-matrices.html
char mapping[8][8]={
  {2,3,4,5,6,7,8,9},
  {1,3,4,5,6,7,8,9},
  {1,2,4,5,6,7,8,9},
  {1,2,3,5,6,7,8,9},
  {1,2,3,4,6,7,8,9},
  {1,2,3,4,5,7,8,9},
  {1,2,3,4,5,6,8,9},
  {1,2,3,4,5,6,7,9}
};
    
  
//two variables used for timekeeping
int animationFrame=0;
long animationTimer = 0;

void setup() 
{
  //nothing to set up
}

void loop() 
{ 
  //a timer, so you can do some other stuff at the same time
  if(millis() - animationTimer > animationDelay) {
  	    
    animationFrame++;        
    if (animationFrame>animationLength)animationFrame=0;
  }
  updatePins();//update the leds
}

//the function which manages the leds
void updatePins(){
  
  for(int i = 0;i<8;i++){
    
    for(int j = 0;j<8;j++){
 

if(animation[animationFrame][i]& 1<<j){
        //This function works in two parts
        // 1<<j makes 00000001 for j=1, 00000010 for j=2, etc
        // then the & operator compares that bit with what is in animation[]
        //so in total, it checks a specific bit in animiation[],
        //if it's 1, a led will light, if it's 0, it will not
       
       resetAllPins();
        //turn off everything
       
       pinMode(UPPERPIN-mapping[i][j]+1, OUTPUT);//+1 for offset
        digitalWrite(UPPERPIN-mapping[i][j]+1, HIGH);
      pinMode(UPPERPIN-i, OUTPUT);
    digitalWrite(UPPERPIN-i, LOW);
        //the mapping array makes sure the right pins are turned on and off       
       
      delayMicroseconds(limiter);
        //to be able to see the effect, we limit the speed
               
      }
      else resetAllPins();
     
    }
  }
}


void resetAllPins(){
  for(int i=LOWERPIN;i<=UPPERPIN;i++){
    pinMode(i, INPUT);
    digitalWrite(i, LOW);
  }
  //set everything to high impendance, so it will not function in the circuit
}

Step 3: PCB

With the code in place and everything functioning as I want it to, I could make the PCB to turn this into a shield. This is a very tedious task, but rewarding when done. I can't wait until it arrives and it actually works!

When you enter PCB view, everything is chaos. My design is quite simple, so I just started with gathering all the resistors and putting them nicely in place.

Now for the LEDs. Somehow 123D Circuit made a really strange ordering of my LEDs. So what I did was go back to breadboard view, check all the numbers of the LEDs and write them down. Now in PCB view I simply copied the layout.

With the LEDs generally in place, align them carefully so the grid is really accurate.

Now on to wiring. I started again at the resistors. Just click the red pad and a green wire will show where you have to go. Be careful not to hit any other pads or that you don't get too close to anything. For the LEDs I went for the vertical connections first.

For the horizontal connections, I needed to make use of the second layer of the PCB. I wasted a lot of time here because I tried to make the vias (connections between the two layers) with the via tool. But as it turned out, this does not work, you have to have this done automatically by drawing a wire and switching layers in the menu on the right. So now just draw the horizontal wires with vias next to the pads to get to the front side again.

After some work you're done! You've got a nice PCB of a Arduino shield ready for production! My design still showed some errors which don't seem a problem to me but which I can't get fixed in the software, these are the yellow spots.

Step 4: Done

That's it, an 8x8 charlieplexed grid using only 9 pins! Doing it the 'ordinary way would have cost 16 pins! 

I hope this Instructable was informative and let me know if you use it for anything!

Check the source here: http://123d.circuits.io/circuits/102918-charlieplexed-arduino-8x8-led-grid-display-shield
123D Circuits Contest

First Prize in the
123D Circuits Contest