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

Firmware

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.

#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;
}

Demonstration

CMiYC Labs

(The old site’s domain name.)

Hello World

Author

Fan of making things beep, blink and fly. Created AddOhms. Stream on Twitch. Video Host on element14 Presents and writing for Hackster.IO. Call sign KN6FGY.

3 Comments

    • Nothing! At the time I built the project, all I had was 5mm LEDs.

Write A Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.