Go Down

Topic: Interfacing with 8x8 Matrices (Read 1 time) previous topic - next topic

SpikedCola

Ive built a display based on the code here, and Ive run into a couple issues along the way. I posted in the linked thread but this seems a more appropriate place, as it involves my own project, not his.

This is the current code Im using:
Code: [Select]

/*
 Arduino 56x8 scrolling LED Matrix

 * Circuit is available at:
http://g33k.blogspot.com/2010/02/arduino-56x8-scrolling-led-matrix.html

Created Feb 2010
By Hari Wiguna
http://g33k.blogspot.com/

Based on things I learn from the Arduino website.
Special credit to aspro648 creating the alphabet that I use.
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1203747843/22

Creative Commons Attribution-Share Alike 3.0 United States License

*/
//-- 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][3];
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
// http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1203747843/22
// 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},
 {31, 36, 68, 36, 31},
 {127, 73, 73, 73, 54},
 {62, 65, 65, 65, 34},
 {127, 65, 65, 34, 28},
 {127, 73, 73, 65, 65},
 {127, 72, 72, 72, 64},
 {62, 65, 65, 69, 38},
 {127, 8, 8, 8, 127},
 {0, 65, 127, 65, 0},
 {2, 1, 1, 1, 126},
 {127, 8, 20, 34, 65},
 {127, 1, 1, 1, 1},
 {127, 32, 16, 32, 127},
 {127, 32, 16, 8, 127},
 {62, 65, 65, 65, 62},
 {127, 72, 72, 72, 48},
 {62, 65, 69, 66, 61},
 {127, 72, 76, 74, 49},
 {50, 73, 73, 73, 38},
 {64, 64, 127, 64, 64},
 {126, 1, 1, 1, 126},
 {124, 2, 1, 2, 124},
 {126, 1, 6, 1, 126},
 {99, 20, 8, 20, 99},
 {96, 16, 15, 16, 96},
 {67, 69, 73, 81, 97},
};

byte numbers[][5] =
{
 { 0,0,0,0,0 },
 { 0x7E, 0x89, 0x91, 0xA1, 0x7E },
 { 0x00, 0x41, 0xFF, 0x01, 0x00 },
 { 0x43, 0x85, 0x89, 0x91, 0x61 },
 { 0x42, 0x81, 0x91, 0x91, 0x6E },
 { 0x18, 0x28, 0x48, 0xFF, 0x08 },
 { 0xF2, 0x91, 0x91, 0x91, 0x8E },
 { 0x1E, 0x29, 0x49, 0x89, 0x86 },
 { 0x80, 0x8F, 0x90, 0xA0, 0xC0 },
 { 0x6E, 0x91, 0x91, 0x91, 0x6E },
 { 0x70, 0x89, 0x89, 0x8A, 0x7C }
};

/*

Space, 0-9, as a comment because CTRL+T messes up the formatting

byte numbers[][5] =
{
 { 0,0,0,0,0 },
 { 0x7E, 0x89, 0x91, 0xA1, 0x7E },
 { 0x00, 0x41, 0xFF, 0x01, 0x00 },
 { 0x43, 0x85, 0x89, 0x91, 0x61 },
 { 0x42, 0x81, 0x91, 0x91, 0x6E },
 { 0x18, 0x28, 0x48, 0xFF, 0x08 },
 { 0xF2, 0x91, 0x91, 0x91, 0x8E },
 { 0x1E, 0x29, 0x49, 0x89, 0x86 },
 { 0x80, 0x8F, 0x90, 0xA0, 0xC0 },
 { 0x6E, 0x91, 0x91, 0x91, 0x6E },
 { 0x70, 0x89, 0x89, 0x8A, 0x7C }
};

*/

//=== 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);
 Serial.begin(9600);
 //-- Clear bitmap --
 for (int row = 0; row < 8; row++)
 {
   for (int zone = 0; zone <= maxZoneIndex; zone++)
   {
     bitmap[row][zone] = 0;
   }
 }

 AlphabetSoup();
}

//=== 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++)
 {
   byte rowbit = 1 << row;
   rowbit = ~rowbit;
   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 --
   delayMicroseconds(500);
 }
}

// 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;
 }
 else
 {
   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[] = "THE OBLIGATORY ARDUINO LED MATRIX PROJECT  ";

 char msg2[] = "1234";

 for (int charIndex=0; charIndex < (sizeof(msg2)-1); charIndex++)
 {
   int alphabetIndex = msg2[charIndex] - 47;
   Serial.println(alphabetIndex);
   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( numbers[alphabetIndex][col], 7-row ); // removed   == 1    between ) and ;
       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 < 20; refreshCount++)
      RefreshDisplay();
      */
     //-- 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 byt
           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() {
 RefreshDisplay();
}


As you can see, I moved RefreshDisplay(); into loop, and this lets me statically display text (instead of scrolling it) - this is what my project requires. However, Ive noticed that there are three blank columns after the last number. How can I leave these out? Also, I was wondering if the space between numbers is configurable. Finally, I would like to add a decimal point, as the matrix will be used to display "xx.xx". I can create the font for the decimal, but Im uncertain how to insert it. Any help would be greatly appreciated.

Also, Ive also had to hook the 74595 up to the columns, while the TPIC6C595 is hooked up to the rows (common-drain outputs means it HAS to go to rows).

However, when I use the TPIC register as a row driver, I get faded blocks instead of letters:


But when I use a normal 595 (I ran 3 matrices overnight and none of the chips became warm, so Im fairly certain they can handle it), it works properly:


This isnt a big issue, just something I ran into along the way.

Grumpy_Mike

The faded columns are due to you not disabling the drive while you change the output.
I couldn't see anything in the code but I only had a quick look and I couldn't follow it it seemed all wrong. You seem to be shifting out all the 'zones' at once, what ever a zone is.

The real way to do it is to shift out the pattern into the shift registers, disable the current drive, latch the output of the shift registers and enable the current drive. In that way you don't see transitory states that show up as dim LEDs.

SpikedCola

Mike, the code is from a project in the Exhibition section. It is not mine. However, I believe a matrix is referred to as a zone, so 2 zones would mean 2 matrices. Zones are being shifted out at once because all the registers are cascaded, so the column bytes needed for each matrix are shifted out that way. I will see about making your recommended modifications when I get home. Thanks!

Go Up