Phipps Electronics

Order within the next 

FREE SHIPPING OVER $199

50,000+ ORDERS

WORLDWIDE SHIPPING

SSL SECURED

Arduino Digital Clock using Seven Segment Display

Contents

Want an Arduino digital clock using a seven-segment as display? Find tips on how to construct one here.

Introduction

Previously, you’ve learned how to create an Arduino clock with an OLED as a display using an Arduino UNO proto shield. This time, you’ll make an Arduino clock using a seven-segment display. Since this project may require space and pins, it will be constructed on an Arduino Mega proto shield.

You can browse through these seven-segment display resources to refresh your memories:

Seven Segment Digital Clock Setup

A seven-segment display can be hooked up easily to your Arduino. Below is an image and schematic where a mini breadboard is placed on top of an Arduino MEGA protoshield. The 4-digit seven-segment is connected to the breadboard, a bunch of resistors, and then to the Arduino MEGA ports. Along with this, an RTC module (DS1302) is connected to the I2C interface of the MEGA. The RTC is in charge of time-keeping functions.

Arduino clock seven segment schematic
Arduino clock seven segment on MEGA proto shield

To make the circuit permanent, you can solder it on the proto shield. You can optionally add a buzzer or switches and make your custom functions for alarm and time adjustment. Here, the DS1302 chip was used stand-alone (not in a module) along with a 32kHz crystal and a battery holder underneath. You can find more in-depth details on working with the DS1302 RTC chip in Create a Simple Arduino Alarm Clock.

Arduino clock seven segment soldered on MEGA proto shield
Arduino clock seven segment battery

Firmware

Below is the firmware for displaying basic time on a seven-segment display using an Arduino MEGA. Note that this code uses the RTClib.h library (for the DS1302 chip). You can vary the ports depending on your setup.

				
					#include <RTClib.h>

RTC_DS1307 rtc;
byte toggle_DP = 0;

// OPTION
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

#define dot_time 1000

// Arduino MEGA
// All pins of the Seven Segment Display defined here
#define Pin1_E  A2 // A0 UNO
#define Pin2_D  A1 //PD7 UNO
#define Pin3_DP A0 //PD5 UNO
#define Pin4_C  A3 // A2 UNO
#define Pin5_G  A4 //PD2 //PB5 UNO

#define Pin6_D4 A5 //PD6 UNO

#define Pin7_B  2 // PD3 //PB4 UNO

#define Pin8_D3 3 // PD4 UNO
#define Pin9_D2 4 // PD1 UNO

#define Pin10_F 5 // A1 UNO
#define Pin11_A 6 // A3 UNO

#define Pin12_D1 7 // PD0 UNO


// Bit Digit Position Pins
#define Dig1  Pin12_D1
#define Dig2  Pin9_D2
#define Dig3  Pin8_D3 
#define Dig4  Pin6_D4 

// Segment Pins (Alphabet)
#define SegA  Pin11_A  
#define SegB  Pin7_B
#define SegC  Pin4_C
#define SegD  Pin2_D
#define SegE  Pin1_E
#define SegF  Pin10_F
#define SegG  Pin5_G
#define SegCL Pin3_DP

// OPTIONAL
// Buzzer
#define Buzzer  10

// Switches
#define Sel_SW  13
#define Hr_SW   12
#define Min_SW  11

unsigned long previousMillis = 0; // Stores the last time an action was performed



void display_digit(byte digit, byte segment) {

  // turn on the supply of the chosen segment
  switch (segment){
    case 0:
      digitalWrite(Dig1, 0);
      digitalWrite(Dig2, 0);
      digitalWrite(Dig3, 0);
      digitalWrite(Dig4, 0);
      break;      
    case 1:
      digitalWrite(Dig1, 1);
      digitalWrite(Dig2, 0);
      digitalWrite(Dig3, 0);
      digitalWrite(Dig4, 0);
      break;

    case 2:
      digitalWrite(Dig1, 0);
      digitalWrite(Dig2, 1);
      digitalWrite(Dig3, 0);
      digitalWrite(Dig4, 0);
      
      break;

    case 3:
      digitalWrite(Dig1, 0);
      digitalWrite(Dig2, 0);
      digitalWrite(Dig3, 1);
      digitalWrite(Dig4, 0);
      break;

    case 4:
      digitalWrite(Dig1, 0);
      digitalWrite(Dig2, 0);
      digitalWrite(Dig3, 0);
      digitalWrite(Dig4, 1);
      break;

    default:
      break;
  }

  // switch on the digit of that segment
  switch (digit) {
    case 0:
      // Display 0
      digitalWrite(SegA, 0);
      digitalWrite(SegB, 0);
      digitalWrite(SegC, 0);
      digitalWrite(SegD, 0);
      digitalWrite(SegE, 0);
      digitalWrite(SegF, 0);
      digitalWrite(SegG, 1);
      digitalWrite(SegCL, 1);
      break;

    case 1:
      // Display 1
      digitalWrite(SegB, 0);
      digitalWrite(SegC, 0);

      digitalWrite(SegA, 1);
      digitalWrite(SegD, 1);
      digitalWrite(SegE, 1);
      digitalWrite(SegF, 1);
      digitalWrite(SegG, 1);
      digitalWrite(SegCL, 1);
      break;

    case 2:
      // Display 2
      digitalWrite(SegA, 0);
      digitalWrite(SegB, 0);
      digitalWrite(SegG, 0);
      digitalWrite(SegE, 0);
      digitalWrite(SegD, 0);

      digitalWrite(SegC, 1);
      digitalWrite(SegF, 1);
      digitalWrite(SegCL, 1);
      break;

    case 3:
      // Display 3
      digitalWrite(SegA, 0);
      digitalWrite(SegB, 0);
      digitalWrite(SegG, 0);
      digitalWrite(SegC, 0);
      digitalWrite(SegD, 0);

      digitalWrite(SegE, 1);
      digitalWrite(SegF, 1);

      digitalWrite(SegCL, 1);
      break;

    case 4:
      // Display 4
      digitalWrite(SegF, 0);
      digitalWrite(SegB, 0);
      digitalWrite(SegG, 0);
      digitalWrite(SegC, 0);

      digitalWrite(SegA, 1);
      digitalWrite(SegE, 1);
      digitalWrite(SegD, 1);
      digitalWrite(SegCL, 1);
      break;

    case 5:
      // Display 1
      digitalWrite(SegA, 0);
      digitalWrite(SegF, 0);
      digitalWrite(SegG, 0);
      digitalWrite(SegC, 0);
      digitalWrite(SegD, 0);

      digitalWrite(SegB, 1);
      digitalWrite(SegE, 1);
      digitalWrite(SegCL, 1);
      break;

    case 6:
      // Display 1
      digitalWrite(SegA, 0);
      digitalWrite(SegF, 0);
      digitalWrite(SegE, 0);
      digitalWrite(SegD, 0);
      digitalWrite(SegC, 0);
      digitalWrite(SegG, 0);

      digitalWrite(SegB, 1);
      digitalWrite(SegCL, 1);
      break;

    case 7:
      // Display 7
      digitalWrite(SegA, 0);
      digitalWrite(SegB, 0);
      digitalWrite(SegC, 0);
      
      digitalWrite(SegD, 1);
      digitalWrite(SegE, 1);
      digitalWrite(SegF, 1);
      digitalWrite(SegG, 1);
      digitalWrite(SegCL, 1);
      break;

    case 8:
      // Display 8
      digitalWrite(SegA, 0);
      digitalWrite(SegB, 0);
      digitalWrite(SegC, 0);
      digitalWrite(SegD, 0);
      digitalWrite(SegE, 0);
      digitalWrite(SegF, 0);
      digitalWrite(SegG, 0);
      digitalWrite(SegCL, 1);
      break;

    case 9:
      // Display 9
      digitalWrite(SegA, 0);
      digitalWrite(SegB, 0);
      digitalWrite(SegC, 0);
      digitalWrite(SegD, 0);
      digitalWrite(SegE, 1);
      digitalWrite(SegF, 0);
      digitalWrite(SegG, 0);
      digitalWrite(SegCL, 1);
      break;

  }

}

void display_dot(byte dot)
{
  digitalWrite(Dig2, 1);
  switch (dot){
    case 1:
      digitalWrite(SegA, 1);
      digitalWrite(SegB, 1);
      digitalWrite(SegC, 1);
      digitalWrite(SegD, 1);
      digitalWrite(SegE, 1);
      digitalWrite(SegF, 1);
      digitalWrite(SegG, 1);
      digitalWrite(SegCL, 0);
    break;

    case 0:
      digitalWrite(SegA, 1);
      digitalWrite(SegB, 1);
      digitalWrite(SegC, 1);
      digitalWrite(SegD, 1);
      digitalWrite(SegE, 1);
      digitalWrite(SegF, 1);
      digitalWrite(SegG, 1);
      digitalWrite(SegCL, 1);
    break;

    default:
    break;
  }
}

void setup() {
  // put your setup code here, to run once:

  // Start and Check RTC
  if(!rtc.begin()){
    while(1);
  }

  // automatically sets the RTC to the date & time on PC this sketch was compiled
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

  // Comment out below line once you set the date & time.
  // Following line sets the RTC with an explicit date & time
  // for example to set January 13 2022 at 12:56 you would call:
  // rtc.set(second(), minute(), hour(), weekday(), day(), month(), year());
  // rtc.set(second, minute, hour, dayOfWeek, dayOfMonth, month, year)
  // set day of week (1=Sunday, 7=Saturday)

  // Set initial pin ports

  // Seven Segment
  pinMode(Dig1, OUTPUT);
  pinMode(Dig2, OUTPUT);
  pinMode(Dig3, OUTPUT);
  pinMode(Dig4, OUTPUT);

  pinMode(SegA, OUTPUT);
  pinMode(SegB, OUTPUT);
  pinMode(SegC, OUTPUT);
  pinMode(SegD, OUTPUT);
  pinMode(SegE, OUTPUT);
  pinMode(SegF, OUTPUT);
  pinMode(SegG, OUTPUT);
  pinMode(SegCL, OUTPUT);

  // OPTIONAL
  // pinMode(Buzzer, OUTPUT);
  // pinMode(Sel_SW, INPUT_PULLUP);
  // pinMode(Hr_SW, INPUT_PULLUP);
  // pinMode(Min_SW, INPUT_PULLUP);

}


void loop() {
  // put your main code here, to run repeatedly:

  unsigned long currentMillis = millis();

  DateTime now = rtc.now();

  // Display clock by lighting up each digit place with a short delay at a time
  // since each pins of the segments are shared between the digit places

  // Display Hour
  display_digit(now.hour()/10, 1);
  delay(3);
  display_digit(now.hour()%10, 2);
  delay(3);

  // Display Minutes
  display_digit(now.minute()/10, 3);
  delay(3);
  display_digit(now.minute()%10, 4);
  delay(3);

  // Blinking Dot
  if((currentMillis - previousMillis) > dot_time){
    toggle_DP ^= 1;
    previousMillis = millis();
  }
  display_dot(toggle_DP);
  delay(3);

}

				
			

All the seven-segment pins to Arduino ports are defined below. Additionally, you’ll also see the digit power pins supplied by another series of Arduino ports. Lastly, the alphabetized segments are mapped to their corresponding port pins (for simplicity).

				
					// Arduino MEGA
// All pins of the Seven Segment Display defined here
#define Pin1_E  A2 // A0 UNO
#define Pin2_D  A1 //PD7 UNO
#define Pin3_DP A0 //PD5 UNO
#define Pin4_C  A3 // A2 UNO
#define Pin5_G  A4 //PD2 //PB5 UNO

#define Pin6_D4 A5 //PD6 UNO

#define Pin7_B  2 // PD3 //PB4 UNO

#define Pin8_D3 3 // PD4 UNO
#define Pin9_D2 4 // PD1 UNO

#define Pin10_F 5 // A1 UNO
#define Pin11_A 6 // A3 UNO

#define Pin12_D1 7 // PD0 UNO


// Bit Digit Position Pins
#define Dig1  Pin12_D1
#define Dig2  Pin9_D2
#define Dig3  Pin8_D3 
#define Dig4  Pin6_D4 

// Segment Pins (Alphabet)
#define SegA  Pin11_A  
#define SegB  Pin7_B
#define SegC  Pin4_C
#define SegD  Pin2_D
#define SegE  Pin1_E
#define SegF  Pin10_F
#define SegG  Pin5_G
#define SegCL Pin3_DP
				
			

The function for displaying digits 0-9 is display_digit(), and its parameters are the digit itself and which segment is to be powered (digit 1 – 4).  Note that the orientation of the seven segments is common anode for this code to work correctly. You’ll just need to reverse the high and low values to make the code compatible to common cathode.

				
					void display_digit(byte digit, byte segment) {

  // turn on the supply of the chosen segment
  switch (segment){
    case 0:
      digitalWrite(Dig1, 0);
      digitalWrite(Dig2, 0);
      digitalWrite(Dig3, 0);
      digitalWrite(Dig4, 0);
      break;      
    case 1:
      digitalWrite(Dig1, 1);
      digitalWrite(Dig2, 0);
      digitalWrite(Dig3, 0);
      digitalWrite(Dig4, 0);
      break;

    case 2:
      digitalWrite(Dig1, 0);
      digitalWrite(Dig2, 1);
      digitalWrite(Dig3, 0);
      digitalWrite(Dig4, 0);
      
      break;

    case 3:
      digitalWrite(Dig1, 0);
      digitalWrite(Dig2, 0);
      digitalWrite(Dig3, 1);
      digitalWrite(Dig4, 0);
      break;

    case 4:
      digitalWrite(Dig1, 0);
      digitalWrite(Dig2, 0);
      digitalWrite(Dig3, 0);
      digitalWrite(Dig4, 1);
      break;

    default:
      break;
  }

  // switch on the digit of that segment
  switch (digit) {
    case 0:
      // Display 0
      digitalWrite(SegA, 0);
      digitalWrite(SegB, 0);
      digitalWrite(SegC, 0);
      digitalWrite(SegD, 0);
      digitalWrite(SegE, 0);
      digitalWrite(SegF, 0);
      digitalWrite(SegG, 1);
      digitalWrite(SegCL, 1);
      break;

    case 1:
      // Display 1
      digitalWrite(SegB, 0);
      digitalWrite(SegC, 0);

      digitalWrite(SegA, 1);
      digitalWrite(SegD, 1);
      digitalWrite(SegE, 1);
      digitalWrite(SegF, 1);
      digitalWrite(SegG, 1);
      digitalWrite(SegCL, 1);
      break;

    case 2:
      // Display 2
      digitalWrite(SegA, 0);
      digitalWrite(SegB, 0);
      digitalWrite(SegG, 0);
      digitalWrite(SegE, 0);
      digitalWrite(SegD, 0);

      digitalWrite(SegC, 1);
      digitalWrite(SegF, 1);
      digitalWrite(SegCL, 1);
      break;

    case 3:
      // Display 3
      digitalWrite(SegA, 0);
      digitalWrite(SegB, 0);
      digitalWrite(SegG, 0);
      digitalWrite(SegC, 0);
      digitalWrite(SegD, 0);

      digitalWrite(SegE, 1);
      digitalWrite(SegF, 1);

      digitalWrite(SegCL, 1);
      break;

    case 4:
      // Display 4
      digitalWrite(SegF, 0);
      digitalWrite(SegB, 0);
      digitalWrite(SegG, 0);
      digitalWrite(SegC, 0);

      digitalWrite(SegA, 1);
      digitalWrite(SegE, 1);
      digitalWrite(SegD, 1);
      digitalWrite(SegCL, 1);
      break;

    case 5:
      // Display 1
      digitalWrite(SegA, 0);
      digitalWrite(SegF, 0);
      digitalWrite(SegG, 0);
      digitalWrite(SegC, 0);
      digitalWrite(SegD, 0);

      digitalWrite(SegB, 1);
      digitalWrite(SegE, 1);
      digitalWrite(SegCL, 1);
      break;

    case 6:
      // Display 1
      digitalWrite(SegA, 0);
      digitalWrite(SegF, 0);
      digitalWrite(SegE, 0);
      digitalWrite(SegD, 0);
      digitalWrite(SegC, 0);
      digitalWrite(SegG, 0);

      digitalWrite(SegB, 1);
      digitalWrite(SegCL, 1);
      break;

    case 7:
      // Display 7
      digitalWrite(SegA, 0);
      digitalWrite(SegB, 0);
      digitalWrite(SegC, 0);
      
      digitalWrite(SegD, 1);
      digitalWrite(SegE, 1);
      digitalWrite(SegF, 1);
      digitalWrite(SegG, 1);
      digitalWrite(SegCL, 1);
      break;

    case 8:
      // Display 8
      digitalWrite(SegA, 0);
      digitalWrite(SegB, 0);
      digitalWrite(SegC, 0);
      digitalWrite(SegD, 0);
      digitalWrite(SegE, 0);
      digitalWrite(SegF, 0);
      digitalWrite(SegG, 0);
      digitalWrite(SegCL, 1);
      break;

    case 9:
      // Display 9
      digitalWrite(SegA, 0);
      digitalWrite(SegB, 0);
      digitalWrite(SegC, 0);
      digitalWrite(SegD, 0);
      digitalWrite(SegE, 1);
      digitalWrite(SegF, 0);
      digitalWrite(SegG, 0);
      digitalWrite(SegCL, 1);
      break;

  }

}
				
			

Another function is the display_dot() that simply toggles the dot character depending on the dot parameter value.

				
					void display_dot(byte dot)
{
  digitalWrite(Dig2, 1);
  switch (dot){
    case 1:
      digitalWrite(SegA, 1);
      digitalWrite(SegB, 1);
      digitalWrite(SegC, 1);
      digitalWrite(SegD, 1);
      digitalWrite(SegE, 1);
      digitalWrite(SegF, 1);
      digitalWrite(SegG, 1);
      digitalWrite(SegCL, 0);
    break;

    case 0:
      digitalWrite(SegA, 1);
      digitalWrite(SegB, 1);
      digitalWrite(SegC, 1);
      digitalWrite(SegD, 1);
      digitalWrite(SegE, 1);
      digitalWrite(SegF, 1);
      digitalWrite(SegG, 1);
      digitalWrite(SegCL, 1);
    break;

    default:
    break;
  }
}
				
			

The setup code initializes the RTC and adjusts its value based on compile time. Next, all seven-segment Arduino ports are configured as digital outputs.

				
					void setup() {
  // put your setup code here, to run once:

  // Start and Check RTC
  if(!rtc.begin()){
    while(1);
  }

  // automatically sets the RTC to the date & time on PC this sketch was compiled
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

  // Comment out below line once you set the date & time.
  // Following line sets the RTC with an explicit date & time
  // for example to set January 13 2022 at 12:56 you would call:
  // rtc.set(second(), minute(), hour(), weekday(), day(), month(), year());
  // rtc.set(second, minute, hour, dayOfWeek, dayOfMonth, month, year)
  // set day of week (1=Sunday, 7=Saturday)

  // Set initial pin ports

  // Seven Segment
  pinMode(Dig1, OUTPUT);
  pinMode(Dig2, OUTPUT);
  pinMode(Dig3, OUTPUT);
  pinMode(Dig4, OUTPUT);

  pinMode(SegA, OUTPUT);
  pinMode(SegB, OUTPUT);
  pinMode(SegC, OUTPUT);
  pinMode(SegD, OUTPUT);
  pinMode(SegE, OUTPUT);
  pinMode(SegF, OUTPUT);
  pinMode(SegG, OUTPUT);
  pinMode(SegCL, OUTPUT);

  // OPTIONAL
  // pinMode(Buzzer, OUTPUT);
  // pinMode(Sel_SW, INPUT_PULLUP);
  // pinMode(Hr_SW, INPUT_PULLUP);
  // pinMode(Min_SW, INPUT_PULLUP);

}
				
			

The loop code consists of displaying each seven-segment digit with the hour and minute values obtained through the RTC functions. Note that there is a delay on every display of a digit so that you’ll be able to see that digit before transitioning to display the next digit. The reason for this procedure is that each segment pins (A-G) are shared among the digit positions to save pin count. Lastly, the blinking dot function is executed through a millis() timer and a toggle_DP variable.

				
					void loop() {
  // put your main code here, to run repeatedly:

  unsigned long currentMillis = millis();

  DateTime now = rtc.now();

  // Display clock by lighting up each digit place with a short delay at a time
  // since each pins of the segments are shared between the digit places

  // Display Hour
  display_digit(now.hour()/10, 1);
  delay(3);
  display_digit(now.hour()%10, 2);
  delay(3);

  // Display Minutes
  display_digit(now.minute()/10, 3);
  delay(3);
  display_digit(now.minute()%10, 4);
  delay(3);

  // Blinking Dot
  if((currentMillis - previousMillis) > dot_time){
    toggle_DP ^= 1;
    previousMillis = millis();
  }
  display_dot(toggle_DP);
  delay(3);

}
				
			

Actual Run

(on bread board)

(soldered on the proto shield)

SUBSCRIBE FOR NEW POST ALERTS

Subscribe to be the first to know when we publish a new article!
List Subscriptions(Required)

POPULAR POSTS

Scroll to Top