Introduction: Arduino LED Matrix Clock

This clock uses five MAX7219 8x8 LED matrices to display a clock.

The two left units display the hour, the right two the minutes, and the middle matrix counts off the seconds. This is accomplished by illuminating one LED per second, counting across each row. The 8th LEDs in alternate rows are skipped, thus two rows count 15 seconds; the full 8 rows tick off one minute.

I am running an Arduino Mega 2560, but this should on most models.

I've learned from many Arduino projects posted to this site, and appreciate members' expertise. I've tried, especially in the sketch listing itself, to explain points I think might be unclear to a newer user.

Any feedback is welcome.

Step 1: Assemble and Wire Your Matrices

Rather than duplicating effort, you are referred to the excellent Multiple LED Matrices with Arduino. In this case, however, wire a fifth matrix in series with the others. You will, of course, need one more matrix and another set of jumpers.

Step 2: Realtime Clock Notes

My realtime clock (RTC) turned out to be a dud and the new one has not yet arrived from HK. The time is therefore set manually; time is kept using the internal clock.

Step 3: Displaying Digits

As this is my first nontrivial project and I am learning as I go, I started with the Makepeace Madrid's LED matrix library LedControlMS.h used in their 4-LED scrolling text example.

The function displayChar takes two integer arguments: the matrix number addressed--starting with zero--and the character to display. Simply pass this function the numbers 0-9 to display those digits.

Since one LED matrix will not display two characters, each digit of the hour and minute must be isolated to a single variable. These are isolated from the hour and minute in the following way:

  • 1st digit: integer division by 10. This throws away the remainder (e.g., 43 so divided results in 4.3 with the 3 thrown away, therefore 4 (the first digit) is returned.
  • 2nd digit: modulo division by 10, returning the remainder (e.g., 43 so divided results in 3.)

I think a blanked first digit looks better than a leading zero, and thus fed displayChar a non-displayable character.

Note that the numbers are displayed left-justified on each LED matrix. I have not investigated correcting this.

Step 4: Seconds

Since I have 5 matrices, I decided to stick the 5th one between the hours and minutes, marking off seconds by illuminating a single LED across each row in turn, using the setLed function. Its arguments are: LED number (again, counting from 0), row, column, and a Boolean (true= on). For some reason, row and column are interchanged on my matrices, so I reversed them.

I used nested loops, testing for the 8th LED on even rows in order to skip. I'm sure there are more elegant ways to write this, but I'm just getting started in C and have not programmed in years.

Step 5: The LED Clock Sketch

/*This sketch runs a clock with five LED matrices based on MAX72xx chipset.
An example that shows writing and scrolls text across 4 LED matrices is shown at
https://www.instructables.com/id/Multiple-LED-Matrixes-with-Arduino
This sketch uses the LedControlMS.h (from Makerspace) from the page above, a modificarion of the LEDControl.h library.
This sketch uses the Arduino time & wire libraries, and the DS3131RTC (DS3232RCTC Library)
Sketch assumes the following wiring for the MAX72xx LED matrices--
pin 12 is connected to the DataIn
pin 11 is connected to the CLK
pin 10 is connected to LOAD
Dataout (middle output pin) is daisy-chained to the DataIn of the next LED for each matrix except the last.
Wiring for the DS3231RTC
VCC and ground are connected to +5VDC and Gnd, respectively
Clock SDA --> Analog 4
SCL --> Analog 5
*/

#include <DS3232RTC.h> // DS3232RTC Clock library that also handles DS3231RTC
#include <Time.h> //Used for clock
#include <Wire.h> //Used for clock
#include "LedControlMS.h" // Note that this is not library LEDControl
int h1, h2, m1, m2; //Each LED matrix will display one number: hour 1&2, minute 1&2. These variables hold the single digits
int s1=2; // LED that counts off the seconds
int hr12; //Used for 12 hour time
int noMatrix=5; //Number of matrices. The library addresses up to 8.
boolean am=true; //To mark am or pm. Initialize as am
LedControl lc=LedControl(12,11,10,noMatrix); //Pin assignments and number of matrices (5)

void setup() {
//First, set the system time to a hard-coded date and time, and then sets the RTC from the system time.
//The setTime() function is part of the Time library.
// Hr Min Sec dd mm yyyy
setTime(18, 18, 30, 25, 11, 2014); //Manually set Arduino clock
//RTC.set(now()); //set the RTC from the system time

//Initialize the MAX72XXs (in power-saving mode on startup--wakeup call.
for (int i=0; i< noMatrix; i++){ //For each of the matrices...
lc.shutdown(i,false);
lc.setIntensity(i,1); // Set brightness to a low value
lc.clearDisplay(i); // Clear the display
}
delay(100); // Wait between updates of the display
lc.clearAll();
}

void loop() {
// Set am or pm Boolean (am was initialized as true)
if (hour() > 12)
{am=false;
hr12=hour()-12;
}

/* Isolate hours and minutes, one digit to each LED matrix.
I think a single-digit hour looks better with a blank first digit.
*/
//Place each digit of the hour in its own variable, h1 and h2
if (hr12 < 10)
{
/*
Blank 1st LED matrix if <10 hrs. (62 is a blank character.)
Could also insert a zero, as with minutes.
*/
h1=151;
h2=hr12; //2nd LED displays single digit of hour
}
else
{
//Othewise, just use the two digits of the hour on h1 and h2.
h1=hr12/10; //Integer division by 10 returns the first digit of the hour.
h2=hr12 % 10; //Modulo division by 10 returns the 2nd digit.
}

//Minutes are displayed by m1 and m2
if (minute() < 10)
{
m1=0; //First minute LED d1splays zero
m2=minute(); //2nd digit of minutes
}
else
{
m1=minute()/10;
m2=minute() % 10;
}

/*
Display hours and minutes using the displayChar function. This uses two integer arguments:
the LED matrix number (0-7) and the character to be displayed. Numbers are displayed simply
by passing the number itself as the 2nd argument: that is, lc.displayChar(0,h1)
*/
lc.displayChar(0,h1); //Hours 1 digit to left-most (#0) LED.
lc.displayChar(1,h2); //Hours 2 digit to LED #1
lc.displayChar(3,m1); //Minutes 1 digit to LED #3. (Recall that #2 is used to mark off the seconds.)
lc.displayChar(4,m2); //Minutes 1 digit to #4

/* This routine determines which single LED to light to count off the seconds.
The middle LED counts off the seconds by illuminating a single LED at a time
across each of the 8 rows. Count 8 LEDs across odd rows, and 7 across even rows.
Thus, two rows count 15 seconds.
*/
for (int r=7; r > -1; r--){ //For each of 8 rows, starting from the top (#7)...
for (int c=0; c < 8; c++){ //For each of the 8 leds in a row (0 on left)...

/*
Illuminate dot on current column and row. These seem to be interchanged on my hardware.
I therefore swapped the arguments to the setLed() function below.
Properly, it is addressed as setLed(int led#, int row, int col, boolean).
Variable s1 holds the LED number (counting from 0) of the LED matrix used for this.
*/

if (r%2 == 0 && c==7) //Even row AND col 7
{}
else
lc.setLed(s1,c,r,true); //Turn addressed LED on for 3/4 sec
delay(750);
lc.setLed(s1,c,r,false); //Turn off for 1/4 sec
delay(250);
}
}
}
}

Step 6: