IT ISATENHALF
QUARTERTWENTY
FIVE MINUTES
PASTTO ONETWO
THREEFOURFIVE
SIXSEVENEIGHT
NINETENELEVEN
TWELVE OCLOCK
Since I decided on a proportional font, I had room for the extra word/letter A in the first row. I also added in some spaces. If you go with a fixed-width font, you would need to remove the A and all the spaces. I created this SVG to guide my stencil, printed it, and glued it to some thick cardboard. I then drilled holes into the center of each letter that will hold an LED for each letter. I also printed the stencil in reverse and used some rubber cement to temporarily glue the stencil to a thick piece of black oak tag paper, which will make the clock face. I used an x-acto knife to cut out each letter. This was a time consuming endeavor, to say the least. Be sure to save the middle cutouts for any letters that have one, so they can be glued back in during the final assembly.reg pin
0 0 IT IS
0 1 A
0 2 TEN
0 3 HALF
0 4 QUARTER
0 5 TWENTY
0 6 FIVE
0 7 MINUTES
1 0 PAST
1 1 TO
1 2 ONE
1 3 TWO
1 4 THREE
1 5 FOUR
1 6 FIVE
1 7 SIX
2 0 SEVEN
2 1 EIGHT
2 2 NINE
2 3 TEN
2 4 ELEVEN
2 5 TWELVE
2 6 OCLOCK
For all: IT IS OCLOCK 0-0, 2-6
1:00 IT IS ONE OCLOCK N
1:05 IT IS FIVE MINUTES PAST ONE OCLOCK 0-6, 1-0, N
1:10 IT IS TEN MINUTES PAST ONE OCLOCK 0-2, 0-7, 1-0, N
1:15 IT IS A QUARTER PAST ONE OCLOCK 0-1, 0-4, 1-0, N
1:20 IT IS TWENTY MINUTES PAST ONE OCLOCK 0-5, 0-7, 1-0, N
1:25 IT IS TWENTY FIVE MINUTES PAST ONE OCLOCK 0-5, 0-6, 0-7, 1-0, N
1:30 IT IS HALF PAST ONE OCLOCK 0-3, 1-0, N
1:35 IT IS TWENTY FIVE MINUTES TO TWO OCLOCK 0-5, 0-6, 0-7, 1-1, N+1
1:40 IT IS TWENTY MINUTES TO TWO OCLOCK 0-5, 0-7, 1-1, N+1
1:45 IT IS A QUARTER TO TWO OCLOCK 0-1, 0-4, 1-1, N+1
1:50 IT IS TEN MINUTES TO TWO OCLOCK 0-2, 0-7, 1-1, N+1
1:55 IT IS FIVE MINUTES TO TWO OCLOCK 0-6, 0-7, 1-1, N+1
2:00 IT IS TWO OCLOCK N
#include < wire.h >
#include "RTClib.h"
RTC_DS1307 RTC;
// Pin connected to ST_CP of 74HC595
int latchPin = 8;
// Pin connected to SH_CP of 74HC595
int clockPin = 12;
// Pin connected to DS of 74HC595
int dataPin = 11;
// Holders for information you're going to pass to shifting function
byte dataArray[10];
byte dataToSend[3];
void setup() {
// Set pins to output because they are addressed in the main loop
pinMode(latchPin, OUTPUT);
Serial.begin(9600);
Wire.begin();
RTC.begin();
// Set pins A2 and A3 so we can power the RTC breakout directly from each
pinMode(A2, OUTPUT);
digitalWrite(A2, LOW);
pinMode(A3, OUTPUT);
digitalWrite(A3, HIGH);
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__));
}
// These are the bitmasks used to set the shift registers
// states 0 - 7 set one of each of the pins to be on
// state 8 turns all the pins on, and state 9 sets them all off
dataArray[0] = 0x01; //00000001
dataArray[1] = 0x02; //00000010
dataArray[2] = 0x04; //00000100
dataArray[3] = 0x08; //00001000
dataArray[4] = 0x10; //00010000
dataArray[5] = 0x20; //00100000
dataArray[6] = 0x40; //01000000
dataArray[7] = 0x80; //10000000
dataArray[8] = 0xFF; //11111111
dataArray[9] = 0x00; //00000000
// Function that blinks all the LEDs, feel free to eliminate...
// I got it directly from the Arduino ShiftOut tutorial and kept it in
blinkAll_2Bytes(2,500);
// Just runs through all the clock states each time its powered on...
// Feel free to eliminate
testAllStates();
}
void loop()
{
// Get the current hour and minute
DateTime now = RTC.now();
int hour = now.hour();
int min = now.minute();
// Print statements for debugging
/*
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.println();
*/
// We need to set the latch to 0 before each set of pin writes
digitalWrite(latchPin, 0);
// IT IS and OCLOCK are lit in all states
// Also initialize register 1 to 0's
dataToSend[0] = dataArray[0];
dataToSend[1] = dataArray[9];
dataToSend[2] = dataArray[6];
// Add bytes needed to light other pins
if(min < 5)
{
//1:00 IT IS ONE OCLOCK
// no need to light anything else
}
else if(min < 10)
{
//1:05 IT IS FIVE MINUTES PAST ONE OCLOCK
dataToSend[0] += dataArray[6];
dataToSend[1] += dataArray[0];
}
else if(min < 15)
{
//1:10 IT IS TEN MINUTES PAST ONE OCLOCK
dataToSend[0] += dataArray[2] + dataArray[7];
dataToSend[1] += dataArray[0];
}
else if(min < 20)
{
//1:15 IT IS A QUARTER PAST ONE OCLOCK
dataToSend[0] += dataArray[1] + dataArray[4];
dataToSend[1] += dataArray[0];
}
else if(min < 25)
{
//1:20 IT IS TWENTY MINUTES PAST ONE OCLOCK
dataToSend[0] += dataArray[5] + dataArray[7];
dataToSend[1] += dataArray[0];
}
else if(min < 30)
{
//1:25 IT IS TWENTY FIVE MINUTES PAST ONE OCLOCK
dataToSend[0] += dataArray[5] + dataArray[6] + dataArray[7];
dataToSend[1] += dataArray[0];
}
else if(min < 35)
{
//1:30 IT IS HALF PAST ONE OCLOCK
dataToSend[0] += dataArray[3];
dataToSend[1] += dataArray[0];
}
else if(min < 40)
{
//1:35 IT IS TWENTY FIVE MINUTES TO TWO OCLOCK
dataToSend[0] += dataArray[5] + dataArray[6] + dataArray[7];
dataToSend[1] += dataArray[1];
}
else if(min < 45)
{
//1:40 IT IS TWENTY MINUTES TO TWO OCLOCK
dataToSend[0] += dataArray[5] + dataArray[7];
dataToSend[1] += dataArray[1];
}
else if(min < 50)
{
//1:45 IT IS A QUARTER TO TWO OCLOCK
dataToSend[0] += dataArray[1] + dataArray[4];
dataToSend[1] += dataArray[1];
}
else if(min < 55)
{
//1:50 IT IS TEN MINUTES TO TWO OCLOCK
dataToSend[0] += dataArray[2] + dataArray[7];
dataToSend[1] += dataArray[1];
}
else if(min < 60)
{
//1:55 IT IS FIVE MINUTES TO TWO OCLOCK
dataToSend[0] += dataArray[6] + dataArray[7];
dataToSend[1] += dataArray[1];
}
// Set hour register and pin
if(min < 35)
{
int reg = getHourRegister(hour);
int pin = getHourPin(hour);
dataToSend[reg] += dataArray[pin];
}
else
{
int reg = getHourRegister(hour + 1);
int pin = getHourPin(hour + 1);
dataToSend[reg] += dataArray[pin];
}
shiftOut(dataPin, clockPin, dataToSend[0]);
shiftOut(dataPin, clockPin, dataToSend[1]);
shiftOut(dataPin, clockPin, dataToSend[2]);
digitalWrite(latchPin, 1);
delay(5000);
}
// the heart of the program
void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {
// This shifts 8 bits out MSB first,
//on the rising edge of the clock,
//clock idles low
//internal function setup
int i=0;
int pinState;
pinMode(myClockPin, OUTPUT);
pinMode(myDataPin, OUTPUT);
//clear everything out just in case to
//prepare shift register for bit shifting
digitalWrite(myDataPin, 0);
digitalWrite(myClockPin, 0);
//for each bit in the byte myDataOut
//NOTICE THAT WE ARE COUNTING DOWN in our for loop
//This means that %00000001 or "1" will go through such
//that it will be pin Q0 that lights.
for (i=7; i>=0; i--) {
digitalWrite(myClockPin, 0);
//if the value passed to myDataOut and a bitmask result
// true then... so if we are at i=6 and our value is
// %11010100 it would the code compares it to %01000000
// and proceeds to set pinState to 1.
if ( myDataOut & (1<<i) ) {
pinState= 1;
}
else {
pinState= 0;
}
//Sets the pin to HIGH or LOW depending on pinState
digitalWrite(myDataPin, pinState);
//register shifts bits on upstroke of clock pin
digitalWrite(myClockPin, 1);
//zero the data pin after shift to prevent bleed through
digitalWrite(myDataPin, 0);
}
//stop shifting
digitalWrite(myClockPin, 0);
}
//blinks the whole register based on the number of times you want to
//blink "n" and the pause between them "d"
//starts with a moment of darkness to make sure the first blink
//has its full visual effect.
void blinkAll_2Bytes(int n, int d)
{
digitalWrite(latchPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
digitalWrite(latchPin, 1);
delay(200);
for (int x = 0; x < n; x++)
{
digitalWrite(latchPin, 0);
shiftOut(dataPin, clockPin, 255);
shiftOut(dataPin, clockPin, 255);
digitalWrite(latchPin, 1);
delay(d);
digitalWrite(latchPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
digitalWrite(latchPin, 1);
delay(d);
}
}
// Returns the register used for the hour word
int getHourRegister(int hour)
{
if(hour > 12)
{
hour-=12;
}
if(hour <= 6)
{
return 1;
}
return 2;
}
// Returns the pin output for the hour word
int getHourPin(int hour)
{
if(hour > 12)
{
hour-=12;
}
if(hour == 1)
{
return 2;
}
else if(hour == 2)
{
return 3;
}
else if(hour == 3)
{
return 4;
}
else if(hour == 4)
{
return 5;
}
else if(hour == 5)
{
return 6;
}
else if(hour == 6)
{
return 7;
}
else if(hour == 7)
{
return 0;
}
else if(hour == 8)
{
return 1;
}
else if(hour == 9)
{
return 2;
}
else if(hour == 10)
{
return 3;
}
else if(hour == 11)
{
return 4;
}
else if(hour == 12)
{
return 5;
}
}
// Mostly cut and paste from above
int testAllStates()
{
int min = 0;
int hour = 12;
while(min < 60)
{
digitalWrite(latchPin, 0);
dataToSend[0] = dataArray[0];
dataToSend[1] = dataArray[9];
dataToSend[2] = dataArray[6];
// Add bytes needed to light other pins
if(min < 5)
{
//1:00 IT IS ONE OCLOCK
// no need to light anything else
}
else if(min < 10)
{
//1:05 IT IS FIVE MINUTES PAST ONE OCLOCK
dataToSend[0] += dataArray[6];
dataToSend[1] += dataArray[0];
}
else if(min < 15)
{
//1:10 IT IS TEN MINUTES PAST ONE OCLOCK
dataToSend[0] += dataArray[2] + dataArray[7];
dataToSend[1] += dataArray[0];
}
else if(min < 20)
{
//1:15 IT IS A QUARTER PAST ONE OCLOCK
dataToSend[0] += dataArray[1] + dataArray[4];
dataToSend[1] += dataArray[0];
}
else if(min < 25)
{
//1:20 IT IS TWENTY MINUTES PAST ONE OCLOCK
dataToSend[0] += dataArray[5] + dataArray[7];
dataToSend[1] += dataArray[0];
}
else if(min < 30)
{
//1:25 IT IS TWENTY FIVE MINUTES PAST ONE OCLOCK
dataToSend[0] += dataArray[5] + dataArray[6] + dataArray[7];
dataToSend[1] += dataArray[0];
}
else if(min < 35)
{
//1:30 IT IS HALF PAST ONE OCLOCK
dataToSend[0] += dataArray[3];
dataToSend[1] += dataArray[0];
}
else if(min < 40)
{
//1:35 IT IS TWENTY FIVE MINUTES TO TWO OCLOCK
dataToSend[0] += dataArray[5] + dataArray[6] + dataArray[7];
dataToSend[1] += dataArray[1];
}
else if(min < 45)
{
//1:40 IT IS TWENTY MINUTES TO TWO OCLOCK
dataToSend[0] += dataArray[5] + dataArray[7];
dataToSend[1] += dataArray[1];
}
else if(min < 50)
{
//1:45 IT IS A QUARTER TO TWO OCLOCK
dataToSend[0] += dataArray[1] + dataArray[4];
dataToSend[1] += dataArray[1];
}
else if(min < 55)
{
//1:50 IT IS TEN MINUTES TO TWO OCLOCK
dataToSend[0] += dataArray[2] + dataArray[7];
dataToSend[1] += dataArray[1];
}
else if(min < 60)
{
//1:55 IT IS FIVE MINUTES TO TWO OCLOCK
dataToSend[0] += dataArray[6] + dataArray[7];
dataToSend[1] += dataArray[1];
}
// Set hour register and pin
if(min < 35)
{
int reg = getHourRegister(hour);
int pin = getHourPin(hour);
dataToSend[reg] += dataArray[pin];
}
else
{
int reg = getHourRegister(hour + 1);
int pin = getHourPin(hour + 1);
dataToSend[reg] += dataArray[pin];
}
shiftOut(dataPin, clockPin, dataToSend[0]);
shiftOut(dataPin, clockPin, dataToSend[1]);
shiftOut(dataPin, clockPin, dataToSend[2]);
digitalWrite(latchPin, 1);
delay(200);
min+=1;
}
}
Next the LEDs need to be hooked up to the Arduino driver board. Lots of wires, lots of fun!Posted: Dec 24, 2013
Keyword tags: arduinoelectronicsclockRTCshift registers
S3 Buckets: Now With Both Leak & Fill Vulnerability
Stealing Data With CSS: Attack and Defense
Move Over S3: Open Directory Indexes Continue to be a Problem
Security Researchers Lose a Favorite DNS Recon Tool Jan 2018
KRACK: How To Protect Yourself on a Flawed Network
Equifax, SEC, & Now Deloitte: Organizations Must Employ Offensive Security