Last days I revisited some older projects on the blog looking for a source of inspiration, and I realized that I did not publish too many clock projects. Well, it’s time to fix this: today I will show you how to make a binary clock using one Arduino Uno, and one Arduino Uno Click shield, one 8×8 LED matrix B click and one RTC2 Click from MikroElektronika.
As usual, when working with MikroElektronika click boards, the hardware part is deceptively simple: attach the Arduino Uno Click shield on top of the Arduino Uno board. Put the 4×4 B click in mikroBUS socket #1. Put the RTC2 click into mikroBUS socket #2. That’s all. Both click boards are designed to run on 5V power, so there’s no need to change jumpers and such.
Binary clock Arduino code
As prerequisites, besides the hardware, one has to install the following code libraries:
- LED Control library from https://github.com/wayoda/LedControl. This is the library that works best with the 8×8 B click – it’s the same library I used before, in the game of life project.
- DS1307 RTC library from https://github.com/adafruit/RTClib. There are many libraries available for the DS1307, but this project requires one library that “knows” how to configure the RTC for SQW output.
The code comes in two flavors, one that shows one binary value for each digit of the hour, minute and seconds respectively; the other version shows each of the hours, minutes and seconds as a single binary value.
Both version will update the RTC values when the program is compiled and uploaded, so there is no need to set the time separately. Then, the RTC is configured to output an 1Hz square wave on its INT pin – that corresponds to pin D3 on the Arduino Board.
The Arduino Uno is configured for the
Thus, an interrupt is generated every second. The ISR routine sets the is_second variable to “true”. In the main loop, the value of this variable is tested and, if true, the LED matrix is updated and the is_second variable is cleared.
The main difference between the two codes is within the update_display() routine that updates the LED matrix.
In the first version, each of the hours, minutes and seconds is split into two digits, one for the tens and one for the units. A look-up table is used to convert those values into meaningful binary values that are then shown onto the LED matrix
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/******************************************************************* | |
____ __ ____ ___ ____ ____ __ __ _ ____ __ | |
( __)( ) ( __)/ __)(_ _)( _ \ / \ ( ( \(__ ) / _\ | |
) _) / (_/\ ) _)( (__ )( ) /( O )/ / / _/ / \ | |
(____)\____/(____)\___) (__) (__\_) \__/ \_)__)(____)\_/\_/ | |
Project name: Arduino LED matrix binary clock | |
Project page: https://electronza.com/arduino-led-matrix-binary-clock | |
Description: This version shows each digit of the hours, minutes and seconds | |
as a binary number | |
********************************************************************/ | |
// Thus, 12:39:45 will be | |
// Hours | |
// 00000001 | |
// 00000010 | |
// Minutes | |
// 00000011 | |
// 00001001 | |
// Seconds | |
// 00000100 | |
// 00000101 | |
// Date and time functions using a DS1307 RTC connected via I2C and Wire lib | |
#include <Wire.h> | |
#include "RTClib.h" | |
// Library for 8x8B click | |
#include "LedControl.h" | |
// The 8×8 click board is placed in mikroBUS socket #1 | |
LedControl lc=LedControl(11,13,10,1); | |
// RTC settings | |
RTC_DS1307 rtc; | |
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; | |
// Clock variables | |
// Look-up table to show binary values on the LED matrix | |
int myBinaryDisp[] = {B00000000, B10000000, B01000000, B11000000, B00100000, | |
B10100000, B01100000, B11100000, B00010000, B10010000}; | |
bool is_second = false; | |
void setup() { | |
// RTC Initialization | |
if (! rtc.begin()) { | |
while (1); | |
} | |
if (! rtc.isrunning()) { | |
// Serial.println("RTC is NOT running!"); | |
// following line sets the RTC to the date & time this sketch was compiled | |
rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); | |
// This line sets the RTC with an explicit date & time, for example to set | |
// January 21, 2014 at 3am you would call: | |
// rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); | |
} | |
/* | |
The MAX72XX is in power-saving mode on startup, | |
we have to do a wakeup call | |
*/ | |
lc.shutdown(0,false); | |
/* Set the brightness to a medium values */ | |
lc.setIntensity(0,4); | |
/* and clear the display */ | |
lc.clearDisplay(0); | |
// Set up interrupts | |
interrupts(); | |
// If the RTC is placed in mikroBUS socket #2 the interrupt pin is D3 | |
attachInterrupt(digitalPinToInterrupt(3), onesecond, RISING); | |
// CONFIGURE RTC for 1Hz square wave output | |
rtc.writeSqwPinMode(SquareWave1HZ); | |
} | |
void loop() { | |
if (is_second == true){ | |
update_display(); | |
is_second = false; | |
} | |
} | |
// This function updates the LED matrix | |
void update_display (void){ | |
// Read the RTC | |
DateTime now = rtc.now(); | |
// lc.clearDisplay(0);// clear screen | |
// update hours | |
// upper digit | |
int hh = now.hour() / 10; | |
lc.setColumn(0,0,myBinaryDisp[hh]); | |
//lower digit | |
int hl = now.hour() % 10; | |
lc.setColumn(0,1,myBinaryDisp[hl]); | |
// update minutes | |
// upper digit | |
int mh = now.minute() / 10; | |
lc.setColumn(0,3,myBinaryDisp[mh]); | |
//lower digit | |
int ml = now.minute() % 10; | |
lc.setColumn(0,4,myBinaryDisp[ml]); | |
// update seconds | |
// upper digit | |
int sh = now.second() / 10; | |
lc.setColumn(0,6,myBinaryDisp[sh]); | |
//lower digit | |
int sl = now.second() % 10; | |
lc.setColumn(0,7,myBinaryDisp[sl]); | |
} | |
// ISR routine | |
void onesecond() { | |
is_second = true; | |
} |
In the second version of the code each of the hours, minutes and seconds are shown as a single binary value. Again, a look-up table is used to convert time into meaningful binary values. However, in this version, the look-up table is much larger because the possible values now range between 0 and 59.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/******************************************************************* | |
____ __ ____ ___ ____ ____ __ __ _ ____ __ | |
( __)( ) ( __)/ __)(_ _)( _ \ / \ ( ( \(__ ) / _\ | |
) _) / (_/\ ) _)( (__ )( ) /( O )/ / / _/ / \ | |
(____)\____/(____)\___) (__) (__\_) \__/ \_)__)(____)\_/\_/ | |
Project name: Arduino LED matrix binary clock | |
Project page: https://electronza.com/arduino-led-matrix-binary-clock | |
Description: This version shows hours, minutes and seconds as binary numbers | |
********************************************************************/ | |
// Each of the above will be shown on two rows (it looks better like this) | |
// Thus, 12:39:45 will be | |
// Hours | |
// 00001100 | |
// Minutes | |
// 00100111 | |
// Seconds | |
// â€00101101‬ | |
// Date and time functions using a DS1307 RTC connected via I2C and Wire lib | |
#include <Wire.h> | |
#include "RTClib.h" | |
// Library for 8x8B click | |
#include "LedControl.h" | |
// The 8×8 click board is placed in mikroBUS socket #1 | |
LedControl lc=LedControl(11,13,10,1); | |
// RTC settings | |
RTC_DS1307 rtc; | |
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", | |
"Thursday", "Friday", "Saturday"}; | |
// Clock variables | |
// Look-up table to show binary values on the LED matrix | |
int myBinaryDisp[] = {B00000000, B10000000, B01000000, B11000000, B00100000, // 0 – 4 | |
B10100000, B01100000, B11100000, B00010000, B10010000, // 5 – 9 | |
B01010000, B11010000, B00110000, B10110000, B01110000, // 10 – 14 | |
B11110000, B00001000, B10001000, B01001000, B11001000, // 15 – 19 | |
B00101000, B10101000, B01101000, B11101000, B00011000, // 20 – 24 | |
B10011000, B01011000, B11011000, B00111000, B10111000, // 25 – 29 | |
B01111000, B11111000, B00000100, B10000100, B01000100, // 30 – 34 | |
B11000100, B00100100, B10100100, B01100100, B11100100, // 35 – 39 | |
B00010100, B10010100, B01010100, B11010100, B00110100, // 40 – 44 | |
B10110100, B01110100, B11110100, B00001100, B10001100, // 45 – 49 | |
B01001100, B11001100, B00101100, B10101100, B01101100, // 50 – 54 | |
B11101100, B00011100, B10011100, B01011100, B11011100,}; // 55 – 59 | |
bool is_second = false; | |
void setup() { | |
// RTC Initialization | |
if (! rtc.begin()) { | |
// Serial.println("Couldn't find RTC"); | |
while (1); | |
} | |
if (! rtc.isrunning()) { | |
Serial.println("RTC is NOT running!"); | |
// following line sets the RTC to the date & time this sketch was compiled | |
rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); | |
// This line sets the RTC with an explicit date & time, for example to set | |
// January 21, 2014 at 3am you would call: | |
// rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); | |
} | |
/* | |
The MAX72XX is in power-saving mode on startup, | |
we have to do a wakeup call | |
*/ | |
lc.shutdown(0,false); | |
/* Set the brightness to a medium values */ | |
lc.setIntensity(0,4); | |
/* and clear the display */ | |
lc.clearDisplay(0); | |
// Set up interrupts | |
interrupts(); | |
// If the RTC is placed in mikroBUS socket #2 the interrupt pin is D3 | |
attachInterrupt(digitalPinToInterrupt(3), onesecond, RISING); | |
// CONFIGURE RTC for 1Hz square wave output | |
rtc.writeSqwPinMode(SquareWave1HZ); | |
} | |
void loop() { | |
if (is_second == true){ | |
update_display(); | |
is_second = false; | |
} | |
} | |
void update_display (void){ | |
// Read the RTC | |
DateTime now = rtc.now(); | |
// update hours | |
lc.setColumn(0,0,myBinaryDisp[now.hour()]); | |
lc.setColumn(0,1,myBinaryDisp[now.hour()]); | |
// update minutes | |
lc.setColumn(0,3,myBinaryDisp[now.minute()]); | |
lc.setColumn(0,4,myBinaryDisp[now.minute()]); | |
// update seconds | |
lc.setColumn(0,6,myBinaryDisp[now.second()]); | |
lc.setColumn(0,7,myBinaryDisp[now.second()]); | |
} | |
// ISR routine | |
void onesecond() { | |
is_second = true; | |
} |