Digital wall clocks are common items seen in almost every household, office, and industry. It is a common but essential household item that allows us to get our bearings and gives us a sense of the day we are spending. Buying a new wall clock will generally cost you a bit more money than you would initially expect since it is the basic habit of shopkeepers to dupe their customers. But luckily there is a simple way of making a digital wall clock. So in today’s tutorial, we are going to go over a step by step procedure on how to design a DIY Digital Wall Clock Using Arduino ATMega328p 8-Bit AVR MCU IC.
ATMega328p AVR IC
ATmega328P is a low-power CMOS 8-bit microcontroller based on the AVR enhanced RISC architecture. The ATmega328P achieves throughputs approaching 1MIPS per MHz By executing powerful instructions in a single clock cycle. This allows system designers to optimize power consumption versus processing speed very easily. ATMega328p is one of the famous MCUs of Atmel because of its use in the Arduino UNO board. ATmega328P is designed with low current consumption features. The chip contains 32 kilobytes of internal flash memory, 1KB of EEPROM, and 2KB of SRAM.
Key Features & Specifications
- No. of Pins: 28
- CPU: RISC 8-Bit AVR
- Operating Voltage: 1.8 to 5.5 V
- Program Memory: 32KB
- Program Memory Type: Flash
- SRAM: 2048 B
- EEPROM: 1024 B
- ADC: 10-Bit
- Number of ADC Channels: 8
- PWM Pins: 6
- Total no. of Comparators: 1
- Packages (4): 8-pin PDIP32-lead, TQFP28-pad, QFN/MLF32-pad, QFN/MLF
- Oscillator: up to 20 MHz
- Timer (3): 8-Bit x 2 & 16-Bit x 1
- Enhanced Power on Reset: Yes
- Power Up Timer: Yes
- I/O Pins: 23
- Manufacturer: Microchip
- SPI: Yes
- I2C: Yes
- Watchdog Timer: Yes
- Brownout detect (BOD): Yes
- Reset: Yes
- USI (Universal Serial Interface): Yes
- Minimum Operating Temperature: -40°C to +85°C
Seven Segment Display
The 7-segment display consists of seven LEDs arranged in a particular fashion in order to exhibit Decimal integers (0 – 9) & Hexadecimal characters (0 – F). Each of the seven LEDs is called a segment because when illuminated the segment forms part of a numerical digit. These segments are named as a,b,c,d,e,f,g. Seven segment displays are available in two main configurations.
- Common Cathode
- Common Anode
Hardware Components
You will need the following parts to build this project:
S.No | Component | Value | Qty |
---|---|---|---|
1) | MCU IC | Microchip ATMega328p | 1 |
2) | Arduino Uno Board | Rev3, 8KB | 1 |
3) | Crystal Oscillator | 16MHz | 1 |
4) | IC Base | 28 – pin | 1 |
5) | 7 – segment display | common anode | 4 |
6) | Capacitors | 22pF | 2 |
7) | Resistors | 220 Ohm, 1K | 28 |
8) | LED | 5mm, 3.5V | 1 |
9) | Header Pins | Female/male | 2 |
10) | Soldering Iron | 45W – 65W | 1 |
11) | Soldering Wire with Flux | – | 1 |
12) | Pushbutton | – | 1 |
13) | Toggle switch | – | 2 |
14) | Veroboard | – | 1 |
15) | DC Battery with Clip | 3.7V | 1 |
16) | Jumper Wires | – | As per need |
ATMega328p Pinout
Seven Segment Display Pinout
Useful Steps
1) Solder the two 7 – segment display LEDs (to display hours) on the veroboard.
2) Solder the two separator LEDs (to display seconds) on the Veroboard.
3) After that, solder the remaining two 7 – segment displays (to display minutes) on the Veroboard.
4) Now solder the toggle switch on the veroboard to connect the four 7 – segment displays together.
5) After that, solder the remaining two pushbuttons on the Veroboard to set the hours and minutes respectively.
6) After that, solder the 28 – pin IC base on the veroboard.
7) Now connect the second toggle switch to control the power to the circuit.
8) Solder the A, B, F, G pin of all seven segment LEDs in parallel with each other using a 220 Ohm resistor. After that, Solder the E, D & C pin of all seven segment LEDs in parallel with each other using a 220 Ohm resistor.
9) Solder the +ve terminal of the seconds LEDs with a 1K resistor to the Vcc of the circuit and -ve pin with the GND of the circuit.
10) After that, solder two 22pF capacitors with a crystal oscillator connected in parallel between them. Join them between pin 9 & 10 of the IC.
11) After that, place your ATMega328p DIP in the Arduino IC socket and burn the code provided below
12) Connect the IC back to your clock circuit.
13) Power up and test the circuit.
Source Code
#include <TimeLib.h>
int digit1 = 10;
int digit2 = 11;
int digit3 = 12;
int digit4 = 13;
int segA = 2;
int segB = 3;
int segC = 4;
int segD = 5;
int segE = 6;
int segF = 7;
int segG = 8;
int segDP = 9;
byte SW0 = A0;
byte SW1 = A1;
byte SW2 = A2;
void setup()
{
pinMode(segA, OUTPUT);
pinMode(segB, OUTPUT);
pinMode(segC, OUTPUT);
pinMode(segD, OUTPUT);
pinMode(segE, OUTPUT);
pinMode(segF, OUTPUT);
pinMode(segG, OUTPUT);
pinMode(segDP, OUTPUT);
pinMode(digit1, OUTPUT);
pinMode(digit2, OUTPUT);
pinMode(digit3, OUTPUT);
pinMode(digit4, OUTPUT);
// pinMode(13, OUTPUT);
Serial.begin(9600);
pinMode(SW0, INPUT);
pinMode(SW1, INPUT);
pinMode(SW2, INPUT);
digitalWrite(SW0, HIGH);
digitalWrite(SW1, HIGH);
digitalWrite(SW2, HIGH);
}
void loop() {
digitalWrite(segDP, HIGH);
int hr = hour();
int timp = ( (hr>12)?(hr%12):hr)*100+minute();
Serial.println(timp);
for(int i = 250 ; i >0 ; i--) {
if (timp > 100) displayNumber01(timp);
else displayNumber02(timp);
}
for(int i = 250 ; i >0 ; i--) {
if (timp > 100) displayNumber03(timp);
else displayNumber04(timp);
}
if (!(digitalRead(SW0))) set_time();
}
void set_time()
{
byte minutes1 = 0;
byte hours1 = 0;
byte minutes = minute();
byte hours = hour();
while (!digitalRead(SW0))
{
minutes1=minutes;
hours1=hours;
while (!digitalRead(SW1))
{
minutes++;
if (minutes > 59) minutes = 0;
for(int i = 20 ; i >0 ; i--) {
int timp= hours*100+minutes;
if (timp > 1000) displayNumber01(timp);
else displayNumber02(timp);
}
delay(150);
}
while (!digitalRead(SW2))
{
hours++;
if (hours > 23) hours = 0;
for(int i = 20 ; i >0 ; i--) {
int timp= hours*100+minutes;
if (timp > 1000) displayNumber01(timp);
else displayNumber02(timp);
}
delay(150);
}
for(int i = 20 ; i >0 ; i--) {
displayNumber01(hours*100+minutes);
}
setTime(hours,minutes,0,0,0,0);
delay(150);
}
}
void displayNumber01(int toDisplay)
{
#define DISPLAY_BRIGHTNESS 500
#define DIGIT_ON HIGH
#define DIGIT_OFF LOW
for(int digit = 4 ; digit > 0 ; digit--) {
switch(digit) {
case 1:
digitalWrite(digit1, DIGIT_ON);
digitalWrite(segDP, LOW);
break;
case 2:
digitalWrite(digit2, DIGIT_ON);
digitalWrite(segDP, LOW);
break;
case 3:
digitalWrite(digit3, DIGIT_ON);
digitalWrite(segDP, LOW);
break;
case 4:
digitalWrite(digit4, DIGIT_ON);
digitalWrite(segDP, LOW);
break;
}
lightNumber(toDisplay % 10);
toDisplay /= 10;
delayMicroseconds(DISPLAY_BRIGHTNESS);
lightNumber(10);
digitalWrite(digit1, DIGIT_OFF);
digitalWrite(digit2, DIGIT_OFF);
digitalWrite(digit3, DIGIT_OFF);
digitalWrite(digit4, DIGIT_OFF);
}
}
void displayNumber02(int toDisplay)
{
#define DISPLAY_BRIGHTNESS 500
#define DIGIT_ON HIGH
#define DIGIT_OFF LOW
for(int digit = 4 ; digit > 0 ; digit--)
{
switch(digit)
{
case 1:
lightNumber(10);
digitalWrite(segDP, LOW);
break;
case 2:
digitalWrite(digit2, DIGIT_ON);
digitalWrite(segDP, LOW);
break;
case 3:
digitalWrite(digit3, DIGIT_ON);
digitalWrite(segDP, LOW);
break;
case 4:
digitalWrite(digit4, DIGIT_ON);
digitalWrite(segDP, LOW);
break;
}
lightNumber(toDisplay % 10);
toDisplay /= 10;
delayMicroseconds(DISPLAY_BRIGHTNESS);
lightNumber(10);
digitalWrite(digit1, DIGIT_OFF);
digitalWrite(digit2, DIGIT_OFF);
digitalWrite(digit3, DIGIT_OFF);
digitalWrite(digit4, DIGIT_OFF);
}
}
void displayNumber03(int toDisplay)
{
#define DISPLAY_BRIGHTNESS 500
#define DIGIT_ON HIGH
#define DIGIT_OFF LOW
for(int digit = 4 ; digit > 0 ; digit--) {
switch(digit) {
case 1:
digitalWrite(digit1, DIGIT_ON);
digitalWrite(segDP, HIGH);
break;
case 2:
digitalWrite(digit2, DIGIT_ON);
digitalWrite(segDP, HIGH);
break;
case 3:
digitalWrite(digit3, DIGIT_ON);
digitalWrite(segDP, HIGH);
break;
case 4:
digitalWrite(digit4, DIGIT_ON);
digitalWrite(segDP, HIGH);
break;
}
lightNumber(toDisplay % 10);
toDisplay /= 10;
delayMicroseconds(DISPLAY_BRIGHTNESS);
lightNumber(10);
digitalWrite(digit1, DIGIT_OFF);
digitalWrite(digit2, DIGIT_OFF);
digitalWrite(digit3, DIGIT_OFF);
digitalWrite(digit4, DIGIT_OFF);
}
}
void displayNumber04(int toDisplay) {
#define DISPLAY_BRIGHTNESS 500
#define DIGIT_ON HIGH
#define DIGIT_OFF LOW
for(int digit = 4 ; digit > 0 ; digit--) {
switch(digit) {
case 1:
lightNumber(10);
digitalWrite(segDP, HIGH);
break;
case 2:
digitalWrite(digit2, DIGIT_ON);
digitalWrite(segDP, HIGH);
break;
case 3:
digitalWrite(digit3, DIGIT_ON);
digitalWrite(segDP, HIGH);
break;
case 4:
digitalWrite(digit4, DIGIT_ON);
digitalWrite(segDP, HIGH);
break;
}
lightNumber(toDisplay % 10);
toDisplay /= 10;
delayMicroseconds(DISPLAY_BRIGHTNESS);
lightNumber(10);
digitalWrite(digit1, DIGIT_OFF);
digitalWrite(digit2, DIGIT_OFF);
digitalWrite(digit3, DIGIT_OFF);
digitalWrite(digit4, DIGIT_OFF);
}
}
void lightNumber(int numberToDisplay)
{
#define SEGMENT_ON LOW
#define SEGMENT_OFF HIGH
switch (numberToDisplay)
{
case 0:
digitalWrite(segA, SEGMENT_ON);
digitalWrite(segB, SEGMENT_ON);
digitalWrite(segC, SEGMENT_ON);
digitalWrite(segD, SEGMENT_ON);
digitalWrite(segE, SEGMENT_ON);
digitalWrite(segF, SEGMENT_ON);
digitalWrite(segG, SEGMENT_OFF);
break;
case 1:
digitalWrite(segA, SEGMENT_OFF);
digitalWrite(segB, SEGMENT_ON);
digitalWrite(segC, SEGMENT_ON);
digitalWrite(segD, SEGMENT_OFF);
digitalWrite(segE, SEGMENT_OFF);
digitalWrite(segF, SEGMENT_OFF);
digitalWrite(segG, SEGMENT_OFF);
break;
case 2:
digitalWrite(segA, SEGMENT_ON);
digitalWrite(segB, SEGMENT_ON);
digitalWrite(segC, SEGMENT_OFF);
digitalWrite(segD, SEGMENT_ON);
digitalWrite(segE, SEGMENT_ON);
digitalWrite(segF, SEGMENT_OFF);
digitalWrite(segG, SEGMENT_ON);
break;
case 3:
digitalWrite(segA, SEGMENT_ON);
digitalWrite(segB, SEGMENT_ON);
digitalWrite(segC, SEGMENT_ON);
digitalWrite(segD, SEGMENT_ON);
digitalWrite(segE, SEGMENT_OFF);
digitalWrite(segF, SEGMENT_OFF);
digitalWrite(segG, SEGMENT_ON);
break;
case 4:
digitalWrite(segA, SEGMENT_OFF);
digitalWrite(segB, SEGMENT_ON);
digitalWrite(segC, SEGMENT_ON);
digitalWrite(segD, SEGMENT_OFF);
digitalWrite(segE, SEGMENT_OFF);
digitalWrite(segF, SEGMENT_ON);
digitalWrite(segG, SEGMENT_ON);
break;
case 5:
digitalWrite(segA, SEGMENT_ON);
digitalWrite(segB, SEGMENT_OFF);
digitalWrite(segC, SEGMENT_ON);
digitalWrite(segD, SEGMENT_ON);
digitalWrite(segE, SEGMENT_OFF);
digitalWrite(segF, SEGMENT_ON);
digitalWrite(segG, SEGMENT_ON);
break;
case 6:
digitalWrite(segA, SEGMENT_ON);
digitalWrite(segB, SEGMENT_OFF);
digitalWrite(segC, SEGMENT_ON);
digitalWrite(segD, SEGMENT_ON);
digitalWrite(segE, SEGMENT_ON);
digitalWrite(segF, SEGMENT_ON);
digitalWrite(segG, SEGMENT_ON);
break;
case 7:
digitalWrite(segA, SEGMENT_ON);
digitalWrite(segB, SEGMENT_ON);
digitalWrite(segC, SEGMENT_ON);
digitalWrite(segD, SEGMENT_OFF);
digitalWrite(segE, SEGMENT_OFF);
digitalWrite(segF, SEGMENT_OFF);
digitalWrite(segG, SEGMENT_OFF);
break;
case 8:
digitalWrite(segA, SEGMENT_ON);
digitalWrite(segB, SEGMENT_ON);
digitalWrite(segC, SEGMENT_ON);
digitalWrite(segD, SEGMENT_ON);
digitalWrite(segE, SEGMENT_ON);
digitalWrite(segF, SEGMENT_ON);
digitalWrite(segG, SEGMENT_ON);
break;
case 9:
digitalWrite(segA, SEGMENT_ON);
digitalWrite(segB, SEGMENT_ON);
digitalWrite(segC, SEGMENT_ON);
digitalWrite(segD, SEGMENT_ON);
digitalWrite(segE, SEGMENT_OFF);
digitalWrite(segF, SEGMENT_ON);
digitalWrite(segG, SEGMENT_ON);
break;
case 10:
digitalWrite(segA, SEGMENT_OFF);
digitalWrite(segB, SEGMENT_OFF);
digitalWrite(segC, SEGMENT_OFF);
digitalWrite(segD, SEGMENT_OFF);
digitalWrite(segE, SEGMENT_OFF);
digitalWrite(segF, SEGMENT_OFF);
digitalWrite(segG, SEGMENT_OFF);
break;
}
}
Working Explanation
The working of this circuit is as follows. the 4 seven-segment LEDs comprise the hours and minutes dials of the clock while the 2 LEDs in the middle represent the second dial of the clock, blinking at every half a second. The operation of this clock is primarily dependent upon setting the appropriate clock cycle of the ATMega328p. In order to do that, connect two 22pF capacitors in parallel with a 16MHz crystal oscillator.
Now let’s move on to a brief description of the code itself. In the above source code, the hourFormat12() function (made accessible through the “Timelib.h” library) notifies us about the hours passed while minutes() shows the corresponding elapsed minutes, from the time we have switched on the board. to the time when the power to the board is cut off. After that it resets again from 00:00 every time
Download Library
In order to run this code, you need to add the library “Timelib.h”. To add this library, simply paste this Time.zip file in the Arduino’s library folder.
Applications
- These DIY Digital wall clock are usually used in places such as offices, homes, schools
- Also used in appliances such as ovens, food timers, washing machines, etc.
See Also: How To Make An IoT Web Server Using ESP32 WROOM With Arduino IDE | How To Interface MQ2 Gas Sensor With Arduino Uno | DIY Arduino Project | Simple Voltage Level Indicator Using LM3914 Dot/Bar Display Driver | DIY
Yes you can use all the points at once
How do we connect the push buttons to the 7 segment display to change its value?