Set arduino RTC alarm every minute

Hello,
I need to drive a motor once at 59S for 1S - The motor drives a huge mechanical clock.
Can someone help me modify this code so that I can set the alarm to start once a minute and adjust its duration in a range between 0.1 and 1 second?
Thank you

/////////////////////////////////////////////////////////////////////
//
//	Arduino RealTimeClock
//
/////////////////////////////////////////////////////////////////////

#include <EEPROM.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_I2CDevice.h>
#include <Adafruit_SPIDevice.h>
#include <Adafruit_SSD1306.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

#define SET_BUTTON 9  // Set button is connected to Arduino pin D9
#define INC_BUTTON 8  // Inc button is connected to Arduino pin D8
#define DEC_BUTTON 7  // Dec button is connected to Arduino pin D7
#define ALARM_BUZZER 3 // alarm buzzer is connected to D3

#define ONE_WIRE_BUS 2

#define EEPROM_SETUP_INDEX 0
#define EEPROM_ALARM_MINUTE 1
#define EEPROM_ALARM_HOUR 2
#define EEPROM_ALARM_LENGTH 3

#define MAIN_MENU_ALARM 0
#define MAIN_MENU_DATE_TIME 1
#define MAIN_MENU_DAYLIGHT 2
#define MAIN_MENU_DISP_STYLE 3

#define DATE_FORMAT_YMD 0
#define DATE_FORMAT_DMY 1
#define DATE_FORMAT_MDY 2
#define DATE_FORMAT_MASK 3

#define DAYLIGHT_CANCEL 0
#define DAYLIGHT_SPRING 1
#define DAYLIGHT_FALL 2

#define TIME_FORMAT_24 0
#define TIME_FORMAT_12 1
#define TIME_FORMAT_MASK 4

#define TEMP_FORMAT_C 0
#define TEMP_FORMAT_F 1
#define TEMP_FORMAT_MASK 8

#define ALARM_SET_MASK 16
#define ALARM_NOT_ACTIVE 0
#define ALARM_ACTIVE 1
#define ALARM_RESET 2

#define SETUP_SUB_MENU 0

#define SETUP_ALARM_START 1
#define SETUP_ALARM_SET 1
#define SETUP_ALARM_HOUR 2
#define SETUP_ALARM_MINUTE 3
#define SETUP_ALARM_LENGTH 4
#define SETUP_ALARM_END 5

#define SETUP_DATE_TIME_START 5
#define SETUP_YEAR 5
#define SETUP_MONTH 6
#define SETUP_DAY 7
#define SETUP_HOUR 8
#define SETUP_MINUTE 9
#define SETUP_DATE_TIME_END 10

#define SETUP_DAYLIGHT_START 10
#define SETUP_DAYLIGHT_END 11

#define SETUP_FORMAT_START 11
#define SETUP_DATE_STYLE 11
#define SETUP_TIME_STYLE 12
#define SETUP_TEMP_UNIT 13
#define SETUP_FORMAT_END 14
#define SETUP_COUNT 15

#define STATE_CLOCK 0
#define STATE_SET_MENU 1
#define STATE_DISP_MENU 2
#define STATE_WAIT_RELEASE 3
#define STATE_SET_PARAM 4

#define BUTTONS_OFF 0
#define BUTTON_SET 1
#define BUTTON_INC 2
#define BUTTON_DEC 4

#define byteToChar1(X) (char) (((X) / 10) + '0')
#define byteToChar2(X) (char) (((X) % 10) + '0')

void drawText(byte y_pos, char *text, byte text_size);
void drawText(byte x_pos, byte y_pos, char *text, byte text_size);
void drawText(byte x_pos, byte y_pos, const char* text, byte text_size, bool highlight);
void drawText(byte y_pos, const char* text, byte text_size, bool highlight);
void displayClock();
void setClockModule(bool setDaylight);
void saveDisplayFormat();
void saveAlarmParameters();
void displaySetupMenu();
void displaySetupMenuParameters();
void drawMainMenuParam();
void drawAlarmOnOffMenu();
void drawDaylightMenu();
void drawDateStyleMenu();
void drawTimeStyleMenu();
void drawTempUnitMenu();
void tempToStr(int temp);
byte readRS3231();
void writeRS3231(byte value);
byte dayOfTheWeek();
byte hourToAMPM(char* ampm);
void getFreeMemory();
 
// Adafruit_SSD1306 display 128x64 constructor 
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// temperature probe class pointers
OneWire *oneWire = NULL;
DallasTemperature *probeSensor = NULL;
DeviceAddress deviceAddress;
bool probeAddressValid;

byte *paramPtr;
byte setupIndex;

byte eepromFlags;
byte eepromAlarmHour;
byte eepromAlarmMinute;
byte eepromAlarmLength;

byte dateStyle;
byte timeStyle;
byte tempUnit;

byte alarmSet;
byte alarmHour;
byte alarmMinute;
byte alarmLength;
byte alarmState;
unsigned long alarmTimer;

byte submenu; // 0 to 3
byte second; // 0 to 59
byte minute; // 0 to 59
byte hour; // 0 to 23
byte dayOfWeek; // 1-sunday to 7-saturday
byte day; // 1 to last day of the month
byte month; // 1 to 12
byte year; // 0 to 99

byte daylight;

byte state;
byte buttonsState;
unsigned long setMenuTimer;
unsigned long setMenuTimeout;

char dispStr[22];

// last day of the month
byte lastDayOfMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

// day of the week
char dayText[7][10] =
  {
    "SUNDAY",
    "MONDAY",
    "TUESDAY",
    "WEDNESDAY",
    "THURSDAY",
    "FRIDAY",
    "SATURDAY"
  };

// parameter maximum value
byte paramMax[SETUP_COUNT] = {3, 1, 23, 59, 99, 99, 12, 31, 23, 59, 2, 2, 1, 1};

// save text strings in program memory
const PROGMEM char SetupStr1[] = {"CLOCK"};
const PROGMEM char SetupStr2[] = {"Alarm, Calendar,"};
const PROGMEM char SetupStr3[] = {"Temperature"};
const PROGMEM char SetupStr4[] = {"Local and Probe"};
const PROGMEM char UziGranot[] = {" By: Uzi Granot "};

const PROGMEM char selectMenuHeading[] = {"SELECT MENU"};
const PROGMEM char selectMenuAlarm[] = {" 1. ALARM CLOCK "};
const PROGMEM char selectMenuDateTime[] = {" 2. DATE TIME "};
const PROGMEM char selectMenuDaylight[] = {" 3. DAYLIGHT "};
const PROGMEM char selectMenuDispStyle[] = {" 4. DISP STYLE "};

const PROGMEM char DaylightMenuHeading[] = {"DAYLIGHT ADJUST"};
const PROGMEM char DaylightMenuCancel[] = {" CANCEL  "};
const PROGMEM char DaylightMenuSpring[] = {" SPRING +1 HOUR "};
const PROGMEM char DaylightMenuFall[] = {" FALL -1 HOUR  "};

const PROGMEM char alarmOnOffMenuHeading[] = {"ALARM CLOCK"};
const PROGMEM char alarmOnOffMenuOff[] = {" 1. ALARM OFF "};
const PROGMEM char alarmOnOffMenuOn[] = {" 2. ALARM ON "};

const PROGMEM char dateStyleMenuHeading[] = {"DATE STYLE MENU"};
const PROGMEM char dateStyleMenuYMD[] = {" 1. YYYY/MM/DD "};
const PROGMEM char dateStyleMenuDMY[] = {" 2. DD/MM/YYYY "};
const PROGMEM char dateStyleMenuMDY[] = {" 3. MM/DD/YYYY "};

const PROGMEM char timeStyleMenuHeading[] = {"TIME STYLE MENU"};
const PROGMEM char timeStyleMenu24[] = {" 1. 24 HOUR "};
const PROGMEM char timeStyleMenu12[] = {" 2. 12 HOUR "};

const PROGMEM char tempUnitMenuHeading[] = {"TEMPERATURE UNIT"};
const PROGMEM char tempUnitMenuC[] = {" 1. CELSIUS "};
const PROGMEM char tempUnitMenuF[] = {" 2. FAHRENHEIT "};

const PROGMEM char yearStr[] = {"YEAR"};
const PROGMEM char monthStr[] = {"MONTH"};
const PROGMEM char dayStr[] = {"DAY"};
const PROGMEM char hourStr[] = {"HOUR"};
const PROGMEM char minuteStr[] = {"MINUTE"};
const PROGMEM char lengthStr[] = {"LENGTH"};
const PROGMEM char setupStr[] = {"SETUP MENU"};
const PROGMEM char alarmSetStr[] = {"ALARM AT: "};

/////////////////////////////////////////////////////////////////////////
// Arduino setup method
// will be executed once at startup
/////////////////////////////////////////////////////////////////////////
void setup()
  {
  // wait a lttle
  delay(200);

  // menu mode buttons
  pinMode(SET_BUTTON, INPUT_PULLUP);
  pinMode(INC_BUTTON, INPUT_PULLUP);
  pinMode(DEC_BUTTON, INPUT_PULLUP);

  // alarm clock buzzer
  pinMode(ALARM_BUZZER, OUTPUT);
  digitalWrite(ALARM_BUZZER, HIGH);

  // display screen SSD1306 initialization
 	display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.setTextColor(WHITE,BLACK);

  // Clear the display buffer.
  display.clearDisplay();

  // display initialization message
  drawText(0, SetupStr1, 2, false);
  drawText(18, SetupStr2, 1, false);
  drawText(30, SetupStr3, 1, false);
  drawText(42, SetupStr4, 1, false);
  drawText(54, UziGranot, 1, true);

  display.display();

  // wait 2 seconds
  delay(2000);
  
  // get saved parameters
  eepromFlags = EEPROM.read(EEPROM_SETUP_INDEX);
  if((eepromFlags & 0xe0) != 0 || (eepromFlags & DATE_FORMAT_MASK) == DATE_FORMAT_MASK)
    {
    eepromFlags = 0;
    EEPROM.write(EEPROM_SETUP_INDEX, eepromFlags);
    }
  
  // extract flags parameters
  dateStyle = eepromFlags & DATE_FORMAT_MASK;
  timeStyle = (eepromFlags & TIME_FORMAT_MASK) >> 2;
  tempUnit = (eepromFlags & TEMP_FORMAT_MASK) >> 3;
  alarmSet = (eepromFlags & ALARM_SET_MASK) >> 4;

  // get alarm time and length
  eepromAlarmHour = EEPROM.read(EEPROM_ALARM_HOUR);
  alarmHour = eepromAlarmHour;
  if(alarmHour >= 24) alarmHour = 12;
  eepromAlarmMinute = EEPROM.read(EEPROM_ALARM_MINUTE);
  alarmMinute = eepromAlarmMinute;
  if(alarmMinute >= 60) alarmMinute = 30;
  eepromAlarmLength = EEPROM.read(EEPROM_ALARM_LENGTH);
  alarmLength = eepromAlarmLength;
  if(alarmLength > 99) alarmLength = 5;

  // set one wire for temperature sensor
	oneWire = new OneWire();
	oneWire->begin(ONE_WIRE_BUS);

	// set temperature sensor
	probeSensor = new DallasTemperature();
	probeSensor->setOneWire(oneWire);
	probeSensor->begin();

  // temperature probe address
  probeAddressValid = false;
  if(probeSensor->getAddress(deviceAddress, 0)) probeAddressValid = true;

  // set clock display state
  state = STATE_CLOCK;
  return;
  }

/////////////////////////////////////////////////////////////////////////
// Arduino main program loop
/////////////////////////////////////////////////////////////////////////
void loop()
  {
  // buttons state
  buttonsState = BUTTONS_OFF;
  if(!digitalRead(SET_BUTTON)) buttonsState |= BUTTON_SET;
  if(!digitalRead(INC_BUTTON)) buttonsState |= BUTTON_INC;
  if(!digitalRead(DEC_BUTTON)) buttonsState |= BUTTON_DEC;

  // switch based on program state
  switch(state)
    {
    // normal state
    case STATE_CLOCK:
      // read clock module and display normal clock plus temperature screen
      displayClock();

      // set button is not pressed
      // and daylight set is not active
      if((buttonsState & BUTTON_SET) == 0 || daylight != DAYLIGHT_CANCEL) return;

      // set button is pressed
      // save current time
      setMenuTimer = millis();

      // and switch to menu state
      state = STATE_SET_MENU;  
      return;

    // set menu button was pressed
    case STATE_SET_MENU:
      // display normal clock plus temperature screen
      displayClock();

      // set button was pressed for at least 2 seconds
      if((int) (millis() - setMenuTimer) > 2000)
        {
        // go to set menu
        setupIndex = SETUP_SUB_MENU;
        state = STATE_DISP_MENU;
        return;
        }

      // set button was released before 2 seconds
      // go back to normal clock temperature display
      if((buttonsState & BUTTON_SET) == 0) state = STATE_CLOCK;

      // if set button is still pressed wait for 2 seconds
      return;

    // display one of the setup menu screens based on setupIndex
    // go to wait release button before allowing the user to
    // change setup values
    case STATE_DISP_MENU:
      displaySetupMenu();
      state = STATE_WAIT_RELEASE;
      return;

    // wait until set button is released
    case STATE_WAIT_RELEASE:
      // set button still pressed
      // stay in wait release button before allowing the user to
      // change setup values
      if((buttonsState & BUTTON_SET) != 0) return;

      // set button is released
      // save current time for no-action timeout test
      setMenuTimer = millis();
      setMenuTimeout = setMenuTimer;
      state = STATE_SET_PARAM;  
      return;

    case STATE_SET_PARAM:
      // look for timeout 12 seconds of no inc or dec buttons activity
      if((int) (millis() - setMenuTimeout) > 12000)
        {
        // all partial changes made will be ignored
        // restore parameters
        dateStyle = eepromFlags & DATE_FORMAT_MASK;
        timeStyle = (eepromFlags & TIME_FORMAT_MASK) >> 2;
        tempUnit = (eepromFlags & TEMP_FORMAT_MASK) >> 3;
        alarmSet = (eepromFlags & ALARM_SET_MASK) >> 4;
        alarmHour = eepromAlarmHour;
        alarmMinute = eepromAlarmMinute;
        alarmLength = eepromAlarmLength;

        // go back to normal display clock temperature state
        state = STATE_CLOCK;
        return;
        }

      // after 0.5 seconds and set button is pressed
      // move to next menu
      if((int) (millis() - setMenuTimer) > 500 && (buttonsState & BUTTON_SET) != 0)
        {
        // main menu exit
        if(setupIndex == SETUP_SUB_MENU)
          {
          if(submenu == MAIN_MENU_ALARM)
            {
            setupIndex = SETUP_ALARM_START;
            }
          else if(submenu == MAIN_MENU_DATE_TIME)
            {
            setupIndex = SETUP_DATE_TIME_START;
            }
          else if(submenu == MAIN_MENU_DAYLIGHT)
            {
            daylight = DAYLIGHT_CANCEL;
            setupIndex = SETUP_DAYLIGHT_START;
            }
          else
            {
            setupIndex = SETUP_FORMAT_START;
            }
          state = STATE_DISP_MENU;
          return;
          }
          
        // next state
        setupIndex++;

        // alarm parameters are done
        if(setupIndex == SETUP_ALARM_END ||
          (setupIndex == SETUP_ALARM_HOUR && alarmSet == 0))
          {
          // save new alarm settings
          saveDisplayFormat();
          saveAlarmParameters();
          state = STATE_CLOCK;
          return;
          }

        // date and time setup is done
        if(setupIndex == SETUP_DATE_TIME_END)
          {
          // upload new date ant time to clock module
          setClockModule(false);
          state = STATE_CLOCK;
          return;
          }

        // daylight setup is done
        if(setupIndex == SETUP_DAYLIGHT_END)
          {
          state = STATE_CLOCK;
          return;
          }

        // format setup is done (calendar date format, time format and temperature units)
        if(setupIndex == SETUP_FORMAT_END)
          {
          saveDisplayFormat();
          state = STATE_CLOCK;
          return;
          }

        // go to next step in the setup process
        state = STATE_DISP_MENU;
        return;
        }

      // both inc and dec buttons are off
      // just stay on the same setup menu
      if((buttonsState & (BUTTON_INC | BUTTON_DEC)) == 0) break;

      // either inc or dec button is pressed
      // reset the 12 second timeout
      setMenuTimeout = millis();

      // increment button was pressed
      if((buttonsState & BUTTON_INC) != 0)
        {
        // current parameter is at maximum value
        if(paramPtr[0] == paramMax[setupIndex])
          {
          // go back to minimum value
          paramPtr[0] = 0;

          // for month and day the minimum is 1
          if(setupIndex == SETUP_MONTH || setupIndex == SETUP_DAY) paramPtr[0]++;
          }
        // increment to next value
        else
          {
          paramPtr[0]++;
          }
        }

      // decrement
      else
        {
        // current parameter is at minimum value
        if(paramPtr[0] == 0 || (paramPtr[0] == 1 && (setupIndex == SETUP_MONTH || setupIndex == SETUP_DAY)))
          {
          // go to maximum value
          paramPtr[0] = paramMax[setupIndex];
          }
        // decrement to previous value
        else
          {
          paramPtr[0]--;
          }
        }

      // display new value
      displaySetupMenuParameters();

      // wait 0.5 second
      delay(500);
      return;
    }
  return;
  }

/////////////////////////////////////////////////////////////////////////
// display clock, calendar and temperature screen
/////////////////////////////////////////////////////////////////////////
void displayClock()
  {
  // get date and time
  // Start I2C protocol with DS3231 address and register 0
  Wire.beginTransmission(0x68);
  Wire.write(0);
  Wire.endTransmission(false);

  // Request 7 bytes from DS3231 and release I2C bus at end of reading
  // read registers 0 to 6
  Wire.requestFrom(0x68, 7);
  second = readRS3231();
  minute = readRS3231();
  hour = readRS3231();
  dayOfWeek = readRS3231();
  day = readRS3231();
  month = readRS3231();
  year = readRS3231();

  // daylight saving time adjustment
  if(daylight != DAYLIGHT_CANCEL)
    {
    // make sure adjustment is not done in the last 3 seconds of an hour
    if(minute < 59 && second < 57)
      {
      setClockModule(true);
      daylight = DAYLIGHT_CANCEL;
      }
    }

  // get temperature
  // Start I2C protocol with DS3231 address and register 17
  Wire.beginTransmission(0x68);
  Wire.write(17);
  Wire.endTransmission(false);

  // read temperature most and least significant bytes
  // Request 2 bytes from DS3231 and release I2C bus at end of reading
  Wire.requestFrom(0x68, 2);
  int temp_msb = Wire.read();
  int temp_lsb = Wire.read();

  // clock module temperature in 1/100 celsius
  int clockTemp = 25 * (((temp_msb << 8) | temp_lsb) >> 6);

  // call sensors.requestTemperatures() to issue a global temperature
  // request to all devices on the bus (we have only one)
  probeSensor->requestTemperatures();

  // get probe temperatore
  int probeTemp = probeSensor->getTemp((uint8_t*) deviceAddress);

  // convert to degree celcius
  // if error result will be PROBE_TEMP_ERROR -5500
  probeTemp = (int) ((25 * (long) probeTemp) >> 5);

  // clear display
  display.clearDisplay();

  // copy day of the week
  char* dayName = dayText[dayOfWeek - 1];
  byte strlen;
  for(strlen = 0; dayName[strlen] != 0; strlen++) dispStr[strlen] = dayName[strlen];

  // add one space
  dispStr[strlen++] = ' ';

  // Display the date year month day
  switch(dateStyle)
    {
    case DATE_FORMAT_YMD:
      dispStr[strlen++] = '2';
      dispStr[strlen++] = '0';
      dispStr[strlen++] = byteToChar1(year);
      dispStr[strlen++] = byteToChar2(year);
      dispStr[strlen++] = '/';
      dispStr[strlen++] = byteToChar1(month);
      dispStr[strlen++] = byteToChar2(month);
      dispStr[strlen++] = '/';
      dispStr[strlen++] = byteToChar1(day);
      dispStr[strlen++] = byteToChar2(day);
      break;

    case DATE_FORMAT_DMY:
      dispStr[strlen++] = byteToChar1(day);
      dispStr[strlen++] = byteToChar2(day);
      dispStr[strlen++] = '/';
      dispStr[strlen++] = byteToChar1(month);
      dispStr[strlen++] = byteToChar2(month);
      dispStr[strlen++] = '/';
      dispStr[strlen++] = '2';
      dispStr[strlen++] = '0';
      dispStr[strlen++] = byteToChar1(year);
      dispStr[strlen++] = byteToChar2(year);
      break;

    case DATE_FORMAT_MDY:
      dispStr[strlen++] = byteToChar1(month);
      dispStr[strlen++] = byteToChar2(month);
      dispStr[strlen++] = '/';
      dispStr[strlen++] = byteToChar1(day);
      dispStr[strlen++] = byteToChar2(day);
      dispStr[strlen++] = '/';
      dispStr[strlen++] = '2';
      dispStr[strlen++] = '0';
      dispStr[strlen++] = byteToChar1(year);
      dispStr[strlen++] = byteToChar2(year);
      break;
    }

  // Display the date year month day
  dispStr[strlen++] = 0;
  drawText(0, dispStr, 1);

  // Display the time
  char ampm;
  if(timeStyle == TIME_FORMAT_24)
    {
    dispStr[0] = byteToChar1(hour);
    dispStr[1] = byteToChar2(hour);
    }
  else
    {
    byte hour1 = hourToAMPM(&ampm);
    dispStr[0] = byteToChar1(hour1);
    dispStr[1] = byteToChar2(hour1);
    }
  dispStr[2] = ':';
  dispStr[3] = byteToChar1(minute);
  dispStr[4] = byteToChar2(minute);
  dispStr[5] = ':';
  dispStr[6] = byteToChar1(second);
  dispStr[7] = byteToChar2(second);

  if(timeStyle == TIME_FORMAT_24)
    {
    dispStr[8] = 0;
    }
  else
    {
    dispStr[8] = ampm;
    dispStr[9] = 'M';
    dispStr[10] = 0;
    }

  // display time
  drawText(15, dispStr, 2);
 
  // alarm is set
  if(alarmSet != 0)
    {
    strcpy_P(dispStr, (PGM_P) alarmSetStr);
    strlen = 10;
    if(timeStyle == TIME_FORMAT_24)
      {
      dispStr[strlen++] = byteToChar1(alarmHour);
      dispStr[strlen++] = byteToChar2(alarmHour);
      }
    else
      {
      byte hour1 = hourToAMPM(&ampm);
      dispStr[strlen++] = byteToChar1(hour1);
      dispStr[strlen++] = byteToChar2(hour1);
      }
    dispStr[strlen++] = ':';
    dispStr[strlen++] = byteToChar1(alarmMinute);
    dispStr[strlen++] = byteToChar2(alarmMinute);
    if(timeStyle == TIME_FORMAT_12)
      {
      dispStr[strlen++] = ampm;
      dispStr[strlen++] = 'M';
      }
    dispStr[strlen] = 0;
    drawText(33, dispStr, 1);
    }

  // convert clock module temperature to string
  tempToStr(clockTemp);

  // Display the temperature
  drawText(0, 45, (char*)"Local", 1);
  drawText(45, dispStr, 1);
  
  // convert to temperature to string
  tempToStr(probeTemp);

  // Display the temperature
  drawText(0, 57, (char*)"Probe", 1);
  drawText(57, dispStr, 1);

  // display temperature units
  display.drawCircle(110, 51, 3, WHITE);     // Put degree symbol ( ° )
  drawText(116, 48, tempUnit == TEMP_FORMAT_C ? (char*)"C" : (char*)"F", 2);

  // display normal clock screen  
  display.display();

  // test alarm
  if(alarmSet != 0)
    {
    switch(alarmState)
      {
      // wait for alarm hour and minute
      case ALARM_NOT_ACTIVE:
        if(hour == alarmHour && minute == alarmMinute)
          {
          digitalWrite(ALARM_BUZZER, LOW);
          alarmTimer = millis();
          alarmState = ALARM_ACTIVE;
          }
        break;

      // alarm is active
      // wait for alarm length in seconds
      case ALARM_ACTIVE:
        if((long) (millis() - alarmTimer) > 1000 * (long) alarmLength)
          {
          digitalWrite(ALARM_BUZZER, HIGH);
          alarmState = ALARM_RESET;
          }
        break;
      
      // wait until alarm start minute is over
      case ALARM_RESET:
        if(hour != alarmHour || minute != alarmMinute) alarmState = ALARM_NOT_ACTIVE;
        break;
      }
    }
  return;
  }

/////////////////////////////////////////////////////////////////////////
// set clock module parameters after user setup
/////////////////////////////////////////////////////////////////////////
void setClockModule
    (
    bool setDaylight  
    )
  {
  // Write data to DS3231 RTC
  Wire.beginTransmission(0x68); // Start I2C protocol with DS3231 address
  if(setDaylight)
    {
    // last day of the month
    byte lastDay = lastDayOfMonth[month];
    if(month == 2 && (year % 4) == 0) lastDay++;

    // daylight +1 hour adjustment
    if(daylight == DAYLIGHT_SPRING)
      {
      if(hour == 23)
        {
        hour = 0;
        if(day == lastDay)
          {
          day = 1;
          if(month == 12)
            {
            month = 1;
            if(year < 99) year++;
            }
          else
            {
            month++;
            }
          }
        else
          {
          day++;
          }
        }
      else
        {
        hour++;
        }
      }

    // daylight +1 hour adjustment
    else
      {
      if(hour == 0)
        {
        hour = 23;
        if(day == 1)
          {
          if(month == 1)
            {
            month = 12;
            if(year > 0) year--;
            }
          else
            {
            month--;
            }
          day = lastDay;
          }
        else
          {
          day--;
          }
        }
      else
        {
        hour--;
        }
      }
    Wire.write(2);              // Send register address (hour)
    }
  else
    {
    Wire.write(0);              // Send register address (seconds)
    Wire.write(0);              // Reset seconds
    writeRS3231(minute);        // Write minute
    }
  writeRS3231(hour);            // Write hour
  dayOfWeek = dayOfTheWeek();   // calculate day of the week from date
  writeRS3231(dayOfWeek);       // Write day of the week
  writeRS3231(day);             // Write day of the month
  writeRS3231(month);           // Write month
  writeRS3231(year);            // Write year
  Wire.endTransmission();       // Stop transmission and release the I2C bus
  delay(200);                   // Wait 200ms
  return;
  }

/////////////////////////////////////////////////////////////////////////
// save in eeprom display style flags
// year, month and day of the month
// time in 24 hours clock and 12 hours clock
// temperature units degree C or F
// alarm set
/////////////////////////////////////////////////////////////////////////
void saveDisplayFormat()
  {
  // test for parameters change
  byte newParameters = dateStyle | (timeStyle << 2) | (tempUnit << 3) | (alarmSet << 4);
  if(newParameters != eepromFlags)
    {
    // write setup parameters to eeprom
    EEPROM.write(EEPROM_SETUP_INDEX, newParameters);
    eepromFlags = newParameters;
    }
  return;
  }

/////////////////////////////////////////////////////////////////////////
// save alarm hour, minute and length
/////////////////////////////////////////////////////////////////////////
void saveAlarmParameters()
  {
  // alarm hour
  if(alarmHour != eepromAlarmHour)
    {
    eepromAlarmHour = alarmHour;
    EEPROM.write(EEPROM_ALARM_HOUR, eepromAlarmHour);
    }

  // alarm minute
  if(alarmMinute != eepromAlarmMinute)
    {
    eepromAlarmMinute = alarmMinute;
    EEPROM.write(EEPROM_ALARM_MINUTE, eepromAlarmMinute);
    }
    
  // alarm length
  if(alarmLength != eepromAlarmLength)
    {
    eepromAlarmLength = alarmLength;
    EEPROM.write(EEPROM_ALARM_LENGTH, eepromAlarmLength);
    }
  return;
  }

/////////////////////////////////////////////////////////////////////////
// display setup menu
/////////////////////////////////////////////////////////////////////////
void displaySetupMenu()
  {
  // clear display
  display.clearDisplay();

  // parameter name
  const char* name;

  // switch based on parameter
  switch(setupIndex)
    {
    case SETUP_SUB_MENU:
      drawText(0, selectMenuHeading, 1, false);
      submenu = MAIN_MENU_ALARM;
      drawMainMenuParam();
      paramPtr = &submenu;
      return;
      
    case SETUP_ALARM_SET:
      drawText(0, alarmOnOffMenuHeading, 1, false);
      drawAlarmOnOffMenu();
      paramPtr = &alarmSet;
      return;

    case SETUP_DAYLIGHT_START:
      drawText(0, DaylightMenuHeading, 1, false);
      drawDaylightMenu();
      paramPtr = &daylight;
      return;
      
    case SETUP_DATE_STYLE:
      if(dateStyle > 2) dateStyle = 0;
      drawText(0, dateStyleMenuHeading, 1, false);
      drawDateStyleMenu();
      paramPtr = &dateStyle;
      return;
      
    case SETUP_TIME_STYLE:
      if(timeStyle > 1) timeStyle = 0;
      drawText(0, timeStyleMenuHeading, 1, false);
      drawTimeStyleMenu();
      paramPtr = &timeStyle;
      return;
      
    case SETUP_TEMP_UNIT:
      if(tempUnit > 1) tempUnit = 0;
      drawText(0, tempUnitMenuHeading, 1, false);
      drawTempUnitMenu();
      paramPtr = &tempUnit;
      return;

    case SETUP_ALARM_HOUR:
      name = hourStr;
      paramPtr = &alarmHour;
      break;
      
    case SETUP_ALARM_MINUTE:
      name = minuteStr;
      paramPtr = &alarmMinute;
      break;
      
    case SETUP_ALARM_LENGTH:
      name = lengthStr;
      paramPtr = &alarmLength;
      break;
      
    case SETUP_YEAR:
      name = yearStr;
      paramPtr = &year;
      break;
      
    case SETUP_MONTH:
      name = monthStr;
      if(month == 0) month++;
      paramPtr = &month;
      break;
      
    case SETUP_DAY:
      name = dayStr;
      if(day == 0) day++;
      paramMax[SETUP_DAY] = lastDayOfMonth[month - 1];
      if(month == 2 && (year % 4) == 0) paramMax[SETUP_DAY]++;
      paramPtr = &day;
      break;
      
    case SETUP_HOUR:
      name = hourStr;
      paramPtr = &hour;
      break;
      
    case SETUP_MINUTE:
      name = minuteStr;
      paramPtr = &minute;
      break;

    }

  // make sure parameter is within limits
  if(paramPtr[0] > paramMax[setupIndex]) paramPtr[0] = paramMax[setupIndex];

  drawText(0, setupStr, 1, false);
  drawText(22, name, 2, false);
  displaySetupMenuParameters();
  return;
  }

/////////////////////////////////////////////////////////////////////////
// display one of the setup menus
/////////////////////////////////////////////////////////////////////////
void displaySetupMenuParameters()
  {
  switch(setupIndex)
    {
    case SETUP_SUB_MENU:
      drawMainMenuParam();
      return;

    case SETUP_ALARM_SET:
      drawAlarmOnOffMenu();
      return;

    case SETUP_DAYLIGHT_START:
      drawDaylightMenu();
      return;

    case SETUP_DATE_STYLE:
      drawDateStyleMenu();
      return;

    case SETUP_TIME_STYLE:
      drawTimeStyleMenu();
      return;

    case SETUP_TEMP_UNIT:
      drawTempUnitMenu();
      return;

    case SETUP_YEAR:
      dispStr[0] = '2';
      dispStr[1] = '0';
      dispStr[2] = byteToChar1(paramPtr[0]);
      dispStr[3] = byteToChar2(paramPtr[0]);
      dispStr[4] = 0;
      drawText(44, dispStr, 2);
      break;

    case SETUP_HOUR:
      if(timeStyle == TIME_FORMAT_12)
        {
        char ampm;
        byte hour1 = hourToAMPM(&ampm);
        dispStr[0] = byteToChar1(hour1);
        dispStr[1] = byteToChar2(hour1);
        dispStr[2] = ampm;
        dispStr[3] = 'M';
        dispStr[4] = 0;
        drawText(44, dispStr, 2);
        break;
        }

    default:
      dispStr[0] = byteToChar1(paramPtr[0]);
      dispStr[1] = byteToChar2(paramPtr[0]);
      dispStr[2] = 0;
      drawText(44, dispStr, 2);
      break;
    }
  display.display();
  return;
  }

/////////////////////////////////////////////////////////////////////////
// draw select menu choices
/////////////////////////////////////////////////////////////////////////
void drawMainMenuParam()
  {
  drawText(13, 16, selectMenuAlarm, 1, submenu == MAIN_MENU_ALARM);
  drawText(13, 28, selectMenuDateTime, 1, submenu == MAIN_MENU_DATE_TIME);
  drawText(13, 40, selectMenuDaylight, 1, submenu == MAIN_MENU_DAYLIGHT);
  drawText(13, 52, selectMenuDispStyle, 1, submenu == MAIN_MENU_DISP_STYLE);
  display.display();
  return;
  }

/////////////////////////////////////////////////////////////////////////
// draw alarm clock on or off
/////////////////////////////////////////////////////////////////////////
void drawAlarmOnOffMenu()
  {
  drawText(19, 28, alarmOnOffMenuOff, 1, alarmSet == 0);
  drawText(19, 40, alarmOnOffMenuOn, 1, alarmSet == 1);
  display.display();
  return;
  }

/////////////////////////////////////////////////////////////////////////
// draw daylight saving time
/////////////////////////////////////////////////////////////////////////
void drawDaylightMenu()
  {
  drawText(19, 28, DaylightMenuCancel, 1, daylight == DAYLIGHT_CANCEL);
  drawText(19, 40, DaylightMenuSpring, 1, daylight == DAYLIGHT_SPRING);
  drawText(19, 52, DaylightMenuFall, 1, daylight == DAYLIGHT_FALL);
  display.display();
  return;
  }

/////////////////////////////////////////////////////////////////////////
// draw date style menu choices
/////////////////////////////////////////////////////////////////////////
void drawDateStyleMenu()
  {
  drawText(16, 28, dateStyleMenuYMD, 1, dateStyle == 0);
  drawText(16, 40, dateStyleMenuDMY, 1, dateStyle == 1);
  drawText(16, 52, dateStyleMenuMDY, 1, dateStyle == 2);
  display.display();
  return;
  } 

/////////////////////////////////////////////////////////////////////////
// draw time style menu choices
/////////////////////////////////////////////////////////////////////////
void drawTimeStyleMenu()
  {
  drawText(16, 28, timeStyleMenu24, 1, timeStyle == 0);
  drawText(16, 40, timeStyleMenu12, 1, timeStyle == 1);
  display.display();
  return;
  } 

/////////////////////////////////////////////////////////////////////////
// draw temperature units choices 
/////////////////////////////////////////////////////////////////////////
void drawTempUnitMenu()
  {
  drawText(16, 28, tempUnitMenuC, 1, tempUnit == 0);
  drawText(16, 40, tempUnitMenuF, 1, tempUnit == 1);
  display.display();
  return;
  }

/////////////////////////////////////////////////////////////////////////
// convert raw temperatur to string
/////////////////////////////////////////////////////////////////////////
void tempToStr
    (
    int temp
    )
  {
  // convert temperature to Fahrenheit
  if(tempUnit != 0)
    {
    temp = (int) (((long) temp * 9) / 5) + 3200;
    }

  // string length
  byte strLen = 0;

  // negative temperature
  if(temp < 0)
    {
    temp = -temp;
    dispStr[0] = '-';
    strLen++;
    }
  
  // remove leading zeros
  bool noZero = false;

  // hundreds
  byte digit = (byte) (temp / 10000);
  if(digit > 0)
    {
    dispStr[strLen++] = digit + '0';
    temp -= 10000 * (int) digit;
    noZero = true;
    }

  // tens
  digit = (byte) (temp / 1000);
  if(digit > 0 || noZero)
    {
    dispStr[strLen++] = digit + '0';
    temp -= 1000 * (int) digit;
    noZero = true;
    }

  // ones
  digit = (byte) (temp / 100);
  dispStr[strLen++] = digit + '0';
  temp -= 100 * digit;

  // decimal point
  dispStr[strLen++] = '.';

  // one tenth
  digit = (byte) (temp / 10);
  dispStr[strLen++] = digit + '0';
  temp -= 10 * digit;

  // last digit 1/100
  dispStr[strLen++] = (byte) temp + '0';
  
  // terminating null
  dispStr[strLen++] = 0;

  // for debugging only
  //getFreeMemory();

  // return
  return;
  }

/////////////////////////////////////////////////////////////////////////
// read one register from real time clock
/////////////////////////////////////////////////////////////////////////
byte readRS3231()
  {
  // Read seconds from RS3231 register
  byte value = Wire.read();

  // convert bcd to integer
  value = (value >> 4) * 10 + (value & 0x0F);
  return value;
  }

/////////////////////////////////////////////////////////////////////////
// write one register to real time clock
/////////////////////////////////////////////////////////////////////////
void writeRS3231
    (
    byte value
    )
  {
  // Convert decimal to BCD and write to RS3231
  Wire.write(((value / 10) << 4) + (value % 10));
  return;
  }

/////////////////////////////////////////////////////////////////////////
// draw text to screen
/////////////////////////////////////////////////////////////////////////
void drawText(byte x_pos, byte y_pos, char *text, byte text_size)
  {
  display.setCursor(x_pos, y_pos);
  display.setTextSize(text_size);
  display.print(text);
  return;
  }

/////////////////////////////////////////////////////////////////////////
// draw text to screen. Text will be centered
/////////////////////////////////////////////////////////////////////////
void drawText(byte y_pos, char *text, byte text_size)
  {
  byte len;
  for(len = 0; text[len] != 0l; len++);
  drawText((byte) (128 - 6 * len * text_size) / 2, y_pos, text, text_size);
  return;
  }

/////////////////////////////////////////////////////////////////////////
// draw text stored in PROGMEM to the screen
/////////////////////////////////////////////////////////////////////////
void drawText(byte x_pos, byte y_pos, const char* text, byte text_size, bool highlight)
  {
  strcpy_P(dispStr, (PGM_P) text);
  if(highlight) display.setTextColor(BLACK,WHITE);
  drawText(x_pos, y_pos, (char*) dispStr, text_size);
  if(highlight) display.setTextColor(WHITE,BLACK);
  return;
  }

/////////////////////////////////////////////////////////////////////////
// draw text stored in PROGMEM to the screen
// text will be centered
/////////////////////////////////////////////////////////////////////////
void drawText(byte y_pos, const char* text, byte text_size, bool highlight)
  {
  strcpy_P(dispStr, (PGM_P) text);
  if(highlight) display.setTextColor(BLACK,WHITE);
  drawText(y_pos, (char*) dispStr, text_size);
  if(highlight) display.setTextColor(WHITE,BLACK);
  return;
  }

/////////////////////////////////////////////////////////////////////////
// calculate day of the week (1-Sunday to 7-Saturady)
// from year, month and day of the month
// will work for 2000 to end of 2099
/////////////////////////////////////////////////////////////////////////
byte dayOfTheWeek()
  {
	// leap year stuff
	byte year2 = year / 4;
	byte year3 = year - 4 * year2;

 	// day of the year
  int dayno = 1461 * year2 + 365 * year3 + day + 5;
  int end = month - 1;
  for(int m = 0; m < end; m++) dayno += lastDayOfMonth[m];
  
  // add one for any date not in leap year or
  // any date on or after march 1 of leap year 
  if(year3 > 0 || month > 2) dayno++;

	// final calculation
  return (byte) ((dayno % 7) + 1);
  }

/////////////////////////////////////////////////////////////////////////
// convert hour in 24 hour format to 12 hour format
/////////////////////////////////////////////////////////////////////////
byte hourToAMPM
    (
    char* ampm  
    )
  {
  // midnight
  if(hour == 0)
    {
    ampm[0] = 'A';  
    return 12;
    }
  // before noon
  if(hour < 12)
    {
    ampm[0] = 'A';  
    return hour;
    }
  // noon time
  if(hour == 12)
    {
    ampm[0] = 'P';  
    return 12;
    }
  // afternoon
  ampm[0] = 'P';
  return hour - 12;
  }

/////////////////////////////////////////////////////////////////////////
// find out how much free memory is available
// for debugging only
/////////////////////////////////////////////////////////////////////////
/*
#ifdef __arm__
// should use uinstd.h to define sbrk but Due causes a conflict
extern "C" char* sbrk(int incr);
#else  // __ARM__
extern char *__brkval;
#endif  // __arm__

extern char *__brkval;
int freeMemory()
  {
    char top;

  #ifdef __arm__
    return &top - reinterpret_cast<char*>(sbrk(0));
  #elif defined(CORE_TEENSY) || (ARDUINO > 103 && ARDUINO != 151)
    return &top - __brkval;
  #else  // __arm__
    return __brkval ? &top - __brkval : &top - __malloc_heap_start;
  #endif  // __arm__
  }

void getFreeMemory()
  {
  char memStr[5];
  int memLen = freeMemory();
  byte digit = (byte) (memLen / 1000);
  memStr[0] = digit + '0';
  memLen -= 1000 * (int) digit;

  digit = (byte) (memLen / 100);
  memStr[1] = digit + '0';
  memLen -= 100 * digit;

  digit = (byte) (memLen / 10);
  memStr[2] = digit + '0';
  memLen -= 10 * digit;

  // last digit 1/100
  memStr[3] = (byte) memLen + '0';

  // terminating null
  memStr[4] = 0;
  drawText(0, 33, memStr, 1);
  return;
  }
*/

What led you to choose this code for your project? I mean, what led you to believe that this would provide an appropriate base for you to work from? This seems much, much more complicated than what you need.

How do you intend to adjust the duration of the "alarm"? You have not specified how you intend to adjust the duration. Also, why is the duration important? You don't intend to control the angle the hands move by controlling the duration of the pulse, do you?

My code to do this would have a loop something like this:

void loop() {
  readRtcSeconds();
  // wait until the seconds are 59
  while (rtcSeconds != 59) {
    readRtcSeconds();
  }
  // turn the clock motor on for 1 second
  digitalWrite(MOTOR_PIN, HIGH);
  delay(1000);
  // turn the clock motor off and wait 1 second (as insurance)
  digitalWrite(MOTOR_PIN, LOW);
  delay(1000);
}

Of course, I would have to define a constant for MOTOR_PIN and a variable for rtcSeconds. I would also have to write the function readRtcSeconds(). But this gives you a general idea of my approach.

Above all else, I would not be taking a project intended to do something completely different and trying to somehow force it to be something it is not. See XY problem.

Hello, Thank you for the quick answer, the code already has the function for adjusting the alarm duration from 1 to 99 seconds.
I want to use the output for the alarm (pin 3) to control the gate of a mosfet which in turn will control the power supply for the 12V DC electric motor.

I would like you to help me if you can modify the code in such a way that the alarm rings once every minute and the duration of the ringing can be adjusted in the range of 0.1 - 1 seconds in steps of 0.1 seconds ( if is possible)
Thank you

Do you have any knowledge of coding at all? Do you have any desire to learn? Or do you just want someone to hand you the solution?

Keep in mind that this code is much more complicated than you need, with many parts which are irrelevant to what you are trying to achieve. Writing a new alarm time to your EEPROM once each minute will burn out your EEPROM within a few months.

Have you already purchased the hardware for this project, including the display? I ask this because I don't think you need this much hardware, because I don't think you need this complicated a project for what you are trying to do. You do, of course, need the RTC in order to make your clock keep reasonably accurate time.

It is not hard to read just the seconds from an RTC, since the seconds are what you care about.

It is not hard to set a digital pin HIGH for 500 (or 600, or 700, or... ) milliseconds and then set it LOW. You can declare some of the Arduino's pins to be INPUT_PULLUPs and then use those as inputs to select the duration you want (with appropriate coding, of course).

Now, I ask you again: are you interested in learning, or do you just want someone to hand you the solution? If it is the latter, then I strongly suggest you post to: Jobs and Paid Consultancy - Arduino Forum

There is no single function for alarm setup in your code. So there is nothing to edit.

The code is a very complex clock project with a lot of functions. I agree with @odometer that in order to move the motor once a minute - this code is a very poor example for reworking. It's like dismantling a truck in order to find an ordinary screw that can be bought at any store for a couple of cents.

Hello, I agree with you.
I need a clock based on RTC that has an LCD and buttons for adjusting the current time and date and the possibility to set an alarm that rings once a minute.
The length of the alarm signal must be able to be set in the range of 1 - 3000 ms.

Or maybe it would be better to drive a stepper motor and be able to set the number of steps it must take once a minute?
Thank you

Whoa. You are trying to control the angle the hands move by controlling the duration of the pulse, aren't you? You do of course realize that small errors will accumulate, and so even a 1% error will mean that your clock will be wrong by about 15 minutes in 24 hours, don't you? You see the problem here.

Yes. Yes, it would be better. Much better. You could in fact use gear ratios to calculate the exact number of steps you would need to move the hands to the next minute. (You would also need to know how many steps per revolution your motor is.) But... for this to work at all, you would need a stepper motor that would provide enough torque to turn the hands of your clock, and be able to handle the weight of those hands. I have no idea about the exact size or weight of the hands of your clock, and I do not know how difficult or expensive it would be to obtain a suitable stepper motor.

I just realized something. You could make this work without a stepper motor, with just your regular DC motor, if you attach some kind of sensor to the mechanism to sense how far the hands have turned (so that the mechanism knows when it is time to stop the motor). But, at this point, it has become a hardware question, and I'm sorry, but I don't have the expertise to help you further.

Hello @odometer :slight_smile:
Can you help me with a code for Arduino + I2C LCD + DS3231 RTC + TB6600 stepper driver that will give me the command to the steper motor once per minute?
It should also have 3 or 4 buttons from which to set the exact time and the number of steps the motor must take.
​The clock is very old and was designed in such a way that the mechanism moves only once per minute - I think to reduce wear and tear on the mechanism over time.

I am 1000000% convinced that you can help me - everything is to have time and want.
Thank you

Why do you need to set the number of steps the motor must take using buttons? Do you not already know the number of steps the motor must take?

All right, what kind of mechanism are we talking about here? What is the procedure for setting the time? Do you rotate a knob, or repeatedly raise and lower a lever, or what? Can you turn the hands of the clock backwards, or only forwards?

I am trying to understand the problem, because any solution has to be appropriate to the specific problem you are trying to solve, or else it will be no use to you.

How is it that you are in doubt as to the correct number of steps that the motor must take each minute? What leads you to believe that making the number of steps adjustable by buttons is part of the correct solution?

Hello, Up until now the clock has worked powered by a motor from a windshield wiper that must make a complete rotation once per minute. This system worked quite well, but being a brush motor, it doesn't last long. I agree with you that the number of steps could be adjusted only from the code. Due to the fact that I still don't know which gear stepper motor i will find here, I should be able to adjust the number of steps in the code.
The mechanism can be rotated in both directions - if that would help us turn back time it would be perfect :slight_smile:
I found this stepper motor and I think it would be suitable for the clock.
17HS13-0404S-PG27.pdf (413.8 KB)

Thank you @odometer

When you were using the windshield wiper motor, what did you use to control the timing and make it one rotation per minute?

you will laugh until all the neighbors will hear you when you find out. I used a mechanical car clock from an old Mercedes :slight_smile:

Do you already have the Arduino and the DS3231? I am going to ask you to try something out to see if it works.

This code is supposed to read the seconds from the RTC and show them on the Serial monitor. Try it and see what you get. (You will need to set Serial baud rate to 115200 for it to work, because that is what it says in the code. And, of course, you will also need to have your DS3231 properly wired up to your Arduino, otherwise the Arduino will not be able to read the time.)

#include <Wire.h>

byte ss=0;
 
void setup()
{
  Wire.begin();
  Serial.begin(115200);
}

void loop()
{
  // ask RTC for the time
  // send request to receive data starting at register 0
  Wire.beginTransmission(0x68); // 0x68 is DS3231 device address
  Wire.write((byte)0); // start at register 0
  Wire.endTransmission();
  Wire.requestFrom(0x68, 1); // request one byte (seconds)
  // check for a reply from the RTC, and use it if we can
  if (Wire.available()) { 
    // if we're here, we got a reply
    // so now we read the seconds
    ss = bcd2bin(Wire.read()); // get seconds
    // show that we successfully got the seconds
    Serial.print("Seconds are: ");
    Serial.println(ss, DEC);
  }
  else {
    // if we're here, that means we were unable to read the time
    Serial.println("Unable to read time from RTC"); 
  }
  delay(200);
}

byte bcd2bin(byte x) {
  // converts from binary-coded decimal to a "regular" binary number
  return ((((x >> 4) & 0xF) * 10) + (x & 0xF)) ;
}

Hello @odometer
This is my serial monitor output:

We can see from that Serial output that your RTC is running: we see the seconds changing.

Next, you will need to write code that moves the motor exactly one revolution, and then stops. If you are going to use a stepper motor for this, I think you should wait until you actually obtain the stepper motor, so you can test it and make sure it works properly. Do you have the stepper motor? Did it come with example code for making the motor rotate?

What exactly do you need the motor to do every minute? Turn one revolution? Or some other amount?

Would you mind posting a picture of your clock mechanism, specifically, of the part that gets moved to make the hands move every minute? Is it a gear, cam, or what?

I ordered a stepper motor but it hasn't arrived yet.
Every minute the motor axis must make a complete rotation and then stop.
The clock is in the tower of a church about 50 km from here.
As I told you, the clock mechanism can be rotated in both directions.
I think it would also be useful to have a way to adjust the time also from the program-
it could be made to rotate continuously until the exact time is set and then to stop at the press of a button.

When you said that I had to write the code for the watch, I looked behind and thought you saw a programmer next to me and I don't see him :slight_smile:

Like I said in a previous message:
If you want someone else to do all the coding for you, then you need to post, not to here, but rather, to the Jobs and Paid Consultancy section of the forum.
Link: Jobs and Paid Consultancy - Arduino Forum

I ask you again:
Do you have any intention of learning to code? Or are you hoping that you will simply be handed the code you ask for?

I have already gone as far as giving you code to read the seconds from the RTC. Now you can write code that will check to see if those seconds are 59, and if they are, then move the motor one revolution, and wait at least one second before moving the motor again.

If it is your intention to simply wait until the code you desire is written for you, then I expect you have a long wait ahead of you, unless perhaps if you post to the Jobs and Paid Consultancy section and express a willingness to pay for the code to be written for you.

I honestly expected to find someone of good faith who can write this code when he has time out of passion. I also install this mechanism without asking for anything in return. If you say I'm in the wrong area, I don't mind - I'll look elsewhere if you say so.
Thank you

Do you know what is the paradox of the days we live in?
We would rather receive help from machines than from our peers.
That's what chat GPT wrote in a few seconds.....

#include <Wire.h>
#include <RTClib.h>
#include <Stepper.h>
#include <LiquidCrystal_I2C.h>

const int stepsPerRevolution = 200;
Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);

RTC_DS3231 rtc;
LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup() {
  Serial.begin(9600);

  if (!rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  if (rtc.lostPower()) {
    Serial.println("RTC lost power, let's set the time!");
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }

  lcd.init();
  lcd.backlight();
  myStepper.setSpeed(10);
}

void loop() {
  DateTime now = rtc.now();

  lcd.clear();
  
  // Display the date
  lcd.print(now.year(), DEC);
  lcd.print('/');
  lcd.print(now.month(), DEC);
  lcd.print('/');
  lcd.print(now.day(), DEC);
  lcd.setCursor(0, 1); // Move to the second line
  
  // Display the time
  lcd.print(now.hour(), DEC);
  lcd.print(':');
  lcd.print(now.minute(), DEC);
  lcd.print(':');
  lcd.print(now.second(), DEC);

  if (now.second() == 59) {
    rotateStepper();
  }

  delay(1000);
}

void rotateStepper() {
  for (int i = 0; i < stepsPerRevolution; i++) {
    myStepper.step(1);
    delay(10);
  }
}

From the guide How to get the best out of this forum: