Subscription Management to Save Your Time and Money!

Dual Seven Segment LED Counter

Written By: Mel Lester Jr. - Apr• 25•15

A few months ago, I was so fed up with my store-bought, digital alarm clock that I decided to make the alarm clock of my dreams.


Finished proof of concept Display

My biggest gripes about the current alarm clock are:

  • The display digits are too small (2cmW by 3cmH) and dim to read easily across the room.
  • The automatic Day Light Saving (DLS) feature predates the current US DLS scheme.
  • The battery backup doesn’t work (to be fair, maybe the battery just needs to be replaced).
  • The User Interface (UI) consists of a confusing assortment of buttons, dials and switches.

The Alarm Clock of My Dreams features:

  • A large, 6 Digit display with each digit measuring  3.8cmW by 4.5cmH (1.5″W x 2.25″H)
    • HH:MM:SS time in user selectable 24 or 12 hour format with PM indicator
    • mm.dd.yy date
    • Room Temperature to 1/10 degree
      • Celsius
      • Fahrenheit
    •   Two Alarm Settings
  • A simple, intuitive User Interface with a single combination push switch and dial.
  • Battery Backup

Seven Segment LEDs purchased from eBay for $1.70 US each

Earlier this year, I purchased on eBay ten  large, Seven Segment LEDS as shown above  for slightly less than $1.70 US each, including freight.  The LED segments are of the common cathode variety, meaning each of the sevenl segments, plus the decimal point,  are individually powered and share common grounds.  Six of these Seven Segment LEDs will be the basis of my Dream Alarm Clock’s display.

I decided the brains of my clock will be based on the Atmel ATmega328 Microcontroller which is the basis of various Arduino small computer models including the ubiquitous Uno, Micro and my favorite, the Nano.  Legal Arduino clones are readily available for less than $4.00 US as the Hardware is Open Source, while a bare bones Atmel ATmega328-PU can be purchased for less than $2.00 US and is fully capable of providing the functionality my Dream Alarm Clock requires.

Each of the six digits in my clock design have eight data pins (seven segments plus a decimal point), for a total requirement of 48 discrete digital signals.  The ATmega328 only has around 20 pins available for output, so a simple assignment of each output pin to an individual segment input pin is out of the question.

There are at least two solutions for this issue, Charlie-plexing, which involves designing a matrix of rows and columns each headed by output pins where the intersecting points are segment input pins on the display and using Shift Registers,  the method I use in my design.

Shift Registers can accept a serial stream of data bits and when signaled, move each bit to a separate output pin on the Shift Register.  These Shift Register output pins can then be connected to display segment input pins.  I am planning on using six 74HC595 Shift Registers, one for each Seven Segment LED as the 74HC595 has eight output pins and they can be daisy chained together using only three ATmega328 output pins, one for sending the Serial data stream, the second provides a clock signal and the third latches the data to the output pins.

You will notice in the picture above, that the Seven Segment LED on the right is inverted, or upside down with respect to it’s decimal point.  This is done on purpose as I need the appearance of colons when the time is displayed, a degree symbol for Temperature and the decimal point for numbers.  By inverting the third and fifth Seven Segment LED on the display, I will be able to display the time as HH:MM:SS, the date as dd.mm.yy, and Temperature as 21.50°C or 70.30°F.

This inversion is possible without too much difficulty because, when the Seven Segments are all lit, the number 8 appears.  The symmetric layout of the segments appears the same, right side up, with the decimal point at the lower right, or inverted where the decimal point is at the upper left where it is perceived as a degree symbol or the upper dot of a colon.

I used a couple of free circuit design programs, Fritzing and Autodesk 123D to create a proof cf concept using an upright and inverted Seven Segment LEDs with 74HC595 Shift Registers and an ATmega328 MicroController to drive a simple counter.  In a future Blog Post, I may review my experiences with Fritzing and 123D but I found Fritzing easy to install both on a PC and a Mac, while 123D is Cloud based and works in your browser. Both programs have a manageable learning curve and I was able to create the equivalent design on both in about an afternoon.  My impression is that Fritzing displays breadboard wiring more clearly than 123D, but 123D has an amazing circuit simulation mode that Fritzing lacks.  Both provide Breadboard, Schematic and PCB board design views and you can send your PCB designs off for fabrication from either product.


Fritzing Breadboard view — Notice the very legible routing for wires.


Equivalent Autodesk 123D Breadboard view running in Simulation mode. The numbers on the display are actually incrementing!

It took another afternoon to wire up and debug the proof of concept circuit on a breadboard.  The only real issue was quickly traced to a loose resistor.  In fact, locating the 16 resistors which are located between the 74HC595 Shift Register output pins and the individual LED segments of the displays, took the most time and patience; the rest was just following the design diagrams.  In the subsequent design phases of this project, I will replace the separate resistors with inline resistor arrays that are packaged in the same format as the 74HC595s with eight resistors (any value from 180 to 330 Ohm should do) in a 16 pin pack.

Here is the completed proof of concept from above:


View of completed project from above. The final design will be three times larger, but lessons learned here should make it much tidier.

This is the Arduino IDE code I used to drive the counter:

/* twoDigitCounter.ino 2015-04-28
   Open Source Software by Mel Lester Jr.
   Two digit counter display with 74HC595
   Orientation of 7 Segment LED Displays
       Inverted             Normal              
   dp=8   D=3                 A=7          
        .----. <- Pin 1     .----.
    C=4 |    | E=2      F=9 |    | B=6
        |G=10|              |G=10|
        |----|              |----|
    B=6 |    | F=9      E=2 |    | C=4
        |A=7 |              |D=3 |
        .----.    Pin 1 ->  .----. dp=8
   Wiring Shift Registers to Seven Segment LEDs
   74HC595 Pin ==> Ohm ==> Wire ==> INV. NORMAL
        QA  15     330     White    D3      A7
        QB   1     330     Grey     E2      B6
        QC   2     330     Purple   F9      C4
        QD   3     330     Blue     A7      D3
        QE   4     330     Green    B6      E2
        QF   5     330     Yellow   C4      F9
        QG   6     330     Orange   G10     G10
         Decimal point and colon
        QH   7     330     Brown    H8      H8
         LED Pins 1 and 5 to GND 
       GND   8 ........... Black   -1,5    -1,5
         Remainder of 74HC595 pins: 
       QH'   9 ....... to SER Pin 14 of next SR
     SRCLR  10 ............... Pull HIGH to +5V
     SRCLK  11 ........... CLK to Arduino Pin 4
      RCLK  12 ......... LATCH to Arduino Pin 7
        OE  13 ................ Pull LOW to GND
       SER  14 ........... SER to Arduino Pin 8
       VCC  16 ........ +5V (or same as Arduino)
const int SER=8;  // Arduino Data to 1st 74HC595 
const int LATCH=7; // to every 74HC595 pin 11
const int CLK=4;   // to every 74HC595 pin 10
/* display values for 7 segemnt LEDs digits 0-9, 
   characters 0-F and Decimal Point */
const byte seg[] = {63,6,91,79,102,109,125,7,127,
const byte dp = 128; // Decimal Point again

void setup() {
  Serial.begin(9600);    // enable for debugging
  Serial.println("Countdown begins here");
  // Set pins as outputs
  pinMode(SER, OUTPUT);
  pinMode(LATCH, OUTPUT);
  pinMode(CLK, OUTPUT);
  digitalWrite(LATCH, LOW);
  shiftOut(SER, CLK, MSBFIRST, 0);      // All seg. off
  shiftOut(SER, CLK, MSBFIRST, 0);      // All seg. off
  // uncomment one or two lines to test displays
  // shiftOut(SER, CLK, MSBFIRST, 1);   // A  Segment
  // shiftOut(SER, CLK, MSBFIRST, 2);   // B  Segment
  // shiftOut(SER, CLK, MSBFIRST, 4);   // C  Segment
  // shiftOut(SER, CLK, MSBFIRST, 8);   // D  Segment
  // shiftOut(SER, CLK, MSBFIRST, 16);  // E  Segment
  // shiftOut(SER, CLK, MSBFIRST, 32);  // F  Segment
  // shiftOut(SER, CLK, MSBFIRST, 64);  // G  Segment
  // shiftOut(SER, CLK, MSBFIRST, 128); // Dp Segment
  // shiftOut(SER, CLK, MSBFIRST, 63);  // 0 Digit
  // shiftOut(SER, CLK, MSBFIRST, 6);   // 1 Digit
  // shiftOut(SER, CLK, MSBFIRST, 91);  // 2 Digit
  // shiftOut(SER, CLK, MSBFIRST, 79);  // 3 Digit
  // shiftOut(SER, CLK, MSBFIRST, 102); // 4 Digit
  // shiftOut(SER, CLK, MSBFIRST, 109); // 5 Digit
  // shiftOut(SER, CLK, MSBFIRST, 125); // 6 Digit
  // shiftOut(SER, CLK, MSBFIRST, 7);   // 7 Digit
  // shiftOut(SER, CLK, MSBFIRST, 127); // 8 Digit
  // shiftOut(SER, CLK, MSBFIRST, 111); // 9 Digit
  // shiftOut(SER, CLK, MSBFIRST, 119); // 'A' Character
  // shiftOut(SER, CLK, MSBFIRST, 124); // 'b' Character
  // shiftOut(SER, CLK, MSBFIRST, 57);  // 'C' Character
  // shiftOut(SER, CLK, MSBFIRST, 94);  // 'd' Character
  // shiftOut(SER, CLK, MSBFIRST, 121); // 'E' Character
  // shiftOut(SER, CLK, MSBFIRST, 113); // 'F' Character 
  digitalWrite(LATCH, HIGH);  

void loop() {
 for (byte i = 0; i <=99; i++) {
  digitalWrite(LATCH, LOW);
  shiftOut(SER, CLK, MSBFIRST, seg[i%10]);    // ones
  if (i > 9) {
   shiftOut(SER, CLK, MSBFIRST, seg[i/10]);   // tens  
  } else {
    // turn tens segment off if count is less than 10
    shiftOut(SER, CLK, MSBFIRST, 0); 
  digitalWrite(LATCH, HIGH);
  delay(1000); // wait a second before incrementing
 digitalWrite(LATCH, LOW);
 shiftOut(SER, CLK, MSBFIRST, dp);  // decimal point
 digitalWrite(LATCH, HIGH);
 delay(2000); // 2 second delay before restarting loop


You can follow any responses to this entry through the RSS 2.0 feed. Both comments and pings are currently closed.