This clock is made of 60 LEDs and the AtMega328 chip with Arduino bootloader. Video of clock in operation. https://www.youtube.com/watch?v=L1F2BAmQfWg
Here is schematics. Board has two button to adjust hours and minutes and Real-time clock ic to keep time accurate.
Back side is not perfect because of cheap soldering iron.
Program code is below.
#include "Wire.h"
boolean LEDarr[60];
unsigned long newMillis = 0;
unsigned long blinkMillis = 0;
int second = 0;
int minute = 0;
int hour = 1;
unsigned long debounceTimer;
boolean A2state = 1;
boolean A3state = 1;
void setup() {
pinMode(0, OUTPUT); // matrix
pinMode(1, OUTPUT);
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT); // matrix
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
pinMode(12, OUTPUT);
pinMode(13, OUTPUT);
pinMode(A0, OUTPUT);
pinMode(A1, OUTPUT);
pinMode(A2, INPUT_PULLUP); // buttons
pinMode(A3, INPUT_PULLUP);
Wire.begin(); // A4,A5
getRTC();
}
int ii = 0;
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - newMillis >= 500) {
newMillis = currentMillis;
getRTC();
}
if(!digitalRead(A2)) {
if(A2state) {
A2state = 0;
debounceTimer = millis();
}
if(millis() - debounceTimer > 150) {
A2state = 1;
if(++hour == 13) hour = 1;
newMillis = currentMillis;
setRTC();
}
}
if(!digitalRead(A3)) {
if(A3state) {
A3state = 0;
debounceTimer = millis();
}
if(millis() - debounceTimer > 150) {
A3state = 1;
if(++minute == 60) minute = 0;
newMillis = currentMillis;
setRTC();
}
}
for(int i = 0; i <= 59; i++) LEDarr[i] = 0;
if(second == 59) {
if (ii < 59) for(int i = 0; i <= ii; i++) LEDarr[i] = 1;
ii = ii + 2;
} else {
ii = 0;
LEDarr[second] = 1;
}
LEDarr[minute] = 1;
LEDarr[(hour*5)-1] = 1;
if(second == (hour*5)-1 && currentMillis - blinkMillis > 200) {
blinkMillis = currentMillis;
LEDarr[second] = !LEDarr[second];
}
if(second == minute && currentMillis - blinkMillis > 200) {
blinkMillis = currentMillis;
LEDarr[second] = !LEDarr[second];
}
if(minute == (hour*5)-1 && currentMillis - blinkMillis > 200) {
blinkMillis = currentMillis;
LEDarr[minute] = !LEDarr[minute];
}
LEDloop();
}
byte decToBcd(byte val) {
return ((val/10*16) + (val%10));
}
byte bcdToDec(byte val) {
return ((val/16*10) + (val%16));
}
void setRTC() {
Wire.beginTransmission(0x51);
Wire.write(0x03);
//Wire.write(decToBcd(second));
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour-1));
Wire.endTransmission();
}
void getRTC() {
Wire.beginTransmission(0x51);
Wire.write(0x02);
Wire.endTransmission();
Wire.requestFrom(0x51, 3);
second = bcdToDec(Wire.read() & B01111111); // remove VL error bit
minute = bcdToDec(Wire.read() & B01111111); // remove unwanted bits from MSB
hour = bcdToDec(Wire.read() & B00111111);
if(hour >= 12) hour = hour - 12;
hour = hour + 1;
}
void LEDloop() {
int led = 0;
for(int a = 8; a <= 15; a++) {
if (a <= 13) digitalWrite(a, 1);
else if(a == 14) digitalWrite(A0, 1);
else if(a == 15) digitalWrite(A1, 1);
if(a != 8) {
for(int i = 4; i <= 7; i++) {
digitalWrite(i, !LEDarr[led++]);
delayMicroseconds(340);
digitalWrite(i, 1);
}
}
for(int i = 0; i <= 3; i++) {
digitalWrite(i, !LEDarr[led++]);
delayMicroseconds(340);
digitalWrite(i, 1);
}
if (a <= 13) digitalWrite(a, 0);
else if(a == 14) digitalWrite(A0, 0);
else if(a == 15) digitalWrite(A1, 0);
}
}

