/* * Simple binary time-of-day clock (Hours Minutes) * Lloyd Milligan - https://www.lloydm.net/ * © CC attribution - https://creativecommons.org/licenses/by/3.0/us/ * * Least significant bit of minutes display is DIO 2 (Minutes = DIO 2 - 7) * Most significant bit of hours display is DIO 12 (Hours = DIO 8 - 12) * */ #include "RTClib.h" // Real-time clock // Constructor RTC_DS3231 rtc; // Oscillator i2c address is 0x68 (can't be changed) // RTC is interfaced via i²c - A4=SDA, A5=SCL // RTC boolean rtcON; // Flag indicating RTC present (found) and successfully initialized DateTime rtcNow; // From rtc.now() int iHr, iMn; // Display #define ON LOW #define OFF HIGH boolean binInt[8]; const unsigned long ONESEC = 1000; // For millis() approximation unsigned long lastUpdate = 0; // Adjustment const int ADD_SECONDS = 6; // Seconds to add to adjust for compile/upload delay when initializing RTC #define SET_CLOCK A0 // Switches and buttons associated with initializing or adjusting clock #define ADJ_MINS A1 // Toggle hours/minutes manual adjustment (ON = minutes) #define UP A2 // Pushbutton - Increment selected value (hours or minutes) #define DN A3 // Pushbutton - Decrement selected value (hours or minutes) const unsigned long RPT_RATE = 500; // Delay between increment or decrement when pushbutton is held down unsigned long lastOneSecAdj = 0; // For non-blocking clock adjustments void setup() { // put your setup code here, to run once: Serial.begin(9600); // For debugging as needed Serial.println(); for (int ioPin=2; ioPin<13; ioPin++) pinMode(ioPin, OUTPUT); // initialize real time clock rtcON = rtc.begin(); if (rtcON && digitalRead(SET_CLOCK) == ON) rtc.adjust(DateTime(F(__DATE__), F(__TIME__)) + TimeSpan(0, 0, 0, ADD_SECONDS)); debugIO(); // Verify that all LED's are functional // Uncomment next to output a page of training examples to the Serial Monitor // genBinaryTimeExamples(); } void loop() { // put your main code here, to run repeatedly: if (millis() - lastUpdate >= ONESEC) { updateTime(); displayBinTime(); lastUpdate = millis(); } if (digitalRead(SET_CLOCK) == ON) adjustClock(); } void toBin(int n) { for (int i=0; i<8; i++) binInt[i] = OFF; for (int i=0; i<8; i++) { if (n == 0) break; if (n % 2 == 1) binInt[i] = ON; n = n/2; } } void updateTime() { // Hours and minutes only for binary clock rtcNow = rtc.now(); iHr = rtcNow.hour(); iMn = rtcNow.minute(); } void displayBinHours() { // Time has been updated before calling display... toBin(iHr); for (int ioPin=12; ioPin>=8; ioPin--) { digitalWrite(ioPin, binInt[ioPin-8]); } } void displayBinMinutes() { // Time has been updated before calling display... toBin(iMn); for (int ioPin=2; ioPin<=7; ioPin++) { digitalWrite(ioPin, binInt[ioPin-2]); } } void displayBinTime() { displayBinHours(); displayBinMinutes(); } // Adjust clock - Manual time setting and adjustment void incrementMinute() { // Add one minute to current time rtc.adjust(DateTime(rtc.now() + TimeSpan(0, 0, 1, 0))); } void decrementMinute() { // Subtract one minute to current time rtc.adjust(DateTime(rtc.now() + TimeSpan(0, 0, -1, 0))); } void incrementHour() { // Add one minute to current time rtc.adjust(DateTime(rtc.now() + TimeSpan(0, 1, 0, 0))); } void decrementHour() { // Subtract one minute to current time rtc.adjust(DateTime(rtc.now() + TimeSpan(0, -1, 0, 0))); } boolean okToIncDecClock() { // Non-blocking delay // when UP or DN button pressed OR held if (millis() - lastOneSecAdj < RPT_RATE) return false; lastOneSecAdj = millis(); return true; } void adjustMinute() { if(digitalRead(UP) == ON) incrementMinute(); if(digitalRead(DN) == ON) decrementMinute(); } void adjustHour() { if(digitalRead(UP) == ON) incrementHour(); if(digitalRead(DN) == ON) decrementHour(); } void adjustClock() { if (okToIncDecClock()) { if (digitalRead(ADJ_MINS) == ON) adjustMinute(); else adjustHour(); } } // Debug void allOff() { for (int ioPin=2; ioPin < 13; ioPin++) digitalWrite (ioPin, OFF); } void allOn() { for (int ioPin=2; ioPin < 13; ioPin++) digitalWrite (ioPin, ON); } void debugIO() { allOn(); delay(ONESEC); allOff(); delay(ONESEC); } void printBinArray() { for (int i=7; i>=0; i--) { Serial.print(binInt[i]); Serial.print(" "); } Serial.println(); } int lastSET_CLOCK = OFF; int lastADJ_MINS = OFF; int lastDN = OFF; int lastUP = OFF; void testAnalogPins() { int pinValue; pinValue = digitalRead(SET_CLOCK); if (pinValue != lastSET_CLOCK) { lastSET_CLOCK = pinValue; if (pinValue == ON) Serial.println("SET_CLOCK = ON"); else Serial.println("SET_CLOCK = OFF"); } pinValue = digitalRead(ADJ_MINS); if (pinValue != lastADJ_MINS) { lastADJ_MINS = pinValue; if (pinValue == ON) Serial.println("ADJ_MINS = ON"); else Serial.println("ADJ_MINS = OFF"); } pinValue = digitalRead(DN); if (pinValue != lastDN) { lastDN = pinValue; if (pinValue == ON) Serial.println("DN = ON"); else Serial.println("DN = OFF"); } pinValue = digitalRead(UP); if (pinValue != lastUP) { lastUP = pinValue; if (pinValue == ON) Serial.println("UP = ON"); else Serial.println("UP = OFF"); } } // Generate training data for acquiring proficiency with binary-format time void genBinaryTimeExamples() { int n=50; // Number of examples to generate (Edit as desired) int h, m; String bH, bM; // const char ONE = '●'; // Serial monitor does not display unicode const char ONE = 'x'; // Select a printable ASCII substitute const char ZERO = 'o'; DateTime dt = rtc.now(); randomSeed(dt.second()*dt.minute()); for (int i=0; i 0) { if (n % 2 == 1) s = '1' + s; else s = '0' + s; n = n/2; } return s; } // Deprecated methods void manuallyAdjustHour() { // while command is blocking while(digitalRead(UP) == ON) { incrementHour(); delay(RPT_RATE); } while(digitalRead(DN) == ON) { decrementHour(); delay(RPT_RATE); } } void manuallyAdjustMinute() { // while command is blocking while(digitalRead(UP) == ON) { incrementMinute(); delay(RPT_RATE); } while(digitalRead(DN) == ON) { decrementMinute(); delay(RPT_RATE); } } void manuallyAdjustClock() { if (digitalRead(ADJ_MINS) == ON) manuallyAdjustMinute(); else manuallyAdjustHour(); }