SOLUCIONADO: Contador Descendente "Sencillo"

Saludes a todos una vez más.

En esta ocasión vengo a ustedes, por un pequeño inconveniente que tengo por el momento, y es que estoy haciendo un pequeño menú de una plancha para hacer PCB, he trabajado el código, y en el menú que tengo hasta ahorita llevó 3 opciones que son los tipos de planchados que se hará.

Estos planchados llevan un tiempo en especifico dado el tipo de papel, y es ahí mi pequeño inconveniente, y es que aún no puedo programar un simple contador descendente, digo simple porque quizás lo sea, pero no sé la verdad que tan complicado puede ser.

Serían 3 contadores, el primero que comience desde 10 min y terminé claro está en 0, el segundo de 8 min, y el tercero de 6 min. Estoy trabajando con la LCD para mostrar el contador.

Me gustaría que vosotros me ayudarán con este proyecto casero, continúo con esto de la programación, pero se que falta aprender muchas cosas más.

Adjunto la parte del código donde debería ir el contador-

//-------------------- Función Secundaria ----------------------
void TiposPapel()
{
 lcd.clear();
        //--------- Papel 1 ----------
  val1= digitalRead(inPin1);
    if(val == HIGH)
      {
        delay(50);
        Papel1();
      } 


        //--------- Papel 2 ----------
  val2= digitalRead(inPin2);
    if(val2 == HIGH)
      {
        delay(50);
        Papel2();
      }


        //--------- Papel 3 ----------
  val3= digitalRead(inPin3);
    if(val3 == HIGH)
      {
        delay(50);
        Papel3();
      }
      
}



//  --------------- Funciones para los tipos de papeles ------------------------
void Papel1();
{
    delay(50);
    lcd.clear();
    digitalWrite(ledPin,HIGH);
    lcd.setCursor(0, 1);          // enviamos la posicion del cursor al display (nota: la linea 1 es la segunda fila, empieza a contar en 0
    // Acá comenzaria el contador descendente de 10 Min
}

void Papel2();
{
    delay(50);
    lcd.clear();
    digitalWrite(ledPin,HIGH);
    lcd.setCursor(0, 1);
    // Acá comenzaria el contador descendente 8 Min
}

void Papel3();
{
    delay(50);
    lcd.clear();
    digitalWrite(ledPin,HIGH);
    lcd.setCursor(0, 1);
    // Acá comenzaria el contador descendente 6 Min
}
//  ------------------------------------------------------------------------------------------

Cuando el tiempo termine mandaré a activar una alarma, pero eso podría trabajarlo, ese contador es el que me tiene algo confundido.

Agradezco con anticipación sus ayudas y sugerencias.

Saludes a todos.. :slight_smile:

Qué te parecen este par de funciones?

void contar(byte minutos) { // Esta función bloquerará el programa hasta que el while muera
  const unsigned long regresiva = minutos * 60000U; // Calculo de la duración de la cuenta regresiva, en milisegundos.
  unsigned int segundosRestantes = minutos * 60; // Calculo de la cuenta regresiva para mostrar en la LCD, en segundos.
  // Si el decremento intenta ir por debajo de cero... ups

  unsigned long tAnterior = 0;
  const unsigned long inicio = millis(); // Oh sí; para la cuenta usaremos el famoso millis. Guarda el momento en que se inició la cuenta.

  while (millis() - inicio < regresiva) {
    // El ciclo se mantiene vivo hasta que la diferencia del tiempo actual e inicial supere la duración requerida.

    unsigned long tActual = millis();
    if (tActual - tAnterior >= 1000) { // Actualizar el temporizador en la LCD cada segundo.
      tAnterior = tActual;
      imprimirTiempo(segundosRestantes);
      segundosRestantes--;
    }
  }
}

void imprimirTiempo(unsigned int s) {
  byte minuto = s / 60;
  byte segundo = s % 60;

  if (minuto < 10) {
    lcd.print('0');
    lcd.print(minuto);
  } else {
    lcd.print(minuto);
  }

  lcd.print(':');

  if (segundo < 10) {
    lcd.print('0');
    lcd.print(segundo);
  } else {
    lcd.print(segundo);
  }
  lcd.setCursor(0, 1);
}

Así, donde dice algo como:

// Acá comenzaria el contador descendente de 10 Min

Lo reemplazarías por:

contar(10);

Atento a tu retroalimentación :slight_smile:

Wooww, estoy algo avergonzado con el término que usé ( sencillo )..

No se vé tan sencillo, ahora mismo, lo pondré a correr.

Muchas gracias Lucario448.

:slight_smile:

Neythan:
Wooww, estoy algo avergonzado con el término que usé ( sencillo )..

Bueno... está entrecomillado; así que de hecho se podría haber interpretado como un sarcasmo... digo yo ::slight_smile:

Lucario448:
Bueno... está entrecomillado; así que de hecho se podría haber interpretado como un sarcasmo... digo yo ::slight_smile:

No, no es sarcasmo, la verdad si se ve algo complicado, yo ni idea tenia de como atarcar ese problemilla, agradezo Lucario448 la ayuda, y ya lo acabo de implementar, y funciona a la perfección, tengo errores pero no son de esas funciones en si, sino por las conexiones que tengo, y el como tengo que arreglar el codigo para que funcione todo.

Una vez mas, agradezco su valiosa ayuda. :slight_smile: Saludes..

Creo que debo colocar "SOLUCIONADO" ahora al inicio del Tema, verdad??

Neythan:
y el como tengo que arreglar el codigo para que funcione todo.

Recuerda que la función contar bloquea el programa hasta que el bloque while (la cuenta regresiva) acabe.
No sé si ese sea el motivo por el cuál debas "arreglar" el código.

Neythan:
Creo que debo colocar "SOLUCIONADO" ahora al inicio del Tema, verdad??

Si de verdad crees ya tenerlo solucionado, sí.

Lucario448:
Recuerda que la función contar bloquea el programa hasta que el bloque while (la cuenta regresiva) acabe.
No sé si ese sea el motivo por el cuál debas "arreglar" el código.

Si, esa parte esta funcionando bien (las funciones del contador) porque ya las probé aparte, lo que sucede es que al unirlo al programa completo y correrlo me aparece una parte del menú y se va directo al contador, creo que es por la manera en que usé la función del mismo (contador) en el codigo, siento que estoy cometiendo un error, y buscaré como solucionarlo. No descarto la posibilidad de seguir consultándoles.

Este es el código que voy armando

// incluimos la libreria LiquidCrystal
#include <LiquidCrystal.h>
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

// --------------- Variable de salida
int ledPin=13;
// ---------------- Variables de lectura --------------
int inPin=3;    // Pushbotton
int inPin1=4;  // Pushbotton
int inPin2=5;  // Pushbotton
int inPin3=6;  // Pushbotton
// ---------------- Variables de asignación --------------
int val0=0;
int val1=0;
int val2=0;
int val3=0;


//---------------------- Inicio del programa ------------------
void setup()
{
    Serial.begin(9600);
    pinMode (ledPin,OUTPUT);
    pinMode(inPin,INPUT);
    pinMode(inPin1,INPUT);
    pinMode(inPin2,INPUT);
    pinMode(inPin3,INPUT);
    lcd.begin(16, 2);                    // establecemos el numero de columnas y filas del display 
}



//-------------------- Función Principal ----------------------
void loop() 
{
    lcd.setCursor(3, 0);
    lcd.print("Bienvenidos");           // enviamos el mensaje a mostrar en el display
    delay(2000);
    lcd.setCursor(0, 0);
    lcd.print("Por favor Cierre");
    lcd.setCursor(4, 1);
    lcd.print("la tapa ");
    val0=digitalRead(inPin);
    if(val0 == HIGH) 
      {  
        delay(50);
        TiposPapel();
      }
      
    else
      {
        lcd.begin(16, 2);
        lcd.setCursor(0, 0);          // enviamos el mensaje a mostrar en el display
        lcd.print(" La Tapa aun no");
        lcd.setCursor(0, 1); 
        lcd.print("ha sido cerrada");
        delay(1000);
      }
}



//-------------------- Función Secundaria ----------------------
void TiposPapel()
{
 lcd.clear();
        //--------- Papel 1 ----------
  val1= digitalRead(inPin1);
    if(val1 == HIGH)
      {
        delay(50);
        papel1();
      } 


        //--------- Papel 2 ----------
  val2= digitalRead(inPin2);
    if(val2 == HIGH)
      {
        delay(50);
        papel2();
      }


        //--------- Papel 3 ----------
  val3= digitalRead(inPin3);
    if(val3 == HIGH)
      {
        delay(50);
        papel3();
      }
      
}



//  --------------- Funciones para los tipos de papeles ------------------------
void papel1()
{
    delay(50);
    lcd.clear();
    digitalWrite(ledPin,HIGH);
    lcd.setCursor(0, 1);          // enviamos la posicion del cursor al display (nota: la linea 1 es la segunda fila, empieza a contar en 0
    contar(1);
}

void papel2()
{
    delay(50);
    lcd.clear();
    digitalWrite(ledPin,HIGH);
    lcd.setCursor(0, 1);
    contar(2);
}

void papel3()
{
    delay(50);
    lcd.clear();
    digitalWrite(ledPin,HIGH);
    lcd.setCursor(0, 1);
    contar(3);
}
//  ------------------------------------------------------------------------------------------



//  ------------------------------------------------------------------------------------------
void contar(byte minutos) 
{                                                                       // Esta función bloquerará el programa hasta que el while muera
  const unsigned long regresiva = minutos * 60000U;                     // Calculo de la duración de la cuenta regresiva, en milisegundos.
  unsigned int segundosRestantes = minutos * 60;                        // Calculo de la cuenta regresiva para mostrar en la LCD, en segundos.
  // Si el decremento intenta ir por debajo de cero... ups

  unsigned long tAnterior = 0;
  const unsigned long inicio = millis();                                // Oh sí; para la cuenta usaremos el famoso millis. Guarda el momento en que se inició la cuenta.

  while (millis() - inicio < regresiva) {
                                                                      // El ciclo se mantiene vivo hasta que la diferencia del tiempo actual e inicial supere la duración requerida.

    unsigned long tActual = millis();
    if (tActual - tAnterior >= 1000) {                                  // Actualizar el temporizador en la LCD cada segundo.
      tAnterior = tActual;
      imprimirTiempo(segundosRestantes);
      segundosRestantes--;
    }
  }
}


void imprimirTiempo(unsigned int s) {
  byte minuto = s / 60;
  byte segundo = s % 60;

  if (minuto < 10) {
    lcd.print('0');
    lcd.print(minuto);
  } else {
    lcd.print(minuto);
  }

  lcd.print(':');

  if (segundo < 10) {
    lcd.print('0');
    lcd.print(segundo);
  } else {
    lcd.print(segundo);
  }
  lcd.setCursor(0, 1);
}

Lucario448:
Si de verdad crees ya tenerlo solucionado, sí

Creo que aún me hace falta aniquilarlo (el programa), pero será pronto. :smiley:

Neythan:
lo que sucede es que al unirlo al programa completo y correrlo me aparece una parte del menú y se va directo al contador

Me huele más a asunto de hardware que de otra cosa. contar sólo se llama cuando se ejecuta papel1, papel2 o papel3; lo cuál supongo que es tu idea.

A nivel físico: hay que mantener pulsados un par de botones para que inicie la cuenta regresiva (o un contacto cerrado y un botón).

Neythan:
Creo que aún me hace falta aniquilarlo (el programa), pero será pronto. :smiley:

Sí, no vaya a ser que sea a mi :o

Lucario448:
Me huele más a asunto de hardware que de otra cosa. contar sólo se llama cuando se ejecuta papel1, papel2] o papel3; lo cuál supongo que es tu idea.

A nivel físico: hay que mantener pulsados un par de botones para que inicie la cuenta regresiva (o un contacto cerrado y un botón).

Si, tambien tenia pensado ese asuntillo de mi circuito fisico porque no veía algun error en el código.

Con respecto a lo de los botones, yo tengo en mente que aparezca el "menú" que solo dice que se presione un pushbotton para continuar, cuando éste se presionó, ahora elegir presionar 1 de los 3 pushbotton que representan a cada uno de los tipos de papel, cuando se presionó uno de los 3, entrar a la función correspondiente. Todos son pushbotton.

La cuestión es que solo me aparece el mensaje de "Bienvenido" y se me tira al "else" jejeje ni siquiera me manda el otro mensajito que tengo.

Lucario448:
Sí, no vaya a ser que sea a mi :o

Descuide, para nada. :smiley:

Neythan:
La cuestión es que solo me aparece el mensaje de "Bienvenido" y se me tira al "else" jejeje ni siquiera me manda el otro mensajito que tengo.

Cual otro mensajito?
En el bloque else dice que "La tapa aun no ha sido cerrada". No se llega a ese mensaje aún sin tocar nada?

Lucario448:
Cual otro mensajito?
En el bloque else dice que "La tapa aun no ha sido cerrada". No se llega a ese mensaje aún sin tocar nada?

Sí, sólo me mostraba el primer "Mensaje" y se lanzaba de una vez al "else", lo revise y le coloqué un delay antes del segundo comentario, y ahora si lo muestra, pero no me funciona el "If", no espera en el segundo mensaje hasta que presione el pushbotton sino que se mantiene intermitente entre el primer y segundo mensaje, luego de unos segundos se pasa al "else", presiono y presiono el pushbotton pero no me entra al menú.

Creo y no se si estoy en lo correcto, pero pienso que el problema es en el hardware. Creéis que sea el código?, estoy revisando el circuito buscando algun posible fallo. :frowning:

Neythan:
Sí, sólo me mostraba el primer "Mensaje" y se lanzaba de una vez al "else", lo revise y le coloqué un delay antes del segundo comentario, y ahora si lo muestra, pero no me funciona el "If", no espera en el segundo mensaje hasta que presione el pushbotton sino que se mantiene intermitente entre el primer y segundo mensaje, luego de unos segundos se pasa al "else", presiono y presiono el pushbotton pero no me entra al menú.

Dos cositas:

  • delay bloquea el programa; entonces durante ese tiempo, todas las entradas son ignoradas.
  • Para que no se REPITA (a manera de "loop") el mensaje de bienvenida, esta debe imprimirse en el setup.

Si quieres que se detecte la entrada en cualquier momento, pero aún así retrasando el cambio de los mensajes; ya ahí habría que jugar con millis también.

Lucario448:
Dos cositas:

  • delay bloquea el programa; entonces durante ese tiempo, todas las entradas son ignoradas.
  • Para que no se REPITA (a manera de "loop") el mensaje de bienvenida, esta debe imprimirse en el setup.

Si quieres que se detecte la entrada en cualquier momento, pero aún así retrasando el cambio de los mensajes; ya ahí habría que jugar con millis también.

En efecto Lucario448 ( Se escucha aún mejor Mega Lucario448 jejeje :smiley: ), hice lo que usted me recomendó (colocar primeros mensajes en el setup) y ha quedado fantástico, ya aprendí algo nuevo, muchas gracias.

Adjunto el código que llevo hasta hoy, sé que hace falta trabajarlo un poco más, pero ya va quedando :smiley:

// incluimos la libreria LiquidCrystal
#include <LiquidCrystal.h>
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

// --------------- Variable de salida
int ledPin=13;
// ---------------- Variables de lectura --------------
int inPin=3;
int inPin1=4;
int inPin2=5;
int inPin3=6;
// ---------------- Variables de asignación --------------
int val0=0;
int val1=0;
int val2=0;
int val3=0;


//---------------------- Inicio del programa ------------------
void setup()
{
    Serial.begin(9600);
    lcd.begin(16, 2);                    // establecemos el numero de columnas y filas del display 
    lcd.setCursor(3, 0);
    lcd.print("Bienvenidos");           // enviamos el mensaje a mostrar en el display
    delay(2000);
    lcd.setCursor(0, 0);
    lcd.print("Por favor Cierre");
    lcd.setCursor(4, 1);
    lcd.print("la tapa ");
    delay(5000);
    pinMode (ledPin,OUTPUT);
    pinMode(inPin,INPUT);
    pinMode(inPin1,INPUT);
    pinMode(inPin2,INPUT);
    pinMode(inPin3,INPUT);
}    



//-------------------- Función Principal ----------------------
void loop() 
{
    val0=digitalRead(inPin);
    if(val0 == HIGH) 
      {  
        
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Seleccione tipo");
        lcd.setCursor(4,1);
        lcd.print(" de papel");
        delay(2000);
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("1.Norm. 2.Firmin");
        lcd.setCursor(3,1);
        lcd.print("3.Otro");
        delay(4000);
        TiposPapel();
      }
      
    else
      {
        lcd.clear();
        lcd.setCursor(0, 0);          // enviamos el mensaje a mostrar en el display
        lcd.print(" La Tapa aun no");
        lcd.setCursor(0, 1); 
        lcd.print("ha sido cerrada");
        delay(1000);
      }
}



//-------------------- Función Secundaria ----------------------
void TiposPapel()
{
 lcd.clear();
        //--------- Papel 1 ----------
  val1= digitalRead(inPin1);
    if(val1 == HIGH)
      {
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("Papel Normal");
        lcd.setCursor(2,1);
        lcd.print("Seleccionado");
        delay(2000);
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("Espere");
        delay(1000);
        papel1();
      } 


        //--------- Papel 2 ----------
  val2= digitalRead(inPin2);
    if(val2 == HIGH)
      {
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("Papel Firmin");
        lcd.setCursor(2,1);
        lcd.print("Seleccionado");
        delay(2000);
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("Espere");
        delay(1000);
        papel2();
      }


        //--------- Papel 3 ----------
  val3= digitalRead(inPin3);
    if(val3 == HIGH)
      {
        lcd.clear();
        lcd.setCursor(5,0);
        lcd.print("Otro");
        lcd.setCursor(2,1);
        lcd.print("Seleccionado");
        delay(2000);
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("Espere");
        delay(1000);
        papel3();
      }
      
}



//  --------------- Funciones para los tipos de papeles ------------------------
void papel1()
{
    lcd.clear();
    digitalWrite(ledPin,HIGH);
    lcd.setCursor(0, 1);          // enviamos la posicion del cursor al display (nota: la linea 1 es la segunda fila, empieza a contar en 0
    contar(1);
}

void papel2()
{
    lcd.clear();
    digitalWrite(ledPin,HIGH);
    lcd.setCursor(0, 1);
    contar(2);
}

void papel3()
{
    lcd.clear();
    digitalWrite(ledPin,HIGH);
    lcd.setCursor(0, 1);
    contar(3);
}
//  ------------------------------------------------------------------------------------------



//  ------------------------------------------------------------------------------------------
void contar(byte minutos) 
{                                                                       // Esta función bloquerará el programa hasta que el while muera
  const unsigned long regresiva = minutos * 60000U;                     // Calculo de la duración de la cuenta regresiva, en milisegundos.
  unsigned int segundosRestantes = minutos * 60;                        // Calculo de la cuenta regresiva para mostrar en la LCD, en segundos.
  // Si el decremento intenta ir por debajo de cero... ups

  unsigned long tAnterior = 0;
  const unsigned long inicio = millis();                                // Oh sí; para la cuenta usaremos el famoso millis. Guarda el momento en que se inició la cuenta.

  while (millis() - inicio < regresiva) {
                                                                      // El ciclo se mantiene vivo hasta que la diferencia del tiempo actual e inicial supere la duración requerida.

    unsigned long tActual = millis();
    if (tActual - tAnterior >= 1000) {                                  // Actualizar el temporizador en la LCD cada segundo.
      tAnterior = tActual;
      imprimirTiempo(segundosRestantes);
      segundosRestantes--;
    }
  }
}


void imprimirTiempo(unsigned int s) {
  byte minuto = s / 60;
  byte segundo = s % 60;

  if (minuto < 10) {
    lcd.print('0');
    lcd.print(minuto);
  } else {
    lcd.print(minuto);
  }

  lcd.print(':');

  if (segundo < 10) {
    lcd.print('0');
    lcd.print(segundo);
  } else {
    lcd.print(segundo);
  }
  lcd.setCursor(0, 1);
}

Agradezco la gran y valiosa ayuda Brindada.

y Ahora sí, el Contador queda SOLUCIONADO.

Una vez más muchas gracias.

Saludes. :smiley:

Neythan:
( Se escucha aún mejor Mega Lucario448 jejeje :smiley: )

No sé si fue una idea tuya; o si es una referencia al Arduino Mega, o a Pokémon...