Interrupciones y temporizador

Buenas noches, estoy enfrascado en un proyecto, en apariencia simple pero me esta dando quebraderos de cabeza.
Se trata de lo siguente, tengo un contador de agua que me da un pulso por litro, estos pulsos los recojo con una interrupción que incrementa un contador, cuando el contador llega a 20000, acciono un rele durante tres horas con un delay, el problema es que cuando el rele esta activo por el delay el contador no se incrementa con los nuevos pulsos.
¿Hay alguna manera de activar una salida esas tres horas y volver a desactivarla sin perder los pulsos intermedios?
Gracias.

tu problema es el comando Delay ya que este detiene por completo tu programa hasta que cumpla su tiempo asignado entonces este vuelve a hacer su trabajo.

puedes especificar mas tu proyecto para poder proponerte algo.

vaqueromadrid:
Buenas noches, estoy enfrascado en un proyecto, en apariencia simple pero me esta dando quebraderos de cabeza.
Se trata de lo siguente, tengo un contador de agua que me da un pulso por litro, estos pulsos los recojo con una interrupción que incrementa un contador, cuando el contador llega a 20000, acciono un rele durante tres horas con un delay, el problema es que cuando el rele esta activo por el delay el contador no se incrementa con los nuevos pulsos.
¿Hay alguna manera de activar una salida esas tres horas y volver a desactivarla sin perder los pulsos intermedios?
Gracias.

usa millis() ,echa un ojo al ejemplo del ide Archivo->Ejemplos->02.Digital->BlynkWhitoutDelay y a esto:

De todas maneras postea tu sketch (lee las normas del foro si no sabes como) ,pues el codigo dentro de la funcion a la que llama la interrupcion deberia ejecutarse,aun estando en un delay().

aaah los famosos timers :slight_smile:
No hace ni unos días estaba aquí preguntando lo mismo.

Por si te sirve yo estoy usando la libería RBD_Timer.

github - RBD_Timer

Documentación en robotsbigdata

#include <RBD_Timer.h>

RBD::Timer activarRele;
RBD::Timer activarContador;
int contador = 0;

void setup() {
  Serial.begin(9600);
  activarRele.setTimeout(20000);
  activarContador.setTimeout(2000);
}

void loop() {

  if(activarRele.isExpired()) { //Tras 20 segundos activar
    Serial.println("Vamos a activar aquí el Rele, cont: " + String(contador) );
  }
  if(activarContador.isExpired()) {
      contador++;
      activarContador.restart(); //reiniciamos el timer cuando acaba.

      //También podemos cambiar el tiempo
      //activarContador.setTimeout(1000);

      // y otras tantas funciones que trae la librería...
  }

}

Perdonad la tardanza, este es el código en cuestión:

const byte salida=4;//salida 4 para rele



int conta = 0;
int n = conta ;



void funcion1(){
      conta++;
           
     }


void setup() {

       

       pinMode(salida, OUTPUT);//defino salida 4 como salida
       
       Serial.begin(9600);// inicio puerto serie
       digitalWrite(salida,HIGH);
       attachInterrupt( 0, funcion1, RISING);
      
}
void loop(){
  if (n != conta)
          {     Serial.println(conta);
                n = conta ;
          }

if(conta>=5){
      digitalWrite(salida,LOW);
      delay(5000);
      digitalWrite(salida, HIGH);
      conta=0;      
          }
}

Hola vaqueromadrid

El codigo que posteas no se corresponde con las condiciones que fijas en tu primer post

  • cuentas = 20000
  • tiempo de activacion del rele = 3 horas

¿ Quizas has puesto una version simplificada ?.

En principio la interrupcion que atiendes con <funcion1()> debe funcionar correctamente incluso estando dentro de un <delay()>. No ocurre lo mismo con <Serial.println()> que sí puede entrar en conflicto con <delay()>, porque tambien usa interrupciones.
Prueba esta modificacion del codigo y comenta el resultado:

const byte salida=4;   //salida 4 para rele

int conta = 0;
int n = conta ;


void funcion1()
{
      conta++;
           
}


void setup()
{
       pinMode(salida, OUTPUT);//defino salida 4 como salida
       
       Serial.begin(9600);// inicio puerto serie
       digitalWrite(salida,HIGH);
       attachInterrupt( 0, funcion1, RISING);
}

void loop()
{
    if (n != conta)
    {
         Serial.println(conta);
         n = conta ;
    }

    if(conta>=5)
    {
         digitalWrite(salida,LOW);
         delay(5000);
         digitalWrite(salida, HIGH);
         Serial.println(conta);   // <<=== Añade esta linea
         conta=0;     
    }
}

Saludos.

Perfecto ahora!!!
He tenido que modificar un poco el código.
Alfaville, he puesto los tiempos y los pulsos mas cortos porque estoy haciendo pruebas y si tengo que meter 20000 y esperar tres horas me hago viejo...
Así ha quedado:

const byte salida=4;   //salida 4 para rele

int conta = 0;
int n = conta ;


void funcion1()
{
      conta++;
           
}


void setup()
{
       pinMode(salida, OUTPUT);//defino salida 4 como salida
       
       Serial.begin(9600);// inicio puerto serie
       digitalWrite(salida,HIGH);
       attachInterrupt( 0, funcion1, RISING);
}

void loop()
{
    if (n != conta)
    {
         Serial.println(conta);
         n = conta ;
    }

    if(conta>=5)
    {
         conta=0;
         digitalWrite(salida,LOW);
         delay(5000);
         digitalWrite(salida, HIGH);
         Serial.println(conta);   // <<=== Añade esta linea
             
    }
}

Gracias por todo.

Si realmente das por finalizada tu consulta edita el titulo del post y añade "SOLUCIONADO".

Saludos.