Arduino Scrolling 56x8 LED matrix

Thanks everyone I couldnt have got this working without you......

I figured it out in the end it was a wiring fault. I have now complete the Sign.

how would I change your code to use matrices who's columns are the anodes, rather than the rows?

Sorry for responding so late. I may be mistaken, but I believe unlike 74HC595, TPIC6C595 can only drain into ground and cannot supply positive to the anode columns of your matrix. There's probably a chip similar to TPIC6C595 that would work with your matrix, but I do not know what that is.

I use 74HC595 for both row and cols and use CA matrixes. I invert the bit of the characters. It's works!

The TPIC is the same as the 595 but it has higher current output. The code will be identical. There is another chip HEF4794 which is also a high power output chip but only drives 40ma.

The standard 595 chip will drive 1 LED per output fine but if it needs to drive more you’re going to have to boost it’s output.

I have actually managed to get this to work now just with the 595's.

I'm intrigued, can you post code for that? maybe a quick sketch of how the 595s are hooked up to each other as well?

I have connected everything up the same way as hari but I used a 595 with transistors for the negative rows.

You can get the code i used at

Hello hari,

wanted to say thank you, i borrowed a few lines of your code for my Arduquee project. Have a look:

Had to modify it heavily because we designed our hardware differently and I used a tri-color matrix. I found your code after I already had the boards made and some of my own code written.

The segments are modular and any length marquee can be built. I plan on making these into kits eventually, as a cheaper alternative to serial backpack boards.

Hi everybody at the Arduino forum!

Hari, is your homepage down for good, or are you improving it?

I would interested in the "56x8ScrollingLEDSchematic.jpg" picture as I am doing this same project myself for school project. Need some help with the wiring as I am designing a circuit board for this.

Is there anyway you could send it to my email, if you still have it on your computer?

Oh sorry about that... I've added the schema to the end of the blog post.

Good luck with your project! It is a lot of work, but very rewarding.

Thanks Hari!

This will be a huge help and I will give credit to you in the written report :)

hi! may i enquire why did you use tpic6c595 in to drive the column and 74hc595 for rows and not the other way round?

hi! may i enquire why did you use tpic6c595 in to drive the column and 74hc595 for rows and not the other way round?

My matrix is wired so the led current goes from the row to the column, and the tpic6c595 will only drain to ground, so i had to use it for the columns. You are on the right track to question my choice, it would be better to have the more powerful tpic6c595 to drive the common row and the less powerful 74hc595 for the individual columns. However, to do this, I would have to rotate my matrix (treating rows as columns and vice versa) -- not practical on my breadboard. :-(

thanks for clarifying =)

one more question though...

so if i decided to use only 5 matrixes

the only thing i have to modify in your code is in the Bitmap section right?

are there anything that i should lookout for?

thanks alot for the reply

Correct. The code looks at the bitmap size and deduce # of columns by assuming 8 rows per column. Good luck and have fun!

Greetings Hari,
i’ve made at school my own ledmatrix of 40x8. thanks for your explaining about the code and stuff.
i’ve made at myself a serial version of it but i got the problem that i lose the text i writen in it when i turn of my arduino. ( cause of i write into a char)
now is my question do you maybe know how i write a char into my EEPROM.

i tryed but it says i can only write a int into it so no char…
do you maybe have an idea?

btw: thanks for your great idea:)
the code of the serial part btw:

void AlphabetSoup()
#define INLENGTH 20        
#define INTERMINATOR 13    

char msg[INLENGTH+1];
char tmpMsg[INLENGTH+1];
int inCount;           
 for (int charIndex=0; charIndex < (sizeof(tmpMsg)-1); charIndex++)
  tmpMsg[charIndex] = 0;
inCount = 0;
  do {
        tmpMsg[inCount] =;    
        if (tmpMsg[inCount] == INTERMINATOR) break;
     } while (++inCount < INLENGTH);
  if (tmpMsg[0] > 30) {         
  for (int charIndex=0; charIndex < (sizeof(tmpMsg)-1); charIndex++)
    msg[charIndex] = tmpMsg[charIndex];

// char msg[] = "[ ]^_`abcdefghijklmnopqrstuvwxyz{|} ";

spikie, that’s cool that you’ve taken it further.
I’ve never worked with EEPROM, but with regards to int vs char, you should be able to write a routine to put two chars into an int and then write the int array into EEPROM.
Something like this maybe? You may have to do type coercion to get this to work.

int twoCharsInOneInt = tmpMsg_*256 + tmpMsg[i+1];_
Don’t forget to pad the char array if they’re not divisible by two.
Good luck!

hari, thanks for the idea but i think i dont really see what you mean with it. you mean just cut the whole "message" into 2 int variable's?

Oh I see how you could arrive to that conclusion.
Let’s say your message is 7 character long. I propose that you pad it to 8 characters with a space character. Then you take the first two characters and put them into first element of an int array, next you take the third and fourth characters and put them into the second element of the int character, and so on and so forth. When done, you can write the int array to EEPROM. You would reverse the process when your program first starts to see if there’s message in EEPROM. I’ve never worked with EEPROM before, so there maybe an easier way.

I looked at how EEPROM library works. It turned out that it writes bytes not ints.
Here’s a test sketch I wrote, you should be able to adapt it.
As you can see it writes one character of msg array at a time to EEPROM, then the second part goes through one character at a time reading it from EEPROM.
Hope this helps.

#include <EEPROM.h>

void setup()
  //-- Write --
  char msg[] = "Message";
  for (int i = 0; i < (sizeof(msg)-1); i++)
    EEPROM.write(i, msg[i]);
  //-- Read --
  char restored[] = "1234567";
  for (int i = 0; i < (sizeof(restored)-1); i++)
    restored[i] =;

void loop()

Hero Hari! thanks for your time and mate I LOVE YOU. you made my day.

at the end of my project i will make pictures and stuff and i will make credit to you. thanks for it.

Greets, Spikie

Hi Hari! thank for the code! i was trying to do a clock based on your codes and i had to add numbers to your current library.

ive already added 0-9 under “byte alphabets[5]”
but how do i modify your codes so they are recognized?

as of now if i try to display the numbers they came out blank on the display. i wished i was able to understand your codes enough to be able to modify them =P

the current code,stock code 0-9 with numbers added

  Arduino 56x8 scrolling LED Matrix
Scrolls any message on up to seven (or more?) 8x8 LED matrices.
Adjust the bitmap array below to however many matrices you want to use.
You can start with as few as two.

The circuit:
* 1 8-bit shift register (SN74HC595) to drive the rows of all displays.
* N power 8-bit shift registers (TPIC6C595) to drive the columns (1 chip per display)
* N 8x8 LED matrix display (rows=Anodes, cold=cathodes)
* N * 8 470ohm resistors, one for each column of each display
* 1 10K resistor
* A big breadboard, or several small ones
* Lots and lots of wires. AT LEAST 16 wires for each display.
* If you plan on driving more than 8 displays, you should add 8 transistors to drive the rows because
potentially you would be lighting up the whole row at one time (56 LEDs at once in my case, 8*n in your case)

Wiring tips:
* Key to success is to put the chips on the left and/or right of the matrix rather than above or below.
This would allow you to run wires above and below the matrix without covering any of them.
* I used several power bus breadboard strips above and below the matrix so all row wires never has to cross the matrix.
* Wire up each matrix one at a time, turning on the Ardunio to verify your work before proceeding to the next matrix.
Correcting your work after you have 32 wires over it is very difficult.
* Circuit is available at:

Created Feb 2010
By Hari Wiguna

Based on things I learn from the Arduino website.
Special credit to aspro648 creating the alphabet that I use.

Creative Commons Attribution-Share Alike 3.0 United States License

// I kept these version notes to show you that it doesn't just all magically happen.  I start simple and keep adding more.
//v01 - Just see if we can drive one matrix, one dot at a time.  Forget multiplexing for now.
//v02 - All three displays show same pattern because they are all tied to same data line.
//v03 - Second and third 595 inputs are tied to outputs of previous, so now shiftout three bytes instead of one.
//v04 - Let's multiplex.  This version has no bleeding, but still flickers quite a bit.
//v05 - Flicker is reduced by using delayMicroseconds() instead of delay().  Flipping both latches HIGH at same time increases brightess of all LEDs.
//v06 - let's animate! (none of this code is in v09, I removed them because they're unrelated to the marquee.
//v07 - We got a scrolling message marquee!
//v08 - Now with SEVEN matrices! 56x8 pixels
//v09 - Add comments and remove experimental code
//v10 - Fixed search and replace error in Plot.  Thanks to Capacea for catching this error.

//-- Columns (Negative Cathodes) --
int latchPin1 = 2; //Arduino pin connected to Green 10 RCK of TPIC6C595
int clockPin1 = 3; //Arduino pin connected to Yellow 15 SRCK of TPIC6C595
int dataPin1 = 4;  //Arduino pin connected to Blue 2 SER IN of TPIC6C595

//-- Rows (Positive Anodes) --
int latchPin2 = 5; //Arduino pinn connected to Green Latch 12 ST_CP / RCK of 74HC595
int clockPin2 = 6; //Arduino pin connected to Yellow Clock 11 SH_CP / SCK of 74HC595
int dataPin2 = 7;  //Arduino pin connected to Blue Data 14 DS / SI of 74HC595

//=== B I T M A P ===
//Bits in this array represents one LED of the matrix
// 8 is # of rows, 7 is # of LED matrix we have
byte bitmap[8][4]; // Change the 7 to however many matrices you want to use.
int numZones = sizeof(bitmap) / 8; // I will refer to each group of 8 columns (represented by one matrix) as a Zone.
int maxZoneIndex = numZones-1;
int numCols = numZones * 8;

//=== F O N T ===
// Font courtesy of aspro648
// First char is @, next is A, B, etc.  Only lower case, no symbols.  
// The @ will display as space character.
byte alphabets[][5] = {
  {0,0,0,0,0},                  //space
  {31, 36, 68, 36, 31},            //a
  {127, 73, 73, 73, 54},      //b
  {62, 65, 65, 65, 34},            //c
  {127, 65, 65, 34, 28},      //d
  {127, 73, 73, 65, 65},        //e
  {127, 72, 72, 72, 64},      //f
  {62, 65, 65, 69, 38},            //g
  {127, 8, 8, 8, 127},            //h
  {0, 65, 127, 65, 0},            //i
  {2, 1, 1, 1, 126},            //j
  {127, 8, 20, 34, 65},            //k
  {127, 1, 1, 1, 1},            //l
  {127, 32, 16, 32, 127},      //m
  {127, 32, 16, 8, 127},      //n
  {62, 65, 65, 65, 62},            //o
  {127, 72, 72, 72, 48},      //p
  {62, 65, 69, 66, 61},            //q
  {127, 72, 76, 74, 49},      //r
  {50, 73, 73, 73, 38},            //s
  {64, 64, 127, 64, 64},      //t
  {126, 1, 1, 1, 126},            //u
  {124, 2, 1, 2, 124},            //v
  {126, 1, 6, 1, 126},            //q
  {99, 20, 8, 20, 99},            //x
  {96, 16, 15, 16, 96},            //y
  {67, 69, 73, 81, 97},            //z
  {62, 69, 73, 81, 62},         //0 - zero
  {0, 33, 127, 1, 0},           //1
  {49, 67, 69, 73, 49},         //2
  {34, 65, 73, 73, 54},         //3
  {24, 104, 8, 127, 8},         //4
  {114, 73, 73, 73, 70},        //5
  {62, 73, 73, 73, 38},         //6
  {64, 64, 71, 72, 112},        //7
  {54, 73, 73, 73, 54},         //8
  {50, 73, 73, 73, 62},         //9  

//=== S E T U P ===

void setup() {
  pinMode(latchPin1, OUTPUT);
  pinMode(clockPin1, OUTPUT);
  pinMode(dataPin1, OUTPUT);

  pinMode(latchPin2, OUTPUT);
  pinMode(clockPin2, OUTPUT);
  pinMode(dataPin2, OUTPUT);
  //-- Clear bitmap --
  for (int row = 0; row < 8; row++) {
    for (int zone = 0; zone <= maxZoneIndex; zone++) {
      bitmap[row][zone] = 0;

//=== F U N C T I O N S ===

// This routine takes whatever we've setup in the bitmap array and display it on the matrix
void RefreshDisplay()
  for (int row = 0; row < 8; row++) {
    int rowbit = 1 << row;
    digitalWrite(latchPin2, LOW);  //Hold latchPin LOW for as long as we're transmitting data
    shiftOut(dataPin2, clockPin2, MSBFIRST, rowbit);   //Transmit data

    //-- Start sending column bytes --
    digitalWrite(latchPin1, LOW);  //Hold latchPin LOW for as long as we're transmitting data

    //-- Shift out to each matrix (zone is 8 columns represented by one matrix)
    for (int zone = maxZoneIndex; zone >= 0; zone--) {
      shiftOut(dataPin1, clockPin1, MSBFIRST, bitmap[row][zone]);

    //-- Done sending Column bytes, flip both latches at once to eliminate flicker
    digitalWrite(latchPin1, HIGH);  //Return the latch pin high to signal chip that it no longer needs to listen for information
    digitalWrite(latchPin2, HIGH);  //Return the latch pin high to signal chip that it no longer needs to listen for information

    //-- Wait a little bit to let humans see what we've pushed out onto the matrix --

// Converts row and colum to actual bitmap bit and turn it off/on
void Plot(int col, int row, bool isOn)
  int zone = col / 8;
  int colBitIndex = col % 8;
  byte colBit = 1 << colBitIndex;
  if (isOn)
    bitmap[row][zone] =  bitmap[row][zone] | colBit;
    bitmap[row][zone] =  bitmap[row][zone] & (~colBit);

// Plot each character of the message one column at a time, updated the display, shift bitmap left.
void AlphabetSoup()
  char msg[] = "LED MATRIX 1234 ";

  for (int charIndex=0; charIndex < (sizeof(msg)-1); charIndex++)
    int alphabetIndex = msg[charIndex] - '@';
    if (alphabetIndex < 0) alphabetIndex=0;
    //-- Draw one character of the message --
    // Each character is only 5 columns wide, but I loop two more times to create 2 pixel space betwen characters
    for (int col = 0; col < 7; col++)
      for (int row = 0; row < 8; row++)
        // Set the pixel to what the alphabet say for columns 0 thru 4, but always leave columns 5 and 6 blank.
        bool isOn = 0;
        if (col<5) isOn = bitRead( alphabets[alphabetIndex][col], 7-row ) == 1;
        Plot( numCols-1, row, isOn); // We ALWAYS draw on the rightmost column, the shift loop below will scroll it leftward.
      //-- The more times you repeat this loop, the slower we would scroll --
      for (int refreshCount=0; refreshCount < 10; refreshCount++)

      //-- Shift the bitmap one column to left --
      for (int row=0; row<8; row++)
        for (int zone=0; zone < numZones; zone++)
          // This right shift would show as a left scroll on display because leftmost column is represented by least significant bit of the byte.
          bitmap[row][zone] = bitmap[row][zone] >> 1;
          // Roll over lowest bit from the next zone as highest bit of this zone.
          if (zone < maxZoneIndex) bitWrite(bitmap[row][zone], 7, bitRead(bitmap[row][zone+1],0));

//=== L O O P ===

void loop() {