DOT MATRIX BOARD
35x7 LED DOT MATRIX DISPLAY BOARD

Arduino Sketch

A few years ago I designed a LED Dot Matrix display board that was intended to fit in a nice enclosure that I liked.  At that time it was programmed with a Freescale microcontroller.  Now I have driven it with an Arduino.  The sketch is below.
Click for larger view

This is a photo of the bare board.  It is for sale; see the ordering page.

Here is the schematic.

 

 
#include <SPI.h>
 // Based on:
 // http://www.instructables.com/id/48x8-SCROLLING-MATRIX-LED-DISPLAY-USING-ARDUINO-CO/
 // Font table based on:
 // http://www.paramaggarwal.com/post/28266451949/scrolling-led-matrix-display-for-arduino 
 // Modified by Roger Schaefer 
 // for a 35x7 LED Dot Matrix Disply
 // using one MIC5891 as a row driver and five A6275's as column drivers
 // http://www.rasmicro.com/Dot_Matrix_Board.htm
 //
 //
 int ss = 10;      //Arduino pin connected to 4 of A6275 and 4 of MIC5891
 //int SCK = 13;   //Arduino pin connected to 3 of A6275 and 2 of MIC5891
 //int MOSI = 11;  //Arduino pin connected to 2 of A6275 
 int ScrollSpeed = 14;  // Lower number = faster scroll speed
 int numScroll = 3;
 // 
 //=== B I T M A P ===
 // Bits in this array represents one LED of the matrix
 // 8 is # of rows, 5 is # of LED matrix we have
 byte bitmap[8][5]; // Change the 5 to however many matrices you want to use.
 int numZones = sizeof(bitmap) / 8;
 int maxZoneIndex = numZones-1;
 int numCols = numZones * 8;



 byte alphabets[][5] = {
   {0x00,0x00,0x00,0x00,0x00},  /*space*/ // is 32 in ASCII
   {0x00,0xF6,0xF6,0x00,0x00},  /*!*/
   {0x00,0xE0,0x00,0xE0,0x00},  /*"*/
   {0x28,0xFE,0x28,0xFE,0x28},  /*#*/
   {0x00,0x64,0xD6,0x54,0x08},  /*$*/
   {0xC2,0xCC,0x10,0x26,0xC6},  /*%*/
   {0x4C,0xB2,0x92,0x6C,0x0A},  /*&*/
   {0x00,0x00,0xE0,0x00,0x00},  /*'*/
   {0x00,0x38,0x44,0x82,0x00},  /*(*/
   {0x00,0x82,0x44,0x38,0x00},  /*)*/
   {0x88,0x50,0xF8,0x50,0x88},  /***/
   {0x08,0x08,0x3E,0x08,0x08},  /*+*/
   {0x00,0x00,0x05,0x06,0x00},  /*,*/
   {0x08,0x08,0x08,0x08,0x08},  /*-*/
   {0x00,0x00,0x06,0x06,0x00},  /*.*/
   {0x02,0x0C,0x10,0x60,0x80},  /*/*/
   {0x7C,0x8A,0x92,0xA2,0x7C},  /*0*/
   {0x00,0x42,0xFE,0x02,0x00},  /*1*/
   {0x42,0x86,0x8A,0x92,0x62},  /*2*/
   {0x44,0x82,0x92,0x92,0x6C},  /*3*/
   {0x10,0x30,0x50,0xFE,0x10},  /*4*/
   {0xE4,0xA2,0xA2,0xA2,0x9C},  /*5*/
   {0x3C,0x52,0x92,0x92,0x0C},  /*6*/
   {0x80,0x86,0x98,0xE0,0x80},  /*7*/
   {0x6C,0x92,0x92,0x92,0x6C},  /*8*/
   {0x60,0x92,0x92,0x94,0x78},  /*9*/
   {0x00,0x00,0x36,0x36,0x00},  /*:*/
   {0x00,0x00,0x35,0x36,0x00},  /*;*/
   {0x10,0x28,0x44,0x82,0x00},  /*<*/
   {0x28,0x28,0x28,0x28,0x28},  /*=*/
   {0x00,0x82,0x44,0x28,0x10},  /*>*/
   {0x40,0x80,0x8A,0x90,0x60},  /*?*/
   {0x7C,0x82,0xBA,0xBA,0x62},  /*@*/
   {0x3E,0x48,0x88,0x48,0x3E},  /*A*/
   {0xFE,0x92,0x92,0x92,0x6C},  /*B*/
   {0x7C,0x82,0x82,0x82,0x44},  /*C*/
   {0xFE,0x82,0x82,0x82,0x7C},  /*D*/   
   {0xFE,0x92,0x92,0x92,0x82},  /*E*/
   {0xFE,0x90,0x90,0x90,0x80},  /*F*/
   {0x7C,0x82,0x82,0x8A,0x4E},  /*G*/
   {0xFE,0x10,0x10,0x10,0xFE},  /*H*/  
   {0x82,0x82,0xFE,0x82,0x82},  /*I*/
   {0x84,0x82,0xFC,0x80,0x80},  /*J*/
   {0xFE,0x10,0x28,0x44,0x82},  /*K*/
   {0xFE,0x02,0x02,0x02,0x02},  /*L*/ 
   {0xFE,0x40,0x20,0x40,0xFE},  /*M*/
   {0xFE,0x60,0x10,0x0C,0xFE},  /*N*/
   {0x7C,0x82,0x82,0x82,0x7C},  /*O*/
   {0xFE,0x90,0x90,0x90,0x60},  /*P*/
   {0x7C,0x82,0x82,0x86,0x7E},  /*Q*/
   {0xFE,0x90,0x98,0x94,0x62},  /*R*/
   {0x64,0x92,0x92,0x92,0x4C},  /*S*/
   {0x80,0x80,0xFE,0x80,0x80},  /*T*/
   {0xFC,0x02,0x02,0x02,0xFC},  /*U*/
   {0xF8,0x04,0x02,0x04,0xF8},  /*V*/
   {0xFC,0x02,0x0C,0x02,0xFC},  /*W*/
   {0xC6,0x28,0x10,0x28,0xC6},  /*X*/
   {0xC0,0x20,0x1E,0x20,0xC0},  /*Y*/
   {0x86,0x8A,0x92,0xA2,0xC2},  /*Z*/    
   {0x00,0x00,0xFE,0x82,0x00},  /*[*/
   {0x00,0x00,0x00,0x00,0x00},  /*this should be / */
   {0x80,0x60,0x10,0x0C,0x02},  /*]*/
   {0x20,0x40,0x80,0x40,0x20},  /*^*/
   {0x02,0x02,0x02,0x02,0x02},  /*_*/ // use for 7 dot high display
   //{0x01,0x01,0x01,0x01,0x01},  /*_*/  use for 8 dot high display
   {0x80,0x40,0x20,0x00,0x00},  /*`*/
   //
   // Lower case decenders are lost on 7 dot high display
   //
   {0x04,0x2A,0x2A,0x2A,0x1E},  /*a*/
   {0xFE,0x12,0x22,0x22,0x1C},  /*b*/
   {0x1C,0x22,0x22,0x22,0x14},  /*c*/
   {0x1C,0x22,0x22,0x12,0xFE},  /*d*/
   {0x1C,0x2A,0x2A,0x2A,0x18},  /*e*/
   {0x10,0x7E,0x90,0x80,0x40},  /*f*/
   {0x18,0x25,0x25,0x25,0x1E},  /*g*/
   {0xFE,0x10,0x10,0x10,0x0E},  /*h*/
   {0x00,0x12,0x5E,0x02,0x00},  /*i*/
   {0x02,0x01,0x01,0x11,0x5E},  /*j*/
   {0xFE,0x08,0x08,0x14,0x22},  /*k*/
   {0x00,0x82,0xFE,0x02,0x00},  /*l*/
   {0x3E,0x20,0x1C,0x20,0x1E},  /*m*/
   {0x3E,0x20,0x20,0x20,0x1E},  /*n*/
   {0x1C,0x22,0x22,0x22,0x1C},  /*o*/
   {0x3F,0x24,0x24,0x24,0x18},  /*p*/
   {0x18,0x24,0x24,0x3F,0x01},  /*q*/
   {0x3E,0x10,0x20,0x20,0x10},  /*r*/
   {0x12,0x2A,0x2A,0x2A,0x04},  /*s*/
   {0x00,0x10,0x3C,0x12,0x04},  /*t*/
   {0x3C,0x02,0x02,0x02,0x3E},  /*u*/
   {0x30,0x0C,0x02,0x0C,0x30},  /*v*/
   {0x38,0x06,0x18,0x06,0x38},  /*w*/
   {0x22,0x14,0x08,0x14,0x22},  /*x*/
   {0x38,0x05,0x05,0x05,0x3E},  /*y*/
   {0x22,0x26,0x2A,0x32,0x22},  /*z*/
   {0x00,0x10,0x6C,0x82,0x82},  /*{*/
   {0x00,0x00,0xFF,0x00,0x00},  /*|*/
   //{0x04,0x02,0xFF,0x02,0x04},  /*|, down arrow*/
   {0x82,0x82,0x6C,0x10,0x00},  /*}*/
   {0x08,0x10,0x18,0x08,0x10},  /*~*/
 };

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

 void setup() {
   SPI.begin(); // wake up the SPI bus.
   pinMode(ss, OUTPUT);
   //pinMode(SCK, OUTPUT);
   //pinMode(MOSI, OUTPUT);
   Serial.begin(9600);
  
   //-- 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(ss, LOW);  //Hold ss LOW for as long as we're transmitting data
     SPI.transfer(rowbit);   //Transmit data row driver

     //-- Start sending column bytes --    

     //-- Shift out to each matrix (zone is 8 columns represented by one matrix)        
       SPI.transfer(bitmap[row][0]);
       SPI.transfer(bitmap[row][1]);
       SPI.transfer(bitmap[row][2]);
       SPI.transfer(bitmap[row][3]);
       SPI.transfer(bitmap[row][4]);

     //-- Done sending Row and Column bytes
     digitalWrite(ss, HIGH);

     //-- Wait a little bit to let humans see what we've pushed out onto the matrix --
     delayMicroseconds(500);
   }
 }

 // Converts row and column to actual bitmap bit and turn it off/on
 void Plot(int col, int row, boolean isOn)
 {
   int x, y;
   int zone = col / 8;       // use remainder in next instruction   
   int colBitIndex = 8 % 8;  // colBitIndex must therefore be 0 to 7
   byte colBit = 1 << colBitIndex;  // colBit can be 00000001, 00000010, 00000100, 00001000,
                                    //               00010000, 00100000, 01000000, 10000000
   // using (row - 1) because display is only 7 high
   if (isOn)
     bitmap[row][zone] =  bitmap[y][zone] | colBit;  //  bitwise OR
   else
     bitmap[row][zone] =  bitmap[y][zone] & (~colBit);  // bitwise AND with NOT of colBit
 }
 // Plot each character of the message one column at a time, updated the display, shift bitmap left.
 void AlphabetSoup()
 {
   numScroll --; 
   char msg[] = "35x7 LED DOT MATRIX DISPLAY DRIVEN BY AN ARDUINO SKETCH       ";
   for (int charIndex=0; charIndex < (sizeof(msg)-1); charIndex++)
   {
     int alphabetIndex = msg[charIndex] - ' ';  //space character
     if (alphabetIndex < 0) alphabetIndex = 0;    
     //-- Draw one character of the message --
     for (int col = 0; col < 6; col++)  // 5 columns in character matrix plus 1 between characters
     {
       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.
         boolean 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 < ScrollSpeed; refreshCount++) //change  this value to vary speed
         RefreshDisplay();
         
       //-- Shift the bitmap one column to left --
       for (int row=0; row < 8; row++)
       {
         for (int zone=0; zone < numZones; zone++)         
         {
           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() {  
   AlphabetSoup();
 }

   

35x7 LED Dot Matrix Display Deluxe

The sketch above will display a message on the 35x7 LED dot matrix display but beyond that is not especially useful.  I decided to add the ability to add time and temperature to the display and while at it to add some other features to make it more convenient to use.

For temperature I used a DS18B20 "one wire" sensor.  I happened to have a waterproof sensor on a two foot cable.  That is good because you don't necessarily want to measure the temperature on the printed circuit board.

The Arduino has a Time library that I use for the time and date functions.  That works but is not real accurate nor is it convenient because the Arduino software clock must be reset each time you start up.  A Real Time Clock is desirable.  I chose a DS1307.  It seems to be quite popular and there are many sources of boards with the chip.  The one from DF Robot seems quite interesting but I had parts on hand so I just used an 8 pin DIP version of the DS1307 on a little breadboard.

As I developed the program I found that it would no longer work on an Arduino UNO.  It seemed that I needed more RAM so I switched to a MEGA 2560.  You can often find these on eBay for less than $15.

 

Here is the software file.  The ZIP file contains the sketch for Dot_Matrix_35x7_delux as well as the SerialCommand library which I slightly modified from the original.  There are several other libraries you will need to download and install.  The source for these are in the sketch.
This is a shot of the Help Screen.  Just type "Help" to list the various commands.
There are ten predefined messages that may be quickly selected with the command "Message x" where "x" is a number 0 to 9.  Type "Message" without the "x" parameter will display the current message number.

The scroll speed may be changed with the "Speed x" command.

Both message number and scroll speed are saved in EEPROM.

I use a caret followed by a letter as a pointer to embedd variable data into a message.  For example, a ^D will be replaced with a date string in the scrolling message.
Here is a video of the display.  The color doesn't come across well.  It is a nice bright deep red.  Some more photos of the same display driven by a different microcontroller is here.

 


Roger's Embedded Microcontrollers Home Page     


This page written by Roger Schaefer. Last updated December 12, 2013