Charlieplexing, Animating by Columns with 30 LEDs in a 5x6 array

The Thread and the Story

Hey guys,

So I couldn't find a good code to charlieplex a 30 led Array and so through some adaptation of what I could find I made my own. I wanted to make something easy and versatile to use for anyone else trying to do the same thing as me. I will update the code the goals at the top of this topic. So if anyone or I add anything useful in the thread I'll update it to the top.

So far I've only seen charlieplexes that light each light for a fraction of a second relative to the number of lights, and moves on to the next light in the array. In my opinion this might be acceptable for arrays of 2x3, or 3x4, but not 5x6 as at best an LED is lit for 1/30th of the time.

What I've Done

  1. Currently I've coded a standard 5x6 charlieplex test and have it up and running. It starts at the top left and scans down and moves to the next row to the right

  2. I've also separately coded to light each column at one time (column A, column B, column C, column D)

  3. Although virtually useless, I was playing around and coded each column minus one light (!A1, !A2, !A3, etc.) This was mainly done as a proof of concept (and I played around more to do multiple unlit lights in a row, but didn't to a complete series so I didn't keep them).

What I'm doing/My Goals/Things I could use help with

  1. My goal is to make a system that will allow me to have it flash the desired lights by column (there are 6 columns) so that my light time is 1/6 of the allotted time per light, not the 1/30th if I were to do them individually

  2. So I'm currently working to make a way to code the outputs as 1 and inputs as 0, so that I can add them using bitwise operations. I'm also seeing if I can do this in array, or if I need to make a reference to what they are out of array (I think this is what I'll have to do)

  3. For whatever reason it won't let me classify row "F" as "F", as it doesn't recognize it. hence I labeled it "G". Anyone have any pointers on this?

Here's my Circuit
I borrowed this picture from online, it's not mine, but everything is the same

Here's my Code

#define A 2
#define B 3
#define C 4
#define D 5
#define E 6
#define G 7

#define PIN_CONFIG 0
#define PIN_STATE 1
 
#define LED_COUNT 6
 
int matrix[LED_COUNT][5][6] = {
  //               PIN_CONFIG (Horizontal)               PIN_STATE (Vertical)
  //    A       B       C      D       E       G        A, B, C, D, E, G
 /*
  // Values by column taking out 1 led 
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, INPUT}, { 1, 0, 0, 0, 0, 0} }, // A !1
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, INPUT, OUTPUT}, { 1, 0, 0, 0, 0, 0} }, // A !2
  { { OUTPUT, OUTPUT, OUTPUT, INPUT, OUTPUT, OUTPUT}, { 1, 0, 0, 0, 0, 0} }, // A !3
  { { OUTPUT, OUTPUT, INPUT, OUTPUT, OUTPUT, OUTPUT}, { 1, 0, 0, 0, 0, 0} }, // A !4
  { { OUTPUT, INPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 1, 0, 0, 0, 0, 0} }, // A !5
  
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, INPUT}, { 0, 1, 0, 0, 0, 0} }, // B !1
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, INPUT, OUTPUT}, { 0, 1, 0, 0, 0, 0} }, // B !2
  { { OUTPUT, OUTPUT, OUTPUT, INPUT, OUTPUT, OUTPUT}, { 0, 1, 0, 0, 0, 0} }, // B !3
  { { OUTPUT, OUTPUT, INPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 1, 0, 0, 0, 0} }, // B !4
  { { INPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 1, 0, 0, 0, 0} }, // B !5
  
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, INPUT}, { 0, 0, 1, 0, 0, 0} }, // C !1
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, INPUT, OUTPUT}, { 0, 0, 1, 0, 0, 0} }, // C !2
  { { OUTPUT, OUTPUT, OUTPUT, INPUT, OUTPUT, OUTPUT}, { 0, 0, 1, 0, 0, 0} }, // C !3
  { { OUTPUT, INPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 1, 0, 0, 0} }, // C !4
  { { INPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 1, 0, 0, 0} }, // C !5 

  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, INPUT}, { 0, 0, 0, 1, 0, 0} }, // D !1
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, INPUT, OUTPUT}, { 0, 0, 0, 1, 0, 0} }, // D !2
  { { OUTPUT, OUTPUT, INPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 0, 1, 0, 0} }, // D !3
  { { OUTPUT, INPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 0, 1, 0, 0} }, // D !4
  { { INPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 0, 1, 0, 0} }, // D !5 
  
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, INPUT}, { 0, 0, 0, 0, 1, 0} }, // E !1
  { { OUTPUT, OUTPUT, OUTPUT, INPUT, OUTPUT, OUTPUT}, { 0, 0, 0, 0, 1, 0} }, // E !2
  { { OUTPUT, OUTPUT, INPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 0, 0, 1, 0} }, // E !3
  { { OUTPUT, INPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 0, 0, 1, 0} }, // E !4
  { { INPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 0, 0, 1, 0} }, // E !5 
  
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, INPUT, OUTPUT}, { 0, 0, 0, 0, 0, 1} }, // G !1
  { { OUTPUT, OUTPUT, OUTPUT, INPUT, OUTPUT, OUTPUT}, { 0, 0, 0, 0, 0, 1} }, // G !2
  { { OUTPUT, OUTPUT, INPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 0, 0, 0, 1} }, // G !3
  { { OUTPUT, INPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 0, 0, 0, 1} }, // G !4
  { { INPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 0, 0, 0, 1} }, // G !5 
*/
 // Values by column
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 1, 0, 0, 0, 0, 0} }, // A
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 1, 0, 0, 0, 0} }, // B
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 1, 0, 0, 0} }, // C
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 0, 1, 0, 0} }, // D
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 0, 0, 1, 0} }, // E
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 0, 0, 0, 1} }, // G

/*
// Values of each light individually
  { { OUTPUT, INPUT, INPUT, INPUT, INPUT, OUTPUT}, { 1, 0, 0, 0, 0, 0} }, // A1
  { { OUTPUT, INPUT, INPUT, INPUT, OUTPUT, INPUT}, { 1, 0, 0, 0, 0, 0} }, // A2
  { { OUTPUT, INPUT, INPUT, OUTPUT, INPUT, INPUT}, { 1, 0, 0, 0, 0, 0} }, // A3
  { { OUTPUT, INPUT, OUTPUT, INPUT, INPUT, INPUT}, { 1, 0, 0, 0, 0, 0} }, // A4
  { { OUTPUT, OUTPUT, INPUT, INPUT, INPUT, INPUT}, { 1, 0, 0, 0, 0, 0} }, // A5
     
  { { INPUT, OUTPUT, INPUT, INPUT, INPUT, OUTPUT}, { 0, 1, 0, 0, 0, 0} }, // B1
  { { INPUT, OUTPUT, INPUT, INPUT, OUTPUT, INPUT}, { 0, 1, 0, 0, 0, 0} }, // B2
  { { INPUT, OUTPUT, INPUT, OUTPUT, INPUT, INPUT}, { 0, 1, 0, 0, 0, 0} }, // B3
  { { INPUT, OUTPUT, OUTPUT, INPUT, INPUT, INPUT}, { 0, 1, 0, 0, 0, 0} }, // B4
  { { OUTPUT, OUTPUT, INPUT, INPUT, INPUT, INPUT}, { 0, 1, 0, 0, 0, 0} }, // B5

  { { INPUT, INPUT, OUTPUT, INPUT, INPUT, OUTPUT}, { 0, 0, 1, 0, 0, 0} }, // C1
  { { INPUT, INPUT, OUTPUT, INPUT, OUTPUT, INPUT}, { 0, 0, 1, 0, 0, 0} }, // C2
  { { INPUT, INPUT, OUTPUT, OUTPUT, INPUT, INPUT}, { 0, 0, 1, 0, 0, 0} }, // C3
  { { INPUT, OUTPUT, OUTPUT, INPUT, INPUT, INPUT}, { 0, 0, 1, 0, 0, 0} }, // C4
  { { OUTPUT, INPUT, OUTPUT, INPUT, INPUT, INPUT}, { 0, 0, 1, 0, 0, 0} }, // C5
 
  { { INPUT, INPUT, INPUT, OUTPUT, INPUT, OUTPUT}, { 0, 0, 0, 1, 0, 0} }, // D1
  { { INPUT, INPUT, INPUT, OUTPUT, OUTPUT, INPUT}, { 0, 0, 0, 1, 0, 0} }, // D2
  { { INPUT, INPUT, OUTPUT, OUTPUT, INPUT, INPUT}, { 0, 0, 0, 1, 0, 0} }, // D3
  { { INPUT, OUTPUT, INPUT, OUTPUT, INPUT, INPUT}, { 0, 0, 0, 1, 0, 0} }, // D4
  { { OUTPUT, INPUT, INPUT, OUTPUT, INPUT, INPUT}, { 0, 0, 0, 1, 0, 0} }, // D5

  { { INPUT, INPUT, INPUT, INPUT, OUTPUT, OUTPUT}, { 0, 0, 0, 0, 1, 0} }, // E1
  { { INPUT, INPUT, INPUT, OUTPUT, OUTPUT, INPUT}, { 0, 0, 0, 0, 1, 0} }, // E2
  { { INPUT, INPUT, OUTPUT, INPUT, OUTPUT, INPUT}, { 0, 0, 0, 0, 1, 0} }, // E3
  { { INPUT, OUTPUT, INPUT, INPUT, OUTPUT, INPUT}, { 0, 0, 0, 0, 1, 0} }, // E4
  { { OUTPUT, INPUT, INPUT, INPUT, OUTPUT, INPUT}, { 0, 0, 0, 0, 1, 0} }, // E5
  
  { { INPUT, INPUT, INPUT, INPUT, OUTPUT, OUTPUT}, { 0, 0, 0, 0, 0, 1} }, // G1
  { { INPUT, INPUT, INPUT, OUTPUT, INPUT, OUTPUT}, { 0, 0, 0, 0, 0, 1} }, // G2
  { { INPUT, INPUT, OUTPUT, INPUT, INPUT, OUTPUT}, { 0, 0, 0, 0, 0, 1} }, // G3
  { { INPUT, OUTPUT, INPUT, INPUT, INPUT, OUTPUT}, { 0, 0, 0, 0, 0, 1} }, // G4
  { { OUTPUT, INPUT, INPUT, INPUT, INPUT, OUTPUT}, { 0, 0, 0, 0, 0, 1} }, // G5
  */
};
 
void turnOn( int led ) {
  pinMode( A, matrix[led][PIN_CONFIG][0] );
  pinMode( B, matrix[led][PIN_CONFIG][1] );
  pinMode( C, matrix[led][PIN_CONFIG][2] );
  pinMode( D, matrix[led][PIN_CONFIG][3] );
  pinMode( E, matrix[led][PIN_CONFIG][4] );
  pinMode( G, matrix[led][PIN_CONFIG][5] );
  digitalWrite( A, matrix[led][PIN_STATE][0] );
  digitalWrite( B, matrix[led][PIN_STATE][1] );
  digitalWrite( C, matrix[led][PIN_STATE][2] );
  digitalWrite( D, matrix[led][PIN_STATE][3] );
  digitalWrite( E, matrix[led][PIN_STATE][4] );
  digitalWrite( G, matrix[led][PIN_STATE][5] );

}
 
void setup() {}
 
void loop() {
  for( int l = 0; l < LED_COUNT; l++ ) {
    turnOn( l );
    delay( 30 / LED_COUNT );
  }
}

I will update the code at the top of this topic as I clean it up and make changes.

Please do not do this.

Please read the how to use this forum sticky post for this and also for how to post code correctly. Use the # icon not the quote next to it.

ok, won't do (I didn't realize that was taboo) and thanks for the code bracket help. Every forum's different still learning all the little tricks here

Thanks for the change.
The thing about charlplexing is that there are only a limited number of LEDs that can be turned on at any one time. And the actual number and their location depends on your wiring. Using charlplexing for a matrix requires you to scan through each individual LED in turn and light the LED or not.

In my opinion this might be acceptable for arrays of 2x3, or 3x4, but not 5x6 as at best an LED is lit for 1/30th of the time.

True but that is the nature of charlyplexing.
I can't see any resistors in this circuit I hope you have some.

I can't see any resistors in this circuit I hope you have some.

I do I have 22Ohm resistors on each pin (thanks for asking) I was just using the graph to illustrate the array

True but that is the nature of charlyplexing.

Hey GrumpyMike, I am able to get multiple leds to light up quite nicely. (although there's one error I get that's driving me nuts.) Take a look at my code (but before you do let me explain something quickly)

  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 1, 0, 0, 0, 0, 0} }, // A
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 1, 0, 0, 0, 0} }, // B
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 1, 0, 0, 0} }, // C
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 0, 1, 0, 0} }, // D
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 0, 0, 1, 0} }, // E
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 0, 0, 0, 1} }, // G

So, due to the nature of charlieplexing, each of the digits is offset by one according to the column number. If you look back at the circuit drawing at the top of the thread, you'll notice this is illustrated by the dots connecting the rows to columns, and in the code by the move to the right of the one in each digit. These dots are applying power to each of the columns, and is why charlieplexes can't be square (eg must be 5x6 not 6x6) The code above allows all the leds to be light one column at a time.

So inorder to make the code easier for humans to read I put this together

  for (int rows = 0; rows < LED_ROWS; rows++) {
    for (int cols = 0; cols < LED_COUNT; cols++){
      if (cols >= rows){
        matrix[rows][PIN_CONFIG][cols+1]=character[rows][PIN_CONFIG][cols];        
      }
      else {
        matrix[rows][PIN_CONFIG][cols]=character[rows][PIN_CONFIG][cols]; 
      }
    }
  }

This allows you to write the 0's and 1's as you would see them on the grid, e.g. like this:

int character[6][1][5] = {
{{1,1,1,1,1}},
{{0,1,0,1,0}},
{{0,1,0,0,1}},
{{0,1,0,1,0}},
{{1,1,1,0,0}},
{{0,0,0,0,0}}};

Here is the full and updated code, but I keep getting an error. It will not allow me to light Column A, I can't figure out why. the issue seems to be in my function (second code in the post) as when I change it I can get the column to write just fine, it just either messes up my other rows, or without the function I have to write with the diagonal 1's in the code which is a big pain in the neck. Suggestions? Also does anyone have an idea why I can't define column "F" as "F" and have to define it as "G"?

#define A 2
#define B 3
#define C 4
#define D 5
#define E 6
#define G 7

#define PIN_CONFIG 0
#define PIN_STATE 1
#define LED_ROWS 5
#define LED_COUNT 6

// Create a Cell Array
// callout is as follow for the cell array [row][column][position within cell]
//       0        1        2    <--- Column
//  0|{0 1 2), {0 1 2), {0 1 2)| <--- Cell
//  1|{0 1 2), {0 1 2), {0 1 2)|
//  2|{0 1 2), {0 1 2), {0 1 2)|
//  ^
//  |____ Row
//

int character[6][1][5] = {
{{1,1,1,1,1}},
{{0,1,0,1,0}},
{{0,1,0,0,1}},
{{0,1,0,1,0}},
{{1,1,1,0,0}},
{{0,0,0,0,0}}};
 
int matrix[LED_COUNT][2][6] = {
  //               PIN_CONFIG (Horizontal)               PIN_STATE (Vertical)
  //    A       B       C      D       E       G        A, B, C, D, E, G

 // Values by column
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 1, 0, 0, 0, 0, 0} }, // A
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 1, 0, 0, 0, 0} }, // B
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 1, 0, 0, 0} }, // C
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 0, 1, 0, 0} }, // D
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 0, 0, 1, 0} }, // E
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 0, 0, 0, 1} }, // G


};
 
void turnOn( int led ) {
  
  pinMode( A, matrix[led][PIN_CONFIG][0] );
  pinMode( B, matrix[led][PIN_CONFIG][1] );
  pinMode( C, matrix[led][PIN_CONFIG][2] );
  pinMode( D, matrix[led][PIN_CONFIG][3] );
  pinMode( E, matrix[led][PIN_CONFIG][4] );
  pinMode( G, matrix[led][PIN_CONFIG][5] );
  digitalWrite( A, matrix[led][PIN_STATE][0] );
  digitalWrite( B, matrix[led][PIN_STATE][1] );
  digitalWrite( C, matrix[led][PIN_STATE][2] );
  digitalWrite( D, matrix[led][PIN_STATE][3] );
  digitalWrite( E, matrix[led][PIN_STATE][4] );
  digitalWrite( G, matrix[led][PIN_STATE][5] );

}
 
void setup() {
}
 
void loop() {

  for (int rows = 0; rows < LED_ROWS; rows++) {
    for (int cols = 0; cols < LED_COUNT; cols++){
      if (cols >= rows){
        matrix[rows][PIN_CONFIG][cols+1]=character[rows][PIN_CONFIG][cols];        
      }
      else {
        matrix[rows][PIN_CONFIG][cols]=character[rows][PIN_CONFIG][cols]; 
      }
    }
  }
  
  for( int L = 0; L < LED_COUNT; L++ ) {
    turnOn( L );
    delay( 20 / LED_COUNT );
  }
}

Ok! Woot Woot,
I understand I'm going back and forth really fast, but this is Christmas vacation for me :stuck_out_tongue: I found out that Column A wasn't the only thing not working, but Column G wasn't either (G is a psudoname for whatever reason it won't let me define it as F)

Fixed both, it ended up being an easy <= LED_ROWS (not just <), and making LED_COUNT - 1 (it was just LED_COUNT before).

Here is the up to date code. and it allows for any image to be Charlieplexed with an led light time of 1 out of 6 :smiley:

#define A 2
#define B 3
#define C 4
#define D 5
#define E 6
#define G 7

#define PIN_CONFIG 0
#define PIN_STATE 1
#define LED_ROWS 5
#define LED_COUNT 6

// Create a Cell Array
// callout is as follow for the cell array [row][column][position within cell]
//       0        1        2    <--- Column
//  0|{0 1 2), {0 1 2), {0 1 2)| <--- Cell
//  1|{0 1 2), {0 1 2), {0 1 2)|
//  2|{0 1 2), {0 1 2), {0 1 2)|
//  ^
//  |____ Row
//

int character[6][1][5] = {
{{1,1,1,0,0}},
{{0,1,0,1,0}},
{{0,1,0,0,1}},
{{0,1,0,1,0}},
{{1,1,1,0,0}},
{{0,0,0,0,0}}};
 
int matrix[LED_COUNT][2][6] = {
  //               PIN_CONFIG (Horizontal)               PIN_STATE (Vertical)
  //    A       B       C      D       E       G        A, B, C, D, E, G

 // Values by column
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 1, 0, 0, 0, 0, 0} }, // A
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 1, 0, 0, 0, 0} }, // B
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 1, 0, 0, 0} }, // C
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 0, 1, 0, 0} }, // D
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 0, 0, 1, 0} }, // E
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 0, 0, 0, 1} }, // G


};
 
void turnOn( int led ) {
  
  pinMode( A, matrix[led][PIN_CONFIG][0] );
  pinMode( B, matrix[led][PIN_CONFIG][1] );
  pinMode( C, matrix[led][PIN_CONFIG][2] );
  pinMode( D, matrix[led][PIN_CONFIG][3] );
  pinMode( E, matrix[led][PIN_CONFIG][4] );
  pinMode( G, matrix[led][PIN_CONFIG][5] );
  digitalWrite( A, matrix[led][PIN_STATE][0] );
  digitalWrite( B, matrix[led][PIN_STATE][1] );
  digitalWrite( C, matrix[led][PIN_STATE][2] );
  digitalWrite( D, matrix[led][PIN_STATE][3] );
  digitalWrite( E, matrix[led][PIN_STATE][4] );
  digitalWrite( G, matrix[led][PIN_STATE][5] );

}
 
void setup() {
}
 
void loop() {

  for (int rows = 0; rows <= LED_ROWS; rows++) {     //Added a +1 to LED Rows, seemed to fix Column G
    for (int cols = 0; cols < LED_COUNT-1; cols++){
      if (cols >= rows){
        matrix[rows][PIN_CONFIG][cols+1]=character[rows][PIN_CONFIG][cols];        
      }
      else {
        matrix[rows][PIN_CONFIG][cols]=character[rows][PIN_CONFIG][cols]; 
      }
    }
  }
  
  for( int L = 0; L < LED_COUNT; L++ ) {
    turnOn( L );
    delay( 20 / LED_COUNT );
  }
}

Alright I've got the animation working. 8)

Please give me any feedback on what you think, or ideas for better ways to go about doing this.

I'd consider this a success, bumping the light time from 1/30 to 1/6, and adding in the ability to code Highs and Lows easily without the "charlieplex diagonal" and in a way that is visually easy for a human (although with 26 frames of animation it does get long lengthwise, but totally worth it).

Here's my final product test:

and here's the code: Still waiting for anyone to help me find why I can't #define F for column F, but instead have to use G

/* 
This sketch allows for a charlieplex 6 columns by 5 rows
(charlieplexing requires there are as many pins as columns, and one less row).
It would be relatively easy to adapt to larger or smaller arrays.

What makes this sketch better/more unique is that it lights by column, NOT by individual light;
this allows the refresh rate of each light to be 1/6th of the alotted time as opposed to 1/30th.
It is also set up to animate, doing one frame after another.

for more information on this sketch, check out the link on arduino forums where I wrote it:
http://forum.arduino.cc/index.php?topic=206743.0

Written by Jake Shealy and Jim Shealy 12/16/2013
Free to use and improve for anyone
*/


#define A 2  //Row A is pin 2
#define B 3  //Row B is pin 3
#define C 4  //Row C is pin 4
#define D 5  //Row D is pin 5
#define E 6  //Row E is pin 6
#define G 7  //Row G is pin 7  This is not a typeo, for whatever reason Arduino won't let me #define F as pin 7. Weird right?

#define PIN_CONFIG 0
#define PIN_STATE 1
#define LED_ROWS 5   // # of rows
#define LED_COUNT 6  // # of leds, for normal charlieplex this would be 30, but because we're going by column it is 6
int animation = 0;
int counter = 0;
int frames = 26; // number of frames in the matrix, change it here and just below in the middle bracket of int character[6][*][5]
int flashtime = 15; //How long the lights in a column stay lit before moving to the next column

//Here's the animation, 0's are off, 1's are on. they are exactly as they look in grid.
int character[6][26][5] = {
{{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{1,0,0,0,0},{1,1,0,0,0},{1,1,1,0,0},{0,1,1,1,0},{0,0,1,1,1},{0,0,0,1,1},{0,0,0,0,1},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,1},{0,0,0,1,1},{0,0,1,1,1},{0,1,1,1,0},{1,1,1,0,0},{1,1,0,0,0},{1,0,0,0,0},{0,0,0,0,0}},
{{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{1,0,0,0,0},{1,1,0,0,0},{1,1,1,0,0},{0,1,1,1,0},{0,0,1,1,1},{0,0,0,1,1},{0,0,0,0,1},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,1},{0,0,0,1,1},{0,0,1,1,1},{0,1,1,1,0},{1,1,1,0,0},{1,1,0,0,0},{1,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0}},
{{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{1,0,0,0,0},{1,1,0,0,0},{1,1,1,0,0},{0,1,1,1,0},{0,0,1,1,1},{0,0,0,1,1},{0,0,0,0,1},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,1},{0,0,0,1,1},{0,0,1,1,1},{0,1,1,1,0},{1,1,1,0,0},{1,1,0,0,0},{1,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0}},
{{0,0,0,0,0},{0,0,0,0,0},{1,0,0,0,0},{1,1,0,0,0},{1,1,1,0,0},{0,1,1,1,0},{0,0,1,1,1},{0,0,0,1,1},{0,0,0,0,1},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,1},{0,0,0,1,1},{0,0,1,1,1},{0,1,1,1,0},{1,1,1,0,0},{1,1,0,0,0},{1,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0}},
{{0,0,0,0,0},{1,0,0,0,0},{1,1,0,0,0},{1,1,1,0,0},{0,1,1,1,0},{0,0,1,1,1},{0,0,0,1,1},{0,0,0,0,1},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,1},{0,0,0,1,1},{0,0,1,1,1},{0,1,1,1,0},{1,1,1,0,0},{1,1,0,0,0},{1,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0}},
{{1,0,0,0,0},{1,1,0,0,0},{1,1,1,0,0},{0,1,1,1,0},{0,0,1,1,1},{0,0,0,1,1},{0,0,0,0,1},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,1},{0,0,0,1,1},{0,0,1,1,1},{0,1,1,1,0},{1,1,1,0,0},{1,1,0,0,0},{1,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0}}};
 
int matrix[LED_COUNT][2][6] = {
  //               PIN_CONFIG (Horizontal)               PIN_STATE (Vertical)
  //    A       B       C      D       E       G         A, B, C, D, E, G

 // Values by column this is referenced and the backbone of telling the whole column to light at one time
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 1, 0, 0, 0, 0, 0} }, // A
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 1, 0, 0, 0, 0} }, // B
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 1, 0, 0, 0} }, // C
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 0, 1, 0, 0} }, // D
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 0, 0, 1, 0} }, // E
  { { OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT, OUTPUT}, { 0, 0, 0, 0, 0, 1} }, // G


};
 
void turnOn( int led ) {
  
  pinMode( A, matrix[led][PIN_CONFIG][0] );
  pinMode( B, matrix[led][PIN_CONFIG][1] );
  pinMode( C, matrix[led][PIN_CONFIG][2] );
  pinMode( D, matrix[led][PIN_CONFIG][3] );
  pinMode( E, matrix[led][PIN_CONFIG][4] );
  pinMode( G, matrix[led][PIN_CONFIG][5] );
  digitalWrite( A, matrix[led][PIN_STATE][0] );
  digitalWrite( B, matrix[led][PIN_STATE][1] );
  digitalWrite( C, matrix[led][PIN_STATE][2] );
  digitalWrite( D, matrix[led][PIN_STATE][3] );
  digitalWrite( E, matrix[led][PIN_STATE][4] );
  digitalWrite( G, matrix[led][PIN_STATE][5] );

}
 
void setup() {
}
 
void loop() {

  for (int rows = 0; rows <= LED_ROWS; rows++) {
    for (int cols = 0; cols < LED_COUNT-1; cols++){
      if (cols >= rows){
        matrix[rows][PIN_CONFIG][cols+1]=character[rows][animation][cols];        
      }
      else {
        matrix[rows][PIN_CONFIG][cols]=character[rows][animation][cols]; 
      }
    }
  }
  
  for( int L = 0; L < LED_COUNT; L++ ) {
    turnOn( L );
    delay( flashtime / LED_COUNT );
  }
  if( animation == frames) {animation = 0;}   //after going through all the frames, restart the animation
  else animation ;
  
  if (counter == 10){animation++;     //after looping 10 times, move to the next animation and reset counter
  counter = 0;}
  else  counter++;
}

Grumpy_Mike:
The thing about charlplexing is that there are only a limited number of LEDs that can be turned on at any one time. And the actual number and their location depends on your wiring. Using charlplexing for a matrix requires you to scan through each individual LED in turn and light the LED or not.

Not correct (but - surely you knew that?). Charlieplexing is at least as good as any other matrix multiplexing; you select each line in turn, say to ground the cathodes and can activate as many of the others as anodes, as you like. In this case, it is a one in six multiplex, just as good as the MAX7219 (which, incidentally, would be the obvious way to drive 30 LEDs with a one in five multiplex and peak current of 40 mA; 8 mA average).

The problem with Charlieplexing is in buffering the current for the line carrying current to multiple LEDs at once. If you keep the matrix "open" so that the common cathodes and common anodes are separate, then you can drive the cathodes directly (via their current limit resistors of course), and the anodes via an NPN emitter follower (no base resistor required) with collector connected to either the Arduino 5V, or more conveniently, your actual supply voltage and thus bypassing the regulator.

You multiplex by anodes one at a time. If you must "close" the matrix so that anode and cathode commons are connected together, you use a diode and the series limit resistor in reverse across each base-emitter junction, in which case you lose another 0.65V in addition to the Vbe of the transistor.

Not correct (but - surely you knew that?).

Please read what I said and stop jumping to conclusions before you finish reading the sentence.
You can not always turn on a whole row or column at the same time due to the way it is wired.

Grumpy_Mike:
You can not always turn on a whole row or column at the same time due to the way it is wired.

I think you should give an example if you wish to make such an assertion.


Actually, the problem was that I had read the whole paragraph. Your comment:

Grumpy_Mike:
Using charlplexing for a matrix requires you to scan through each individual LED in turn and light the LED or not.

In my opinion this might be acceptable for arrays of 2x3, or 3x4, but not 5x6 as at best an LED is lit for 1/30th of the time.

True but that is the nature of charlyplexing.

... implies that only one LED at a time can be illuminated, which is palpably wrong. In the diagram originally cited, it is always possible to light a whole column (not row) of LEDs simultaneously - given adequate buffering - with a one in six multiplex. The limitation is really no different from "straight" multiplexing.

Hi SuperSynapse,

Have a look at what I did here: Useful circuit: Charlieplexed 4 x 7-Segment display - Exhibition / Gallery - Arduino Forum

In my case I have 32 LEDS, arranged as 4x8 matrix. The LEDS just happen to be 7-segment displays, but the principle is the same. I have up to 8 LEDs lit at any one instant (using NPN emitter followers as Paul__B says to source more current than an Arduino output can do un-aided) and a 1:4 multiplex ratio. This circuit could drive up to 64 LEDs (8x8 matrix) with the addition of 4 more NPNs and a 1:8 multiplex ratio.

Hope this helps.

Paul

Hey Paul RB,

That's sick! Thanks for the link, I really like what you did there. Question though. Why were you using transistors? (this was also mentioned by the other Paul above)
I read your thread and you mentioned damaging the arduino from current flow etc. In my current configuration each pin is powering only one LED at a time per pin, which is 20mA at 5v (3v with the resistor) How could this ever be an issue? I totally understand if I wanted to drive something MORE than 5v, such as multiple leds, or a super bright LED, but why would you use transistors for a circuit so low on power usage? And either way, the current you're transist-ing to is coming from the 5V pin on the arduino (not an external source).

I guess in other words, what is the arduino meant to handle? My understanding was as long as it's less than 40ma and 5V, you can power as many pins at a time as you want. (so with the Arduino Uno, that's 19 pins, and the mega, something like 50)

edit: on afterthought I did realize I am grounding 5 leds per pin, is that the issue? How is it different grounding to a pin, vs grounding to the "GND pin"? Much thanks!

SuperSynapse:
edit: on afterthought I did realize I am grounding 5 leds per pin, is that the issue? How is it different grounding to a pin, vs grounding to the "GND pin"?

Each Arduino output can only handle around 40mA of current (many experts say you should not exceed 20~25mA if you want the Arduino have a long life).

This 40mA limit applies whether the pin is sourcing or sinking current. When you "ground" 5 leds to the same pin, if there is, say, 20mA flowing through each LED, the pin has to sink 100mA! This could easily damage it.

In my circuit, each pin only sinks the current from one LED. When a pin has to source the current for 8 leds, the transistor takes the strain, reducing the current the Arduino pin has to source by a factor of 100 (assuming the transistor's gain is around 100).

There is also a limit on the total current the Arduino can source or sink through all outputs combined. For an uno (based on an atmega328) this is around 200mA.

There is also a limit on the total current the Arduino can source or sink through all outputs combined. For an uno (based on an atmega328) this is around 200mA.

Very good to know, as I just got a few Arduino Mega boards in, and it'll be even easier to over do it on them.