Duda con un codigo

Hola a todos, hace una semana que hice un temporizador a 0 con un arduino uno, encontre el codigo en internet y funciona de maravilla lo anexo al final del post, pero se me ocurrio el hecho de que, que pasaria si necesitase pausar la cuenta regresiva y luego volverla a comenzar desde donde se quedo, si alguien me pudiera dar una idea de como hacerlo, pues yo estaba pensando en un "if" por ejemplo

int boton_pausa = 1;
analogRead(pinMode, boton_pausa);

if(boton_pausa ==1)

{

aqui es donde no se como puedo pausar la cuenta regrasiva

}

si alguien me pudiese ayudar le agradeceria

#include <LiquidCrystal.h> //Libreria del display LCD

LiquidCrystal lcd(12, 11, 5, 4, 3, 2); //Inicializamos la libreria con el numero de los pines a utilizar

int buzzer = 13; //Alarma
int ahoras = 0; //Variable a mostrar por LCD de las horas
int aminutos = 0; //Variable a mostrar por LCD de los minutos
int asegundos = 0; //Variable a mostrar por LCD de los segundos
int segundostotal = 0; //Tiempo total
int msg= 0; //Barrera para el mensaje de bienvenida

int start = A2; //Pulsador de arranque
int empieza = 1024; // Variable para almacenaje del pulsador de arranque

int buth = A5; //Pulsador de Horas
int butm = A4; //Pulsador de Minutos
int buts = A3; //Pulsador de segundos

int varbuth = 0; //Variable para almacenar el valor del pulsador de horas
int varbutm = 0; //Variable para almacenar el valor del pulsador de minutos
int varbuts = 0; //Variable para almacenar el valor del pulsador de segundos

void setup()
{
lcd.begin(16, 2); // Configuramos el numero de columnas y filas del LCD.

pinMode(buzzer, OUTPUT); //Pin de alarma --> Salida
pinMode(buth, INPUT); //Pin de pulsador de horas --> Entrada
pinMode(butm, INPUT); //Pin de pulsador de minutos --> Entrada
pinMode(buts, INPUT); //Pin de pulsador de segundos --> Entrada
pinMode(start, INPUT); //Pin de pulsador de arranque --> Entrada

msg = 0; //Barrera del mensaje de bienvenida
empieza = 1024; //Barrera de arranque

varbuth = 1; //Barrera de horas
varbutm = 1; //Barrera de minutos
varbuts = 1; //Barrera de segundos
}

void loop()
{
if(msg==0) //Mostramos el mensaje de bienvenida solo una vez
{
lcd.setCursor(0,0);
lcd.print("Temporizador con");
lcd.setCursor(1,1);
lcd.print("Arduino + LCD");
delay(2500);
msg = 1;
lcd.clear();
}

//-------------------------------------------------------------------------------------------------
// LECTURA DE LOS BOTONES Y ELECCIÓN DEL TIEMPO, NO SALE DEL BUCLE HASTA PULSAR
// EL BOTON DE ARRANQUE
//-------------------------------------------------------------------------------------------------

do
{

varbuth = analogRead(buth); //Leemos boton de horas
varbutm = analogRead(butm); //Leemos boton de minutos
varbuts = analogRead(buts); //Leemos boton de segundos

if(varbuth == 0) //Si el boton ha sido pulsado, aumentamos las horas en una unidad
{
ahoras = ahoras + 1 ;
delay(250);
}

if(varbutm == 0) //Si el boton ha sido pulsado, aumentamos los minutos en una unidad
{
aminutos = aminutos + 1;
delay(250);
}

if(varbuts == 0) //Si el boton ha sido pulsado, aumentamos los segundos en una unidad
{
asegundos = asegundos + 1;
delay(250);
}

lcd.setCursor(0,0);
lcd.print("Elige el tiempo"); //Muestra mensaje y las HH:MM:SS que vayamos aumentando

lcd.setCursor(4,1);

if (ahoras < 10) lcd.print("0"); // Si las horas son menor que 10, pone un "0" delante.
lcd.print(ahoras); // Sin este codigo, se muestra asi: H:M:S (1:M:S)
lcd.print(":");

if (aminutos < 10) lcd.print("0"); // Si los minutos son menor que 10, pone un "0" delante.
lcd.print(aminutos); // Sin este codigo, se muestra asi: H:M:S (H:1:S)

lcd.print(":");
if (asegundos < 10) lcd.print("0"); // Si los segundos son menor que 10, pone un "0" delante.
lcd.print(asegundos); // Sin este codigo, se muestra asi: H:M:S (H:M:1)

empieza = analogRead(start); //Lee el boton de arranque

if (empieza == 0) //Si el boton de arranque, fue pulsado...
{
segundostotal = asegundos + (aminutos * 60) + (ahoras * 60 * 60); //Convierte el tiempo elegido en segundos!!
}

} while(empieza != 0); // Se repite el menu de elegir tiempo hasta que pulsemos el boton de arranque.

//-------------------------------------------------------------------------------------------------
// UNA VEZ PULSADO EL BOTON DE ARRANQUE Y ACUMULADO EL TIEMPO, ENTRA EN EL SIGUIENTE WHILE
// Y NO FINALIZA HASTA TERMINAR LA CUENTA.
//-------------------------------------------------------------------------------------------------

while (segundostotal > 0)
{
delay (1000); //Descontamos en periodos de 1 segundo
segundostotal--;

ahoras = ((segundostotal / 60)/ 60); //Convertimos los segundos totales en horas
aminutos = (segundostotal / 60) % 60; //Convertimos los segundos totales en minutos
asegundos = segundostotal % 60; //Convertimos los segundos totales en periodos de 60 segundos

lcd.setCursor(0,0);
lcd.print("Tiempo restante"); //Mostramos mensaje de tiempo restante

lcd.setCursor(4,1);
if (ahoras < 10) lcd.print("0"); // Si las horas son menor que 10, pone un "0" delante.
lcd.print(ahoras); // Sin este codigo, se muestra asi: H:M:S (1:M:S)
lcd.print(":");

if (aminutos < 10) lcd.print("0"); // Si los minutos son menor que 10, pone un "0" delante.
lcd.print(aminutos); // Sin este codigo, se muestra asi: H:M:S (H:1:S)

lcd.print(":");
if (asegundos < 10) lcd.print("0"); // si el valor de segundo esta por debajo de 9 (unidad) antepone un cero
lcd.print(asegundos); // Sin este codigo, se muestra asi: H:M:S (H:M:1)

if (segundostotal == 0) //Si finaliza el tiempo
{
while(1) //Bucle infinito mostrando mensaje y haciendo parpadear un led
{
lcd.clear();
lcd.setCursor(5,0);
lcd.print("Tiempo");
lcd.setCursor(3,1);
lcd.print("Finalizado");

digitalWrite(buzzer, HIGH);
delay(200);
digitalWrite(buzzer, LOW);
delay(200);
}
}
}

}

Saludos.

Hola Mike!!
Ante todo no puedo dejar de comentarte que es un código que tiene algunas cosas no muy bien programadas.
Pulsadores y switches son una cosa y se leen con digitalRead no con analogRead
Ejemplo de ello:

varbuth = analogRead(buth);   //Leemos boton de horas
varbutm = analogRead(butm);   //Leemos boton de minutos
varbuts = analogRead(buts);   //Leemos boton de segundos

Estas instrucciones deberian reemplazarse por

varbuth = digitalRead(buth);   //Leemos boton de horas
varbutm = digitalRead(butm);   //Leemos boton de minutos
varbuts = digitalRead(buts);   //Leemos boton de segundos

Si llevas adelante estos cambios puedes o no cambiar estas definiciones previas
int start = A2; //Pulsador de arranque
int buts = A3; //Pulsador de segundos
int butm = A4; //Pulsador de Minutos
int buth = A5; //Pulsador de Horas

Luego repite el error

empieza = analogRead(start);   //Lee el boton de arranque

debe ser

empieza = digitalRead(start);   //Lee el boton de arranque

Ahora define un nuevo pulsador

Hola Mike, se me ocurre que podrías programas una interrupción mediante la función attachInterrupt() Te dejo la documentación: http://arduino.cc/en/pmwiki.php?n=Reference/AttachInterrupt

No nos dices qué Arduino tienes pero, por ejemplo para el arduino UNO.

Define la variable global:
Boton_pausa=digitalRead(0) // Elegimos el Pin 0 porque es el que nos produce la interrupción

Podrías poner justo antes de comenzar la cuenta atrás el siguiente código:

attachInterrupt(0,Pausa,CHANGE); // Usamos el pin 0 porque es uno de los dos que nos permite hacer //interrupciones

Y haz una función antes del setup de la siguiente manera:

void Pausa(){

while(Boton_pausa){} // Si el botón está por defecto en alta, si estuviese en baja while(!Boton_pausa){}

}

No sé si estará bien pero ahí tienes una idea que creo que te puede funcionar.

He

para que una interrupcón?
Si es cierto que el código requiere de algunos "toques".

Hola surbyte, había pensado en una interrupción para poder hacer la pausa, al darle al pulsador o al botón se ejecutaría la rutina de interrupción y el programa quedaría en ella hasta que se le vuelva a dar al botón, cuando esto suceda continuaría la cuenta atrás que creo que es lo que Mike quería, o seo he entendido yo al menos.

Un saludo y lo siento si he cometido algún error.

No se usan interrupciones para permanecer segundos dentro de ella. No es la idea.
Se ejecuta un código corto, cambias una variable y vuelves al programa normal y con esa variables tomas una acción. Pero como te dije, en un programa que usa un delay(1000) consumiendo 1000 mseg no tiene sentido la interrupción porque puede hacerse sin ella.
En un momento posteo el código

#include <LiquidCrystal.h> //Libreria del display LCD
#define T1000 995   // debería ser 1000 pero dejo 5mseg para considerar todo el loop. Habria que medirlo para poner el valor correcto
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); //Inicializamos la libreria con el numero de los pines a utilizar

int buzzer       = 13;     // Alarma
int msg          = 0;      // Barrera para el mensaje de bienvenida

const byte start = 2;      // Pulsador de arranque
const byte buts  = 3;      // Pulsador de segundos
const byte butm  = 4;      // Pulsador de Minutos
const byte buth  = 5;      // Pulsador de Horas
const byte pausaPin = 6;      // Pulsador de pausa

int empieza      = 1024;   // Variable para almacenaje del pulsador de arranque
int pausa        = 0;
int varbuth      = 0;      // Variable para almacenar el valor del pulsador de horas
int varbutm      = 0;      // Variable para almacenar el valor del pulsador de minutos
int varbuts      = 0;      // Variable para almacenar el valor del pulsador de segundos

int ahoras       = 0;      // Variable a mostrar por LCD de las horas
int aminutos     = 0;      // Variable a mostrar por LCD de los minutos
int asegundos    = 0;      // Variable a mostrar por LCD de los segundos
int segundostotal= 0;      // Tiempo total
boolean detener = false;
unsigned long time = 0;

void setup()
{
   lcd.begin(16, 2);         // Configuramos el numero de columnas y filas del LCD. 
   
   pinMode(buzzer, OUTPUT);  // Pin de alarma --> Salida
   pinMode(buth, INPUT);     // Pin de pulsador de horas --> Entrada
   pinMode(butm, INPUT);     // Pin de pulsador de minutos --> Entrada
   pinMode(buts, INPUT);     // Pin de pulsador de segundos --> Entrada
   pinMode(start, INPUT);    // Pin de pulsador de arranque --> Entrada
   pinMode(pausaPin, INPUT);    // Pin de pulsador de pausa --> Entrada
   
   msg = 0;                  //Barrera del mensaje de bienvenida
   empieza = 1024;           //Barrera de arranque
   
   varbuth = 1;              //Barrera de horas
   varbutm = 1;              //Barrera de minutos
   varbuts = 1;              //Barrera de segundos
}

void loop()
{
     if(msg==0) {            //Mostramos el mensaje de bienvenida solo una vez
       lcd.setCursor(0,0);
       lcd.print("Temporizador con");
       lcd.setCursor(1,1);
       lcd.print("Arduino + LCD");
       delay(2500);
       msg = 1;
       lcd.clear();
     }
     
     //-------------------------------------------------------------------------------------------------     
     // LECTURA DE LOS BOTONES Y ELECCIÃ"N DEL TIEMPO, NO SALE DEL BUCLE HASTA PULSAR
     // EL BOTON DE ARRANQUE
     //-------------------------------------------------------------------------------------------------
     
     do  {
       
       varbuth = digitalRead(buth);   //Leemos boton de horas
       varbutm = digitalRead(butm);   //Leemos boton de minutos
       varbuts = digitalRead(buts);   //Leemos boton de segundos
       
       if(varbuth == 0)              //Si el boton ha sido pulsado, aumentamos las horas en una unidad
       {
        ahoras = ahoras + 1 ;
        delay(250);
       } 
       
        if(varbutm == 0)            //Si el boton ha sido pulsado, aumentamos los minutos en una unidad
       {
         aminutos = aminutos + 1;
         delay(250);
       } 
       
        if(varbuts == 0)            //Si el boton ha sido pulsado, aumentamos los segundos en una unidad
       {
         asegundos = asegundos + 1;
         delay(250);
       } 
             
       lcd.setCursor(0,0);
       lcd.print("Elige el tiempo");  //Muestra mensaje y las HH:MM:SS que vayamos aumentando
       
       lcd.setCursor(4,1);     

      if (ahoras < 10) lcd.print("0");    // Si las horas son menor que 10, pone un "0" delante.
       lcd.print(ahoras);                 // Sin este codigo, se muestra asi: H:M:S  (1:M:S)
       lcd.print(":");

      if (aminutos < 10) lcd.print("0");  // Si los minutos son menor que 10, pone un "0" delante.
       lcd.print(aminutos);               // Sin este codigo, se muestra asi: H:M:S  (H:1:S)

       lcd.print(":");
      if (asegundos < 10) lcd.print("0"); // Si los segundos son menor que 10, pone un "0" delante.
       lcd.print(asegundos);              // Sin este codigo, se muestra asi: H:M:S  (H:M:1)
       
       empieza = digitalRead(start);   //Lee el boton de arranque
       
       if (empieza == 0)              //Si el boton de arranque, fue pulsado...
       {
        segundostotal = asegundos + (aminutos * 60) + (ahoras * 60 * 60);  //Convierte el tiempo elegido en segundos!!
       }
             
     } while(empieza != 0);  // Se repite el menu de elegir tiempo hasta que pulsemos el boton de arranque.
       
      //-------------------------------------------------------------------------------------------------
      // UNA VEZ PULSADO EL BOTON DE ARRANQUE Y ACUMULADO EL TIEMPO, ENTRA EN EL SIGUIENTE WHILE
      // Y NO FINALIZA HASTA TERMINAR LA CUENTA.
      //-------------------------------------------------------------------------------------------------

      while (segundostotal > 0)
      {
        
        pausa = digitalRead(pausaPin);
        if (pausa == 0) {
            detener = !detener;
        }
        
        if (!detener) {              // lo que hago solo elimina el descuento de segundos, entonces luce como pausa
            //delay (1000);          //Descontamos en periodos de 1 segundo
            if (millis()-time > T1000) {
                segundostotal--;
                time = millis();
            }
        }     
   
        ahoras = ((segundostotal / 60)/ 60);   //Convertimos los segundos totales en horas
        aminutos = (segundostotal / 60) % 60;  //Convertimos los segundos totales en minutos
        asegundos = segundostotal % 60;        //Convertimos los segundos totales en periodos de 60 segundos

        lcd.setCursor(0,0);
        lcd.print("Tiempo restante");        //Mostramos mensaje de tiempo restante
 
        lcd.setCursor(4,1);
        if (ahoras < 10) lcd.print("0");     // Si las horas son menor que 10, pone un "0" delante.
        lcd.print(ahoras);                   // Sin este codigo, se muestra asi: H:M:S  (1:M:S)
        lcd.print(":");

        if (aminutos < 10) lcd.print("0");   // Si los minutos son menor que 10, pone un "0" delante.
        lcd.print(aminutos);                 // Sin este codigo, se muestra asi: H:M:S  (H:1:S)

        lcd.print(":");
        if (asegundos < 10) lcd.print("0");  // si el valor de segundo esta por debajo de 9 (unidad) antepone un cero
        lcd.print(asegundos);                // Sin este codigo, se muestra asi: H:M:S  (H:M:1)
       
          if (segundostotal == 0)            //Si finaliza el tiempo
          {           
             while(1)                        //Bucle infinito mostrando mensaje y haciendo parpadear un led
             {               
                  lcd.clear();
                  lcd.setCursor(5,0);
                  lcd.print("Tiempo");
                  lcd.setCursor(3,1);
                  lcd.print("Finalizado");
               
                 digitalWrite(buzzer, HIGH);
                 delay(200);
                 digitalWrite(buzzer, LOW);
                 delay(200);
             }     
          }
     }
     
}

NOTA: Olvidé comentar que una presion de pausa detiene y una segunda vuelve a poner en marcha el contador

No sabía que las interrupciones no se debían usar así, en clase sí que las hemos usado de esa forma y por eso había puesto ese código, pero intentaré usarlas tal y como comentas de aquí en adelante.

Gracias por el comentario !

una interrupción es para ejecutar un código corto, y devolver rápido el control al programa.
Es un error conceptual pensar como te han enseñado y te explico porque.

Imaginemos un arduino que esta controlando un proceso crítico, no hagamos ciencia ficción, supongamos solo un control de temperatura digamos de un producto comestible.
Encontes durante el loop el arduino lee temperatura y en función de su lectura, varia la fase de un triac para calentar mas o menos una resistencia.

Ahora supongamos que conectas a una interrupción algo como tu dices, y se queda ahi... simplemente interrumpiendo, bueno resulta que la temperatura crece y crece porque nadie le dice que se apague y conclusión algo se quemará o saltará la térmica indicando un exceso de corriente en la resistencia.

Es un ejemplo burdo si se quiere pero demuestra para que no fueron diseñadas las interrupciones.

Por otro lado, supon un motor de DC y un enconder pues los enconders suelen leerse usando interrupciones en la salida A y B, Si A esta adelantada a B es porque va en un sentido y sino lo contrario.
En todo momento las interrupciones cuentan pulsos de A y B y establecen la posicion del enconder.
Eso es rápido, porque ejecutada la interrupcion incremetan un contador y determinan una y dos cosas y devuelven el control. Todo es ocurre dentro de un loop donde se esta controlando la velocidad o posicion del motor con este enconder.

Asi que ves que la idea es diametralmente opuesta a la que suponías. Perooo en este caso podria usarse, aunque es un exceso pero como aprendizaje sirve.

Comprendo el problema, en clase ya hicimos ejemplos con un contador de pulsos y un display de 7 segmentos donde podíamos ver que a altas frecuencias el display no funcionaba bien debido a las interrupciones. Pero el profesor no dijo nada más al respecto y creo recordar que hemos usado interrupciones largas.

De todas formas ya he aprendido como se deben usar así que lo intentaré hacer así, gracias por la lección. :slight_smile:

Bueno. No he revisado muy a fondo el código, pero si sólo se trata de congelar la cuenta atrás, con usar una variable auxiliar int descuento = 1;

y sustityendo segundostotal--;
por segundostotal-=descuento;

sólo necesitaríamos que al pulsar el botón descuento=0, y al volver a pulsarlo descuento=1

¿Podría valer así?

EDITO:
Si la detección de pulsación va a ser por interrupción, no olvidar declarar descuento como volatile.

Claro, es otra manera de hacerlo, pero al soltar el botón pausa sigue? Yo entendí que quería pausar y luego volver a presionar pausa para continuar.

Más sencillo entonces:
if (digitalRead(boton)==HIGH)
descuento=0;
else
descuento=1;

De nuevo si sueltas el boton sigue
Repito: entendí que pausa detenien y otra pulsada recomienza. O sea que el boton latchea.

Por eso decía que al pulsar sería 0 y al volver a pulsar, de nuevo 1. Claro, que con delays de un segundo de por medio, la detección de pulsación debería ser por interrupción de flanco de subida (habría que lidiar, además, con los posibles rebotes). Otra opción más "terrenal" sería cambiar delay por millis y determinar mediante lecturas si el botón ha pasado de LOW a HIGH.

Traducido a código:

if (previousState==LOW && currentState==HIGH)
descuento ^= B00000001;

Saludos
Utilizando la idea de noter. Puedes hacer:
boolean descuento= true;

if (digitalRead(boton)==HIGH){
descuento= ~descuento;
}

Nota: no he probando este metodo

hola amigos, pues investigando en internet, pensaba hacerlo por una interrupcion como dicen algunos compañeros en sus comentarios, agradezco a subryte por las correciones hechas, como info adicional, añado que uso un arduino uno, y que asi como esta ese codigo lo tengo funcionando bien, intentare probar con el codigo que me ha dado subryte y les comentaré como como quedo el dispositivo

una vez más les agredezco por su ayuda :slight_smile: