Status: Completed
GitHub: https://github.com/baldengineer/8×6-LED-Matrix-Shield
Abstract
After getting a couple of flashing lights working on a microprocessor, the next fun project is generally building some kind of Matrix. At first I built a 5×5 LED matrix which was relatively simple to solder together. When trying to make one much larger, the task because significantly more complex. That’s when I decided to build a LED Matrix Shield for the Arduino which did not use Charliplexing, like the LoL shield. I wanted something that was simpler to understand and (ultimately) code for. Unfortunately, 5mm LEDs means 8 columns x 6 rows, instead of the traditional 8×8.Electronics
Parts list:
- (1) – 8×6 LED Matrix LED PCB
- (48) – Bright blue 5mm LEDs
- (6) – SMT 1206 150Ω resistors
- Header Pins
- Optionally, for power and analog inputs, only 8 header pins necessary.
- (1) – SMT 1206 LED [optional]
- (1) – SMT 1206 150Ω resistor [optional]
- (1) – SMT push button [optional]
- Sunglasses [optional]
Schematic
The matrix is a simple direct driven LED matrix. Unlike a charlieplexed display, this design DOES include current limiting resistors. The current limiting resistors where picked to ensure no more than 40mA were allowed, to prevent damage to the Arduino I/O pins. The schematic and PCB do show an optional reset button (since the RESET on the arduino may not be accessible) and a LED Power indicator. Note that in my build, I did not include the LED since it did not seem necessary.
Schematic (PDF): LED_Matrix_v1_schem.pdf
Eagle Project Files: See “Eagle” at 8×6 LED Matrix on GitHub
The actual code used to demonstrate the shield in the attached YouTube videos has been lost. Below is an early example of the code, which used hard coded letters.
Firmware
#define numOfColumns 8
#define numOfRows 6
#define matrixSize 48
#define bigWait 500 // milliseconds
#define povWait 250 // microseconds
#define animationWait 100 // milliseconds
#define frames 10
int columnPins[numOfColumns] = {2,3,4,5,6,7,8,9};
//int sourcePins[numOfColumns] = {2,3,4,5,6,7,8,9};
int rowPins[numOfRows] = {10,11,12,A0,A1,A2};
//int sinkPins[numOfSinks] = {10,11,12,A0,A1,A2};
unsigned int rowStates[6] = {0,0,0,0,0,0};
unsigned long characters[4] = {0x699F99,0x99FF99,0xF6666F,0x666606}; // A, H, I, !
unsigned char messageString[25] = {1,2,3}; // "Hi!"
int messageLength = 3;
void setup() {
Serial.begin(9600);
// fillRowStates(0);
setupLEDs();
blankLEDs();
}
void loop() {
for (int messageCharacter=0; messageCharacter < messageLength; messageCharacter++) {
// load column X for Y letter in message
for (int characterColumn=4; characterColumn > 0; characterColumn--) {
shiftDisplayLeft(1,loadCharacterColumn(characterColumn, characters[messageString[messageCharacter]]));
myDelay(animationWait);
}
shiftDisplayLeft(1,0x0);
myDelay(animationWait);
shiftDisplayLeft(1,0x0);
myDelay(animationWait);
}
for (int i=0; i<6; i++) {
shiftDisplayLeft(1,0x0);
myDelay(animationWait);
}
}
int loadCharacterColumn(int column, long character) {
// example character: 0x699F99
int returnedValue=0;
int pointer=0;
Serial.println(character, HEX);
for (int i=(20+column); i>0; i=i-4) {
if (bitRead(character,(i-1))) {
bitSet(returnedValue,pointer);
} else {
bitClear(returnedValue,pointer);
}
pointer++;
}
return returnedValue;
}
void loadCharacter(unsigned long thisCharacter) {
long newCharacter;
long shiftValue = 0xF00000;
// thisCharacter example: 0x699F99
for(int i=0; i<6; i++) {
rowStates[(i)] = (shiftValue & thisCharacter) >> (20-(i*4));
shiftValue = shiftValue >> 4;
}
}
void shiftDisplayLeft(int steps, int newRows) {
int newRowMask = 0x20;
for (int row=5; row > -1; row--) {
if (newRows & (newRowMask)) {
rowStates[row] = (rowStates[row] << steps) | (0x000001);
} else {
rowStates[row] = (rowStates[row] << steps) & (0xFFFFFE);
}
newRowMask = newRowMask >> 1;
}
}
void fillRowStates(int setToValue) {
for (int i=0; i < 8; i++) {
rowStates[i] = setToValue;
}
}
void lightMatrix() {
int LEDCount = -1;
int thisColumnState = 0;
for (int rowCount = 0; rowCount < numOfRows; rowCount++) {
lightColumn(rowStates[rowCount]);
digitalWrite(rowPins[rowCount], HIGH);
delayMicroseconds(povWait);
digitalWrite(rowPins[rowCount], LOW);
}
}
void lightColumn(int columnState) {
for (int columnCount=0; columnCount < numOfColumns; columnCount++) {
if (bitRead(columnState,columnCount)==1) {
digitalWrite(columnPins[columnCount], LOW);
} else {
digitalWrite(columnPins[columnCount], HIGH);
}
}
}// end of lightColumn
void setupLEDs() {
// LEDs are forward biased from Row to Column. Rows have the current limiting resistors.
for (int i=0; i < numOfColumns; i++) {
pinMode(columnPins[i], OUTPUT);
digitalWrite(columnPins[i], HIGH); // columns need to stay high, to keep LEDs off even for very brief moments.
}
for (int i=0; i < numOfRows; i++) {
pinMode(rowPins[i], OUTPUT);
digitalWrite(rowPins[i], LOW); // eliminates the ability for LEDs to turn on
}
}
void blankLEDs() {
// the same as the setupLEDs, but this moves a little bit faster!
for (int i=0; i < numOfColumns; i++) {
digitalWrite(columnPins[i], HIGH); // columns need to stay high, to keep LEDs off even for very brief moments.
}
for (int i=0; i < numOfRows; i++) {
digitalWrite(rowPins[i], LOW); // eliminates the ability for LEDs to turn on
}
}
void myDelay(int waitTime) {
long incomingMills = millis();
long waitUntilMills = incomingMills + waitTime;
while(millis() < waitUntilMills) {
lightMatrix();
}
}
unsigned long pow2(unsigned long j) {
unsigned long result=1;
for(int i=0; i < j; i++) {
result = result * 2;
}
return result;
}
3 Comments
What’s wrong with 3mm LEDs ?
Nothing! At the time I built the project, all I had was 5mm LEDs.
Test Comment.