0% found this document useful (0 votes)
96 views

How To Make A Digital Clock Using Arduino

This document provides instructions for making a digital clock using an Arduino nano that displays temperature, humidity, date, day and allows setting alarms. It requires an Arduino nano, DS1302 RTC module, MAX7219 display, DHT11 sensor, buzzer, momentary switches, resistors, jumper wires and an MDF board. The circuit connects these components based on a provided diagram. The Arduino code uploads to the board to read the RTC and DHT11 values and control the display and alarms based on button presses to cycle through menus to set time, date, alarms and on/off settings stored in EEPROM.

Uploaded by

MAN4 BANTUL
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
96 views

How To Make A Digital Clock Using Arduino

This document provides instructions for making a digital clock using an Arduino nano that displays temperature, humidity, date, day and allows setting alarms. It requires an Arduino nano, DS1302 RTC module, MAX7219 display, DHT11 sensor, buzzer, momentary switches, resistors, jumper wires and an MDF board. The circuit connects these components based on a provided diagram. The Arduino code uploads to the board to read the RTC and DHT11 values and control the display and alarms based on button presses to cycle through menus to set time, date, alarms and on/off settings stored in EEPROM.

Uploaded by

MAN4 BANTUL
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 14

How to make a digital clock using

Arduino
Implementation of digital clock using Arduino, MAX7219 dot matrix display, DS1302 RTC real time
clock, DHT11 humidity and temperature sensor and alarm active buzzer

Digital_Clock_Code_Files

    In this article we will learn how to make a digital clock using Arduino nano with below features:

1. Display temperature & humidity


2. Display date and day
3. Can set alarm
4. Can set time, day and date

Prerequisites:

1. Arduino nano with cable


2. DS1302 RTC
3. MAX7219 4in1 Display
4. DHT11 Temperature and Humidity sensor
5. Active buzzer
6. Momentary switches
7. Two 220 ohm and one 10K ohm resistor
8. Female to female jumper wires, normal wires
9. 5v charger
10. MDF board, paint, drill machine, screws, glue gun etc

Implementation
We will design our circuit based on below diagram. Momentary switches use 220ohm resistors and DHT sensor
uses 10K ohm resistor.
 

Fig 1: Digital clock Circuit diagram

Two momentary switches are "back" and "select". On press back clock can display day, temperature, humidity
etc. Select button works as menu which supports momentary press and long press. Momentary press is used to
display menu items and long press is used to get into menu item also to save and exit.
If you want to change time, click on select button(button-2 in video) keep clicking until you see option "Time".
Once time is displayed press and hold same button, you will be able to get into time setting mode. Click
back(Button-1 in video) to change between hours and minutes, press select button to change time and again log
press to save and exit.
Full video of making this clock:

Below is the code will be uploading to Arduino:

#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include "Font_Data.h"
#include <virtuabotixRTC.h>
#include "DHT.h"
#include <EEPROM.h>

//Display
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
#define DISPLAY_CLK_PIN 13
#define DISPLAY_DATA_PIN 11
#define DISPLAY_CS_PIN 10
//RTC
#define RTC_CLK_PIN 2
#define RTC_DATA_PIN 3
#define RTC_RST_PIN 4
//DHT
#define DHT_PIN 6
#define DHTTYPE DHT11

// Hardware SPI connection


MD_Parola P = MD_Parola(HARDWARE_TYPE, DISPLAY_CS_PIN, MAX_DEVICES);
//RTC
virtuabotixRTC myRTC(RTC_CLK_PIN,RTC_DATA_PIN,RTC_RST_PIN);
//DHT
DHT dht(DHT_PIN, DHTTYPE);

//OTHER PINS
#define BTN_BACK_PIN 8
#define BTN_SELECT_PIN 7
#define ALARM_PIN 5

char Buffer[7];

int SELECT = 0;
int SUBSELECT = 0;
int BACK = 0;
int OPTION = 0;
int RING = 0;
int ALARMHOUR = 6;
int ALARMMINUTE = 30;
int ALARMON = 0;
int ALARMOFFONBUTTONPRESS = 0;
int ROMALARMHOURADD = 0;
int ROMALARMMINUTEADD = 2;
int ROMALARMONADD = 4;

void setup(void)
{
P.begin();
dht.begin();
Serial.begin(9600);
P.setFont(newFont);
P.setIntensity(1);

pinMode(ALARM_PIN, OUTPUT);
pinMode(BTN_BACK_PIN, INPUT);
pinMode(BTN_SELECT_PIN, INPUT);

ALARMHOUR=EEPROM.read(ROMALARMHOURADD);
ALARMMINUTE=EEPROM.read(ROMALARMMINUTEADD);
ALARMON=EEPROM.read(ROMALARMONADD);
if(ALARMHOUR > 23) ALARMHOUR = 6;
if(ALARMMINUTE > 59) ALARMHOUR = 30;
if(ALARMON > 1) ALARMON = 0;
}

void loop(void)
{
int alarmMinDiff = (myRTC.hours*60 + myRTC.minutes) - (ALARMHOUR*60 + ALARMMINUTE);
//Ring if time is alarm time, alarm is on, user did not press any button and user is not inside menu
if(alarmMinDiff == 0 && ALARMON == 1 && ALARMOFFONBUTTONPRESS == 0 && SELECT == 0)
{
ringAlarm();
}
else
{
digitalWrite(ALARM_PIN, LOW);
}
if(alarmMinDiff != 0)
{
ALARMOFFONBUTTONPRESS = 0;
}

int longPress = 0;
if(digitalRead(BTN_BACK_PIN)==HIGH)
{
if(tryStopAlarm(alarmMinDiff) == 0)
clickedBack();
}

while(digitalRead(BTN_SELECT_PIN)==HIGH)
{
longPress += 100;
delay(100);
if(longPress > 1500 || digitalRead(BTN_SELECT_PIN)==LOW)
break;

continue;
}

if(longPress > 0)
{
if(tryStopAlarm(alarmMinDiff) == 0)
{
if(SELECT > 0 && longPress > 1500)
{
clickedLongSelect();
}
else if(longPress > 0)
{
clickedSelect();
}
}
}

P.displayAnimate();

while(digitalRead(BTN_BACK_PIN)==HIGH)
delay(100);
while(digitalRead(BTN_SELECT_PIN)==HIGH)
delay(100);

if(BACK == 0 && SELECT == 0)


{
displayTime();
}

delay(100);
}

void ringAlarm()
{
if(RING == 0)
{
digitalWrite(ALARM_PIN, HIGH);
RING = 1;
}
else
{
digitalWrite(ALARM_PIN, LOW);
RING = 0;
}
}

int tryStopAlarm(int alarmMinDiff)


{
if(alarmMinDiff == 0 && ALARMON == 1 && ALARMOFFONBUTTONPRESS == 0)
{
ALARMOFFONBUTTONPRESS = 1;
digitalWrite(ALARM_PIN, LOW);
return 1;
}
return 0;
}
//---------------------------------Button click methods--------------------------------------//
void clickedBack()
{
BACK++;
if(SELECT == 0)
{
switch(BACK)
{
case 1:
{
displayDay();
break;
}
case 2:
{
displayDate();
break;
}
case 3:
{
displayTemparature();
break;
}
case 4:
{
displayHumidity();
break;
}
default:
{
BACK = 0;
break;
}
}
}
else if(SELECT > 0)
{
switch(SUBSELECT)
{
case 1:
{
updateTime();
break;
}
case 2:
{
updateDate();
break;
}
case 3:
{
updateDay();
break;
}
case 4:
{
updateAlarm();
break;
}
case 5:
{
updateOnOffAlarm();
break;
}
default:
{
reset();
}
}
}
}

void clickedSelect()
{
SELECT++;
if(SUBSELECT == 0)
{
switch(SELECT)
{
case 1:
{
P.displayText("Time", PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
break;
}
case 2:
{
P.displayText("Date", PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
//P.displayText("Set Date", PA_LEFT, 60, 0, PA_SCROLL_LEFT, PA_NO_EFFECT);
break;
}
case 3:
{
P.displayText("Day", PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
break;
}
case 4:
{
P.displayText("Alarm", PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
break;
}
case 5:
{
P.displayClear();
P.displayText("ON/OFF - Alarm", PA_LEFT, 60, 0, PA_SCROLL_LEFT, PA_NO_EFFECT);
break;
}
default:
{
SELECT = 0;
}
}
}
else
{
switch(SUBSELECT)
{
case 1:
{
if(OPTION == 0) OPTION++; else OPTION=0;
displayOptionTime();
break;
}
case 2:
{
if(OPTION < 2) OPTION++; else OPTION=0;
displayOptionDate();
break;
}
case 3:
{
displayOptionDay();
break;
}
case 4:
{
if(OPTION == 0) OPTION++; else OPTION=0;
displayOptionAlarm();
break;
}
case 5:
{
displayOptionOnOffAlarm();
break;
}
default:
{
SELECT = 0;
}
}
}
}

void clickedLongSelect()
{
if(SELECT > 0 && SUBSELECT > 0)
{
reset();
displayTime();
}
if(SELECT > 0)
{
SUBSELECT = SELECT;
switch(SELECT)
{
case 1:
{
displayOptionTime();
break;
}
case 2:
{
displayOptionDate();
break;
}
case 3:
{
displayOptionDay();
break;
}
case 4:
{
displayOptionAlarm();
break;
}
case 5:
{
displayOptionOnOffAlarm();
break;
}
}
}
}
//---------------------------------Update Date Time--------------------------------------//
void updateTime()
{
if(OPTION == 0)
{
int hours = myRTC.hours < 23 ? myRTC.hours + 1 : 0;
myRTC.setDS1302Time(00, myRTC.minutes, hours, myRTC.dayofweek, myRTC.dayofmonth, myRTC.month,
myRTC.year);
}
else
{
int minutes = myRTC.minutes < 59 ? myRTC.minutes + 1 : 0;
myRTC.setDS1302Time(00, minutes, myRTC.hours, myRTC.dayofweek, myRTC.dayofmonth, myRTC.month,
myRTC.year);
}
myRTC.updateTime();
displayOptionTime();
}

void updateDate()
{
if(OPTION == 0)
{
int dayofmonth = myRTC.dayofmonth < 31 ? myRTC.dayofmonth + 1 : 1;
myRTC.setDS1302Time(00, myRTC.minutes, myRTC.hours, myRTC.dayofweek, dayofmonth, myRTC.month,
myRTC.year);
}
else if(OPTION == 1)
{
int month = myRTC.month < 12 ? myRTC.month + 1 : 1;
myRTC.setDS1302Time(00, myRTC.minutes, myRTC.hours, myRTC.dayofweek, myRTC.dayofmonth, month,
myRTC.year);
}
else if (OPTION == 2)
{
int year = myRTC.year < 2050 ? myRTC.year + 1 : 2020;
myRTC.setDS1302Time(00, myRTC.minutes, myRTC.hours, myRTC.dayofweek, myRTC.dayofmonth,
myRTC.month, year);
}
myRTC.updateTime();
displayOptionDate();
}
void updateDay()
{
int dayofweek = myRTC.dayofweek < 7 ? myRTC.dayofweek + 1 : 1;
myRTC.setDS1302Time(00, myRTC.minutes, myRTC.hours, dayofweek, myRTC.dayofmonth, myRTC.month,
myRTC.year);
myRTC.updateTime();
displayOptionDay();
}
void updateAlarm()
{
if(OPTION == 0)
{
ALARMHOUR = ALARMHOUR < 23 ? ALARMHOUR + 1 : 0;
EEPROM.write(ROMALARMHOURADD, ALARMHOUR);
}
else
{
ALARMMINUTE = ALARMMINUTE < 59 ? ALARMMINUTE + 1 : 0;
EEPROM.write(ROMALARMMINUTEADD, ALARMMINUTE);
}
displayOptionAlarm();
}
void updateOnOffAlarm()
{
if(ALARMON == 0) ALARMON++; else ALARMON = 0;
EEPROM.write(ROMALARMONADD, ALARMON);
displayOptionOnOffAlarm();
}
//---------------------------------Display methods--------------------------------------//
void displayTime()
{
myRTC.updateTime();
int hours = myRTC.hours > 12 ? myRTC.hours - 12 : myRTC.hours == 0 ? 12 : myRTC.hours;
sprintf(Buffer,"%02d : %02d",hours,myRTC.minutes);
P.displayText(Buffer, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
}
void displayTemparature()
{
int tempC = dht.readTemperature();
sprintf(Buffer,"%02d ºC", tempC);
P.displayText(Buffer, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
}

void displayHumidity()
{
int humi = dht.readHumidity();
sprintf(Buffer,"%02d %%", humi);
P.displayText(Buffer, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
}

void displayDay()
{
myRTC.updateTime();
char* dayPtr = getDay(myRTC.dayofweek);
P.displayText(dayPtr, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
}

void displayDate()
{
myRTC.updateTime();
char* monthPtr = getMonth(myRTC.month);
sprintf(Buffer,"%s %02d", monthPtr, myRTC.dayofmonth);
P.displayText(Buffer, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
}

void displayOptionTime()
{
if(OPTION == 0)
sprintf(Buffer,">%02d:%02d",myRTC.hours,myRTC.minutes);
else
sprintf(Buffer,"%02d:>%02d",myRTC.hours,myRTC.minutes);

P.displayText(Buffer, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);


}

void displayOptionDate()
{
if(OPTION == 0)
sprintf(Buffer,"D>%02d",myRTC.dayofmonth);
else if(OPTION == 1)
sprintf(Buffer,"M>%02d",myRTC.month);
else
sprintf(Buffer,"Y>%02d",myRTC.year);

P.displayText(Buffer, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);


}
void displayOptionDay()
{
char* dayName = getDay(myRTC.dayofweek);
sprintf(Buffer,"D>%0s",dayName);
P.displayText(Buffer, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
}
void displayOptionAlarm()
{
if(OPTION == 0)
sprintf(Buffer,">%02d:%02d",ALARMHOUR,ALARMMINUTE);
else
sprintf(Buffer,"%02d:>%02d",ALARMHOUR,ALARMMINUTE);

P.displayText(Buffer, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);


}
void displayOptionOnOffAlarm()
{
if(ALARMON == 0)
P.displayText("> OFF", PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
else
P.displayText("> ON", PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
}
//-------------------------------Day/month int to string methods----------------------------------//
char* getDay(int dayofweek)
{
switch(dayofweek)
{
case 1:
return "MON";
case 2:
return "TUE";
case 3:
return "WED";
case 4:
return "THU";
case 5:
return "FRI";
case 6:
return "SAT";
case 7:
return "SUN";
}
}

char* getMonth(int monthNo)


{
switch(monthNo)
{
case 1:
return "JAN";
case 2:
return "FEB";
case 3:
return "MAR";
case 4:
return "APR";
case 5:
return "MAY";
case 6:
return "JUN";
case 7:
return "JUL";
case 8:
return "AUG";
case 9:
return "SEP";
case 10:
return "OCT";
case 11:
return "NOV";
case 12:
return "DEC";
}
}

void reset()
{
SELECT = 0;
BACK = 0;
SUBSELECT = 0;
OPTION = 0;
}

 
Font_Data.h file also to be added to Arduino code:

// Data file for user example user defined fonts


#ifndef FONTDATA_H
#define FONTDATA_H

MD_MAX72XX::fontType_t newFont[] PROGMEM =


{
0, // 0
0, // 1
0, // 2
0, // 3
0, // 4
0, // 5
0, // 6
0, // 7
0, // 8
0, // 9
0, // 10
0, // 11
0, // 12
0, // 13
0, // 14
0, // 15
0, // 16
0, // 17
0, // 18
0, // 19
0, // 20
0, // 21
0, // 22
0, // 23
0, // 24
0, // 25
0, // 26
0, // 27
0, // 28
0, // 29
0, // 30
0, // 31
1, 0, // 32
0, // 33
0, // 34
0, // 35
0, // 36
5, 152, 88, 32, 208, 200, // 37
0, // 38
0, // 39
0, // 40
0, // 41
0, // 42
0, // 43
0, // 44
0, // 45
0, // 46
5, 64, 32, 16, 8, 4, // 47
5, 124, 162, 146, 138, 124, // 48
5, 136, 132, 254, 128, 128, // 49
5, 132, 194, 162, 146, 140, // 50
5, 68, 146, 146, 146, 108, // 51
5, 48, 40, 36, 254, 32, // 52
5, 78, 138, 138, 138, 114, // 53
5, 124, 146, 146, 146, 100, // 54
5, 2, 226, 18, 10, 6, // 55
5, 108, 146, 146, 146, 108, // 56
5, 76, 146, 146, 146, 124, // 57
1, 40, // 58
0, // 59
0, // 60
0, // 61
3, 68, 40, 16, // 62
0, // 63
0, // 64
5, 252, 18, 18, 18, 252, // 65
5, 254, 146, 146, 146, 108, // 66
5, 124, 130, 130, 130, 68, // 67
5, 254, 130, 130, 130, 124, // 68
5, 254, 146, 146, 146, 130, // 69
5, 254, 18, 18, 18, 2, // 70
5, 124, 130, 130, 162, 100, // 71
5, 254, 16, 16, 16, 254, // 72
3, 130, 254, 130, // 73
5, 64, 130, 130, 130, 126, // 74
5, 254, 16, 16, 40, 198, // 75
5, 254, 128, 128, 128, 128, // 76
5, 254, 4, 8, 4, 254, // 77
5, 254, 8, 16, 32, 254, // 78
5, 124, 130, 130, 130, 124, // 79
5, 254, 18, 18, 18, 12, // 80
5, 124, 130, 162, 194, 252, // 81
5, 254, 18, 18, 18, 236, // 82
5, 76, 146, 146, 146, 100, // 83
5, 2, 2, 254, 2, 2, // 84
5, 126, 128, 128, 128, 126, // 85
5, 62, 64, 128, 64, 62, // 86
5, 254, 64, 32, 64, 254, // 87
5, 198, 40, 16, 40, 198, // 88
5, 6, 8, 240, 8, 6, // 89
5, 194, 162, 146, 138, 134, // 90
8, 0, 0, 0, 0, 0, 0, 0, 0, // 91
0, // 92
0, // 93
0, // 94
0, // 95
0, // 96
5, 64, 168, 168, 168, 248, // 97
5, 254, 144, 136, 136, 112, // 98
5, 112, 136, 136, 136, 64, // 99
5, 112, 136, 136, 144, 254, // 100
5, 112, 168, 168, 168, 48, // 101
4, 16, 252, 18, 2, // 102
5, 16, 168, 168, 168, 120, // 103
5, 254, 16, 8, 8, 240, // 104
3, 136, 250, 128, // 105
3, 128, 136, 122, // 106
4, 254, 32, 80, 136, // 107
3, 130, 254, 128, // 108
5, 248, 8, 240, 8, 240, // 109
5, 248, 8, 8, 8, 240, // 110
5, 112, 136, 136, 136, 112, // 111
5, 248, 40, 40, 40, 16, // 112
5, 16, 40, 40, 40, 248, // 113
5, 248, 16, 8, 8, 16, // 114
5, 144, 168, 168, 168, 72, // 115
5, 4, 254, 132, 128, 64, // 116
5, 120, 128, 128, 128, 248, // 117
5, 24, 96, 128, 96, 24, // 118
5, 120, 128, 96, 128, 120, // 119
5, 136, 72, 112, 144, 136, // 120
5, 136, 144, 96, 32, 24, // 121
5, 136, 200, 168, 152, 136, // 122
0, // 123
0, // 124
0, // 125
0, // 126
0, // 127
0, // 128
0, // 129
0, // 130
0, // 131
0, // 132
0, // 133
0, // 134
0, // 135
0, // 136
0, // 137
0, // 138
0, // 139
0, // 140
0, // 141
0, // 142
0, // 143
0, // 144
0, // 145
0, // 146
0, // 147
0, // 148
0, // 149
0, // 150
0, // 151
0, // 152
0, // 153
0, // 154
0, // 155
0, // 156
0, // 157
0, // 158
0, // 159
0, // 160
0, // 161
0, // 162
0, // 163
0, // 164
0, // 165
0, // 166
0, // 167
0, // 168
0, // 169
0, // 170
0, // 171
0, // 172
0, // 173
0, // 174
0, // 175
0, // 176
0, // 177
0, // 178
0, // 179
0, // 180
0, // 181
0, // 182
0, // 183
0, // 184
0, // 185
4, 12, 18, 18, 12, // 186
0, // 187
0, // 188
0, // 189
0, // 190
0, // 191
0, // 192
0, // 193
0, // 194
0, // 195
0, // 196
0, // 197
0, // 198
0, // 199
0, // 200
0, // 201
0, // 202
0, // 203
0, // 204
0, // 205
0, // 206
0, // 207
0, // 208
0, // 209
0, // 210
0, // 211
0, // 212
0, // 213
0, // 214
0, // 215
0, // 216
0, // 217
0, // 218
0, // 219
0, // 220
0, // 221
0, // 222
0, // 223
0, // 224
0, // 225
0, // 226
0, // 227
0, // 228
0, // 229
0, // 230
0, // 231
0, // 232
0, // 233
0, // 234
0, // 235
0, // 236
0, // 237
0, // 238
0, // 239
0, // 240
0, // 241
0, // 242
0, // 243
0, // 244
0, // 245
0, // 246
0, // 247
0, // 248
0, // 249
0, // 250
0, // 251
0, // 252
0, // 253
0, // 254
0, // 255
};
#endif

Like 1 Person
Last modified on 10 October 2020

Nikhil Joshi
Ceo &
Founder at Dotnetlovers
Atricles: 140
Questions: 12
Given Best Solutions: 12 *

Reference:
Music Credits: https://www.bensound.com

Comments:

Weka Man
Hi great clock, just breadboarded it and might make it an actual for my workshop but with a 16x64 matrix. Not much of a coder
and have been trying to make it change back to time after a minute on the other options and scroll through time, date, temp and
humidity as an option. Also would like 24 hour time. Any ideas on how to change my code to suit?

Like   1 Person on 28 February 2021

Nikhil Joshi
Thanks Weka, Could not get you question 1 but for changing it to 24hours clock you change where I'm displaying time:

void displayTime()
{
myRTC.updateTime();
int hours = myRTC.hours > 12 ? myRTC.hours - 12 : myRTC.hours == 0 ? 12 : myRTC.hours;
sprintf(Buffer,"%02d : %02d",hours,myRTC.minutes);
P.displayText(Buffer, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
}

Just remove calculation of hours and display as it is:

void displayTime()
{
myRTC.updateTime();
sprintf(Buffer,"%02d : %02d",myRTC.hours,myRTC.minutes);
P.displayText(Buffer, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
}

You may have to make this change at couple of places.


With breadboard setup will become more cleaner and less messy. Good luck with clock, let me also know once you complete it.

Like   0 People on 28 February 2021

Weka Man
Thanks. Only had to change the code there. Looks like Ill have to get a nano to shrink the form factor as my pro minis' havent
got enough power to handle the matrix, temp sensor, RTC and buzzer at once

Like   1 Person on 1 March 2021

You might also like