Introduction

In this project, I used a MAX7219 for the LED dot matrix, and a DS3231 for the RTC module. Complete code here

Five second video of the binary clock at 5:11 pm.

Reading a binary clock

This is binary-coded decimal. It represents each digit in the 24-hour HH:MM:SS format in a binary column, using a lit dot for 8, 4, 2, and 1.
In the first column, only the bottom dot is lit, signifying 1. The second row has the dots for 2 and 4 lit, signifying 6. The hour is 16, which is 4 pm.

LED matrix diagram that represents the time 16:34:39.
This LED matrix BCD display represents 16:34:39.

Wiring

  • The SCL and SDA pins on the RTC module go into the SCL and SDA pins on the Arduino.
  • In my code, the DIN, CS, and CLK pins on the LED matrix go into Arduino pins 7, 6, and 5.
  • The VCC and GND pins on both the RTC and the LED matrix need to go into the 5V and GND pins on the Arduino. Since there's only one 5V pin, I had to use a small breadboard to link everything together.
Fritzing wiring diagram of the Arduino Uno, clock module, and LED dot matrix.
Wiring diagram.

Code

Initialization code

This includes Arduino's LedControl library for programming the LED matrix and the DS3231 library.

#include "LedControl.h"
#include <DS3231.h>

// Initialize the dot matrix and the clock
LedControl lc = LedControl(7, 5, 6, 1);
DS3231 clock;

Setup code

The second parameter of setIntensity can be between 0 and 15 inclusive, with 15 being the brightest.

Calibrating the clock by setting its datetime is only necessary the first time the program is uploaded. The RTC module will stay up-to-date by itself.

void setup() {
	// Start up and clear the matrix
	lc.shutdown(0, false);
	lc.setIntensity(0, 1);
	lc.clearDisplay(0);

	// Start the clock and set its time to the sketch compiling time
	clock.begin();
	clock.setDateTime(__DATE__, __TIME__);
}

Loop code

Since all the clock's values only have two digits, (value / 10) obtains the 10s digit and (value % 10) obtains the 1s digit.

The << 2 is a bitwise shift operator that moves the value two bits to the left (e.g. 0b00000011 << 2 == 0b00001100). This moves the binary clock up two rows so it occupies the middle four rows of the eight-row matrix.

The one-second delay ensures that the display doesn't update more than necessary.

void loop() {
	RTCDateTime dt = clock.getDateTime();

	lc.setColumn(0, 1, (dt.hour / 10) << 2);   // Tens digit of hour
	lc.setColumn(0, 2, (dt.hour % 10) << 2);   // Ones digit of hour
	lc.setColumn(0, 3, (dt.minute / 10) << 2); // Tens digit of minute
	lc.setColumn(0, 4, (dt.minute % 10) << 2); // Ones digit of minute
	lc.setColumn(0, 5, (dt.second / 10) << 2); // Tens digit of second
	lc.setColumn(0, 6, (dt.second % 10) << 2); // Ones digit of second

	delay(1000);
}

Complete code

#include "LedControl.h"
#include <DS3231.h>

// Initialize the dot matrix and the clock
LedControl lc = LedControl(7, 5, 6, 1);
DS3231 clock;

void setup() {
	// Start up and clear the matrix
	lc.shutdown(0, false);
	lc.setIntensity(0, 1);
	lc.clearDisplay(0);

	// Start the clock and set its time to the sketch compiling time
	clock.begin();
	clock.setDateTime(__DATE__, __TIME__);
}

void loop() {
	RTCDateTime dt = clock.getDateTime();

	lc.setColumn(0, 1, (dt.hour / 10) << 2);   // Tens digit of hour
	lc.setColumn(0, 2, (dt.hour % 10) << 2);   // Ones digit of hour
	lc.setColumn(0, 3, (dt.minute / 10) << 2); // Tens digit of minute
	lc.setColumn(0, 4, (dt.minute % 10) << 2); // Ones digit of minute
	lc.setColumn(0, 5, (dt.second / 10) << 2); // Tens digit of second
	lc.setColumn(0, 6, (dt.second % 10) << 2); // Ones digit of second

	delay(1000);
}