Arduino Clock with 7-Seg LED, DS1307 & 74HC595

Finally made my first useful application for Arduino after so many breadboard prototyping - a 4 digit clock.

It is made using an Arduino, DS1307 realtime clock, four 35mm 7-segments LEDs and driven by four 74HC595 shift registers.

The fun part of this is that I can customize the behavior of the display like blinks or scrolls, add sensors or relays, do time related functions ...

Wiring is a bit messy... I have not acquired the skills to etch my own PCB yet... I take one small steps at a time...

Most of the shift register codes are taken from Paul site :- http://www.sqlskills.com/blogs/paulselec/post/Arduino-cascading-shift-registers-to-drive-7-segment-displays.aspx

Needed 7 220R to get consistency LED brightness...

The battery holder is a bit big and took up a lot of real estate on the veroboard...

Details article about the Arduino clock on my blog : http://arduino-for-beginners.blogspot.com/

Cool - glad you found my page useful!

Hi Stanley, could you possibly post the sketch/code up?
Many thanks
Warren

PS> Looks good! :slight_smile:

Here is the sketch :-

Realtime clock with 74595 shift registers on 7-segment LED common cathode.

Stanley

/* 
 Original sketch from Paul Electronics 7-segment shift register posting
 RTC libraries from http://jeelabs.net/projects/cafe/wiki/RTClib
 Setting realtime clock on-compile was from Ladyada.net
 
 Pin assignment on the 74595 to 7-segment common cathode as follows :-
 
 QA - a
 QB - b
 QC - c
 QD - d
 QE - e
 QF - f
 QG - g
 
 3 & 8 are common cathode
 resistors is 220R
 
 I just combine both the codes together and make it work...
 
 Can add in temp sensors or a piezo for hourly chime
 
 Stanley 
 http://arduino-for-beginners.blogspot.com
 
 
 */

#include <Wire.h>
#include "RTClib.h"
const int  g_pinData = 10;
const int  g_pinCommLatch = 11;
const int  g_pinClock = 12;
const int ledPin = 13;

RTC_DS1307 RTC;

// Definitions of the 7-bit values for displaying digits
byte g_digits [10];

// Current number being displayed
int g_numberToDisplay = 0;

// Number of shift registers in use
const int g_registers = 4;

// Array of numbers to pass to shift registers
byte g_registerArray [g_registers];

void setup()
{

  Wire.begin();
  RTC.begin();

  // Only set the time on compile if the RTC is not running...
  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(__DATE__, __TIME__));
  }

  pinMode (g_pinCommLatch, OUTPUT);
  pinMode (g_pinClock, OUTPUT);
  pinMode (g_pinData, OUTPUT);
  pinMode (speakerPin, OUTPUT);
  pinMode (ledPin, OUTPUT);
  
  Serial.begin (9600);

  int a = 1, b = 2, c = 4, d = 8, e = 16, f = 32, g = 64;

  g_digits [0] = a + b + c + d +e + f;
  g_digits [1] = b + c;
  g_digits [2] = a + b + g + e + d;
  g_digits [3] = a + b + g + c + d;
  g_digits [4] = f + g + b + c;
  g_digits [5] = a + f + g + c + d;
  g_digits [6] = a + f + g + c + d + e;
  g_digits [7] = a + b + c;
  g_digits [8] = a + b + c + d + e + f + g;
  g_digits [9] = a + b + c + d + g + f;


} // setup

// Simple function to send serial data to one or more shift registers by iterating backwards through an array.
// Although g_registers exists, they may not all be being used, hence the input parameter.
void sendSerialData (
byte registerCount,  // How many shift registers?
byte *pValueArray)   // Array of bytes with LSByte in array [0]
{
  // Signal to the 595s to listen for data
  digitalWrite (g_pinCommLatch, LOW);

  for (byte reg = registerCount; reg > 0; reg--)
  {
    byte value = pValueArray [reg - 1];

    for (byte bitMask = 128; bitMask > 0; bitMask >>= 1)
    {
      digitalWrite (g_pinClock, LOW);
      digitalWrite (g_pinData, value & bitMask ? HIGH : LOW);
      digitalWrite (g_pinClock, HIGH);
    }
  }
  // Signal to the 595s that I'm done sending
  digitalWrite (g_pinCommLatch, HIGH);
}  // sendSerialData

// Print a message specifying valid inputs, given the number of registers defined and then consume all current input.
void badNumber ()
{
  int dummy;

  Serial.print ("Please enter a number from 0 to ");
  for (int loop = 0; loop < g_registers; loop++)
  {
    Serial.print ("9");
  }
  Serial.println (" inclusive.");

  while (Serial.available () > 0)
  {
    dummy = Serial.read ();
    delay (10);
  }
} //badNumber

// Read a number from the PC with no more digits than the defined number of registers.
// Returns: number to display. If an invalid number was read, the number returned is the current number being displayed
//
int readNumberFromPC ()
{
  byte incomingByte;
  int  numberRead;
  byte incomingCount;

  if (Serial.available () > 0)
  {
    numberRead = 0;
    incomingCount = 0;

    while (Serial.available () > 0)
    {
      incomingByte = Serial.read () - 48;
      incomingCount++;

      if (incomingByte < 0 || incomingByte > 9 || incomingCount > g_registers)
      {
        badNumber ();
        return g_numberToDisplay;
      }

      numberRead = 10 * numberRead + incomingByte;

      // Necessary to get all input in one go.
      delay (10);
    }

    Serial.print ("Now displaying: ");
    Serial.println (numberRead, DEC);

    return numberRead;
  }

  return g_numberToDisplay;
} // readNumberFromPC


void loop()
{
  int hour,minute,sec,disp = 0;

  DateTime now = RTC.now();

  hour = now.hour();
  minute = now.minute();
  sec = now.second();

  /* Serial output debugging for the date & time 
  
   Serial.print(now.year(), DEC);
   Serial.print('/');
   Serial.print(now.month(), DEC);
   Serial.print('/');
   Serial.print(now.day(), DEC);
   Serial.print(' ');
 
   Serial.print(hour);
   Serial.print(':');
   Serial.print(minute);
   Serial.print(':');    
   Serial.print(sec);
   Serial.println();
  */
  
  // Original code
  //g_numberToDisplay = readNumberFromPC ();
  
  
  // Push the hour 2 digits to the left by multiplying 100
  disp = (hour * 100) + minute;
  g_numberToDisplay = disp;

  if (g_numberToDisplay < 10)
  {
    g_registerArray [0] = g_digits [0];
    g_registerArray [1] = g_digits [0];
    g_registerArray [2] = g_digits [0];
    g_registerArray [3] = g_digits [g_numberToDisplay];
  }
  else if (g_numberToDisplay < 100)
  {
    g_registerArray [0] = g_digits [0];
    g_registerArray [1] = g_digits [0];
    g_registerArray [2] = g_digits [g_numberToDisplay / 10];
    g_registerArray [3] = g_digits [g_numberToDisplay % 10];
  }
  else if (g_numberToDisplay < 1000)
  {
    g_registerArray [0] = g_digits [0];
    g_registerArray [1] = g_digits [g_numberToDisplay / 100];
    g_registerArray [2] = g_digits [(g_numberToDisplay % 100) / 10];
    g_registerArray [3] = g_digits [g_numberToDisplay % 10];
  }
  else
  {
    g_registerArray [0] = g_digits [g_numberToDisplay / 1000];
    g_registerArray [1] = g_digits [(g_numberToDisplay % 1000) / 100];
    g_registerArray [2] = g_digits [(g_numberToDisplay % 100) / 10];
    g_registerArray [3] = g_digits [g_numberToDisplay % 10];
  }

  sendSerialData (g_registers, g_registerArray);
  
  // Blink the LED to indicate seconds
  digitalWrite(ledPin,HIGH);
  delay(500);
  digitalWrite(ledPin,LOW);
  delay(500);

} // loop

Nice.

This picture with this gave me an idea. That bike is the Victory Cross Country, I plan on getting that next year. I noticed how well the LEDs reflected off of the windshield. So that got me thinking, 7 segment display, GPS, and Arduino I could make a HUD. Include a button to toggle between time and speed.

this is mine version

*read the description

Nice clock on the fireplace :slight_smile:

I should have go for 6 digits instead of four!!!

I modified mine to include a DHT11 temp/relative humidity sensor that will be display for 1 sec each every 10 secs.

I also display the voltage of the SecretVoltmeter as I find that using different 5V power source, like USB power, linear regulated power supply, mobile phone charger and switching power supply, it gives a different temp reading relative of the input voltage.