Crear bucle para establecer fecha y hora a modulo RTC mediante botones

Saludos, hace unos meses atrás consulté sobre como mantener el estado actual de las salidas en función de la hora del día, es decir, si es de día mantener salida apagada o si es de noche, mantener encendida. Afortunadamente logré subsanar ese inconveniente mediante el uso de la EEPROM de Arduino. Ahora el asunto que nuevamente me trae por acá es el hecho de saber cómo hacer para que mediante varios botones yo pueda establecer la fecha y la hora del módulo RTC I2C DS3231 sin necesidad de recurrir a la línea de código. He intentado hacerlo mediante contadores que se incrementen o decrementen y que esos valores sean tomados por la Tarjeta para establecerlos como fecha y hora pero no he podido lograr mi objetivo. ¿Que me sugieren que haga al respecto?. Gracias por la colaboración.

Ahora el asunto que nuevamente me trae por acá es el hecho de saber cómo hacer para que mediante varios botones yo pueda establecer la fecha y la hora del módulo RTC I2C DS3231 sin necesidad de recurrir a la línea de código.

Qué quieres decir con "sin necesidad de recurrir a la línea de código"?

Saludos, me disculpo por la respuesta a ese hilo y por esta si no respondí a tiempo. Cuando hice mención a "sin recurrir a la linea de código" quise referirme al hecho de que actualmente al modulo RTC para modificar hora y fecha, debo hacerlo mediante el IDE. Lo que quiero es simplemente crear un menú que me permita modificar y/o ajustar lo siguiente:

1.- Fecha y Hora
2.- Ajustar Hora de encendido y apagado
3.- Encender o apagar luces de manera manual.

Buscando información en Internet me topé con FSM para diseñar un menú y pensé en crear variables que me permitan almacenar bien sea en la EEPROM de Arduino o en una externa la información que quiero modificar y que la tarjeta la tome como valor para fijar tales parámetros. Al principio hice el conexionado con botones en configuración pull-up y después intente usar un rotary encoder para desplazarme por las diferentes opciones del menú. ¿que me sugieren hacer?

Aqui les dejo el codigo que a traves de un video tutorial pude reescribirpero que sin embargo no funciona:

#include <LCD.h>
#include <LiquidCrystal.h>
#include <LiquidCrystal_I2C.h>


#include <Wire.h>

#define I2C_ADDR 0x27

#define S_HOME 0
#define S_SET_RED 1
#define S_SET_GREEN 2
#define S_SET_BLUE 3

uint8_t estado = S_HOME; //Estado Actual

#define BTN_MENU 0
#define BTN_EXIT 1
#define BTN_UP 2
#define BTN_DOWN 3

uint8_t r = 0, g = 0, b = 0;

uint8_t button[4] {2, 3, 4, 5};

uint8_t button_state[4];

uint8_t flancoSubida(int btn)//Detección del flanco de subida
{
  uint8_t valor_nuevo = (digitalRead[btn]);
  uint8_t result = button_state[btn] != valor_nuevo && valor_nuevo == 1;
  button_state[btn] = valor_nuevo;
  return result;
}

LiquidCrystal_I2C lcd(I2C_ADDR, 2, 1, 0, 4, 5, 6, 7);

void setup()
{
  lcd.setBacklightPin(3, POSITIVE);
  lcd.setBacklight(HIGH);
  pinMode(button[BTN_MENU], INPUT_PULLUP);
  pinMode(button[BTN_EXIT], INPUT_PULLUP);
  pinMode(button[BTN_UP], INPUT_PULLUP);
  pinMode(button[BTN_DOWN], INPUT_PULLUP);

  button_state[0] = HIGH;
  button_state[1] = HIGH;
  button_state[2] = HIGH;
  button_state[3] = HIGH;

  printHome();
}
/** Inicio de funciones de dibujado de mensajes **/

void printHome()
{
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("[MENU] Set RGB");
  printColor();
}

void printRed()
{
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("[MENU] Set Red");
  printColor();
}

void printGreen()
{
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("[MENU] Set Green");
  printColor();
}

void printBlue()
{
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("[MENU] Set Blue");
  printColor();
}

void printColor()
{
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("RGB: ");
  lcd.print(r, DEC);
  lcd.print(" ");
  lcd.print(g, DEC);
  lcd.print(" ");
  lcd.print(b, DEC);
}
void loop()
{
  switch (estado)
  {
    case S_HOME:                    //inicio home
      if (flancoSubida[BTN_MENU])
      {
        estado = S_SET_RED;
        printRed();
        lcd.setBacklight(HIGH);
        break;
      }
      break;                        //fin home

    case S_SET_RED:                 //inicio rojo
      {
        if (flancoSubida[BTN_MENU])
        {
          estado = S_SET_GREEN;
          printGreen();
          break;
        }
      }
      if (flancoSubida[BTN_EXIT])
      {
        estado = S_HOME; //(Evento de salida) repetir en cada estado.
        printHome();
      }
      break;

      if (flancoSubida[BTN_UP])
      {
        if (r < 255)
        {
          r++;
          printRed();
        }
        else
        {
          r = 0;
        }
        break;
      }
      if (flancoSubida[BTN_DOWN])
      {
        if (r > 0)
        {
          r--;
        }
        else
        {
          r = 255;
        }
        printRed();
        break;
      }                 //Fin rojo
    case S_SET_GREEN:
      if (flancoSubida[BTN_MENU])
      {
        estado = S_SET_BLUE;
        printBlue();
        break;
      }
      if (flancoSubida[BTN_EXIT])
      {
        estado = S_HOME; //(Evento de salida) repetir en cada estado.
        printHome();
        break;
      }
      if (flancoSubida[BTN_UP])
      {
        if (g < 255)
        {
          g++;
          printGreen();
        }
        else
        {
          g = 0;
        }
        break;
      }
      if (flancoSubida[BTN_DOWN])
      {
        if (g > 0)
        {
          g--;
        }
        else
        {
          g = 255;
        }
        printGreen();

        break;

      }
    case S_SET_BLUE:
      if (flancoSubida[BTN_MENU])
      {
        estado = S_SET_RED;
        printBlue();
        break;
      }
      if (flancoSubida[BTN_EXIT])
      {
        estado = S_HOME; //(Evento de salida) repetir en cada estado.
        printHome();
        break;
      }
      if (flancoSubida[BTN_UP])
      {
        if (b < 255)
        {
          b++;
          printBlue();
        }
        else
        {
          b = 0;
        }
        break;
      }
      if (flancoSubida[BTN_DOWN])
      {
        if (b > 0)
        {
          b--;
        }
        else
        {
          b = 255;
        }
        printBlue();
        break;
      }
  }
}

Tanto la pantalla como el modulo RTC estan conectados via I2C a Arduino. este codigo lo copie tal cual del tutorial antes mencionado para efectuarla prueba, dado que, intente adecuarlo a un codigo original de mi autoria pero igual no pude hacerlo funcionar. Gracias de antemano.

Si solo necesitas poner la hora, te doy la solución que yo he usado alguna vez y con un solo botón.
Cuando se desajusta, simplemente espero a que sean las 12h 00' (u otra que quieras) y al pulsar el botón llama a una rutina para ajustarlo a esa hora y minuto. Y asunto resuelto.

Hola,
Mira te pongo mi código para hacer precisamente lo que quieres, lo hice en mi primer proyecto así que seguro es mejorable.
El código esta pensado para usarlo con 2 botones analógicos conectados en dos pines analógicos, se podría haber hecho en un solo pin pero come en este caso me sobraban pues utilice 2.
Primero el método que comprueba que si se a pulsado una tecla

// Metodo para comprobar pulsacion de tecla
byte ComprobarPulsacion(int intervalo)
{
	byte pulsada=0;
	long tpulsa = millis();
	do
	{
	if (int(analogRead(A1)) > 200) // Segun la rersistencia de pup-up el valor de comparación puede variar
	{
		pulsada = 1;
		digitalWrite(leddisplaypin, HIGH); // Enciendo el backgraud del display
	}
	if (int(analogRead(A2)) > 200) // Segun la rersistencia de pup-up el valor de comparación puede varia
	{
		pulsada = 2;
		digitalWrite(leddisplaypin, HIGH); // Enciendo el backgraud del display
	}
	// Si la alguna tecla es pulsada nos mantenemos en el bucle hasta soltarla o pasan el tiempo prefijado en intervalo
	// Si no hay tecla pulsada sale inmediatamente.
	} while ((int(analogRead(A1)) > 200 && (millis() - tpulsa) < intervalo) || (int(analogRead(A2)) > 200 && (millis() - tpulsa) < intervalo));
	return pulsada; // Debuelvo que tecla ha sido pulsada 0 ninguna, 1 tecla 1, 2 tecla 2
}

Ahora el menú en si que edita la fecha y hora, esta poco comentado pero creo que se entiende bien, destacar que lo pensé para un LCD de 2X16. Es posible que tengas que modificar algo según lo que uses tú.

void mhora()
{
	int hora = rtc.now().hour();
	int minutos = rtc.now().minute();
	int mes = rtc.now().month();
	int ano = rtc.now().year();
	int dias = rtc.now().day();;
	int diasmax[12]{ 31,28,31,30,31,30,31,31,30,31,30,31 };
	int cursor = 5;
	byte h1, h2,m1,m2, d1, d2, me1, me2, a1, a2, a3, a4;
	h1 = hora / 10;
	h2 = hora % 10;
	m1 = minutos / 10;
	m2 = minutos % 10;
	d1 = dias / 10;
	d2 = dias % 10;
	me1 = mes / 10;
	me2 = mes % 10;
	a1 = ano / 1000;
	a2 = (ano % 1000) /100;
	a3 = ((ano % 1000) % 100) /10;
	a4 = ((ano % 1000) % 100) % 10;
	lcd.clear();
	lcd.setCursor(2, 0);
	lcd.print("EDITAR HORA");
	lcd.setCursor(5, 1);
	ImprimirHora(hora, minutos);
	lcd.blink();
	do
	{
		lcd.setCursor(cursor, 1);
		teclapulsada = ComprobarPulsacion(500);
		if (teclapulsada == 1) // Pulsada tecla edición de numero
		{
			teclapulsada = 0;// Reseteo la pulsación de tecla
			if (cursor == 5) { h1++; }
			if (cursor == 6) { h2++; }
			if (cursor == 8) { m1++; }
			if (cursor == 9) { m2++; }
			if (h1 > 2) { h1 = 0; }
			if ((h1 > 1 && h2 > 3)|| h2 >9) { h2 = 0; }
			if (m1 > 5) { m1 = 0; }
			if (m2 > 9) { m2 = 0; }
			hora = h1 * 10 + h2;
			minutos = m1 * 10 + m2;
			lcd.setCursor(5, 1);
			ImprimirHora(hora, minutos);
			lcd.setCursor(5, 1);
		}
		if (teclapulsada == 2) // Pulsada tecla pasar al siguiente
		{
			teclapulsada = 0;// Reseteo la pulsación de tecla
			cursor++;// Desplazo el cursor una posición
			if (cursor == 7 ) { cursor++; } // Si esta en la posición 7 esta en : incrimento una posición mas.
		}
	} while (cursor<10); // Lo posición 10 significa que se ha terminado la edición.
	ConHora(dias, mes, ano, hora, minutos); // Grabo la hora en el reloj

// Edición de fecha
	lcd.clear();
	lcd.setCursor(3, 0);
	lcd.print("EDITAR FECHA");
	lcd.setCursor(3, 1);
	cursor = 3;
	ImprimiFecha(dias, mes, ano);
	do
	{
		lcd.setCursor(cursor, 1);
		teclapulsada = ComprobarPulsacion(500);
		if (teclapulsada == 1)
		{
			teclapulsada = 0;
			if (cursor == 3)
			{
				d1++;
			}
			if (cursor==4)
			{
				d2++;
			}
			if (cursor==6)
			{
				me1++;
			}
			if (cursor==7)
			{
				me2++;
			}
			if (cursor==9)
			{
				a1++;
			}
			if (cursor==10)
			{
				a2++;
			}
			if (cursor==11)
			{
				a3++;
			}
			if (cursor==12)
			{
				a4++;
			}

			if (a1 > 9) { a1 = 0; }
			if (a2 > 9) { a2 = 0; }
			if (a3 > 9) { a3 = 0; }
			if (a4 > 9) { a4 = 0; }
			if (d1 > 3) { d1 = 0; }
			if (d1>2 && d2>1 || d2 > 9) { d2 = 0; }
			if (me1 > 1) { me1 = 0; }
			if (me1>0 && me2>2 || me2 > 9) { me2 = 0; }
			dias = d1 * 10 + d2;
			mes = me1 * 10 + d2;
			ano = a1 * 1000 + a2 * 100 + a3 * 10 + a4;
			// Comprobar si el año es bisiesto
			if ((ano % 4 == 0 && ano % 100 != 0) || ano % 400 == 0)
			{
				diasmax[1] = 29; // Año bisiesto Febrero 29 días
			}
			if (dias > diasmax[mes]) { dias = diasmax[mes]; }
			lcd.setCursor(3, 1);
			dias = d1 * 10 + d2;
			mes = me1 * 10 + me2;
			ano = a1 * 1000 + a2 * 100 + a3 * 10 + a4;
			ImprimiFecha(dias, mes, ano);
			lcd.setCursor(3, 1);
		}

		if (teclapulsada == 2)
		{
			cursor++;
			//Serial.println(cursor);
			if (cursor == 5 || cursor == 8) { cursor++; }
		}
	} while (cursor < 13);
	ConHora(dias, mes, ano, rtc.now().hour(), rtc.now().minute());// Grabo la fecha reloj
	lcd.noBlink();
}

Método para puesta en hora del reloj

// Configurar hora en el reloj
void ConHora(int dia, int mes, int ano, int hora, int minutos)
{
	rtc.adjust(DateTime(ano, mes, dia, hora, minutos, 0));
}

Método para mostrar la hora en el display

// Presentar Hora y Minuto en el LCD
void ImprimirHora(int hora, int minutos)
{
	if (hora<10) // Si es menor de 10 pongo un cero delante
	{
		lcd.print("0");
		lcd.print(int(hora));
	}
	else
	{
		lcd.print(int(hora));
	}
	lcd.print(":");
	if (minutos<10)// Si es menor de 10 pongo un cero delante
	{
		lcd.print("0");
		lcd.print(int(minutos));
	}
	else
	{
		lcd.print(int(minutos));
	}
}

Espero te sirva, al resto les animo a mejorar mi código y/o comentar que les parece

Un saludo.