Problema con encoder

Hola a todos, soy ralampa, no soy programador y no entiendo mucho por no decir nada. Hace unos días monte un msx omega y ya que el diseño de la carcasa lleva un hueco para una pantalla oled de 128,32, decidí aprovecharla. Como ya he dicho no tengo ni idea, entre en chatgpt y conseguí compilar un código, me llevo 2 semanas, el cual funciona bien todo menos el encoder. Tienes que girarlo mucho para que detecte un movimiento y tanto si vas a izquierdas como a derechas el sentido es el mismo. He comprobado el encoder con otro sketch y el problema no es el encoder.
Os paso el código haber si alguno de vosotros me puede hechar un cable:

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <RTClib.h>
#include "LOGO.H"

const int clkPin = 8;
const int dtPin = 7;
const int btnPin = 9;
unsigned long ultimoTiempoActualizacion = 0;
const unsigned long intervaloActualizacion = 1000;  // Intervalo de actualización en milisegundos (por ejemplo, cada segundo)

int state_clk_old;
int count = 0;

// DECLARAMOS LAS VARIABLES QUE INDICAN LOS PINES QUE VAMOS A UTILIZAR EN RELES
  int rele1_interruptor =  12;         // Para el pin que controlará el pulsador del relé 1 
  int rele1_activador = 2;           // Para el pin que controlará el relé 1
  int rele2_interruptor =  11;         // Para el pin que controlará el pulsador del relé 2 
  int rele2_activador = 3;           // Para el pin que controlará el relé 2
  int rele3_interruptor = 10;       // Pin para leer el estado del pulsador
  int rele3_activador = 4;          // Pin para controlar el tercer relé
  
 
  
  bool rele1_estado_anterior = LOW; // Variable para rastrear el estado anterior del rele1
  bool rele2_estado_anterior = false; // Declaración de la variable rele2_estado_anterior
  bool rele3_estado_anterior = LOW; // Variable para rastrear el estado anterior del tercer relé
  bool rele1_activo = false; // Variable para rastrear si el relé1 está activo
  bool rele3_activo = false;        // Variable para rastrear si el tercer relé está activo
  bool mostrar_turbo_actualizado = false; // Variable para controlar si se debe actualizar el mensaje "TURBO"
  bool mostrar_turbo = false; // Variable para controlar si se muestra el mensaje "TURBO"
  bool mostrar_bios = false; // Variable para controlar si se muestra el mensaje "BIOS"
  bool mostrar_reset = false;       // Bandera para controlar la visualización del mensaje "RESET"
  bool buffer_clear = true; // Flag para indicar si se debe limpiar el buffer 
  bool actualizarPantalla = true; // Variable para controlar si se debe actualizar la pantalla
  bool mostrar_turbo_temporal = false;
  bool mostrar_turbo_anterior = false;
 
// Declaraciones de funciones
void mostrar_menu();
void ejecutar_opcion(int opcion);
void encoder();
void reloj();
bool menu_visible = false;
bool boton_previo = HIGH;
bool mostrarMenuEnEncoder = false; // Nueva variable para controlar la visualización del menú al girar el encoder
bool menu_anterior = false; // Variable para rastrear el estado anterior del menú
bool mostrar_dos_puntos = true; // Variable para controlar la visibilidad de los dos puntos
unsigned long tiempo_anterior = 0; // Variable para controlar el tiempo


#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define OLED_ADDR 0x3C
#define OLED_RESET -1

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
RTC_DS3231 rtc;

String opciones[] = {"HORAS", "MINUTOS", "DATOS MSX", "ATRAS"};
int max_opciones = sizeof(opciones)/sizeof(opciones[0]);

void setup() {
  // Inicializar la comunicación serial
  Serial.begin(9600); 
  //Serial.println(max_opciones);
  if (!rtc.begin()) {
    Serial.println("No se pudo encontrar RTC");
    while (1);
  }

  if (rtc.lostPower()) {
    Serial.println("RTC perdió la alimentación, estableciendo la hora...");
    // Coloca el código para establecer la hora aquí
  }
  
  // Inicializar pantalla
  display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);
  display.display();
  delay(2000);

  // Inicializar logo
  display.clearDisplay();
  display.drawBitmap(0, 0, logo, 128, 32, WHITE);
  display.display();
  delay(5000);

  // Inicializar pines como entradas
  pinMode(clkPin, INPUT);
  pinMode(dtPin, INPUT);
  pinMode(btnPin, INPUT_PULLUP);

 // Declaramos los pines que vamos a utilizar y el tipo que van a tener dichos pines RELES
  pinMode(rele1_activador, OUTPUT);      // Para activar el rele 1
  pinMode(rele1_interruptor, INPUT);     // Para leer el interruptor que activa el rele 1 turbo
  pinMode(rele2_activador, OUTPUT);      // Para activar el rele 2
  pinMode(rele2_interruptor, INPUT);     // Para leer el interruptor que activa el rele 2 bios
  pinMode(rele3_interruptor, INPUT);     // Para leer el interruptor que activa el rele 3 reset
  
  pinMode(rele3_activador, OUTPUT);
  digitalWrite(rele1_activador,LOW);     //apagamos las salida para inicializar el programa rele 1
  digitalWrite(rele2_activador,LOW);     //apagamos las salida para inicializar el programa rele 2
  digitalWrite(rele3_activador, LOW); // Apaga inicialmente el relé

state_clk_old = digitalRead(clkPin);
mostrar_menu();
}

void loop() {
  int state_btn = digitalRead(btnPin);
  int rele1_estado_actual = digitalRead(rele1_interruptor);
  int rele2_estado_actual = digitalRead(rele2_interruptor);
  int rele3_estado_actual = digitalRead(rele3_interruptor);
  unsigned long tiempoActual = millis();

 if (rele1_estado_actual != rele1_estado_anterior) {
    if (rele1_estado_actual == HIGH) {
      mostrar_turbo = true;
      Serial.println("Relé activado. Mostrando mensaje TURBO.");
    } else {
      mostrar_turbo = false;
      // No limpiar el área específica cuando el relé se desactiva
    }
    rele1_estado_anterior = rele1_estado_actual;
  }
if (rele2_estado_actual != rele2_estado_anterior) {
        if (rele2_estado_actual == HIGH) {
            mostrar_bios = true;
      Serial.println("Relé 2 activado. Mostrando mensaje correspondiente.");
        } else {
            mostrar_bios = false;
            // No limpiar el área específica cuando el relé se desactiva
        }
        rele2_estado_anterior = rele2_estado_actual;
    }
if (rele3_estado_actual != rele3_estado_anterior) {
    if (rele3_estado_actual == HIGH) {
        rele3_activo = !rele3_activo; // Invierte el estado del tercer relé al presionar el botón
        digitalWrite(rele3_activador, rele3_activo ? HIGH : LOW); // Activa o desactiva el tercer relé
        mostrar_reset = true; // Establece la bandera para mostrar el mensaje "RESET"
    } else {
        // Si se suelta el botón, desactiva el relé y la bandera para mostrar el mensaje
        digitalWrite(rele3_activador, LOW);
        rele3_activo = false;
        mostrar_reset = false;
    }
    rele3_estado_anterior = rele3_estado_actual;  
}
  //reloj(mostrar_turbo); // Llama a la función reloj() pasando el estado de mostrar_turbo

  if (state_btn == LOW && boton_previo == HIGH) {
    delay(50); // Pequeña pausa para evitar rebotes

    if (digitalRead(btnPin) == LOW) {
      if (!menu_visible) {
        // Si el menú no está visible, mostrarlo al presionar y soltar el botón
        menu_visible = true;
        count = 0;
      } else if (count == max_opciones - 1) {
        // Si el menú está visible y se selecciona "ATRAS", ocultar el menú
        menu_visible = false;
      } else if (opciones[count] == "HORAS") {
        // Si se selecciona la opción "HORAS" al presionar y soltar el botón, mostrar la hora
        ejecutar_opcion(count);
        delay(100); // Pequeña pausa antes de entrar a la selección de horas
        cambiar_hora(); // Llamar a la función para cambiar la hora
      } else if (opciones[count] == "MINUTOS") {
        // Si se selecciona la opción "MINUTOS" al presionar y soltar el botón, modificar los minutos
        ejecutar_opcion(count);
        delay(100); // Pequeña pausa antes de entrar a la selección de minutos
        cambiar_minutos(); // Llamar a la función para modificar los minutos
      } else if (opciones[count] == "DATOS MSX") {
        // Si se selecciona la opción "DATOS MSX", mostrar los mensajes y esperar
        ejecutar_opcion(count);
        display.clearDisplay();
        display.setTextSize(2);
        display.setCursor(0, 0);
        display.print("S/N 000023");
        display.setCursor(0, 17);
        display.print("21/11/2023");
        display.display();
        delay(6000); // Mostrar los mensajes durante 6 segundos
        display.clearDisplay(); // Limpiar la pantalla después de mostrar los mensajes
        display.display();
        mostrar_menu(); // Volver al menú después de mostrar los mensajes
        delay(500); // Pequeña pausa para evitar rebotes del botón
      } else {
        ejecutar_opcion(count);
      }
    }
  }
  boton_previo = state_btn;

  // Lógica para manejar el menú y la visualización del reloj
  if (menu_visible) {
    mostrar_menu(); // Mostrar el menú si está visible
  } else {
   reloj(mostrar_turbo, mostrar_bios, mostrar_reset); // Mostrar el reloj si el menú no está visible
  }

  // Actualizar la pantalla después de un intervalo de tiempo
  if (tiempoActual - ultimoTiempoActualizacion >= intervaloActualizacion) {
     display.clearDisplay();
  
  if (!menu_visible) {
   reloj(mostrar_turbo, mostrar_bios, mostrar_reset); // Mostrar el reloj si el menú no está visible
  } else {
    mostrar_menu(); // Mostrar el menú si está visible
  }

  display.display();
  encoder();
  delay(50);
}

  if (digitalRead(rele1_interruptor) == HIGH)
   {
      digitalWrite(rele1_activador,HIGH);    //activamos el pin que controla el rele 1     
   } else{
      digitalWrite(rele1_activador,LOW);     //desactivamos el pin que controla el rele 1         
   }
   if (digitalRead(rele2_interruptor) == HIGH)
   {
      digitalWrite(rele2_activador,HIGH);    //activamos el pin que controla el rele 1
   } else{
      digitalWrite(rele2_activador,LOW);     //desactivamos el pin que controla el rele 1                
  }

  if (buffer_clear) {
    actualizarPantalla = true; // Si se necesita limpiar el buffer, se establece para actualizar la pantalla
    buffer_clear = false; // Restablecer el flag
  }
}

void cambiar_hora() {
  DateTime hora_actual = rtc.now();
  int horas_modificadas = hora_actual.hour(); // Guardar las horas actuales para comparación
  int minutos = hora_actual.minute(); // Guardar los minutos actuales

  bool horario_cambiando = true;
  while (horario_cambiando) {
    display.clearDisplay();
    //display.setTextSize(2);
    //display.setCursor(0, 0);
    //display.print("CAMBIAR HORAS:");
    //display.setTextSize(3);
    //display.setCursor(0, 0);
    //display.print(hora_actual.toString("HH")); // Mostrar la hora actual

    display.display();

    encoder(); // Leer el encoder para incrementar o decrementar las horas

    int state_btn = digitalRead(btnPin);

    // Detectar cambio de estado del botón para confirmar el cambio de hora
    if (state_btn == LOW && boton_previo == HIGH) {
      delay(50); // Pequeña pausa para evitar rebotes
      if (digitalRead(btnPin) == LOW) {
        rtc.adjust(DateTime(hora_actual.year(), hora_actual.month(), hora_actual.day(), horas_modificadas, minutos, 0));
        horario_cambiando = false; // Salir del bucle cuando se confirme el cambio
      }
    }
    boton_previo = state_btn;

    // Incrementar o decrementar las horas según el giro del encoder
    if (count > 0) {
      horas_modificadas = (horas_modificadas + 1) % 24; // Incrementar las horas
      count = 0;
    } else if (count < 0) {
      horas_modificadas = (horas_modificadas + 23) % 24; // Decrementar las horas
      count = 0;
    }

    // Comprobar si las horas han cambiado para actualizar la visualización en la pantalla
    int horas_nuevas = hora_actual.hour();
    if (horas_modificadas != horas_nuevas) {
      horas_modificadas = horas_nuevas;
      delay(150); // Pequeña pausa para evitar cambios rápidos
    }
  }
}

void cambiar_minutos() {
  DateTime hora_actual = rtc.now();
  int minutos_modificados = hora_actual.minute(); // Guardar los minutos actuales para comparación
  int minutos_nuevos = minutos_modificados; // Guardar los minutos modificados actualizados

  bool minutos_cambiando = true;
  bool boton_previo = HIGH;

  while (minutos_cambiando) {
    display.clearDisplay();
    //display.setTextSize(2);
    //display.setCursor(0, 0);
    //display.print("CAMBIAR MINUTOS:");
    display.setTextSize(3);
    display.setCursor(45, 8);
    display.print(minutos_modificados < 10 ? "0" + String(minutos_modificados) : String(minutos_modificados)); // Mostrar los minutos

    display.display();

    encoder(); // Leer el encoder para incrementar o decrementar los minutos

    int state_btn = digitalRead(btnPin);

    // Detectar cambio de estado del botón para confirmar el cambio de minutos
    if (state_btn == LOW && boton_previo == HIGH) {
      delay(50); // Pequeña pausa para evitar rebotes
      if (digitalRead(btnPin) == LOW) {
        rtc.adjust(DateTime(hora_actual.year(), hora_actual.month(), hora_actual.day(), hora_actual.hour(), minutos_modificados, 0));
        minutos_cambiando = false; // Salir del bucle cuando se confirme el cambio
      }
    }
    boton_previo = state_btn;

    // Incrementar o decrementar los minutos según el giro del encoder
    if (count > 0) {
      minutos_modificados = (minutos_modificados + 1) % 60; // Incrementar los minutos
      count = 0;
    } else if (count < 0) {
      minutos_modificados = (minutos_modificados + 59) % 60; // Decrementar los minutos
      count = 0;
    }

    // Comprobar si los minutos han cambiado para actualizar la visualización en la pantalla
    minutos_nuevos = hora_actual.minute();
    if (minutos_modificados != minutos_nuevos) {
      minutos_nuevos = minutos_modificados;
      delay(150); // Pequeña pausa para evitar cambios rápidos
    }
  }
}

void encoder() {
  int state_clkPin = digitalRead(clkPin);
  int state_dtPin = digitalRead(dtPin);

  if (state_clk_old == HIGH && state_clkPin == LOW) {
    if (state_dtPin == LOW) {
      count--;
    } else {
      count++;
    }
     if (count < 0) {
      count = max_opciones - 1;
    }
    if (count > max_opciones - 1) {
      count = 0;
    }

    mostrarMenuEnEncoder = true; // Establecer la bandera para mostrar el menú al girar el encoder
  } else {
    mostrarMenuEnEncoder = false; // Si no se está girando el encoder, desactivar la bandera
  }

  delay(5);
  state_clk_old = state_clkPin;
}


void mostrar_menu(){
    display.clearDisplay();
    display.setTextSize(2);
    display.setCursor(0, 0);
    display.print("MENU:");
    display.setTextColor(SSD1306_WHITE);
    display.setCursor(0, 16);
    display.print(opciones[count]);
    display.display();
}
void reloj(bool mostrar_turbo, bool mostrar_bios, bool mostrar_reset) {
  DateTime now = rtc.now(); // Obtener la fecha y hora actual del RTC

  // Formatear la hora en una cadena (HH:MM)
  String hora = String(now.hour());
  String minuto = String(now.minute());

  // Asegurarse de que la hora y los minutos tengan dos dígitos
  if (hora.length() == 1) hora = '0' + hora;
  if (minuto.length() == 1) minuto = '0' + minuto;

  // Mostrar la hora en la pantalla OLED junto con el mensaje "TURBO"
  display.clearDisplay();
  display.setTextSize(3);
  display.setCursor(3, 8); // Posición de la hora
  display.print(hora);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(37, 8); // Posición de los dos puntos
  display.print(":");
  display.setCursor(53, 8); // Posición de los minutos
  display.print(minuto);

  if (mostrar_turbo) {
    display.setTextSize(1);
    display.setCursor(95, 0); // Posición del mensaje "TURBO"
    display.println("TURBO");
  }
if (mostrar_bios) {
    display.setTextSize(1);
    display.setCursor(96, 15); // Posición del mensaje "MSX2"
    display.println("MSX2+");
  } else {
    display.setTextSize(1);
    display.setCursor(96, 10); // Posición del mensaje "MSX2+" (cuando relé 2 está desactivado)
    display.println("MSX2");
  }
  
  

if (mostrar_reset) {
    display.clearDisplay();
    display.setTextSize(3);
    display.setCursor(20, 8); // Posición del mensaje "RESET"
    display.println("RESET");
  } 
  
  display.display();

}

void ejecutar_opcion(int opcion) {
  switch (opcion) {
    case 0: // HORAS
      if (menu_visible && opcion == count) {
        bool horario_cambiando = true;
        int horas = rtc.now().hour(); // Obtener las horas actuales
        int minutos = rtc.now().minute(); // Obtener los minutos actuales
        int horas_previas = horas; // Guardar las horas iniciales para comparación
        
        while (horario_cambiando) {
          display.clearDisplay();
          //display.setTextSize(2);
          //display.setCursor(0, 0);
          //display.print("CAMBIAR HORAS:");
          display.setTextSize(3);
          display.setCursor(45, 8);
          display.print(String(horas)); // Mostrar la hora actual

          display.display();

          encoder(); // Leer el encoder para incrementar o decrementar las horas
          
          if (count > 0) {
            horas = (horas + 1) % 24; // Incrementar las horas
            count = 0;
          } else if (count < 0) {
            horas = (horas + 23) % 24; // Decrementar las horas
            count = 0;
          }

          // Mostrar las horas y minutos en la pantalla OLED
          //display.print(String(horas));
          display.display();

          delay(100); // Pequeña pausa para evitar cambios rápidos
          
          // Confirmar el cambio de horas al presionar el botón
          int state_btn = digitalRead(btnPin);
          if (state_btn == LOW && horas != horas_previas) {
            rtc.adjust(DateTime(rtc.now().year(), rtc.now().month(), rtc.now().day(), horas, minutos, 0));
            horario_cambiando = false; // Salir del bucle
          }
        }
      }
      break;
    case 1: // MINUTOS
      if (menu_visible && opcion == count) {
        cambiar_minutos(); // Llamar a la función para modificar los minutos
      }
      break;
  case 2: // DATOS MSX
      // if (menu_visible && opcion == count) {
        //display.clearDisplay();
        //display.setTextSize(2);
        //display.setCursor(0, 0);
        //display.print("S/N 000023");
        //display.setCursor(0, 17);
        //display.print("21/11/2023");
        //display.display();
        //delay(6000); // Mostrar los mensajes durante 2 segundos
        //display.clearDisplay(); // Limpiar la pantalla después de mostrar los mensajes
        //display.display();
        //mostrar_menu(); // Volver al menú después de mostrar los mensajes
     // }
      break;
    case 3: // ATRAS
      // Acciones para la opción ATRAS
      break;
    default:
      // Opción inválida
      break;
  }
}

el código lo que realiza es al arrancar sale un logo, pasado unos segundos aparece el reloj para dar la hora, también lleva e relés que al activarlos lanzan un mensaje a la pantalla. al apretar el pulsador del encoder me aparece un menú en el cual hay 4 opciones con el encoder me muevo por el menú y con el botón del encoder entro en la opción seleccionada. 2 opciones son "horas" y "minutos" en el cual al entrar me aparecen dos dígitos para modificar las horas y los minutos. Otra opción es "atras" la cual al seleccionar y pulsar me devuelve al reloj. La otra opción que queda al seleccionarla y pulsarla sale un mensaje durante unos segundos. utilizo un encoder rotativo, una pantalla oled de 128x32 un Rtc, 3 relés y un arduino nano.

gracias y salu2.

he conseguido que los encoders de las opciones minutos y horas funcionen bien, pero que el encoder funcione bien con el menu no hay manera os dejo actualizacion del codigo por si a alguien le sirve.

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <RTClib.h>
#include "LOGO.H"
#include <Encoder.h>
 
unsigned long ultimoTiempoActualizacion = 0;
const unsigned long intervaloActualizacion = 1000;  // Intervalo de actualización en milisegundos (por ejemplo, cada segundo)
int ANTERIOR = 0;

// Definir los pines del encoder
#define CLK 8 // Pin A del encoder
#define DT 7  // Pin B del encoder
#define SW 9  // Pin del botón del encoder

// Crear una instancia de Encoder
Encoder myEnc(CLK, DT);



// DECLARAMOS LAS VARIABLES QUE INDICAN LOS PINES QUE VAMOS A UTILIZAR EN RELES
  int rele1_interruptor =  12;         // Para el pin que controlará el pulsador del relé 1 
  int rele1_activador = 2;           // Para el pin que controlará el relé 1
  int rele2_interruptor =  11;         // Para el pin que controlará el pulsador del relé 2 
  int rele2_activador = 3;           // Para el pin que controlará el relé 2
  int rele3_interruptor = 10;       // Pin para leer el estado del pulsador
  int rele3_activador = 4;          // Pin para controlar el tercer relé
  
 
  
  bool rele1_estado_anterior = LOW; // Variable para rastrear el estado anterior del rele1
  bool rele2_estado_anterior = false; // Declaración de la variable rele2_estado_anterior
  bool rele3_estado_anterior = LOW; // Variable para rastrear el estado anterior del tercer relé
  bool rele1_activo = false; // Variable para rastrear si el relé1 está activo
  bool rele3_activo = false;        // Variable para rastrear si el tercer relé está activo
  bool mostrar_turbo_actualizado = false; // Variable para controlar si se debe actualizar el mensaje "TURBO"
  bool mostrar_turbo = false; // Variable para controlar si se muestra el mensaje "TURBO"
  bool mostrar_bios = false; // Variable para controlar si se muestra el mensaje "BIOS"
  bool mostrar_reset = false;       // Bandera para controlar la visualización del mensaje "RESET"
  bool buffer_clear = true; // Flag para indicar si se debe limpiar el buffer 
  bool actualizarPantalla = true; // Variable para controlar si se debe actualizar la pantalla
  bool mostrar_turbo_temporal = false;
  bool mostrar_turbo_anterior = false;





bool minutos_cambiando = false;
bool horas_cambiando = false;
bool menu_visible = false;
bool boton_previo = HIGH; 
volatile int pedo = 0;
int state_clk_old;



 
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define OLED_ADDR 0x3C
#define OLED_RESET -1

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
RTC_DS3231 rtc;

String opciones[] = {"HORAS",   "MINUTOS",  "DATOS MSX", "ATRAS"};
int max_opciones = sizeof(opciones)/sizeof(opciones[0]);

void setup() {
  // Inicializar la comunicación serial
  Serial.begin(9600); 
  //Serial.println(max_opciones);
  if (!rtc.begin()) {
    Serial.println("No se pudo encontrar RTC");
    while (1);
  }

  if (rtc.lostPower()) {
    Serial.println("RTC perdió la alimentación, estableciendo la hora...");
    // Coloca el código para establecer la hora aquí
  }
  
  // Inicializar pantalla
  display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);
  display.display();
  delay(2000);

  // Inicializar logo
  display.clearDisplay();
  display.drawBitmap(0, 0, logo, 128, 32, WHITE);
  display.display();
  delay(5000);

  // Inicializar pines como entradas
  pinMode(8,  INPUT_PULLUP);
  pinMode(7,  INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
  //attachInterrupt(digitalPinToInterrupt(8), codificador, LOW);
 
 // Declaramos los pines que vamos a utilizar y el tipo que van a tener dichos pines RELES
  pinMode(rele1_activador, OUTPUT);      // Para activar el rele 1
  pinMode(rele1_interruptor, INPUT);     // Para leer el interruptor que activa el rele 1 turbo
  pinMode(rele2_activador, OUTPUT);      // Para activar el rele 2
  pinMode(rele2_interruptor, INPUT);     // Para leer el interruptor que activa el rele 2 bios
  pinMode(rele3_interruptor, INPUT);     // Para leer el interruptor que activa el rele 3 reset
  
  pinMode(rele3_activador, OUTPUT);
  digitalWrite(rele1_activador,LOW);     //apagamos las salida para inicializar el programa rele 1
  digitalWrite(rele2_activador,LOW);     //apagamos las salida para inicializar el programa rele 2
  digitalWrite(rele3_activador, LOW); // Apaga inicialmente el relé

state_clk_old = digitalRead(8);
mostrar_menu();
}

void loop() {
  int state_btn = digitalRead(9);
  int rele1_estado_actual = digitalRead(rele1_interruptor);
  int rele2_estado_actual = digitalRead(rele2_interruptor);
  int rele3_estado_actual = digitalRead(rele3_interruptor);
  unsigned long tiempoActual = millis();

if (pedo != ANTERIOR) {
    Serial.println(pedo);
    ANTERIOR = pedo;
  }


if (rele1_estado_actual != rele1_estado_anterior) {
    if (rele1_estado_actual == HIGH) {
      mostrar_turbo = true;
      Serial.println("Relé activado. Mostrando mensaje TURBO.");
    } else {
      mostrar_turbo = false;
      // No limpiar el área específica cuando el relé se desactiva
    }
    rele1_estado_anterior = rele1_estado_actual;
  }
if (rele2_estado_actual != rele2_estado_anterior) {
        if (rele2_estado_actual == HIGH) {
            mostrar_bios = true;
      Serial.println("Relé 2 activado. Mostrando mensaje correspondiente.");
        } else {
            mostrar_bios = false;
            // No limpiar el área específica cuando el relé se desactiva
        }
        rele2_estado_anterior = rele2_estado_actual;
    }
if (rele3_estado_actual != rele3_estado_anterior) {
    if (rele3_estado_actual == HIGH) {
        rele3_activo = !rele3_activo; // Invierte el estado del tercer relé al presionar el botón
        digitalWrite(rele3_activador, rele3_activo ? HIGH : LOW); // Activa o desactiva el tercer relé
        mostrar_reset = true; // Establece la bandera para mostrar el mensaje "RESET"
    } else {
        // Si se suelta el botón, desactiva el relé y la bandera para mostrar el mensaje
        digitalWrite(rele3_activador, LOW);
        rele3_activo = false;
        mostrar_reset = false;
    }
    rele3_estado_anterior = rele3_estado_actual;  
}
  //reloj(mostrar_turbo); // Llama a la función reloj() pasando el estado de mostrar_turbo

  if (state_btn == LOW && boton_previo == HIGH) {
    delay(50); // Pequeña pausa para evitar rebotes

    if (digitalRead(9) == LOW) {
      if (!menu_visible) {
        // Si el menú no está visible, mostrarlo al presionar y soltar el botón
        menu_visible = true;
        pedo = 0;
      } else if (pedo == max_opciones - 1) {
        // Si el menú está visible y se selecciona "ATRAS", ocultar el menú
        menu_visible = false;
      } else if (opciones[pedo] == "HORAS") {
        // Si se selecciona la opción "HORAS" al presionar y soltar el botón, mostrar la hora
        ejecutar_opcion(pedo);
        delay(100); // Pequeña pausa antes de entrar a la selección de horas
        cambiar_horas(); // Llamar a la función para cambiar la hora
      } else if (opciones[pedo] == "MINUTOS") {
        // Si se selecciona la opción "MINUTOS" al presionar y soltar el botón, modificar los minutos
        ejecutar_opcion(pedo);
        delay(300); // Pequeña pausa antes de entrar a la selección de minutos
        cambiar_minutos(); // Llamar a la función para modificar los minutos
      } else if (opciones[pedo] == "DATOS MSX") {
        // Si se selecciona la opción "DATOS MSX", mostrar los mensajes y esperar
        ejecutar_opcion(pedo);
        display.clearDisplay();
        display.setTextSize(2);
        display.setCursor(0, 0);
        display.print("S/N 000023");
        display.setCursor(0, 17);
        display.print("21/11/2023");
        display.display();
        delay(6000); // Mostrar los mensajes durante 6 segundos
        display.clearDisplay(); // Limpiar la pantalla después de mostrar los mensajes
        display.display();
        mostrar_menu(); // Volver al menú después de mostrar los mensajes
        delay(500); // Pequeña pausa para evitar rebotes del botón
      } else {
        ejecutar_opcion(pedo);
      }
    }
  }
  boton_previo = state_btn;

  // Lógica para manejar el menú y la visualización del reloj
  if (menu_visible) {
    mostrar_menu(); // Mostrar el menú si está visible
  } else {
   reloj(mostrar_turbo, mostrar_bios, mostrar_reset); // Mostrar el reloj si el menú no está visible
  }

  // Actualizar la pantalla después de un intervalo de tiempo
  if (tiempoActual - ultimoTiempoActualizacion >= intervaloActualizacion) {
     display.clearDisplay();
  
  if (!menu_visible) {
   reloj(mostrar_turbo, mostrar_bios, mostrar_reset); // Mostrar el reloj si el menú no está visible
  } else {
    mostrar_menu(); // Mostrar el menú si está visible
  }

  display.display();
  codificador();
  delay(50);
}

  if (digitalRead(rele1_interruptor) == HIGH)
   {
      digitalWrite(rele1_activador,HIGH);    //activamos el pin que controla el rele 1     
   } else{
      digitalWrite(rele1_activador,LOW);     //desactivamos el pin que controla el rele 1         
   }
   if (digitalRead(rele2_interruptor) == HIGH)
   {
      digitalWrite(rele2_activador,HIGH);    //activamos el pin que controla el rele 1
   } else{
      digitalWrite(rele2_activador,LOW);     //desactivamos el pin que controla el rele 1                
  }

  if (buffer_clear) {
    actualizarPantalla = true; // Si se necesita limpiar el buffer, se establece para actualizar la pantalla
    buffer_clear = false; // Restablecer el flag
  }
}

void cambiar_horas() {
  static int horas_modificadas = 0; // Declarar la variable como estática para conservar su valor entre llamadas

  if (!horas_cambiando) {
    horas_modificadas = rtc.now().hour();
    horas_cambiando = true;

    display.clearDisplay();
    display.setTextSize(2);
    display.setCursor(0, 0);
    display.setTextSize(3);
    display.setCursor(45, 8);
    display.print(horas_modificadas < 10 ? "0" + String(horas_modificadas) : String(horas_modificadas));
    display.display();
  }

  while (horas_cambiando) {
    int encoderValue = myEnc.read() / 4; // Dividir por 4 para ajustar la sensibilidad del encoder

    if (encoderValue != 0) {
      if (encoderValue > 0) {
        horas_modificadas = (horas_modificadas + encoderValue) % 24;
      } else {
        horas_modificadas = (horas_modificadas + encoderValue + 24) % 24; // Ajuste para decrementar correctamente
      }
      myEnc.write(0); // Reiniciar el valor del encoder a cero para el siguiente ajuste
      display.clearDisplay();
      display.setTextSize(2);
      display.setCursor(0, 0);
      display.setTextSize(3);
      display.setCursor(45, 8);
      display.print(horas_modificadas < 10 ? "0" + String(horas_modificadas) : String(horas_modificadas));
      display.display();
      delay(150); // Pequeña pausa para evitar cambios rápidos
    }

    int state_btn = digitalRead(SW);
    if (state_btn == LOW) {
      rtc.adjust(DateTime(rtc.now().year(), rtc.now().month(), rtc.now().day(), horas_modificadas, rtc.now().minute(), 0));
      horas_cambiando = false;
      break;
    }
  }
}


void cambiar_minutos() {
  static int minutos_modificados = 0; // Declarar la variable como estática para conservar su valor entre llamadas

  if (!minutos_cambiando) {
    minutos_modificados = rtc.now().minute();
    minutos_cambiando = true;

    display.clearDisplay();
    display.setTextSize(2);
    display.setCursor(0, 0);
    display.setTextSize(3);
    display.setCursor(45, 8);
    display.print(minutos_modificados < 10 ? "0" + String(minutos_modificados) : String(minutos_modificados));
    display.display();
  }

  while (minutos_cambiando) {
    int encoderValue = myEnc.read() / 4; // Dividir por 4 para ajustar la sensibilidad del encoder

    if (encoderValue != 0) {
      if (encoderValue > 0) {
        minutos_modificados = (minutos_modificados + encoderValue) % 60;
      } else {
        minutos_modificados = (minutos_modificados + encoderValue + 60) % 60; // Ajuste para decrementar correctamente
      }
      myEnc.write(0); // Reiniciar el valor del encoder a cero para el siguiente ajuste
      display.clearDisplay();
      display.setTextSize(2);
      display.setCursor(0, 0);
      display.setTextSize(3);
      display.setCursor(45, 8);
      display.print(minutos_modificados < 10 ? "0" + String(minutos_modificados) : String(minutos_modificados));
      display.display();
      delay(150); // Pequeña pausa para evitar cambios rápidos
    }

    int state_btn = digitalRead(SW);
    if (state_btn == LOW) {
      rtc.adjust(DateTime(rtc.now().year(), rtc.now().month(), rtc.now().day(), rtc.now().hour(), minutos_modificados, 0));
      minutos_cambiando = false;
      break;
    }
  }
}
 
void codificador() {
  static int estado_anterior = LOW;
  static unsigned long tiempo_anterior = 0;
  unsigned long tiempo_actual = millis();
  const int debounceDelay = 10; // Tiempo de debounce en milisegundos

  if (tiempo_actual - tiempo_anterior >= debounceDelay) {
    int estado_actual = digitalRead(8);
    if (estado_actual != estado_anterior) {
      if (digitalRead(7) != estado_actual) {
        pedo--;
      } else {
        pedo++;
      }
      
      if (pedo < 0) {
        pedo = max_opciones - 1;
      }
      if (pedo >= max_opciones) {
        pedo = 0;
      }
      mostrar_menu(); // Mostrar el menú cuando se detecta un cambio en la posición del encoder
    }
    estado_anterior = estado_actual;
    tiempo_anterior = tiempo_actual;
  }
}

void mostrar_menu(){
    display.clearDisplay();
    display.setTextSize(2);
    display.setCursor(0, 0);
    display.print("MENU:");
    display.setTextColor(SSD1306_WHITE);
    display.setCursor(0, 16);
    display.print(opciones[pedo]);
    display.display();
}
void reloj(bool mostrar_turbo, bool mostrar_bios, bool mostrar_reset) {
  DateTime now = rtc.now(); // Obtener la fecha y hora actual del RTC

  // Formatear la hora en una cadena (HH:MM)
  String hora = String(now.hour());
  String minuto = String(now.minute());

  // Asegurarse de que la hora y los minutos tengan dos dígitos
  if (hora.length() == 1) hora = '0' + hora;
  if (minuto.length() == 1) minuto = '0' + minuto;

  // Mostrar la hora en la pantalla OLED junto con el mensaje "TURBO"
  display.clearDisplay();
  display.setTextSize(3);
  display.setCursor(3, 8); // Posición de la hora
  display.print(hora);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(37, 8); // Posición de los dos puntos
  display.print(":");
  display.setCursor(53, 8); // Posición de los minutos
  display.print(minuto);

  if (mostrar_turbo) {
    display.setTextSize(1);
    display.setCursor(95, 0); // Posición del mensaje "TURBO"
    display.println("TURBO");
  }
if (mostrar_bios) {
    display.setTextSize(1);
    display.setCursor(96, 15); // Posición del mensaje "MSX2"
    display.println("MSX2+");
  } else {
    display.setTextSize(1);
    display.setCursor(96, 10); // Posición del mensaje "MSX2+" (cuando relé 2 está desactivado)
    display.println("MSX2");
  }
  
  if (mostrar_reset) {
    display.clearDisplay();
    display.setTextSize(3);
    display.setCursor(20, 8); // Posición del mensaje "RESET"
    display.println("RESET");
  } 
  
  display.display();

}

void ejecutar_opcion(int opcion) {
  switch (opcion) {
    case 0: // HORAS
      if (menu_visible && opcion == pedo) {
        cambiar_horas(); // Llamar a la función para modificar las horas
      }
      break;
    case 1: // MINUTOS
      if (menu_visible && opcion == pedo) {
        cambiar_minutos(); // Llamar a la función para modificar los minutos
      }
      break;
  case 2: // DATOS MSX
      // if (menu_visible && opcion == pedo) {
        //display.clearDisplay();
        //display.setTextSize(2);
        //display.setCursor(0, 0);
        //display.print("S/N 000023");
        //display.setCursor(0, 17);
        //display.print("21/11/2023");
        //display.display();
        //delay(6000); // Mostrar los mensajes durante 2 segundos
        //display.clearDisplay(); // Limpiar la pantalla después de mostrar los mensajes
        //display.display();
        //mostrar_menu(); // Volver al menú después de mostrar los mensajes
     // }
      break;
    case 3: // ATRAS
      // Acciones para la opción ATRAS
      break;
    default:
      // Opción inválida
      break;
  }
}

No hay nadie que me pueda orientar??? :pray:
Gracias y salu2

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.