// Define stepper motor connections
/*
28BYJ-48 stepper motor with ULN2003
IN1 7
IN2 6
IN3 5
IN4 4
*/
#include <Stepper.h>
#include <DS1307RTC.h> // https://github.com/PaulStoffregen/DS1307RTC // SDA to A4, CLK to A5, VCC to 5V
#include <Timezone.h> // https://github.com/JChristensen/Timezone
#include <EEPROM.h>
// US Pacific Time - assuming RTC is set to PST
TimeChangeRule myDST = { "PDT", Second, Sun, Mar, 2, +60 }; //Daylight time = RTC + 60 minutes
TimeChangeRule mySTD = { "PST", First, Sun, Nov, 2, 0 }; //Standard time = RTC + 0 minutes
Timezone myTZ(myDST, mySTD);
TimeChangeRule *tcr; //pointer to the time change rule, use to get TZ abbrev
// Define stepper motor connections
const long stepsPerRevolution = 4096; // Adjust based on your motor
const int IN4 = 4;
const int IN3 = 5;
const int IN2 = 6;
const int IN1 = 7;
// 7,5,6,4
Stepper stepperMinute(stepsPerRevolution, IN1, IN3, IN2, IN4);
// 4,6,5,7 TO REVERSE DIRECTION
//Stepper stepperMinute(stepsPerRevolution, IN4, IN2, IN3, IN1);
char buf[128]; //buffer for sprintf
time_t t;
time_t tz;
unsigned long prevminuteSteps = 0;
const char *monthName[12] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
void setup() {
Serial.begin(115200);
setSyncProvider(RTC.get); // the function to get the time from the RTC
if (timeStatus() != timeSet)
Serial.println("Unable to sync with the RTC");
else
Serial.println("RTC has set the system time");
// intialize steps
t = now();
tz = myTZ.toLocal(t, &tcr); //set to local time zone
int seconds = second(tz);
int minutes = minute(tz);
int hours = hour(tz);
unsigned long minuteSteps = hours * stepsPerRevolution + (minutes * stepsPerRevolution + seconds * stepsPerRevolution / 60) / 60;
prevminuteSteps = minuteSteps; //remove intial time offest
}
int interval = 10000;
long prevTime = 0;
long cumuSteps = 0;
int prevDST = 0;
int hour12 = 0;
void loop() {
// Calculate current time and steps needed
long currentTime = millis();
if (currentTime - prevTime > interval) {
prevTime = currentTime;
t = now();
tz = myTZ.toLocal(t, &tcr);
hour12 = (hour(tz) + 11) % 12 + 1; // take care of noon and midnight-- converts 24h time to 12h time
int seconds = second(tz);
int minutes = minute(tz);
int hours = hour(tz);
bool isDST = myTZ.locIsDST(tz); // if true, then in daylight savings is active.
// verify RTC is set to standard time
sprintf(buf, "%02d %s %02d:%02d %d", day(tz), monthName[month(tz) - 1], hour(tz), minute(tz), isDST);
Serial.println(buf);
// increment every minute
//unsigned long minuteSteps = hours * stepsPerRevolution + minutes * stepsPerRevolution / 60;
// increment every second
unsigned long minuteSteps = hours * stepsPerRevolution + (minutes * stepsPerRevolution + seconds * stepsPerRevolution / 60) / 60;
long steps = minuteSteps - prevminuteSteps;
prevminuteSteps = minuteSteps;
// Move stepper motors to correct positions
stepperMinute.step(steps);
// power cut
digitalWrite(IN1, LOW); digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); digitalWrite(IN4, LOW);
//long cumuSteps = cumuSteps + steps;
cumuSteps >= stepsPerRevolution ? cumuSteps = 0 : cumuSteps = cumuSteps + steps;
Serial.println ((double(cumuSteps) / double(stepsPerRevolution)) * 12 );
//check if dst has changed
//track isDST and if this changes then move the hour hand +1 or -1 hour depending on if moving into or out of DST.
prevDST = EEPROM.read(0); //if EEPROM has never been set, this will be 255
//bool isDST = myTZ.locIsDST(tz); // if true, then in daylight savings is active.
Serial.println(prevDST);
if (prevDST >= 2) {
EEPROM.update(0, isDST); //if invalid data, update with current isDST value
prevDST = EEPROM.read(0);
}
//compare prevDST to currentDST
//if prevDST = 0 (not DST) and isDST = 1 (is DST) then time has moved from standard time to daylight savings time. Diff = -1
//if prevDST = 0 (not DST) and isDST = 0 (not DST) then no change. Diff = 0
//if prevDST = 1 (is DST) and isDST = 0 (not DST) then time has moved from daylight savings to standard time. Diff = 1
//if prevDST = 1 (is DST) and isDST = 1 (is DST) then no change. Diff = 0
int diff = prevDST - isDST;
if (diff == -1) { // moved from ST to DST, so "Spring Back"
// roll back an hour | stepper -4096 steps
EEPROM.update(0, isDST); //store new DST value
for (int i = 0; i <= 15; i++) {
stepperMinute.step(-256);
}
// power cut
digitalWrite(IN1, LOW); digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); digitalWrite(IN4, LOW);
}
if (diff == 1) { // moved from DST to ST, so "Fall Forward"
// add an hour | stepper motor +4096 steps
EEPROM.update(0, isDST); //store new DST value
for (int i = 0; i <= 15; i++) {
stepperMinute.step(256);
}
// power cut
digitalWrite(IN1, LOW); digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); digitalWrite(IN4, LOW);
}
}
}