##include #include "RTClib.h" RTC_DS3231 rtc; // --- Pines --- const int motorPinsHour[4] = {10, 11, 12, 13}; const int motorPinsMinute[4] = {4, 5, 6, 7}; const int hallPinHour = 9; const int hallPinMinute = 3; const int btnHour = A0; const int btnMinute = A1; // --- Parámetros --- const int STEPS_PER_REV = 4096; // 28BYJ-48 const int FLAPS_HOUR = 24; const int FLAPS_MINUTE = 60; const float STEPS_PER_FLAP_H = 170.70; const float STEPS_PER_FLAP_M = STEPS_PER_REV / (float)FLAPS_MINUTE; const int stepDelayUs = 1200; // --- Secuencia half-step --- const int seq[8][4] = { {1,0,0,0}, {1,1,0,0}, {0,1,0,0}, {0,1,1,0}, {0,0,1,0}, {0,0,1,1}, {0,0,0,1}, {1,0,0,1} }; // --- Estado --- int seqPosH = 0, seqPosM = 0; int flapHour = 0, flapMinute = 0; bool lastBtnHour = HIGH, lastBtnMinute = HIGH; int lastRTCMinute = -1; int lastRTCHour = -1; void setup() { for(int i=0;i<4;i++){ pinMode(motorPinsHour[i], OUTPUT); pinMode(motorPinsMinute[i], OUTPUT); } pinMode(hallPinHour, INPUT_PULLUP); pinMode(hallPinMinute, INPUT_PULLUP); pinMode(btnHour, INPUT_PULLUP); pinMode(btnMinute, INPUT_PULLUP); Wire.begin(); rtc.begin(); if(rtc.lostPower()){ rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); } homingAll(); DateTime now = rtc.now(); moveToFlapHour(now.hour()); flapHour = now.hour(); moveToFlapMinute(now.minute()); flapMinute = now.minute(); lastRTCHour = now.hour(); lastRTCMinute = now.minute(); } void loop() { DateTime now = rtc.now(); int prevMinute = lastRTCMinute; int prevHour = lastRTCHour; // --- Avance automático cada minuto --- if(now.minute() != lastRTCMinute){ moveToFlapMinute(now.minute()); flapMinute = now.minute(); if(prevMinute == 59){ // pasa de 59 → 00 campanadaMinute(); homingMinute(); flapMinute = 0; } if(now.minute() == 0){ // pasa de hh:59 → hh+1:00 moveToFlapHour(now.hour()); flapHour = now.hour(); if(prevHour == 23){ // pasa de 23 → 00 campanadaHour(); homingHour(); flapHour = 0; } } } lastRTCMinute = now.minute(); lastRTCHour = now.hour(); // --- Botones de ajuste manual --- bool bHour = digitalRead(btnHour); bool bMinute = digitalRead(btnMinute); if(bHour == LOW && lastBtnHour == HIGH){ int prevFlapHour = flapHour; adjustTime(1,0,false); // Detectar paso de 23 → 00 manualmente if(prevFlapHour == 23 && flapHour == 0){ campanadaHour(); homingHour(); } delay(200); } if(bMinute == LOW && lastBtnMinute == HIGH){ adjustTime(0,1,false); delay(200); } lastBtnHour = bHour; lastBtnMinute = bMinute; } // --------------------------------------------------- void homingAll(){ homingHour(); homingMinute(); seqPosH = seqPosM = 0; flapHour = flapMinute = 0; } // --- HOMING HORAS --- void homingHour() { // Si arrancamos justo sobre el imán, retrocedemos un poco para salir if (digitalRead(hallPinHour) == LOW) { for (int k = 0; k < 40; k++) stepMotor(1, -1); delay(30); } int stableCount = 0; bool found = false; for (long i = 0; i < 10000; i++) { int hallState = digitalRead(hallPinHour); if (hallState == LOW) { stableCount++; } else { stableCount = 0; } if (stableCount >= 6) { found = true; break; } stepMotor(1, 1); // dirección normal del reloj } delay(50); // Pequeño microajuste hacia adelante (sin tocar la dirección de giro) if (found) { for (int j = 0; j < 15; j++) stepMotor(1, 1); } } // --- HOMING MINUTOS --- void homingMinute() { // Si arrancamos con el sensor LOW (imán delante), salimos del campo if (digitalRead(hallPinMinute) == LOW) { for (int k=0; k<40; k++) stepMotor(2, 1); delay(30); } int stable = 0; for (long i=0; i<10000; i++) { int s = digitalRead(hallPinMinute); if (s == LOW) stable++; else stable = 0; if (stable >= 6) break; stepMotor(2, -1); } delay(50); for (int j=0; j<12; j++) stepMotor(2,-1); // microajuste más largo } // --------------------------------------------------- void moveToFlapHour(int target){ int diff = target - flapHour; if(diff<0) diff+=FLAPS_HOUR; for(int i=0;i<(int)(diff*STEPS_PER_FLAP_H);i++) stepMotor(1,1); flapHour = target; } void moveToFlapMinute(int target){ int diff = target - flapMinute; if(diff<0) diff+=FLAPS_MINUTE; for(int i=0;i<(int)(diff*STEPS_PER_FLAP_M);i++) stepMotor(2,-1); flapMinute = target; } // --------------------------------------------------- void campanadaHour(){ for(int i=0;i7) seqPos=0; if(seqPos<0) seqPos=7; for(int i=0;i<4;i++) digitalWrite(pins[i],seq[seqPos][i]); delayMicroseconds(stepDelayUs); }