I got this far with the clock about three weeks ago. At that point, I gave up. I can of course dream the rest, and 100:1 odds I can program the rest, but to fabricate the rest would require more time and far more money than I can justify on such a thing.
As I said, it shows only the minutes. There is a button to set the minutes. When the button is pressed, the minutes advance, and the seconds are reset to zero. That last sentence is an oversimplification: there are no seconds per se. The code is here:
Code: Select all
long mzero = 0L;
long munit = 60011300; // in theory, should be 60000000; adjusted for individual Arduino
long minute = 0L;
boolean pushed = false;
boolean oldinput = true;
boolean newinput = true;
//Pin connected to latch pin (ST_CP, pin 12) of 74HC595
const int latchPin = 4;
//Pin connected to clock pin (SH_CP, pin 11) of 74HC595
const int clockPin = 3;
////Pin connected to Data in (DS, pin 14) of 74HC595
const int dataPin = 2;
void setup() {
pinMode(latchPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(5, INPUT);
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, 253);
shiftOut(dataPin, clockPin, MSBFIRST, 246);
shiftOut(dataPin, clockPin, MSBFIRST, 251);
digitalWrite(latchPin, HIGH);
}
void loop() {
boolean changeminute;
long mlights;
changeminute=false;
mlights=0L;
newinput = digitalRead(5);
if (newinput!=oldinput) {
oldinput=newinput;
pushed=true;
delay(50); //debounce
if (!newinput) {
changeminute=true;
mzero=micros();
}
}
if (micros()-mzero>=munit) {
mzero+=munit;
changeminute=true;
}
if (changeminute) {
minute++;
if (minute>=60L) minute-=60L;
// now write this to the shift registers for display
mlights=0L;
switch(minute%10) {
case 0: mlights+=0x2cdL; break;
case 1: mlights+=0x29L; break;
case 2: mlights+=0x9eL; break;
case 3: mlights+=0xa7L; break;
case 4: mlights+=0x30bL; break;
case 5: mlights+=0x387L; break;
case 6: mlights+=0x3c7L; break;
case 7: mlights+=0x1b2L; break;
case 8: mlights+=0x3cfL; break;
case 9: mlights+=0x38fL; break;
default: mlights+=0; break;
}
switch(minute/10) {
case 0: mlights+=0xb3400L; break;
case 1: mlights+=0xa400L; break;
case 2: mlights+=0x27800L; break;
case 3: mlights+=0x29c00L; break;
case 4: mlights+=0xc2c00L; break;
case 5: mlights+=0xe1c00L; break;
default: mlights=0x40902L; break;
}
mlights=0xffffff-mlights; // common anode
if (pushed) {
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, (unsigned byte)(mlights%256L));
shiftOut(dataPin, clockPin, MSBFIRST, (unsigned byte)((mlights/256L)%256L));
shiftOut(dataPin, clockPin, MSBFIRST, (unsigned byte)(mlights/65536L));
digitalWrite(latchPin, HIGH);
}
}
}
The long segments each get a 2000-ohm resistor, and the short segments each get about 3500 ohms resistance. (This would be 4000 but I had no 4000-ohm resistors handy.)
The display is very bright, due to the low resistance and the lack of multiplexing. It could even serve as a night-light, if you don't mind the abrupt change in brightness from time to time.
There are three 8-bit shift registers. This is because of the 20 display segments (some of which are actually two segments wired together as one) and the lack of multiplexing.
Please note how, in my code, I determined the start of a new minute. Absolutely nothing special happens when micros() rolls over. I hope that other programmers find this trick useful in their own code.