Hi guys! I have a plan to make a 32x8 led matrix. To interface I will be daisy chaining 2 tlc5940 chips together in order to control the columns. The other 8 pins will be connected to the I/O pins via PNP transistors. My real question is ... Hoe do I make the LEDs scan? Thanks in advance
My real question is ... Hoe do I make the LEDs scan?
Is that anything like making a speaker listen? Or a microphone make some sound? What do you mean by making the LEDs scan?
Sorry. I should have been a little bit more explanatory. Have u seen those displays which scroll text from right to left? That is what I am aiming for. Sorry again for the crappy explanation.
Have u seen those displays which scroll text from right to left? That is what I am aiming for.
Step 1: Learn how to light a single LED on the matrix.
Step 2: Make it the one you meant to light up.
Step 3: Learn how to light up a collection of LEDs on the matrix.
Step 4: Make it the ones you meant to light up.
Step 5: Figure out what rows and column need to light up to look like an A, a B, a C, etc.
Step 6: Figure out how to light up static text.
Step 7: Figure out how to shift the rows right or left so the "text" appears to scroll.
chathuraisawesome101:
Sorry. I should have been a little bit more explanatory. Have u seen those displays which scroll text from right to left? That is what I am aiming for. Sorry again for the crappy explanation.
Maybe a little late, but look at this:
http://arduino.cc/playground/Main/DirectDriveLEDMatrix
You will have to adapt it to the fact that you are controlling the rows directly and the columns via the TLC chip, but the algorithm should be similar. You might also want to provide a more comprehensive character set.
This sketch works, I built it myself and then expanded it to 3 8x8 displays on a Mega. Wires all over the damn place. The TLC and Maxim driver chips make it so much easier and adding displays requires no more wires off the Arduino/ATMega.
wow that page was really helpful.
I never knew you could define letters like that.
funkyguy4000:
wow that page was really helpful.I never knew you could define letters like that.
A better way is to bitmap them, what he is doing is ineffecient, but it is straightforward. Think of mapping characters to an 8x7 grid. 8 is a nice number because we can fit it in a byte if we only need 2 colors (let's call them on and off). Think of the letter A, you might map it like this:
1234567
1 ..XX...
2 .X..X..
3 X....X.
4 XXXXXX.
5 X....X.
6 X....X.
7 X....X.
8 .......
What you want to do is convert this into column values with 0 for unlit and 1 for lit. The columns are:
1 00111110 which is 3EH
2 01010000 which is 50H
3 10010000 which is 90H
4 10010000 which is 90H
5 01010000 which is 50H
6 00111110 which is 3EH
7 00000000 which is 00H
So you have defined a character in 7 bytes total. You define all your characters this way. Then all you need to do is add the bytes of your characters to your display buffer to display them. When you are scanning your rows, you just scan through all the bytes and use an AND mask against the row you are scanning to see if it is lit or not and send that bit to the shift register, TLC chip, or whatever you are using.
So the display buffer simply is an array of one byte for each column, 32 in the OP's post. To scroll the display, you move all the bytes for n = 1 to 31 from n to n-1, and the one at position 0 is lost and you add your next column at the 31 index (rightmost position). To do this you have to keep track of the next column on your next character, but that is not hard. It keeps everything quite simple, assuming you are using a display with no more than 8 LEDs in a column.
Why is it 3EH or 50H? When i converted the binary values to a hexidecimal value, I only got 3E or 50, where do the H's come from?
funkyguy4000:
Why is it 3EH or 50H? When i converted the binary values to a hexidecimal value, I only got 3E or 50, where do the H's come from?
Those are hexadecimal values, they are easier to convert, you can just eye the bits to convert them. Here it is in decimal too:
1 00111110 which is 3E (base 16) which is 62 (base 10)
2 01010000 which is 50 (base 16) which is 80 (base 10)
3 10010000 which is 90 (base 16) which is 144 (base 10)
4 10010000 which is 90 (base 16) which is 144 (base 10)
5 01010000 which is 50 (base 16) which is 80 (base 10)
6 00111110 which is 3E (base 16) which is 62 (base 10)
7 00000000 which is 00 (base 16) which is 0 (base 10)
So the array definition might be something like:
unsigned char char_A[7]= {0x3E,0x50,0x90,0x90,0x50,0x3E,0x00};
Though in the end you would probably make it multidimensional and have all your character definitions in a big 50x7 or so array.
I hope that is right, I don't have my source code here for the modifications I did to the scrolling software that I linked, but I modifed it extensively.
But then why was it 3EH before?
funkyguy4000:
But then why was it 3EH before?
It still is 3EH in the original post. I took the H off the numbers in the second post and added (base 16). They mean the same thing. The H is to specify that it is base 16. Here is some additional information:
Ohh okay okay. I knew it was hex. I didn't understand the H. haha.
We did binary to hex conversions in digital logic and I'm thinking, "I don't remember an H"
I have some code that uses a shift register library if it helps at all
#include <SPI.h>
byte alphabets[95][5] = {
{B00000000,B00000000,B00000000,B00000000,B00000000},
{B00000000,B00000000,B11111011,B00000000,B00000000},
{B00000000,B11000000,B00000000,B11000000,B00000000},
{B00010100,B01111111,B00010100,B01111111,B00010100},
{B00110010,B01001001,B11111111,B01001001,B00100110},
{B01100100,B01101000,B00010000,B00101100,B01001100},
{B00000110,B01101001,B10011001,B01100110,B00001001},
{B00000000,B00000000,B11000000,B00000000,B00000000},
{B00000000,B00000000,B01111110,B10000001,B00000000},
{B00000000,B10000001,B01111110,B00000000,B00000000},
{B00000000,B10100000,B01000000,B10100000,B00000000},
{B00001000,B00001000,B00111110,B00001000,B00001000},
{B00000000,B00000001,B00000110,B00000000,B00000000},
{B00000000,B00001000,B00001000,B00001000,B00000000},
{B00000000,B00000011,B00000011,B00000000,B00000000},
{B00000000,B00000011,B00011100,B11100000,B00000000},
{B01111110,B10000001,B10000001,B10000001,B01111110},
{B00100001,B01000001,B11111111,B00000001,B00000001},
{B01000011,B10000101,B10001001,B10010001,B01100001},
{B01000010,B10000001,B10011001,B10011001,B01100110},
{B00011000,B00101000,B01001000,B11111111,B00001000},
{B11110010,B10010001,B10010001,B10010001,B10001110},
{B01111110,B10010001,B10010001,B10010001,B01001110},
{B10000000,B10000000,B10011111,B10100000,B11000000},
{B01101110,B10010001,B10010001,B10010001,B01101110},
{B01110010,B10001001,B10001001,B10001001,B01111110},
{B00000000,B00000000,B01100110,B00000000,B00000000},
{B00000000,B00000001,B01100110,B00000000,B00000000},
{B00000100,B00001010,B00001010,B00010001,B00010001},
{B00000000,B00010100,B00010100,B00010100,B00000000},
{B00010001,B00010001,B00001010,B00001010,B00000100},
{B01100000,B10000000,B10001101,B10010000,B01110000},
{B01111110,B10010001,B10101001,B10011001,B01111110},
{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},
{B00000000,B00000000,B11111111,B10000001,B00000000},
{B00000000,B11100000,B00011100,B00000011,B00000000},
{B00000000,B10000001,B11111111,B00000000,B00000000},
{B00000000,B01000000,B10000000,B01000000,B00000000},
{B00000001,B00000001,B00000001,B00000001,B00000001},
{B00000000,B10000000,B01000000,B00100000,B00000000},
{B00010010,B00100101,B00100101,B00100101,B00011111},
{B11111111,B00010001,B00010001,B00010001,B00001110},
{B00001110,B00010001,B00010001,B00010001,B00000000},
{B00001110,B00010001,B00010001,B00010001,B11111111},
{B00001110,B00010101,B00010101,B00010101,B00001001},
{B00000100,B00111111,B01000100,B00100100,B00000000},
{B00011001,B00100101,B00100101,B00100101,B00111111},
{B11111111,B00001000,B00010000,B00010000,B00001111},
{B00000000,B00000000,B00101111,B00000000,B00000000},
{B00000010,B00000001,B01011110,B00000000,B00000000},
{B11111111,B00001100,B00001100,B00010010,B00100001},
{B00000000,B00000000,B11111111,B00000000,B00000000},
{B00011111,B00001000,B00000110,B00001000,B00000111},
{B00000000,B00001111,B00001000,B00000111,B00000000},
{B00000000,B00000110,B00001001,B00000110,B00000000},
{B00000000,B00011111,B00010100,B00001000,B00000000},
{B00000000,B00001000,B00010100,B00011111,B00000000},
{B00000000,B00001111,B00001000,B00000100,B00000000},
{B00000000,B00001001,B00010101,B00010010,B00000000},
{B00000000,B00001000,B00111111,B00001000,B00000000},
{B00000000,B00001110,B00000001,B00001110,B00000000},
{B00000000,B00001100,B00000011,B00001100,B00000000},
{B00001110,B00000001,B00000110,B00000001,B00001110},
{B00000000,B00011011,B00000100,B00011011,B00000000},
{B00000000,B00110011,B00001100,B00110000,B00000000},
{B00000000,B00010011,B00010101,B00011001,B00000000},
{B00000000,B00011000,B01111110,B10000001,B00000000},
{B00000000,B00000000,B11111111,B00000000,B00000000},
{B00000000,B10000001,B01111110,B00011000,B00000000},
{B00001000,B00010000,B00001000,B00010000,B00000000},
};
const int ShiftMatrixPWM_columnLatchPin=9;
const int ShiftMatrixPWM_rowDataPin=6;
const int ShiftMatrixPWM_rowClockPin=7;
const int ShiftMatrixPWM_rowLatchPin=8;
const bool ShiftMatrixPWM_invertColumnOutputs = 1; // if invertColumnOutputs is 1, outputs will be active low. Usefull for common anode RGB led's.
const bool ShiftMatrixPWM_invertRowOutputs = 0; // if invertOutputs is 1, outputs will be active low. Used for PNP transistors.
#include <ShiftMatrixPWM.h> // include ShiftMatrixPWM.h after setting the pins!
byte maxBrightness = 40;
byte pwmFrequency = 75;
byte numColumnRegisters = 3;
byte r = maxBrightness;
byte g = maxBrightness;
byte b = maxBrightness;
byte bitmap[8][1]; // Change the 7 to however many matrices you want to use.
byte numZones = sizeof(bitmap) / 8; // I will refer to each group of 8 columns (represented by one matrix) as a Zone.
byte maxZoneIndex = numZones-1;
byte numCols = numZones * 8;
const byte numRows=sizeof(bitmap) / numZones;
void setup() {
pinMode(ShiftMatrixPWM_columnLatchPin, OUTPUT);
pinMode(ShiftMatrixPWM_rowDataPin, OUTPUT);
pinMode(ShiftMatrixPWM_rowClockPin, OUTPUT);
pinMode(ShiftMatrixPWM_rowLatchPin, OUTPUT);
SPI.setBitOrder(LSBFIRST);
// SPI_CLOCK_DIV2 is only a tiny bit faster in sending out the last byte.
// SPI transfer and calculations overlap for the other bytes.
SPI.setClockDivider(SPI_CLOCK_DIV4);
SPI.begin();
ShiftMatrixPWM.SetMatrixSize(numRows, numColumnRegisters);
ShiftMatrixPWM.Start(pwmFrequency,maxBrightness);
}
void loop() {
Scroll("The quick brown fox jumps over the lazy dog ",75);
}
// Converts row and colum to actual bitmap bit and turn it off/on
void Plot(int col, int row, bool isOn)
{
byte zone = col / 8;
byte 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 Scroll(char *msg, int Speed)
{
for (int charIndex=0; charIndex < strlen(msg); charIndex++)
{
int alphabetIndex = msg[charIndex] - 32;
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 < 6; col++)
{
if(alphabets[alphabetIndex][col] !=0 || alphabetIndex == 0 || col==5){
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){
Plot( numCols-1, row, 0);
}
else{
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 scrolly --
delay(Speed);
for (byte row = 0; row < 8; row++) {
for (int zone = maxZoneIndex; zone >= 0; zone--) {
for(byte q=0; q<8; q++){
ShiftMatrixPWM.SetGroupOf3(row,q,(bitRead(bitmap[row][zone],q))*r,(bitRead(bitmap[row][zone],q))*g,(bitRead(bitmap[row][zone],q))*b);
}
}
}
//-- 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));
}
}
}}
}
}