Activar salida digital con millis() por unica vez dada una condicion

Buenos días a todos, mi nombre es Ignacio.
Estoy intentando programar una función en un nodemcu y no doy pie. Leí todo el tutorial que amablemente edito victorjam y aun así no lo pude solucionar.
La intensión es, en una determinada hora y minuto, necesito que se active una salida por un tiempo determinado (menor a 60 segundos) programable utilizando la funcion millis().
Esta función (millis()) ya la utilizo en otras partes de mi código y funciona perfecto, pero aquí el problema es que dado la siguiente función:


    if(HoraActual == HoraRiego && MinutosActual == MinutosRiego) 
    {
    if(digitalRead(Bomba)==LOW)
    {
    digitalWrite(Bomba, HIGH);
    t = millis();
    }
    else
    {
     if(millis()-t >= TiempoRiego)
    {
     digitalWrite(Bomba, LOW);
    }
    }
    }

se enciende la salida durante el tiempo programado (TiempoRiego (milisegundos)), luego se apaga, y al ejecutar nuevamente la función (por estar dentro del loop) y estar dentro de la condición IF (de hora y minutos) se vuelve a encender.
Lo que necesito lograr es que a una determinada hora y minutos, la bomba se encienda por un tiempo en segundos (que puede ser de 1 a 60) y se apague.

EDITO
Logre temporalmente hacerlo funcionar con un bool que cambia de condición cuando cambia la hora o los minutos, aunque no considero sea la forma correcta de hacerlo. El codigo quedo asi:

if (riegorealizado == true)
{
if(HoraActual == HoraRiego && MinutosActual == MinutosRiego) 
    {
    if(digitalRead(Bomba)==LOW)
    {
    digitalWrite(Bomba, HIGH);
    t = millis();
    riegorealizado = true;
    }
    else
    {
     if(millis()-t >= TiempoRiego)
    {
     digitalWrite(Bomba, LOW);
     riegorealizado = false;
    }
    }
    }
}

if(HoraActual != HoraRiego || MinutosActual != MinutosRiego) 
    {
      riegorealizado = true;
    }

El mayor problema que le veo es que se te solapa la duración con la hora. Es decir te encuentras que para tiempos de riego de 1 segundo, se te puede ejecutar 60 veces a la misma hora.

Por lo tanto se necesita una variable para controlar eso, tal y como has hecho muy acertadamente, aunque con el código un poco enmarañado.

Quizás, te aconsejaria cambiar el nombre de la variable a algo que sea más acorde a lo que pretendes hacer. Por ejemplo, una variable bool llamada regar. Cuando esta variable es falsa debes comprobar la hora/minuto y si es el momento de regar enciendes la bomba, guardas millis y la pones a cierto.

Mientras esta variable sea cierta debes mirar el tiempo, asi que cuando transcurra este basta con apagar la bomba. La variable regar solo se vuelve a poner en falso cuando no sea la hora/minuto de riego. Así evitas el que en el mismo minuto te esté regando todo el rato.

En código, quedaría aproximadamente asi:


// Si 'regar' es falsa, comprobamos que es hora de regar, si lo es, iniciamos
// el temporizador, encendemos la bomba e indicamos que vamos a regar.
if ( regar == false ) {
  if ( horaActual == horaRiego && minutoActual == minutosRiego ) {
	  regar == true;
		t = millis();
		digitalWrite(bomba, HIGH);
	}
}
else {
  // Estamos regando, por lo tanto hemos de comprobar si el tiempo de riego ha
	// transcurrido en cuyo caso, solo apagamos la bomba.
  if ( millis()-t > tiempoRiego ) {
	  digitalWrite(bomba, LOW);
  }
	// Para evitar que se vuelva a repetir en el mismo minuto, solo cambiamos
	// la variable cuando la hora no sea la correcta.
	if ( horaActual != horaRiego || minutoActual == minutoRiego ) {
	  regar = false;
	}
}

Como ves, el código es muy parecido al tuyo, solo que parece un poco más legible.

Enhorabuena! Has conseguido superar el tutorial con exito!

1 Like

Como alternativa ¿Y si comparas horas, minutos y segundos?
Salvo que tu "pulso" dure menos de 1 seg, no tendrías problemas de repeticiones.

Imagino que puedes ingresar horas y minutos, en ese caso no sería necesario agregar el ingreso de los segundos, simplemente elige el segundo que prefieras para la comparación 0, 10, 30, etc. y listo.
Algo así

if(HoraActual == HoraRiego && MinutosActual == MinutosRiego && SegundosActual == 0)  {

Obviamente debes agregar la variable SegundosActual y asignarle los segundos que lees del RTC

Saludos

1 Like

Muchas gracias!!! Ya mismo lo pruebo!!

Muchas gracias por responder! Eso ya lo hice, solo que el programa tiene muchas funciones y pasaba que no coincidía con un número exacto de segundos. Esa función se recorre aprox cada 5 segundos, lo que hice fue poner segundosactual < 10 y funcionó, pero no me daba seguridad de que siempre vaya a estar dentro de los primeros 10 segundos por eso lo evité