Instructables
This is a relatively simple clock to build, in terms of the hardware required and in terms of hooking up all the wires. The complexity lies in the software, which I've conveniently included as part of this instructable :)

This instructable illustrates a few things:
* Keeping relatively accurate time on an Arduino without using a real time clock (RTC)
* Using a basic clock display - the type you see on most alarm clocks. In this case an LTC-617.
* Multiplexing a display to make it appear all digits are shown at once, even though the display only display one digit at a time.
* Controlling the brightness of individual digits (more LEDs on = dimmer digit)

I originally built this for a different platform, and decided it was time to port it to Arduino!

I hope you enjoy this instructable and find it useful - it makes a great start for so many evil project possibilities!
 
Remove these adsRemove these ads by Signing Up

Step 1: Parts

For this Instructable, you will need:

1 Arduino (I used an Arduino-nano)
1 LTC-617 clock display (you might need to solder male headers onto it)
many jumper wires
1 button
1 resistor: 10k or close (to prevent short between gnd and 5v on button press)

For me this was a no-cost project as I already had all the parts.
The clock display was part of a grab bag I bought long ago. I imagine they should be very inexpensive and might even be salvageable from old clock radios.
Little buttons and resistors are also salvageable from old electronics (reset buttons from old computers, for example), and also very inexpensive to purchase.
The Arduino starts at around $15 on eBay, though I would expect anyone would be unlikely to ever use it for only just this one project!

I used a breadboard for easy connections, but that's not necessary. 


Step 2: About the LTC-617 Clock Display

Picture of About the LTC-617 Clock Display
I received several of these displays in a grab bag of electronics a few years ago, so I decided to put one to use.

This particular display does not have any smarts added to it. All of the pins go directly to the LEDs in the display. That means the smarts have to come from the software that controls the display.

You'll notice from the attached picture that each of the 4 digits is controlled by a single IO line, and all digits share the IO lines for the individual 7 segments. Which means that you cannot have two different digits shown at the same time.
To get around that limitation, we use the Arduino to show each digit for just a fraction of a second. When this is done repeatedly and fast enough, our eyes just see one steady display. In the code you can change the timing to make it blink each digit more slowly, if you wish to see how it works.

You could save some I/O pins and software complexity by using a 4511 binary (BCD) to 7-segment decoder, which allows you to use 3 Arduino pins to send a binary number to the decoder chip, which then does all the work of figuring out which LEDs in the digit to light up.
Here is a good link explaining how the decoder chip works: http://www.doctronics.co.uk/4511.htm
That link also contains the logic table that shows which segments need to be on for any given number. I used something similar to this when I was building my software.

So what was the point of all that? My point is just that different displays will behave differently and the code would need to be modified accordingly.

Step 3: Make the connections

There are quite a few wires that need to be hooked up, but if you go carefully and double check each line as you hook it up, it should be pretty straightforward.

I'm assuming you already know the basics of getting your Arduino going, so I won't get into those details. If not, there are a lot of nice examples online to get you started (I like the ones at oomlout.com).

Here are the connections that need to be made. On the left is the pin of the LTC, on the right is the Arduino pin. For example, LTC pin 4 is connected to Arduino pin digital7. nc means that pin of the LTC is not connected to anything.

The button is connected in the usual buttony way using a pull-down resistor which connects the pin to gnd for LOW, and the button when pressed connects it to 5v for HIGH. As a side effect, pressing the button also connects 5v to gnd, which is why we need that 10k resistor to keep it from being a short.

LTC - Arduino
1 - nc
2 - nc
3 - nc
4 - d7
5 - d3
6 - d2
7 - d11
8 - d10
9 - d4
10 - gnd
22 - d9
23 - d5
24 - d6
25 - A0  // because d13 already has a built-in LED getting in the way
26 - d8
27 - d12
28 - A1
29 - gnd

button:
5v - button - A4 - 10k resistor - gnd

I didn't have space near the Arduino, so in the picture you'll see that the button is connected through a few extra jumper wires.

Note that pin 1 on the clock display is at the bottom left (the pins are under the display area), and every hole counts, even the ones that don't have any connections. On this LTC display, "pins" 11 to 21 are just holes.

Step 4: Install (upload) the software

Picture of Install (upload) the software
The final step is to download the attached software sketch, and upload it to your Arduino.

Viola - we have a clock!

You can press the button to set the time. Hold the button down to set it quickly. If you hold it for longer than 5 seconds, it will go 10 times as fast.

The centre hour:minute colon blinks for the seconds.

The software has some comments to help you figure it out, but essentially it keeps track of time by checking the value of millis(), and every time 1000 millis have gone by it increments 1 second. Millis() returns the number of milliseconds since startup.

Obviously this won't be as accurate as using a real time clock (RTC), but it's good enough for plenty of fun projects involving time.

You'll notice that I remove 1,000 from the time tracking variable, rather than resetting to the current millis() - this helps it remain quite accurate. The code that updates the time will take some time to run, and the clock would lose a few milliseconds every time we do that. This way keeps it compared to the original start time and the accuracy depends on the accuracy of millis(), which I would guess is fairly decent.
Also, using a delay() to count to the next second would block the chip from other things, like detecting the button press.

ps, for the button code I heavily borrowed from the basic button example that comes with the Arduino software. My use is slightly different, but I debounce it in the same way.

I also noticed that different digits had different brightnesses - for example, the digit one has 2 LEDs lit, while 8 has 7 LEDs - lighting 7 LEDs at the same time makes it a fair bit dimmer. To compensate, I simply keep each digit on for a set amount of time multiplied by the number of segments in that digit.

Enjoy!

jukees1 year ago
here are the wiring instructions if some one (like me) does not have the ltc-617.
A d7
B d8
C d9
D d10
E d11
F d12
G A0
Colon d4
digit1 d2
digit2 d3
digit3 d5
digit4 d6
jukees1 year ago
i have completed this instructable using 4 7 segment screens,
i have also modified the code, so it's 24 hour clock.
if anyone wants the new code, let me know.
Great instructable BTW.
kello.JPG
anachum jukees9 months ago
Hi Jukees,
sure, can you send me your code for the 24H, do you have a schematics as well?
have you implemented RTC?
tnx so much
Amos

if you wan't implement RTC check this : http://www.instructables.com/id/Arduino-based-clock/

ntewinkel (author)  jukees1 year ago
Great job, Jukees!!
Thanks for sharing the picture :)
jojox1 year ago
Hi
I did some tests, with
lastTime += 998;,
there is no further delay, I can make the circuit.

I changed the polarity of the display by changing

#define ON HIGH
#define OFF LOW

by

#define ON LOW
#define OFF HIGH

it's easier than taking all lines "digitalWrite"

Thank you again for this great subject.

Joël
ntewinkel (author)  jojox1 year ago
Excellent, that's good to know.

ps, the millis() call resets back to 0 after about 50 days, which I think will cause this clock to just stop at that point.
jojox1 year ago
Hi Nico
Thank you for your answer, I think has a RTC but I wanted to test this clock because I could make a miniature circuit. Essary your suggestion I'll thank you again.

Good lock
Joël
jojox1 year ago
Hello,

Super thank you project!

I had already changed the code to pass a 24h everything is ok apart my clock takes about 2 minutes late around 7am. I'm searching I can not find the solution, someone else will this problem?

Thank you in advance
ntewinkel (author)  jojox1 year ago
Hi Jojox,

The basic timing on the Arduino isn't designed to keep time accurately, unfortunately.

You can keep accurate time by using a Real Time Clock (RTC) unit and the Arduino Time library, but this project isn't set up to use that.

You could make the clock run faster by changing the "1000" to a lower value for this line:

lastTime += 1000;

So you might try using 998 or 999.
Or every minute include an adjustment to add or subtract from lastTime.

Good luck, and enjoy :)
Cheers,
-Nico
Niels_L1 year ago
Nice Thanks Jukees
Niels_L1 year ago
Will you post the code for 24 hours clock, please ??
And if you have the diagram on how you connect the 7 seg display ??
Thanks
jukees Niels_L1 year ago
/*
Arduino clock on a standard 4-digit clock display
Uses a Liteon LTC-617D1G clock display

Connections:
LTC - Arduino
1 - nc
2 - nc
3 - nc
4 - d7
5 - d3
6 - d2
7 - d11
8 - d10
9 - d4
10 - gnd
22 - d9
23 - d5
24 - d6
25 - A0 // because d13 already has a built-in LED getting in the way
26 - d8
27 - d12
28 - A1
29 - gnd

button:
5v - button - A4 - 10k resistor - gnd

*/

#define DIGIT1 2
#define DIGIT2 3
#define DIGIT3 5
#define DIGIT4 6

#define SEGMENTA 7
#define SEGMENTB 8
#define SEGMENTC 9
#define SEGMENTD 10
#define SEGMENTE 11
#define SEGMENTF 12
#define SEGMENTG A0

#define COLON 4
#define AMPM A1

#define BUTTON A4

#define ON HIGH
#define OFF LOW

#define DELAYTIME 50

unsigned short hours, minutes, seconds;
boolean pm;
unsigned long lastTime; // keeps track of when the previous second happened

int buttonState; // the current reading from the button pin
int lastButtonState = LOW; // the previous reading from the button pin
unsigned long button_down_start = 0; // how long the button was held down
unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
unsigned long debounceDelay = 50; // the debounce time

void setup() {
// initialize all the required pins as output.
pinMode(DIGIT1, OUTPUT);
pinMode(DIGIT2, OUTPUT);
pinMode(DIGIT3, OUTPUT);
pinMode(DIGIT4, OUTPUT);

pinMode(SEGMENTA, OUTPUT);
pinMode(SEGMENTB, OUTPUT);
pinMode(SEGMENTC, OUTPUT);
pinMode(SEGMENTD, OUTPUT);
pinMode(SEGMENTE, OUTPUT);
pinMode(SEGMENTF, OUTPUT);
pinMode(SEGMENTG, OUTPUT);

pinMode(COLON, OUTPUT);
pinMode(AMPM, OUTPUT);

// button is input
pinMode(BUTTON, INPUT);

// set the initial time
hours = 9;
minutes = 7;
seconds = 0;
pm = true;

lastTime = millis();
}

void loop() {

// Keep showing the display while waiting for timer to expire
while (millis() - lastTime < 1000) {
clock_show_time(hours, minutes);

// blink the colon, every even second
if (seconds % 2 == 0) {
clock_show_colon();
}

// button presses increase minutes
int reading = digitalRead(BUTTON);

// If the switch changed, due to noise or pressing:
if (reading != lastButtonState) {
// reset the debouncing timer
lastDebounceTime = millis();
}

if ((millis() - lastDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer
// than the debounce delay, so take it as the actual current state:

if (buttonState != reading) {
button_down_start = millis(); // record the start of the current button state
}

buttonState = reading;

// buttonState is now either on or off
if (buttonState == HIGH) {
// if the button was held down more than 5 seconds, make it go faster
if ((millis() - button_down_start) > 5000) {
seconds += 10;
if (seconds > 59) seconds = 59;
}

// button has been pressed
incrementTime();
}
}

lastButtonState = reading;
}

lastTime += 1000;

incrementTime();
}

//
// a call to incrementTime increases time by one second.
//
void incrementTime() {

if (seconds == 59) {
seconds = 0;

if (minutes == 59) {
minutes = 0;

if (hours == 23) {
hours = 0;
}
else {
hours++;

if (hours == 12) {
pm = !pm;
}
}
}
else {
minutes++;
}
}
else {
seconds++;
}
}

//
// clock_show_time - displays the given time on the clock display
// Note that instead of hr/min the user can also send min/sec
// Maximum hr is 99, Maximum min is 59, and minimum is 0 for both (it's unsigned, heh).
//
void clock_show_time(unsigned short hours, unsigned short minutes) {
unsigned short i;
unsigned short delaytime;
unsigned short num_leds[10] = { 6, 2, 5, 5, 4, 5, 6, 3, 7, 6 };
unsigned short digit[4];
unsigned short hide_leading_hours_digit;

// convert minutes and seconds into the individual digits
// check the boundaries
if (hours > 99) hours = 99;
if (minutes > 59) minutes = 59;

// convert hr
if (hours < 10 && hours > 0) {
hide_leading_hours_digit = 1;
}
else {
hide_leading_hours_digit = 0;
}

digit[0] = hours / 10;
digit[1] = hours % 10; // remainder
digit[2] = minutes / 10;
digit[3] = minutes % 10; // remainder

for (i = hide_leading_hours_digit; i < 4; i++) {
clock_all_off();
clock_show_digit(i, digit[i]);

// fewer leds = brighter display, so delay depends on number of leds lit.
delaytime = num_leds[digit[i]] * DELAYTIME;
delayMicroseconds(delaytime);
}

clock_all_off();

if (pm) {
clock_show_ampm();
}

clock_all_off();
}

//
// clock_all_off - turns off all the LEDs on the clock to give a blank display
//
void clock_all_off(void) {

// digits must be ON for any LEDs to be on
digitalWrite(DIGIT1, OFF);
digitalWrite(DIGIT2, OFF);
digitalWrite(DIGIT3, OFF);
digitalWrite(DIGIT4, OFF);

// segments must be OFF for any LEDs to be on
digitalWrite(SEGMENTA, ON);
digitalWrite(SEGMENTB, ON);
digitalWrite(SEGMENTC, ON);
digitalWrite(SEGMENTD, ON);
digitalWrite(SEGMENTE, ON);
digitalWrite(SEGMENTF, ON);
digitalWrite(SEGMENTG, ON);

// turn off colon and alarm too
digitalWrite(COLON, OFF);
digitalWrite(AMPM, OFF);
}

//
// clock_show_digit - turns on the LEDs for the digit in the given position
// position can be from 0 through 3: 0 and 1 being the hour, 2 and 3 being the seconds
// value can be from 0 through 9, ie, a valid single digit.
//
// (if value is out of range, it displays a 9. if digit is out of range display remains blank)
//
void clock_show_digit(unsigned short position, unsigned short value) {
byte a;
byte b;
byte c;
byte d;
byte e;
byte f;
byte g;

switch (position) {
case 0:
digitalWrite(DIGIT1, ON);
break;
case 1:
digitalWrite(DIGIT2, ON);
break;
case 2:
digitalWrite(DIGIT3, ON);
break;
case 3:
digitalWrite(DIGIT4, ON);
break;
}

a = !(value == 1 || value == 4);
b = !(value == 5 || value == 6);
c = !(value == 2);
d = !(value == 1 || value == 4 || value == 7);
e = (value == 0 || value == 2 || value == 6 || value == 8);
f = !(value == 1 || value == 2 || value == 3 || value == 7);
g = !(value == 0 || value == 1 || value == 7);

if (a) digitalWrite(SEGMENTA, OFF);
if (b) digitalWrite(SEGMENTB, OFF);
if (c) digitalWrite(SEGMENTC, OFF);
if (d) digitalWrite(SEGMENTD, OFF);
if (e) digitalWrite(SEGMENTE, OFF);
if (f) digitalWrite(SEGMENTF, OFF);
if (g) digitalWrite(SEGMENTG, OFF);
}

//
// clock_show_colon - shows the colon that separates minutes from seconds
//
void clock_show_colon(void) {
unsigned short delaytime;

digitalWrite(COLON, ON);
// 2 leds = 2 delays needed
delaytime = DELAYTIME * 2; // must use variable to have similar delay to rest of clock
delayMicroseconds(delaytime); // because use of variable slows it down slightly.
digitalWrite(COLON, OFF);
}

//
// clock_show_alarm - shows the ampm dot (bottom right of clock display)
//
void clock_show_ampm(void) {
unsigned short delaytime;

digitalWrite(AMPM, ON);

delaytime = DELAYTIME; // must use variable to have similar delay to rest of clock
delayMicroseconds(delaytime); // because use of variable slows it down slightly.
digitalWrite(AMPM, OFF);
}


The led wiring instructions are the ones written in my comment which you replied, Segments in the led are A B C D E F G, and in the led datasheet you can see what pin is what segment.
Hey,

I want to create your clock and your delightful countdown timer, but I can't seem to find the display you specify anywhere. Any tips on where I might get one or an equivalent replacement?
ntewinkel (author)  RebelWithoutASauce2 years ago
Hi RebelWithoutASauce (great name btw!),

I got mine from Jameco.com as part of a "grab bag" of displays: http://www.jameco.com/webapp/wcs/stores/servlet/Product_10001_10001_18201_-1

I don't see the ltc617 clock display listed anywhere though, which means its likely outdated and probably why they stuffed it in a grab bag.
It's a common anode display, so another common anode clock display would work (although I can't find too many of those either). Here is one at Jameco that would do the trick, but you'd have to move a few wires: http://www.jameco.com/webapp/wcs/stores/servlet/Product_10001_10001_1956549_-1
I saw some on eBay too, but they didn't have pins to light the dots for the clock.

I'm sure other clock displays would work just as well, but may require the wires to be hooked up differently. My first thought was that taking apart an old clock radio would likely work.

The display is pretty basic though - no special ICs in it, just direct connections to each individual LED. In a pinch you could even line up a bunch of individual digits up and connect up the anodes to make them "common" to match the ltc617 spec sheet.

Cheers,
-Nico