Multiplexing?

Is there a website somewhere that clearly explains how to do multiplexing?

I am trying to get an 8x8 RGB LED Array to work but cannot figure out how to do it. I have read several sites about multiplexing but it goes over the top of my head. Also I have yet to see a decent schematic that shows how to wire an an 8x8 RGB array up for multiplexing.

Can someone point me in the direction of a "Multiplexing LED arrays for idiots" page please?

using a max 7219 IC is often a better choice than multiplexing.

Here is an example with code and everything: http://www.bryanchung.net/?p=177

It's also in the playground

The 8x8 LED array is organised into eight rows and eight columns. The idea behind multiplexing (in this context) is to light up just one column at a time, then go on to the next column, and so on, fast enough that the eye can't see what you're doing. The LEDs will appear to be lit up all the time, even though each one is only "on" for one-eighth of the time.

So you need to write a program to select one column, then light the LEDs needed in that column, wait for a short time, then switch off the LEDs, select the next column, light the LEDs, wait, and so on looping forever. The overall speed should be fast enough for the LEDs not to flicker, but for testing, it may be easier to run the slower (longer delays).

You can, of course, swap "row" and "column" if it makes the code easier (select a row, light LEDs, wait, next row...). With a square matrix, there's no advantage to either direction.

Thanks for the info. I wired up 2 x 74HC595N's exactly as in the Shiftout example in the playground. I then wired one 595 up to the rows of the matrix (Anode) with resistors in series and the other to the columns with no resistors.

I then used this modified version of the Shiftout code to test it worked which it did first time :slight_smile: :-

//Pin connected to ST_CP of 74HC595
int latchPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 12;
////Pin connected to DS of 74HC595
int dataPin = 11;
byte charA[8];



void setup() {

  //set pins to output because they are addressed in the main loop
  pinMode(latchPin, OUTPUT);
charA[0] = B00011000;
charA[1] = B00100100;
charA[2] = B01000010;
charA[3] = B10011001;
charA[4] = B10011001;
charA[5] = B01000010;
charA[6] = B00100100;
charA[7] = B00011000;
}

void loop() {
  
   for (int a = 0; a <8; a = a + 1 ) {

     for (int time = 0; time <10; time = time + 1 ) {
     
            byte char1 = B11111110;
           int x = a;
   for (int j = 0; j < 8; j = j + 1) {
     

    //ground latchPin and hold low for as long as you are transmitting
    digitalWrite(latchPin, 0);
  int z = j + x;
  if (z>7) {z = z - 8;};
    shiftOut(dataPin, clockPin, charA[z]); 
    //count down on RED LEDs
    shiftOut(dataPin, clockPin, char1);
    //return the latch pin high to signal chip that it 
    //no longer needs to listen for information
    digitalWrite(latchPin, 1);


   char1 = char1 << 1;
 char1 = char1 + 1;
 // x=x+1;
 // if (x==8) { x = 0; }
    delayMicroseconds(1000);
   }
     }
   }
  
}

void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {
  // This shifts 8 bits out MSB first, 
  //on the rising edge of the clock,
  //clock idles low

//internal function setup
  int i=0;
  int pinState;
  pinMode(myClockPin, OUTPUT);
  pinMode(myDataPin, OUTPUT);

 //clear everything out just in case to
 //prepare shift register for bit shifting
  digitalWrite(myDataPin, 0);
  digitalWrite(myClockPin, 0);

  //for each bit in the byte myDataOut[ch65533]
  //NOTICE THAT WE ARE COUNTING DOWN in our for loop
  //This means that %00000001 or "1" will go through such
  //that it will be pin Q0 that lights. 
  for (i=7; i>=0; i--)  {
    digitalWrite(myClockPin, 0);

    //if the value passed to myDataOut and a bitmask result 
    // true then... so if we are at i=6 and our value is
    // %11010100 it would the code compares it to %01000000 
    // and proceeds to set pinState to 1.
    if ( myDataOut & (1<<i) ) {
      pinState= 1;
    }
    else {      
      pinState= 0;
    }

    //Sets the pin to HIGH or LOW depending on pinState
    digitalWrite(myDataPin, pinState);
    //register shifts bits on upstroke of clock pin  
    digitalWrite(myClockPin, 1);
    //zero the data pin after shift to prevent bleed through
    digitalWrite(myDataPin, 0);
  }

  //stop shifting
  digitalWrite(myClockPin, 0);
}

(Yes I know it isn't very elegant code, it was just to test my understanding of how the 595's worked)

My confusion was in that the 595's when low were acting as a ground for the matrix. At least that's how I think it works. As I was unsure how the same IC could use the same outputs to go to both the anode and cathode of the array.

Here is a link to a video of the test in action :- RGB 8x8 LED Matrix Test 1 on Vimeo

I've also tried this modified code to give a little animation :-

byte dataPin = 11; // 74HC595 pin 14
byte latchPin = 8; // 74HC595 pin 12
byte clockPin = 12; // 74HC595 pin 11

byte data; // storage for the current data byte
byte dataArray[2][8]; // define the data array

byte row; // storrage for the current row byte
byte rowArray[8]; // define the row array

void setup()
{
 pinMode(dataPin, OUTPUT); //pinmode setup
 pinMode(latchPin, OUTPUT);
 pinMode(clockPin, OUTPUT);

// column registers for image data.
 dataArray[0][0] = B01111110;
 dataArray[0][1] = B10000001;
 dataArray[0][2] = B10000001;
 dataArray[0][3] = B10011001;
 dataArray[0][4] = B10011001;
 dataArray[0][5] = B10000001;
 dataArray[0][6] = B10000001;
 dataArray[0][7] = B01111110;
 
 dataArray[1][0] = B11111111;
 dataArray[1][1] = B10000001;
 dataArray[1][2] = B10011001;
 dataArray[1][3] = B10100101;
 dataArray[1][4] = B10100101;
 dataArray[1][5] = B10011001;
 dataArray[1][6] = B10000001;
 dataArray[1][7] = B11111111;

// row registers... DO NOT CHANGE THESE!
 rowArray[0] = B01111111;
 rowArray[1] = B10111111;
 rowArray[2] = B11011111;
 rowArray[3] = B11101111;
 rowArray[4] = B11110111;
 rowArray[5] = B11111011;
 rowArray[6] = B11111101;
 rowArray[7] = B11111110;
}

void loop()
{
 drawSprite();
}

void drawSprite()
{
  for (int repeat = 0; repeat < 50; repeat += 1 ) {
 for(int j = 0; j < 8; j++){ // load the byte...
   data = dataArray[0][j]; // from the data array...
   row = rowArray[j]; // and the row array
   digitalWrite(latchPin, LOW); // ground the latch pin
   shiftOut(dataPin, clockPin, MSBFIRST, data); // shift out the data
   shiftOut(dataPin, clockPin, MSBFIRST, row); // shift out the row byte
   digitalWrite(latchPin, HIGH); // it's finished so bring the latch pin high
   delayMicroseconds(1000); // left in to display the plex at low speed    
 }
  }
  
    for (int repeat = 0; repeat < 50; repeat += 1 ) {
 for(int j = 0; j < 8; j++){ // load the byte...
   data = dataArray[1][j]; // from the data array...
   row = rowArray[j]; // and the row array
   digitalWrite(latchPin, LOW); // ground the latch pin
   shiftOut(dataPin, clockPin, MSBFIRST, data); // shift out the data
   shiftOut(dataPin, clockPin, MSBFIRST, row); // shift out the row byte
   digitalWrite(latchPin, HIGH); // it's finished so bring the latch pin high
   delayMicroseconds(1000); // left in to display the plex at low speed    
 }
  }
}

Glad to hear that you've got the code working! As for the74HC595, it has so-called "totem pole" outputs, which means that there are two output transistors, one above the other on the diagram (hence the name). To drive high, the upper transistor conducts, and to drive low, the lower transistor conducts. There are some diagrams in the Wikipedia page: Transistor–transistor logic - Wikipedia

Anyway, the 595 can (I think) drive more current to ground than it can drive to 5V, if it's anything like most normal TTL chips. That's why you often see LEDs connected from a pin to +5V and not to ground, to take advantage of the higher current "sink" capability.

But be careful if you're using a 595 in this way, because you can be exceeding it maximum current capacity. That is, if a whole column of LEDs are grounded via one pin on the chip (and they're all "on"). For a more powerful chip to use at the ground end (a "low-side driver"), have a look at the ULN2803. It's an 8-bit version of the more well-known ULN2003.

Is there a LED library for the 595's? I see there is one for the MAX chips. Has anyone modified it for the 595's?

Thanks for the info. Anachrocomputer.