Here is the circuit diagram. Each display is the same.
Code (once I have it all working correctly I plan to tidy this up a lot, just want to fix one problem at a time). I borrowed the button check function for testing for a long press (sorry can't remember where on the web I found it :-[). The clock came from Rob Faludi and his open source clock.
/*
Count Down Timer
Usage - Three buttons: Mode, Hour and Minute.
Short press Mode = Start/Pause timer
Long press Mode (2.5sec) = Enter/exit timer setting mode
With timer paused press Minute and Hour together to reset clock
In Timer Setting mode, press Hour/Minute to increment time settings.
*/
#define timeroffest -3 //adjustment for error in timing
#define resetPin 8
#define minutePin 9
#define hourPin 10
#define debounce 50 // ms debounce period to prevent flickering when pressing or releasing the button
#define holdTime 2500 // ms hold period: how long to wait for press+hold event
#define Tserial 4
#define Tclk 6
#define Trck 5
#define dBlank 7 // pin to blank display - low = display off - high = display on
byte character[10] = {
B01000010, B11101110, B11000001, B11000100, B01101100, B01010100, B01010000, B11001110, B01000000, B01001100};
boolean runMode = false;
boolean setMode = false;
boolean run=0, reset=0;
int second=0, minute=0, hour=0; // declare working time variables
int sMin=30, sHour=2; //declare set time variables
void setup() {
pinMode(resetPin, INPUT); //pins for normally closed switches to set the time
pinMode(minutePin, INPUT);
pinMode(hourPin, INPUT);
digitalWrite(resetPin, HIGH); // writing an input high turns on pull-up resistors
digitalWrite(minutePin, HIGH);
digitalWrite(hourPin, HIGH);
pinMode(Tserial, OUTPUT);
pinMode(Tclk, OUTPUT);
pinMode(Trck, OUTPUT);
pinMode(dBlank, OUTPUT);
digitalWrite(Trck, LOW);
digitalWrite(dBlank, LOW);
minute = sMin;
hour = sHour;
}
void loop() {
if (second == 0 && minute == 0 && hour == 0 || runMode == 0) {
if (setMode == false) displayOut(false);
}
else if (setMode == false) {
clock();
displayOut(false);
}
if (setMode == true) {
setTime();
displayOut(true);
}
if (runMode == 0 && reset == 1) {
second =0;
minute = sMin;
hour = sHour;
reset = 0;
}
checkButtons(); // runs a function that checks the setting buttons
}
void setTime() {
static boolean minStat = false, hrStat = false;
int minBut, hrBut;
minBut = digitalRead(minutePin);
hrBut = digitalRead(hourPin);
if (hrBut == LOW && hrStat == false) {
sHour = sHour + 1;
if (sHour > 9) sHour = 0;
hrStat = true;
}
if (hrBut == HIGH && hrStat == true) {
hrStat=false;
}
if (minBut == LOW && minStat == false) {
sMin = sMin + 1;
if (sMin > 59) sMin = 0;
minStat = true;
}
if (minBut == HIGH && minStat == true) {
minStat=false;
}
hour = sHour;
minute = sMin;
second = 0;
}
void checkButtons() {
static long btnDnTime; // time the button was pressed down
static long btnUpTime; // time the button was released
static boolean ignoreUp = false; // whether to ignore the button release because the click+hold was triggered
static int R = 0; //Mode button state
static int Rstate = 0;
R = digitalRead(resetPin); //read Mode button state
//Test for button pressed and store the down time
if (R == LOW && Rstate == HIGH && (millis() - btnUpTime) > long(debounce))
{
btnDnTime = millis();
}
//Test for button release and store the up time
if (R == HIGH && Rstate == LOW && (millis() - btnDnTime) > long(debounce) && setMode == false)
{
if (ignoreUp == false) runMode = !runMode; //test if Low-High set mode should be toggled
else ignoreUp = false;
btnUpTime = millis();
}
//Test for button held down for longer than the hold time
if (R == LOW && (millis() - btnDnTime) > long(holdTime))
{
setMode = !setMode; //toggle Set mode to Timing mode or vice versa
runMode = 0;
ignoreUp = true;
btnDnTime = millis();
}
Rstate = R;
if (runMode == 0) {
if (digitalRead(minutePin) == LOW && digitalRead(hourPin) == LOW) reset = 1;
}
}
void clock() {
static unsigned long lastTick = 0; // set up a local variable to hold the last time we moved forward one second
// (static variables are initialized once and keep their values between function calls)
// move forward one second every 1000 milliseconds
if (millis() - lastTick >= 1000+timeroffest) {
lastTick = millis();
second--;
}
// move back one minute every 60 seconds
if (second < 0) {
minute--;
second = 59; // reset seconds to zero
}
// move back one hour every 60 minutes
if (minute < 0) {
hour--;
minute = 59; // reset minutes to zero}
}
if (hour < 0) {
hour = 0; // reset hours to zero
}
}
void displayOut(boolean set) {
byte output;
byte minH;
byte minL;
byte hourL;
static byte secFlash, secReg;
static unsigned long update = 0;
if (millis() - update >= 100) {
hourL = hour;
minH = minute / 10;
minL = minute % 10;
digitalWrite(dBlank, LOW);
output = character[minL];
if(setMode==true) {
bitClear(output, 6);
}
for(int c=0; c<=7; c++)
{
digitalWrite(Tserial, bitRead(output, c));
digitalWrite(Tclk, HIGH);
digitalWrite(Tclk, LOW);
}
output = character[minH];
for(int c=0; c<=7; c++)
{
digitalWrite(Tserial, bitRead(output, c));
digitalWrite(Tclk, HIGH);
digitalWrite(Tclk, LOW);
}
digitalWrite(Trck, HIGH);
digitalWrite(Trck, LOW);
output = character[hourL];
if (secFlash != second) {
secReg = !secReg;
secFlash = second;
}
bitWrite(output, 6, secReg);
for(int c=0; c<=7; c++)
{
digitalWrite(Tserial, bitRead(output, c));
digitalWrite(Tclk, HIGH);
digitalWrite(Tclk, LOW);
}
digitalWrite(Trck, HIGH);
digitalWrite(Trck, LOW);
digitalWrite(dBlank, HIGH);
}
}