Here’s a video of it in action:
Parts used:
Libraries used:
My code:
#include "Bounce2.h" #include "LedControl.h" const byte lowA[8] = {B00000000, B00000000, B00000000, B01111100, B10000010, B10000010, B10000010, B01111101}; const byte capB[8] = {B11111110, B10000001, B10000001, B10000001, B11111110, B10000001, B10000001, B11111110}; const byte lowE[8] = {B00000000, B00000000, B00000000, B01111110, B10000001, B11111111, B10000000, B01111110}; const byte lowG[8] = {B00000000, B00000000, B01111110, B10000001, B10000001, B01111110, B00000001, B01111110}; const byte capH[8] = {B10000001, B10000001, B10000001, B11111111, B10000001, B10000001, B10000001, B10000001}; const byte lowR[8] = {B00000000, B00000000, B00000000, B01111111, B10000000, B10000000, B10000000, B10000000}; const byte lowS[8] = {B00000000, B00000000, B00000000, B01111111, B10000000, B01111110, B00000001, B01111110}; const byte lowU[8] = {B00000000, B00000000, B00000000, B10000001, B10000001, B10000001, B10000011, B01111101}; const byte capW[8] = {B10000001, B10000001, B10000001, B10010001, B10010001, B10010001, B10010001, B01111110}; const byte space[8] = {0, 0, 0, 0, 0, 0, 0, 0}; const byte digits[10][8] = { { B0111110, B1100011, B1100111, B1101011, B1110011, B1100011, B0111110, 0}, { B0001110, B0011110, B0001110, B0001110, B0001110, B0001110, B0001110, 0}, { B0111110, B1100011, B0000011, B0011110, B0110000, B1100000, B1111111, 0}, { B0111110, B1100011, B0000011, B0011110, B0000011, B1100011, B0111110, 0}, { B1100110, B1100110, B1100110, B1100110, B1111111, B0000110, B0000110, 0}, { B1111111, B1100000, B1111110, B0000011, B0000011, B1100011, B0111110, 0}, { B0111110, B1100011, B1100000, B1111110, B1100011, B1100011, B0111110, 0}, { B1111111, B0000011, B0000110, B0001100, B0011100, B0011100, B0011100, 0}, { B0111110, B1100011, B1100011, B0111110, B1100011, B1100011, B0111110, 0}, { B0111110, B1100011, B1100011, B0111111, B0000011, B1100011, B0111110, 0} }; const unsigned long maxTicks = 0xFFFFFFFF; const unsigned twentyFourHour = false; LedControl lc = LedControl(11, 12, 10, 4); Bounce hourButton = Bounce(); Bounce minuteButton = Bounce(); Bounce tenMinuteButton = Bounce(); Bounce brightnessButton = Bounce(); Bounce *buttonArray[4] = {&hourButton, &minuteButton, &tenMinuteButton, &brightnessButton}; boolean firstLoop = true; void clearAll(LedControl lc) { for(int i = 0; i < lc.getDeviceCount(); ++i) { lc.clearDisplay(i); } } void setAll(LedControl lc, const int x, const int y) { for(int i = 0; i < lc.getDeviceCount(); ++i) { lc.setRow(i, x, y); } } void writeLetter(LedControl lc, const int digit, const byte letter[8], const boolean colon = false) { for(int i = 0; i < 8; ++i) { int bits = letter[i]; if(colon && (i == 2 || i == 4)) { bits |= B10000000; } lc.setRow(digit, i, bits); } } void setIntensity(LedControl lc, const int brightness) { for(int i = 0; i < lc.getDeviceCount(); ++i) { lc.setIntensity(i, brightness); } } void setup() { for(int i = 0; i < lc.getDeviceCount(); ++i) { lc.shutdown(i, false); lc.setIntensity(i, 0); lc.clearDisplay(i); } pinMode(1, INPUT_PULLUP); brightnessButton.attach(1); pinMode(2, INPUT_PULLUP); hourButton.attach(2); pinMode(3, INPUT_PULLUP); tenMinuteButton.attach(3); pinMode(4, INPUT_PULLUP); minuteButton.attach(4); } // returns array {hourTens, hourOnes, minuteTens, minuteOnes} const byte *timeDigits(const unsigned long seconds) { static byte ret[4] = {9,9,9,9}; byte hour = seconds / 3600; if(twentyFourHour) { hour %= 24; } else { hour %= 12; if(hour == 0) { hour = 12; } } byte min = (seconds % 3600) / 60; ret[0] = hour / 10; ret[1] = hour % 10; ret[2] = min / 10; ret[3] = min % 10; return ret; } unsigned long secondsFromTime(byte hourTens, byte hourOnes, byte minuteTens, byte minuteOnes) { return hourTens * 36000 + hourOnes * 3600 + minuteTens * 600 + minuteOnes * 60; } void loop() { boolean reset = false; static unsigned long ticks; static unsigned long offsetSeconds; static unsigned long lastSeconds; static unsigned long offsetTicks; static unsigned long lastTicks; static unsigned short brightness; ticks = millis(); if(hourButton.fell()) { const byte *currentDigits = timeDigits(lastSeconds % 86400); long hours = currentDigits[0] * 10 + currentDigits[1]; hours += 1; if(twentyFourHour) { hours %= 24; } else { hours %= 12; if (hours == 0) { hours = 12; } } offsetSeconds = secondsFromTime(hours / 10, hours % 10, currentDigits[2], currentDigits[3]) % 86400; reset = true; } if(tenMinuteButton.fell()) { const byte *currentDigits = timeDigits(lastSeconds % 86400); offsetSeconds = secondsFromTime(currentDigits[0], currentDigits[1], (currentDigits[2] + 1) % 6, currentDigits[3]) % 86400; reset = true; } if(minuteButton.fell()) { const byte *currentDigits = timeDigits(lastSeconds % 86400); offsetSeconds = secondsFromTime(currentDigits[0], currentDigits[1], currentDigits[2], (currentDigits[3] + 1) % 10) % 86400; reset = true; } if(brightnessButton.fell()) { brightness = (brightness + 1) % 0x10; setIntensity(lc, brightness); } if(firstLoop) { brightness = 0; firstLoop = false; offsetSeconds = 0; reset = true; } if(reset) { offsetTicks = 0; lastTicks = ticks; offsetTicks = -ticks; lastSeconds = offsetSeconds; } else { if(lastTicks > ticks) { offsetSeconds = lastSeconds; offsetTicks = maxTicks - lastTicks; } } for(byte i = 0; i < 4; ++i) { buttonArray[i]->update(); } lastSeconds = offsetSeconds + (ticks + offsetTicks) / 1000; const byte *currentDigits = timeDigits(lastSeconds % 86400); // Write the clock if(currentDigits[0] == 0) { writeLetter(lc, 3, space); } else { writeLetter(lc, 3, digits[currentDigits[0]]); } writeLetter(lc, 2, digits[currentDigits[1]]); writeLetter(lc, 1, digits[currentDigits[2]], (lastSeconds % 2) == 1); writeLetter(lc, 0, digits[currentDigits[3]]); }