2 timers mediante teclado con lcd

Estoy intentando sacar adelante un programa que activa y desactiva unas salidas relacionadas con dos pausas que tiene que hacer. El primer programa fue sencillo introduciendo las pausas con la instruccion delay. El problema es que quiero que las pausas se puedan elegir por ello le he adaptado un teclado ( keypad library) y una pantalla lcd (liquidcrystal library) para poder visualizar el tiempo k queda para finalizar cada pausa. No trabajan los tiempos de pausa al misjo tiempo. Primero uno y lego el otro. Bien pues el teclado funciona bien ( he hecho una prueba con un programa de teclado) y el lcd tambien funciona bien ( he escrito algun mensaje), pero no consigo hacerme con los temporizadores. He buscado algun programa que haga de temporizador para adaptarlo a mi proposito y alguno de como introducir los valores de los tiempos de las pausas con el teclado, pero sigo perdido. Ahora he descubierto que hay librerias que hacen la funcion de contador ( timer library). El programa consistiria en introducir 2 tiempo en minutos visualizandolo por el lcd y mediante un pulsador que comenzara a descontar el primer tiempo visualizandolo en el lcd y despues de finalizar este mediante otro pulsador que comenzara a descontar el segundo tiempo visualizandolo igual. Os agradeceria que me hecharais un cable pues llevo tiempo perdido. Gracias

Como tiene que funcionar esas pausas? cuando finaliza el tiempo de la primera arranca la segunda?

No, la primera pausa arrancaria al recibir una señal proviniente del rele de un termostato y la segunda arrancaria, siempre al rato de haber finalizado la primera, recibiendo otra señal de otro termostato y por otro pin.

Osea, que al recibir la señal E-1 cambiamos estado de S-1 durante un tiempo T-3, esperamos un tiempo minimo T-2 y esperamos la señal E-2 para cambiar el estado de S-2 durante un tiempo T-2. Quieres ver por el lcd el estado, movimiento de los temporizadores y poder editar los tiempos T-1 y T-2 desde el teclado Correcto?

Que pantalla tienes , cuantas filas y cuantas columnas? Tiempo en horas, minutos y segundos, décimas? Tiempos maximos?

#include <LiquidCrystal.h>
LiquidCrystal lcd(13, 8, 9, 10, 11 , 12); //pines de control de la lcd
#include <Keypad.h>
const byte filas = 4; //four rows
const byte columnas = 3; //three columns
char teclas[filas][columnas] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'#','0','*'}
};
byte PinsFilas[filas] = {14, 15, 16, 17}; //connect to the row pinouts of the keypad
byte PinsColumnas[columnas] = {18, 19, 6}; //connect to the column pinouts of the keypad
Keypad teclado = Keypad( makeKeymap(teclas), PinsFilas, PinsColumnas, filas, columnas );

Al recibir la señal E-1 comenzara un cuenta atras T-3 y al finalizar cambiara el estado de S-1 y esperamos la señal E-2 para comenzar una cuenta atras T-2 y al finalizar cambiara el estado de S-2 .Quiero ver por el lcd el estado, movimiento de los temporizadores y poder editar los tiempos T-1 y T-2 desde el teclado. Correcto.
Gracias marcial por tu ayuda.

El estado de S-1 y S-2 permanecen cambiados o retornan a su valor original en algun momento?

Cuando termina la primera cuenta atras se activa la s-1. Con esta salida lo que hare sera pasar de trabajar con un termostato a trabajar con el otro, que estara a diferente temperatura. Cuando termine la segunda cuenta atras utilizare la s-2 para activar un zumbador ya que el proceso habra finalizado. (Utilizo una placa con cuatro reles a 5v. para trabajar con las salidas s-1 , s-2 ) No necesito que vuelvan a su posicion inicial. Una vez finalizado el proceso desconectaria el arduino.

Me falta el tamaño de la pantalla y de los temporizadores, horas, minutos, segundos y cuantos como maximo

La pantalla es de 16 columnas y dos filas. En cuanto al tiempo con introducir los minutos totales seria suficiente, aunque cuando se vea la cuenta atras si que estaria bien que aparecieran minutos y segundos. Como maximo podria llegar a introducir 120 min. Si es mas comodo para programar introducir horas, min. y seg. pues tambien esta bien. Como maximo 2 horas.

No tengo teclado para poder comprobarlo :grin:
así que te toca a ti hacerlo.
mira los pines que no coincidirán con los tuyos, la pantalla mía es de 4 lineas, así q ya te veo cambiando los textos que saco a tu gusto y los limites ya los tenis puestos en segundos, prueba así y después cambiamos por minutos

dime que errores hay e intentare enmendarlos :stuck_out_tongue:

#include <LiquidCrystal.h>                        // Libreria lcd
#include <Keypad.h>                               // Libretia teclado

#define F_Lcd   4                                 // Filas del lcd    
#define C_Lcd  20                                 // Columnas del lcd
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);              // Conexiones del lcd

#define F_Key 4                                   // Filas del teclado
#define C_Key 3                                   // Columnas del teclado

char keys[F_Key][C_Key] = {{'1','2','3'},{'4','5','6'},{'7','8','9'},{'#','0','*'}};

byte rowPins[F_Key] = {15, 14, 13, 12};           // Pines usados para las filas del teclado
byte colPins[C_Key] = {18, 17, 16};               // Pines usados para las columnas del teclado
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, F_Key, C_Key );

byte PinS[] = {19, 20};                           // Pines de salida 
byte PinE[] = {21, 22};                           // Pines de entrada

#define OF  LOW                                   // Cambiar aqui para logica positiva/negativa
#define ON  HIGH

    
unsigned long MilisT[]={0,0};                     // Tiempos em milisegundos
unsigned long MilisFinal[]={0,0};                 // Auxiliar para controlar los tiempos
unsigned long T_restante=0;                       // Auxiliar 

bool Editando         = false;                    // Estamos editando tiempos?
bool Inicio_Proceso[] = {false, false};           // Estamos ejecutando el temporizador 
bool Fin_Proceso[]    = {false, false};           // Finalizamos temporizador 

bool Salida1=false;                               // Estado salida 1
bool Salida2=false;                               // Estado salida 2

int Segundos_maximos=999;                         // Tiempo maximo que vamos apermitir programar

void setup()
{
  Serial.begin(9600);
  pinMode(PinS[0], OUTPUT);                        // Definir pines de salidas
  pinMode(PinS[1], OUTPUT);
  digitalWrite(PinS[0], OF);                       // Apagar reles 
  digitalWrite(PinS[1], OF);
  pinMode(PinE[0], INPUT);                         // Definir pines de entrada
  pinMode(PinE[1], INPUT);
  lcd.begin(C_Lcd, F_Lcd);                         // Iniciar lcd                      
  Pantalla_Inicial();                              // Pintar menu principal 
}

void loop()
{ 
  if (!Inicio_Proceso[0]) {Temporizadores(0);}      // Comprobar proceso 1
  else if (!Inicio_Proceso[1]) {Temporizadores(1);} // Comprobar proceso 2
  else
  {
    char key = keypad.getKey();                    // Leer teclado 
    if (key=='1')                                  // Pulso '1', editar T-1
    {
      Editando=true;                               // Estamos editando, ya no permitimos arrancar el tiempo
      EditarTiempo(0);                             // Editar tiempo 1
    }
    if (key=='2')                                  // Pulso '2', editar T-2
    {
      Editando=true;                               // Estamos editando, ya no permitimos arrancar el tiempo
      EditarTiempo(1);                             // Editar tiempo 1
    }          
  } 
}

void Pantalla_Inicial()                            // Saca por pantalla el menu principal
{
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Estado : En espera");
  lcd.setCursor(0,1);
  lcd.print("Tiempo 1:     Seg");
  lcd.setCursor(10,1);
  lcd.print(MilisT[0]/1000);    
  lcd.setCursor(0,2);
  lcd.print("Tiempo 2:     Seg");
  lcd.setCursor(10,2);
  lcd.print(MilisT[1]/1000);     
  lcd.setCursor(0,3);
  lcd.print("1/2 -> EDITA TIEMPOS");
  lcd.setCursor(0,0);
  lcd.print("Estado : En espera");
}
void Pantalla_Editar(int T)                        // Saca por pantalla el menu de edicion de tiempo
{
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Estado : Edit. T-");
  lcd.setCursor(17,0);
  lcd.print(T);
  lcd.setCursor(0,1);
  lcd.print("Actual:   Seg");
  lcd.setCursor(8,1);
  lcd.print(MilisT[T]/1000);    
  lcd.setCursor(0,2);
  lcd.print("Segundos :");
  lcd.setCursor(0,3);
  lcd.print("*=Cancelar #=Aceptar");   
}
void Pantalla_Proceso(int T)
{
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Temporizador ");
  lcd.setCursor(13,0);
  lcd.print(T);
  lcd.setCursor(0,1);
  lcd.print("Restan     Seg");    
}

void EditarTiempo(int T)                             
{
  Pantalla_Editar(T);                                // Saca por pantalla el menu de edicion 
  int Columna=11;                                    // Donde vamos a empezar a escribir
  int tiempo=0;                                      // nuevo tiempo deseado
  int digitos=0;                                     // cuantos digitos llevamos escrito
  while (Editando)                                   // Hasta que pulse aceptar o cancelar
  {
    char key = keypad.getKey();                      // Leer teclado
    if (key!=NO_KEY)                                 // Ha pulsado una tecla?
    {
      lcd.setCursor(Columna+digitos,3);              // Situa cursor en su lugar
      lcd.print(key);                                // Pinta la tecla pulsada
      digitos++;                                     // un digito mas pulsado
      if (key=='0') {tiempo = tiempo * 10;}          // Calcular el valor de timepo en funcion de lo que pulso  
      else if (key=='1') {tiempo = tiempo * 10 + 1;}
      else if (key=='2') {tiempo = tiempo * 10 + 2;}
      else if (key=='3') {tiempo = tiempo * 10 + 3;}
      else if (key=='4') {tiempo = tiempo * 10 + 4;}
      else if (key=='5') {tiempo = tiempo * 10 + 5;}
      else if (key=='6') {tiempo = tiempo * 10 + 6;}
      else if (key=='7') {tiempo = tiempo * 10 + 7;}
      else if (key=='8') {tiempo = tiempo * 10 + 8;}
      else if (key=='9') {tiempo = tiempo * 10 + 9;}
      else if (key=='*') {Editando=false;}           // Pulso cancelar, dejamos de editar y no cambiamos nada
      else                                           // Pulso enter, guardar nuevo valor de timepo y regresar a menu primcipal                                
      {
        if (tiempo <= Segundos_maximos)              // El valor es valido
        {
          MilisT[T] = tiempo * 1000;                 // Cargamos nuevo timepo
          Editando = false;                          // dejamos de editar para pasar a pantalla principal
          lcd.setCursor(0,3);                        // sacamos mensaje de advertencia
          lcd.print("Tiempo cambiado   ");
          delay(1500);
        }
      }
    }
    if (tiempo > Segundos_maximos)                   // El valor introducido es demasiado alto
    {
      lcd.setCursor(0,3);
      lcd.print("Tiempo excesivo   ");
      delay(1500);
      int tiempo=0;                                  // Reiniciamos menu edicion tiempo
      int digitos=0;
      Pantalla_Editar(T);
    }
  }
  Pantalla_Inicial();                                // Edicion finalizada, sacar pantalla principal
}
void Temporizadores(int T)
{
  if (!Inicio_Proceso[T] && digitalRead(PinE[T]))  // Señal de inicio 
  {
    Inicio_Proceso[T] =true;                       // Iniciamos proceso
    MilisFinal[T]=millis() + MilisT[T];            // Tiempo para el cambio de estrado
    Pantalla_Proceso(T);
    while (!Fin_Proceso[T])                        // Actuando las salidas temporizadas
    {
      if (T_restante != (MilisFinal[T] - millis() ) / 1000 )  // Tiempo restante ha cambiado?
      {
        T_restante = ( MilisFinal[T] - millis() ) / 1000;    // Nuevo tiempo restante
        lcd.setCursor(7,1);                        // Situar el cursor       
        lcd.print("   ");                          // Borra tiempo anterior
      }
      lcd.setCursor(7,1);                          
      lcd.print(T_restante);                       // Pintar timepo restante
      if (millis()>MilisFinal[T])                  // Acabo la cuanta atras?
      {
        digitalWrite(PinS[T], ON);                 // Rele 
        Fin_Proceso[T]=true;                       // Fin roceso 
      }
    } 
  }
}

Muchas gracias Marcial. No me funciona el teclado le he puesto los pines correspondientes ,pero no funciona. Abro el monitor serial y no aparece nada al pulsar las teclas. No se si seran los " if else " que hay continuados en “comprobar procesos”.
Eliminando los if y else de “comprobar procesos 1 y 2” ya me deja acceder a la edicion del tiempo y el teclado funciona.
El programa por ahora lo he dejado asi:

#include <LiquidCrystal.h>                        // Libreria lcd
#include <Keypad.h>                               // Libretia teclado

#define F_Lcd   2                                 // Filas del lcd    
#define C_Lcd  16                                 // Columnas del lcd
LiquidCrystal lcd(13, 8, 9, 10, 11 , 12);              // Conexiones del lcd

#define F_Key 4                                   // Filas del teclado
#define C_Key 3                                   // Columnas del teclado

char keys[F_Key][C_Key] = {{'1','2','3'},{'4','5','6'},{'7','8','9'},{'#','0','*'}};

byte rowPins[F_Key] = {14, 15, 16, 17};           // Pines usados para las filas del teclado
byte colPins[C_Key] = {18, 19, 6};               // Pines usados para las columnas del teclado
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, F_Key, C_Key );

byte PinS[] = {4, 5};                           // Pines de salida 
byte PinE[] = {2, 3};                           // Pines de entrada

#define OF  LOW                                   // Cambiar aqui para logica positiva/negativa
#define ON  HIGH

    
unsigned long MilisT[]={0,0};                     // Tiempos em milisegundos
unsigned long MilisFinal[]={0,0};                 // Auxiliar para controlar los tiempos
unsigned long T_restante=0;                       // Auxiliar 

bool Editando         = false;                    // Estamos editando tiempos?
bool Inicio_Proceso[] = {false, false};          // Estamos ejecutando el temporizador 
bool Fin_Proceso[]    = {false, false};           // Finalizamos temporizador 

bool Salida1=false;                               // Estado salida 1
bool Salida2=false;                               // Estado salida 2

int Segundos_maximos=999;                         // Tiempo maximo que vamos apermitir programar

void setup()
{
  Serial.begin(9600);
  pinMode(PinS[0], OUTPUT);                        // Definir pines de salidas
  pinMode(PinS[1], OUTPUT);
  digitalWrite(PinS[0], OF);                       // Apagar reles 
  digitalWrite(PinS[1], OF);
  pinMode(PinE[0], INPUT);                         // Definir pines de entrada
  pinMode(PinE[1], INPUT);
  lcd.begin(C_Lcd, F_Lcd);                         // Iniciar lcd                      
  Pantalla_Inicial();                             // Pintar menu principal 
}

void loop()

  {

    char key = keypad.getKey();                    // Leer teclado 
    if (key=='1')                                  // Pulso '1', editar T-1
    {
      Editando=true;                               // Estamos editando, ya no permitimos arrancar el tiempo
      EditarTiempo(0);                             // Editar tiempo 1
    }
    if (key=='2')                                  // Pulso '2', editar T-2
    {
      Editando=true;                               // Estamos editando, ya no permitimos arrancar el tiempo
      EditarTiempo(1);                             // Editar tiempo 1
    }          
  } 


void Pantalla_Inicial()                            // Saca por pantalla el menu principal
{
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("T1:     Seg");
  lcd.setCursor(4,0);
  lcd.print(MilisT[0]/1000);    
  lcd.setCursor(0,1);
  lcd.print("T2:     Seg");
  lcd.setCursor(4,1);
  lcd.print(MilisT[1]/1000);     
}
void Pantalla_Editar(int T)                        // Saca por pantalla el menu de edicion de tiempo
{
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("T-");
  lcd.setCursor(2,0);
  lcd.print(T);
  
  lcd.setCursor(8,1);
  lcd.print(MilisT[T]/1000);    
  lcd.setCursor(0,1);
  lcd.print("Seg:");
   //"*=Canc #=Acpt");   
}
void Pantalla_Proceso(int T)
{
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Temporizador ");
  lcd.setCursor(13,0);
  lcd.print(T);
  lcd.setCursor(0,1);
  lcd.print("Restan     Seg");    
}

void EditarTiempo(int T)                             
{
  Pantalla_Editar(T);                                // Saca por pantalla el menu de edicion 
  int Columna=5;                                    // Donde vamos a empezar a escribir
  int tiempo=0;                                      // nuevo tiempo deseado
  int digitos=0;                                     // cuantos digitos llevamos escrito
  while (Editando)                                   // Hasta que pulse aceptar o cancelar
  {
    char key = keypad.getKey();                      // Leer teclado
    if (key!=NO_KEY)                                 // Ha pulsado una tecla?
    {
      lcd.setCursor(Columna+digitos,1);              // Situa cursor en su lugar
      lcd.print(key);                                // Pinta la tecla pulsada
      digitos++;                                     // un digito mas pulsado
      if (key=='0') {tiempo = tiempo * 10;}          // Calcular el valor de timepo en funcion de lo que pulso  
      else if (key=='1') {tiempo = tiempo * 10 + 1;}
      else if (key=='2') {tiempo = tiempo * 10 + 2;}
      else if (key=='3') {tiempo = tiempo * 10 + 3;}
      else if (key=='4') {tiempo = tiempo * 10 + 4;}
      else if (key=='5') {tiempo = tiempo * 10 + 5;}
      else if (key=='6') {tiempo = tiempo * 10 + 6;}
      else if (key=='7') {tiempo = tiempo * 10 + 7;}
      else if (key=='8') {tiempo = tiempo * 10 + 8;}
      else if (key=='9') {tiempo = tiempo * 10 + 9;}
      else if (key=='*') {Editando=false;}           // Pulso cancelar, dejamos de editar y no cambiamos nada
      else                                           // Pulso enter, guardar nuevo valor de timepo y regresar a menu primcipal                                
      {
        if (tiempo <= Segundos_maximos)              // El valor es valido
        {
          MilisT[T] = tiempo * 1000;                 // Cargamos nuevo timepo
          Editando = false;                          // dejamos de editar para pasar a pantalla principal
          lcd.setCursor(0,1);                        // sacamos mensaje de advertencia
          lcd.print("Tiempo cambiado   ");
          delay(1500);
        }
      }
    }
    if (tiempo > Segundos_maximos)                   // El valor introducido es demasiado alto
    {
      lcd.setCursor(0,1);
      lcd.print("Tiempo excesivo   ");
      delay(1500);
      int tiempo=0;                                  // Reiniciamos menu edicion tiempo
      int digitos=0;
      Pantalla_Editar(T);
       
     
    }
  }
  Pantalla_Inicial();                                // Edicion finalizada, sacar pantalla principal
}
void Temporizadores(int T)
{
  if(!Inicio_Proceso[T] && digitalRead(PinE[T])) // Señal de inicio 
  {
    Inicio_Proceso[T] =true;                       // Iniciamos proceso
    MilisFinal[T]=millis() + MilisT[T];            // Tiempo para el cambio de estrado
    Pantalla_Proceso(T);
    while (!Fin_Proceso[T])                        // Actuando las salidas temporizadas
    {
      if (T_restante != (MilisFinal[T] - millis() ) / 1000 )  // Tiempo restante ha cambiado?
      {
        T_restante = ( MilisFinal[T] - millis() ) / 1000;    // Nuevo tiempo restante
        lcd.setCursor(7,1);                        // Situar el cursor       
        lcd.print("   ");                          // Borra tiempo anterior
      }
      lcd.setCursor(7,1);                          
      lcd.print(T_restante);                       // Pintar timepo restante
      if (millis()>MilisFinal[T])                  // Acabo la cuanta atras?
      {
        digitalWrite(PinS[T], ON);                 // Rele 
        Fin_Proceso[T]=true;                       // Fin roceso 
      }
    } 
  }
}

Puedo introducir los segundos, pero creo que al eliminar los if ,no puedo iniciar los contadores

Corregido (creo :roll_eyes:)

#include <LiquidCrystal.h>                        // Libreria lcd
#include <Keypad.h>                               // Libretia teclado

#define F_Lcd   2                                 // Filas del lcd    
#define C_Lcd  16                                 // Columnas del lcd
LiquidCrystal lcd(13,8, 9, 10, 11, 12);           // Conexiones del lcd

#define F_Key 4                                   // Filas del teclado
#define C_Key 3                                   // Columnas del teclado

char keys[F_Key][C_Key] = {{'1','2','3'},{'4','5','6'},{'7','8','9'},{'#','0','*'}};

byte rowPins[F_Key] = {14, 15, 16, 17};           // Pines usados para las filas del teclado
byte colPins[C_Key] = {18, 19, 6};                // Pines usados para las columnas del teclado
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, F_Key, C_Key );

byte PinS[] = {4, 5};                            // Pines de salida 
byte PinE[] = {2, 3};                            // Pines de entrada

#define OF  LOW                                   // Cambiar aqui para logica positiva/negativa
#define ON  HIGH

    
unsigned long MilisT[]={0,0};                     // Tiempos em milisegundos
unsigned long MilisFinal[]={0,0};                 // Auxiliar para controlar los tiempos

bool Editando         = false;                    // Estamos editando tiempos?
bool Inicio_Proceso[] = {false, false};           // Estamos ejecutando el temporizador 
bool Fin_Proceso[]    = {false, true};            // Finalizamos temporizador 

bool Salida1=false;                               // Estado salida 1
bool Salida2=false;                               // Estado salida 2

int Segundos_maximos=999;                         // Tiempo maximo que vamos apermitir programar

void setup()
{
  Serial.begin(9600);
  pinMode(PinS[0], OUTPUT);                        // Definir pines de salidas
  pinMode(PinS[1], OUTPUT);
  digitalWrite(PinS[0], OF);                       // Apagar reles 
  digitalWrite(PinS[1], OF);
  pinMode(PinE[0], INPUT);                         // Definir pines de entrada
  pinMode(PinE[1], INPUT);
  lcd.begin(C_Lcd, F_Lcd);                         // Iniciar lcd                      
  Pantalla_Inicial();                              // Pintar menu principal 
}

void loop()
{ 
  Serial.println(digitalRead(PinE[0]));
  if (!Fin_Proceso[0] && digitalRead(PinE[0]) )    // Arrancamos proceso 1
  {  
    Temporizadores(0);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Esperando...");
    Fin_Proceso[1]=false;
  } 
  else if (!Fin_Proceso[1] && digitalRead(PinE[1]))  // Arrancamos proceso 2
  {
    Temporizadores(1);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Finalizado...");
    lcd.setCursor(0,1);
    lcd.print("# = Reiniciar");
    while (keypad.getKey() != '#')  {;}              // Mientras no pulse reinicar
    Fin_Proceso[0]=false;
    Fin_Proceso[1]=true;
    digitalWrite(PinS[0], OF);                 
    digitalWrite(PinS[1], OF);
    Pantalla_Inicial();
  }
  else if (!Fin_Proceso[0])
  {
    char key = keypad.getKey();                      // Leer teclado 
    if (key!=NO_KEY)
    {
      Serial.print("Pulso ");
      Serial.println(key);
      delay(10); 
      if (key=='1')                                  // Pulso '1', editar T-1
      {
        Serial.println("Entrando a edition T-1");                              
        EditarTiempo(0);                             // Editar tiempo 1
      }
      if (key=='2')                                  // Pulso '2', editar T-2
      {
        Serial.println("Entrando a edition T-2");
        EditarTiempo(1);                             // Editar tiempo 1
      }
    }    
  } 
}

void Pantalla_Inicial()                            // Saca por pantalla el menu principal
{
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("   En  espera   ");
  lcd.setCursor(0,1);
  lcd.print("T1:       T2:   ");
  lcd.setCursor(3,1);
  lcd.print(MilisT[0]/1000);    
  lcd.setCursor(13,1);
  lcd.print(MilisT[1]/1000);     
}
void Pantalla_Editar(int T)                        // Saca por pantalla el menu de edicion de tiempo
{
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("  Editando T-   ");
  lcd.setCursor(13,0);
  lcd.print(T+1);
  lcd.setCursor(0,1);
  lcd.print("Actual:     Seg");
  lcd.setCursor(8,1);
  lcd.print(MilisT[T]/1000);
  delay(1500); 
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("*=Cancel #=Enter");
  lcd.setCursor(0,1);
  lcd.print("Nuevo :");  
}
void Pantalla_Proceso(int T)
{
  lcd.clear();
  lcd.setCursor(0,0);  
  lcd.print(" Temporizador   ");
  lcd.setCursor(14,0);
  lcd.print(T+1);
  lcd.setCursor(0,1);
  lcd.print("Restan       Seg");    
}

void EditarTiempo(int T)                             
{
  Editando=true;                                     // Estamos editando, ya no permitimos arrancar el tiempo
  Pantalla_Editar(T);                                // Saca por pantalla el menu de edicion 
  int Columna=8;                                     // Donde vamos a empezar a escribir
  unsigned long tiempo=0;                            // nuevo tiempo deseado
  int digitos=0;                                     // cuantos digitos llevamos escrito
  while (Editando)                                   // Hasta que pulse aceptar o cancelar
  {
    char key = keypad.getKey();                      // Leer teclado
    if (key!=NO_KEY)                                 // Ha pulsado una tecla?
    {
      lcd.setCursor(Columna+digitos,3);              // Situa cursor en su lugar
      lcd.print(key);                                // Pinta la tecla pulsada
      digitos++;                                     // un digito mas pulsado
      if (key=='0') {tiempo = tiempo * 10;}          // Calcular el valor de timepo en funcion de lo que pulso  
      else if (key=='1') {tiempo = tiempo * 10 + 1;}
      else if (key=='2') {tiempo = tiempo * 10 + 2;}
      else if (key=='3') {tiempo = tiempo * 10 + 3;}
      else if (key=='4') {tiempo = tiempo * 10 + 4;}
      else if (key=='5') {tiempo = tiempo * 10 + 5;}
      else if (key=='6') {tiempo = tiempo * 10 + 6;}
      else if (key=='7') {tiempo = tiempo * 10 + 7;}
      else if (key=='8') {tiempo = tiempo * 10 + 8;}
      else if (key=='9') {tiempo = tiempo * 10 + 9;}
      else if (key=='*') {Editando=false;}           // Pulso cancelar, dejamos de editar y no cambiamos nada
      else                                           // Pulso enter, guardar nuevo valor de timepo y regresar a menu primcipal                                
      {
        if (tiempo <= Segundos_maximos)              // El valor es valido
        {
          MilisT[T] = tiempo * 1000;                 // Cargamos nuevo timepo
          Editando = false;                          // dejamos de editar para pasar a pantalla principal
          lcd.setCursor(0,3);                        // sacamos mensaje de advertencia
          lcd.print("Tiempo cambiado   ");
          delay(1500);
        }
      }
    }
    if (tiempo > Segundos_maximos)                   // El valor introducido es demasiado alto
    {
      lcd.setCursor(0,3);
      lcd.print("Tiempo excesivo   ");
      delay(1500);
      tiempo=0;                                     // Reiniciamos menu edicion tiempo
      digitos=0;
      Pantalla_Editar(T);
    }
  }
  Pantalla_Inicial();                                // Edicion finalizada, sacar pantalla principal
}
void Temporizadores(int T)
{
  int Tiempo, TiempoA=0;                         // Auxiliares
  Inicio_Proceso[T] =true;                       // Iniciamos proceso
  Pantalla_Proceso(T);
  MilisFinal[T]=millis() + MilisT[T];            // Tiempo para el cambio de estrado
  while (!Fin_Proceso[T])                        // Actuando las salidas temporizadas
  {
    Tiempo=((MilisFinal[T] - millis())/ 1000 );  // Segundos restantes
    if (Tiempo != TiempoA )                      // Tiempo restante ha cambiado?
    {
      TiempoA = Tiempo;                          // Nuevo tiempo restante
      lcd.setCursor(7,1);                        // Situar el cursor       
      lcd.print("   ");                          // Borra tiempo anterior
      lcd.setCursor(7,1);                          
      lcd.print(Tiempo);                         // Pintar timepo restante
    }
    if (millis()>=MilisFinal[T])                 // Acabo la cuanta atras?
    {
      digitalWrite(PinS[T], ON);                 // Rele 
      Fin_Proceso[T]=true;                       // Fin roceso 
    }
  } 
}

Eres una maquina tio. Te iba a escribir diciendote que me habia pedido una pantalla de cuatro lineas, pero asi se ha quedado de lujo. Me falta comprobar las salidas ( Esta noche le hecho un vistazo). Las entradas van bien. Muchas Gracias. Luego te digo algo y lo cambiamos a minutos.

Ya me contaras

Perfecto Marcial. Funciona correctamente. Solo falta que lo que seleccionamos sean minutos. :blush: No se si estoy pidiendo demasiado. Muchas gracias

No me lo pidas en colores que la pantalla es B/N :stuck_out_tongue:

#include <LiquidCrystal.h>                        // Libreria lcd
#include <Keypad.h>                               // Libretia teclado

#define F_Lcd   2                                 // Filas del lcd    
#define C_Lcd  16                                 // Columnas del lcd
LiquidCrystal lcd(13,8, 9, 10, 11, 12);           // Conexiones del lcd

#define F_Key 4                                   // Filas del teclado
#define C_Key 3                                   // Columnas del teclado

char keys[F_Key][C_Key] = {{'1','2','3'},{'4','5','6'},{'7','8','9'},{'#','0','*'}};

byte rowPins[F_Key] = {14, 15, 16, 17};           // Pines usados para las filas del teclado
byte colPins[C_Key] = {18, 19, 6};                // Pines usados para las columnas del teclado
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, F_Key, C_Key );

byte PinS[] = {4, 5};                            // Pines de salida 
byte PinE[] = {2, 3};                            // Pines de entrada

#define OF  LOW                                   // Cambiar aqui para logica positiva/negativa
#define ON  HIGH

    
unsigned long MilisT[]={0,0};                     // Tiempos em milisegundos
unsigned long MilisFinal[]={0,0};                 // Auxiliar para controlar los tiempos

bool Editando         = false;                    // Estamos editando tiempos?
bool Inicio_Proceso[] = {false, false};           // Estamos ejecutando el temporizador 
bool Fin_Proceso[]    = {false, true};            // Finalizamos temporizador 

bool Salida1=false;                               // Estado salida 1
bool Salida2=false;                               // Estado salida 2

int Minutos_maximos=999;                         // Tiempo maximo que vamos apermitir programar

void setup()
{
  Serial.begin(9600);
  pinMode(PinS[0], OUTPUT);                        // Definir pines de salidas
  pinMode(PinS[1], OUTPUT);
  digitalWrite(PinS[0], OF);                       // Apagar reles 
  digitalWrite(PinS[1], OF);
  pinMode(PinE[0], INPUT);                         // Definir pines de entrada
  pinMode(PinE[1], INPUT);
  lcd.begin(C_Lcd, F_Lcd);                         // Iniciar lcd                      
  Pantalla_Inicial();                              // Pintar menu principal 
}

void loop()
{ 
  Serial.println(digitalRead(PinE[0]));
  if (!Fin_Proceso[0] && digitalRead(PinE[0]) )    // Arrancamos proceso 1
  {  
    Temporizadores(0);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Esperando...");
    Fin_Proceso[1]=false;
  } 
  else if (!Fin_Proceso[1] && digitalRead(PinE[1]))  // Arrancamos proceso 2
  {
    Temporizadores(1);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Finalizado...");
    lcd.setCursor(0,1);
    lcd.print("# = Reiniciar");
    while (keypad.getKey() != '#')  {;}              // Mientras no pulse reinicar
    Fin_Proceso[0]=false;
    Fin_Proceso[1]=true;
    digitalWrite(PinS[0], OF);                 
    digitalWrite(PinS[1], OF);
    Pantalla_Inicial();
  }
  else if (!Fin_Proceso[0])
  {
    char key = keypad.getKey();                      // Leer teclado 
    if (key!=NO_KEY)
    {
      Serial.print("Pulso ");
      Serial.println(key);
      delay(10); 
      if (key=='1')                                  // Pulso '1', editar T-1
      {
        Serial.println("Entrando a edition T-1");                              
        EditarTiempo(0);                             // Editar tiempo 1
      }
      if (key=='2')                                  // Pulso '2', editar T-2
      {
        Serial.println("Entrando a edition T-2");
        EditarTiempo(1);                             // Editar tiempo 1
      }
    }    
  } 
}

void Pantalla_Inicial()                            // Saca por pantalla el menu principal
{
  int Tiempo=MilisT[0]/60000;                      // Minutos T1
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("   En  espera   ");
  lcd.setCursor(0,1);
  lcd.print("1>");
  if (Tiempo/60<9) {lcd.print("0");}
  lcd.print(Tiempo/60);
  lcd.print(":");
  if (Tiempo%60<9) {lcd.print("0");}
  lcd.print(Tiempo%60);
  Tiempo=MilisT[1]/60000;                      // Minutos T2
  lcd.print(" 2>");
  if (Tiempo/60<9) {lcd.print("0");}
  lcd.print(Tiempo/60);
  lcd.print(":");
  if (Tiempo%60<9) {lcd.print("0");}
  lcd.print(Tiempo%60);
}
void Pantalla_Editar(int T)                        // Saca por pantalla el menu de edicion de tiempo
{
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("  Editando T-   ");
  lcd.setCursor(13,0);
  lcd.print(T+1);
  lcd.setCursor(0,1);
  lcd.print("Actual:     Min");
  lcd.setCursor(8,1);
  lcd.print(MilisT[T]/60000);
  delay(1500); 
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("*=Cancel #=Enter");
  lcd.setCursor(0,1);
  lcd.print("Nuevo :");  
}
void Pantalla_Proceso(int T)
{
  lcd.clear();
  lcd.setCursor(0,0);  
  lcd.print(" Temporizador   ");
  lcd.setCursor(14,0);
  lcd.print(T+1);   
}

void EditarTiempo(int T)                             
{
  Editando=true;                                     // Estamos editando, ya no permitimos arrancar el tiempo
  Pantalla_Editar(T);                                // Saca por pantalla el menu de edicion 
  int Columna=8;                                     // Donde vamos a empezar a escribir
  unsigned long tiempo=0;                            // nuevo tiempo deseado
  int digitos=0;                                     // cuantos digitos llevamos escrito
  while (Editando)                                   // Hasta que pulse aceptar o cancelar
  {
    char key = keypad.getKey();                      // Leer teclado
    if (key!=NO_KEY)                                 // Ha pulsado una tecla?
    {
      lcd.setCursor(Columna+digitos,3);              // Situa cursor en su lugar
      lcd.print(key);                                // Pinta la tecla pulsada
      digitos++;                                     // un digito mas pulsado
      if (key=='0') {tiempo = tiempo * 10;}          // Calcular el valor de timepo en funcion de lo que pulso  
      else if (key=='1') {tiempo = tiempo * 10 + 1;}
      else if (key=='2') {tiempo = tiempo * 10 + 2;}
      else if (key=='3') {tiempo = tiempo * 10 + 3;}
      else if (key=='4') {tiempo = tiempo * 10 + 4;}
      else if (key=='5') {tiempo = tiempo * 10 + 5;}
      else if (key=='6') {tiempo = tiempo * 10 + 6;}
      else if (key=='7') {tiempo = tiempo * 10 + 7;}
      else if (key=='8') {tiempo = tiempo * 10 + 8;}
      else if (key=='9') {tiempo = tiempo * 10 + 9;}
      else if (key=='*') {Editando=false;}           // Pulso cancelar, dejamos de editar y no cambiamos nada
      else                                           // Pulso enter, guardar nuevo valor de timepo y regresar a menu primcipal                                
      {
        if (tiempo <= Minutos_maximos)               // El valor es valido
        {
          MilisT[T] = tiempo * 60000;                // Cargamos nuevo timepo en minutos
          Editando = false;                          // dejamos de editar para pasar a pantalla principal
          lcd.setCursor(0,3);                        // sacamos mensaje de advertencia
          lcd.print("Tiempo cambiado   ");
          delay(1500);
        }
      }
    }
    if (tiempo > Minutos_maximos)                   // El valor introducido es demasiado alto
    {
      lcd.setCursor(0,3);
      lcd.print("Tiempo excesivo   ");
      delay(1500);
      tiempo=0;                                     // Reiniciamos menu edicion tiempo
      digitos=0;
      Pantalla_Editar(T);
    }
  }
  Pantalla_Inicial();                                // Edicion finalizada, sacar pantalla principal
}
void Temporizadores(int T)
{
  int Tiempo, TiempoA=0;                         // Auxiliares
  Inicio_Proceso[T] =true;                       // Iniciamos proceso
  Pantalla_Proceso(T);
  MilisFinal[T]=millis() + MilisT[T];            // Tiempo para el cambio de estrado
  while (!Fin_Proceso[T])                        // Actuando las salidas temporizadas
  {
    Tiempo=((MilisFinal[T] - millis())/ 1000 );  // Segundos restantes
    if (Tiempo != TiempoA )                      // Tiempo restante ha cambiado?
    {
      lcd.setCursor(0,1);
      lcd.print("Restan:         "); 
      TiempoA = Tiempo;                          // Nuevo tiempo restante
      lcd.setCursor(8,1);
      if (Tiempo/3600<9) {lcd.print("0");}
      lcd.print(Tiempo/3600);                    // Horas
      lcd.print(":");
      Tiempo=Tiempo%3600;
      if (Tiempo/60<9) {lcd.print("0");}
      lcd.print(Tiempo/60);                      // Minutos
      lcd.print(":");
      if (Tiempo%60<9) {lcd.print("0");}
      lcd.print(Tiempo%60);                      // Segundos
    }
    if (millis()>=MilisFinal[T])                 // Acabo la cuanta atras?
    {
      digitalWrite(PinS[T], ON);                 // Rele 
      Fin_Proceso[T]=true;                       // Fin roceso 
    }
  } 
}

Perfecto Marcial. Creo k es perfecto. Muchas gracias. Si puedo ayudar en algo... Voy a intentar entender el programa, pero veo que hay algunas cosas que me quedan muy lejos. Gracias

Pregunta lo q no entiendas, todo sera que te líe mas :P

¿Las entradas 2 y 3 actuan indiferentemente en el proceso 1 o 2?

La señal de entrada pins 2, la lee siempre que no este editando tiempos y que no haya actuado ya la salida pin 4, y la entrtada pin 3, la lee siempre que no este editando tiempos, haya actuado el pin 4 y no haya actuado el 5.