The arduino code is commented as well as possible. Keep in mind that I'm not a programmer, I have minimal arduino experience (be kind). The code runs continually checking to see if the current time matches the "Reset Time". Because I couldn't think of a way to translate the current time into steps, it only corrects itself once daily (midnight by default). At midnight the gears rotate to the midnight position then wait until 00:01 moving to that time then continues from there. As it currently sits, the clock only loses about 5 seconds over a 24 hour period.

You will need the Stepper and RTClib libraries installed.

I know the code can be optimized by someone with more experience than myself. If you are up to the challenge, please recreate this project for yourself and share your knowledge.

#include <Stepper.h> #include "RTClib.h" RTC_DS1307 rtc; #define oneRotation 2038 // the number of steps in one revolution of 28BYJ-48 stepper motor Stepper hourHand(oneRotation, 3, 5, 4, 6); Stepper minuteHand(oneRotation, 7, 9, 8, 10); #define hourStopSensor 12 #define minuteStopSensor 11 int endStep = 0; // Time dealy for speed of the clock. int setDelay1 = 168; int setDelay2 = 166; int setDelay3 = 5; // Current time to do math with. float hr = 0; float mn = 0; float sc = 0; // Set the time of day to reset clock (24 hour format). int resetHour = 0; int resetMinute = 0; // Variables to set correct time at startup and reset. float setTimeStepHour = 0; float setTimeStepMinute = 0; float handDelay = 0; float hourTest = 0; float minuteTest = 0; void setup() { Serial.begin(115200); // Setup real time clock and reset hall effect sensors. pinMode(hourStopSensor, INPUT_PULLUP); pinMode(minuteStopSensor, INPUT_PULLUP); rtc.begin(); // Uncomment line below to set time. // rtc.adjust(DateTime(2020, 2, 19, 23, 40, 30)); // rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // Set top speed of stepper motors. hourHand.setSpeed(15); minuteHand.setSpeed(15); // Loop until minute and hour hand are at noon while (digitalRead(hourStopSensor) == LOW || digitalRead(minuteStopSensor) == LOW) { if (digitalRead(hourStopSensor) == LOW ) { hourHand.step(2); } else { delay(3); } if (digitalRead(minuteStopSensor) == LOW) { minuteHand.step(3); } else { delay(4); } } while (digitalRead(hourStopSensor) != LOW || digitalRead(minuteStopSensor) != LOW) { if (digitalRead(hourStopSensor) != LOW ) { hourHand.step(2); } else { delay(3); } if (digitalRead(minuteStopSensor) != LOW) { minuteHand.step(3); } else { delay(4); } } // Get current time DateTime now = rtc.now(); hr = now.hour(); mn = now.minute(); sc = now.second(); // Change to 12 hour format if (hr >= 12) { hr = hr - 12; } // See what hand must travel across the face further and use that distance // to adjust set time accordingly. hourTest = hr / 12; minuteTest = mn / 60; if (hourTest > minuteTest) { handDelay = hourTest; } else { handDelay = minuteTest; } // Set current hour setTimeStepHour = (hr * 498) + (mn * 8.3) + ((sc + (handDelay * 36)) * .1383); // Set current minute setTimeStepMinute = (mn * 114) + ((sc + (handDelay * 45)) * 1.9); // Test which hand will need more steps and set that to the longest step count for the for loop. if (setTimeStepHour > setTimeStepMinute) { endStep = setTimeStepHour; } else { endStep = setTimeStepMinute; } for (int i = 0; i <= endStep; i++) { if (i < setTimeStepHour) { hourHand.step(2); } else { delay(3); } if (i < setTimeStepMinute) { minuteHand.step(3); } else { delay(4); } } // Set clock running RPM hourHand.setSpeed(1); minuteHand.setSpeed(1); } void loop() { // Start clock running loop. for (int i = 0; i < 22; i++) { minuteHand.step(1); delay(setDelay1); // Test for reset time, if ready to be reset, break. if (rtc.now().hour() == resetHour && rtc.now().minute() == resetMinute) { break; } } delay(setDelay3); for (int i = 0; i < 38; i++) { hourHand.step(1); delay(setDelay1); // Test for reset time, if ready to be reset, break. if (rtc.now().hour() == resetHour && rtc.now().minute() == resetMinute) { break; } for (int i = 0; i < 20; i++) { minuteHand.step(1); delay(setDelay2); // Test for reset time, if ready to be reset, break. if (rtc.now().hour() == resetHour && rtc.now().minute() == resetMinute) { break; } } } // Reset clock at reset time if (rtc.now().hour() == resetHour && rtc.now().minute() == resetMinute) { // Change speed of clock hourHand.setSpeed(10); minuteHand.setSpeed(10); // Loop till minute and hour hand reach noon. while (digitalRead(hourStopSensor) == LOW || digitalRead(minuteStopSensor) == LOW) { if (digitalRead(hourStopSensor) == LOW ) { hourHand.step(2); } else { delay(3); } if (digitalRead(minuteStopSensor) == LOW) { minuteHand.step(3); } else { delay(4); } } while (digitalRead(hourStopSensor) != LOW || digitalRead(minuteStopSensor) != LOW) { if (digitalRead(hourStopSensor) != LOW ) { hourHand.step(2); } else { delay(3); } if (digitalRead(minuteStopSensor) != LOW) { minuteHand.step(3); } else { delay(4); } } // Wait here until the reset time has passed. while (rtc.now().minute() == resetMinute) { delay(1000); } // Get current time DateTime now = rtc.now(); hr = now.hour(); mn = now.minute(); sc = now.second(); // Change to 12 hour format if (hr >= 12) { hr = hr - 12; } // See what hand must travel across the face further and use that distance // to adjust set time accordingly. hourTest = hr / 12; minuteTest = mn / 60; if (hourTest > minuteTest) { handDelay = hourTest; } else { handDelay = minuteTest; } // Set current hour setTimeStepHour = (hr * 498) + (mn * 8.3) + ((sc + (handDelay * 36)) * .1383); // Set current minute setTimeStepMinute = (mn * 114) + ((sc + (handDelay * 45)) * 1.9); // Test which hand will need more steps and set that to the longest step count for the for loop. if (setTimeStepHour > setTimeStepMinute) { endStep = setTimeStepHour; } else { endStep = setTimeStepMinute; } for (int i = 0; i <= endStep; i++) { if (i < setTimeStepHour) { hourHand.step(2); } else { delay(3); } if (i < setTimeStepMinute) { minuteHand.step(3); } else { delay(4); } } hourHand.setSpeed(1); minuteHand.setSpeed(1); } }