#include <Wire.h>
#include <RTClib.h>
// ─── MOTOR CONFIG ──────────────────────────────────────────────────────
// Your 20-step motor at 2× microstep → 40 steps/rev:
#define FULL_STEPS 20
#define MS2_STEPS_DIG 2
#define STEPS_REV_DIG (FULL_STEPS * MS2_STEPS_DIG) // 40
// For digits 0–9: 4 steps per flap
#define STEPS_PER_DIGIT 1 //(STEPS_REV_DIG / 10) // 4
// A/P and M-letter spools: 2 states → half-rev
#define STEPS_AP_M 1 //(STEPS_REV_DIG / 2) // 20
// Weekday spool at 4× microstep → 80 steps/rev
#define MS2_STEPS_WD 4
#define STEPS_REV_WD (FULL_STEPS * MS2_STEPS_WD) // 80
#define STEPS_PER_DAY ((STEPS_REV_WD + 3) / 7) // round(80/7)=11
// ─── PIN ASSIGNMENTS ────────────────────────────────────────────────────
// Indices: 0=H10,1=H1,2=M10,3=M1,4=AP,5=Mchar,6=WD
//const uint8_t MS1_PINS[7] = { 2, 6, 10, 14, 18, 22, 26};
//const uint8_t MS2_PINS[7] = { 3, 7, 11, 15, 19, 23, 27};
//const uint8_t DIR_PINS[7] = { 4, 5, 8, 9, 12, 13, 25};
const uint8_t STEP_PINS[7] = {7, 6, 5, 4, 3, 2, 8};
// Track current states:
uint8_t currentState[7] = {0};
// RTC
RTC_DS3231 rtc;
void setup(){
Serial.begin(115200);
Wire.begin();
initRTC();
// Initialize all steppers
for(uint8_t i=0; i<7; i++){
//pinMode(MS1_PINS[i], OUTPUT);
//pinMode(MS2_PINS[i], OUTPUT);
//pinMode(DIR_PINS[i], OUTPUT);
pinMode(STEP_PINS[i], OUTPUT);
// Set microstep mode:
if(i < 6){
// Digit, A/P, Mchar → 2× microstep
digitalWrite(MS1_PINS[i], HIGH);
digitalWrite(MS2_PINS[i], LOW);
} else {
// Weekday → 4× microstep
digitalWrite(MS1_PINS[i], LOW);
digitalWrite(MS2_PINS[i], HIGH);
}
// Always forward
digitalWrite(DIR_PINS[i], HIGH);
digitalWrite(STEP_PINS[i], LOW);
}
}
void loop(){
DateTime now = rtc.now();
// Convert to 12-hour + AM/PM
uint8_t h12 = now.twelveHour(); //% 12; // 0–11
bool isPM = now.isPM();
uint8_t m = now.minute(); // 0–59
uint8_t wd = now.dayOfTheWeek(); // 0=Sun..6=Sat
// Build targets
uint8_t target[7];
target[0] = h12 / 10; // H10 (0 or 1)
target[1] = h12 % 10; // H1 (0–9)
target[2] = m / 10; // M10 (0–5)
target[3] = m % 10; // M1 (0–9)
target[4] = isPM ? 1 : 0; // A/P spool: 0=A, 1=P
target[5] = isPM ? 1 : 0; // M-letter spool: 0=blank, 1=M
target[6] = wd; // Weekday 0–6
// Step each forward-only to its new position
for(uint8_t i=0; i<7; i++){
uint16_t newStep = computeStepCount(i, target[i]);
stepForward(i, newStep);
currentState[i] = target[i];
}
delay(1000);
}
// ─── RTC INIT ───────────────────────────────────────────────────────────
void initRTC(){
if(!rtc.begin()){
Serial.println("RTC init failed"); while(1);
}
if(!rtc.isrunning()){
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
}
// ─── COMPUTE ABSOLUTE STEP POSITION ─────────────────────────────────────
uint16_t computeStepCount(uint8_t idx, uint8_t state){
if(idx < 4){
// Digit spools
return state * STEPS_PER_DIGIT;
}
else if(idx < 6){
// A/P and Mchar spools
return state * STEPS_AP_M;
}
// Weekday spool
return state * STEPS_PER_DAY;
}
// ─── FORWARD-ONLY STEPPING (WITH WRAP) ───────────────────────────────────
void stepForward(uint8_t idx, uint16_t targetStep){
uint16_t oldStep = computeStepCount(idx, currentState[idx]);
uint16_t rev = (idx<6 ? STEPS_REV_DIG : STEPS_REV_WD);
uint16_t delta = (targetStep >= oldStep)
? (targetStep - oldStep)
: (rev - (oldStep - targetStep));
// Pulse STEP pin delta times
for(uint16_t s=0; s<delta; s++){
digitalWrite(STEP_PINS[idx], HIGH);
delayMicroseconds(600);
digitalWrite(STEP_PINS[idx], LOW);
delayMicroseconds(600);
}
}goobergoobergoobergoobergoobergoobergoobergoobergoobergoobergoobergoober