Consulta sobre While

Buenas.
tengo una duda a cerca del While.
Tengo una serie de funciones en el loop, una de ellas, tiene desarrollado un bucle while.
Las funciones dan los resultados esperados.
La duda es, si se esta ejecutando el while, mientras esta dure, el resto de las funciones estan en ejecucion? o todo el sistema queda atento hasta el fin del bucle?

por ejemplo: una de las funciones es un riego, y hay un while esperando el fin del tiempo para parar la bomba. Durante el proceso, se produce un movimiento el cual debe ser detectado por un sensor de movimiento y producir un evento. Este se produce?

Espero haberme explicado mas o menos bien jajajaa.
Desde ya agradezco su ayuda.

saludos.

La respuesta es muy simple: Todo lo que esta dentro del while se mantendrá actualizado.
Si la función de riego no lo esta entonces no le va a prestar atención.

supongamos un caso en el que no actualiza

        update_riego();
        while(condición) {
        
            // resto de funciones dentro del while Si se ejecutan

        }

y acá si se actualizaría

        while(condición) {
        update_riego();
            // resto de funciones dentro del while Si se ejecutan

        }

Gracias por responder surbyte.
mira, mi ejemplo es este:

void loop {
funcion_1();
funcion_2();
funcion_3();
}

void funcion_1() {
bla bla bla bla
}

void funcion_2() {
bla bla bla bla
}

void funcion_3() {
bla bla bla bla
}

La funcion 1 es la que ejecuta el bucle de while y las otras simplemente leen sensores.
cuando se cumpla la condición para ejecutar el While, las otras funciones siguen leyendo los sensores, o simplemente esperan hasta que la primera finalice?
debo meter el update_funcion_xx() dentro del bucle while? (por cada función que necesito que se ejecute siempre?)

un saludo y muchas gracias de nuevo..

Este procesador trabaja en forma secuencial. Paso a paso... hasta no cumplir algo no hace lo siguiente. No existe la multitarea.
Entonces... hasta no cumplir tu condición no hara otra cosa.. no terminará funcion1() y por ende no hara 2 ni 3.

Es dificil responder cuando no muestras el problema.
Por eso siempre las normas dicen que ahorres tiempo a todos publicando tu código completo.
Tu muestras lo que TU crees que es el problema pero verás que si pones el código encontraremos que tu código esta mal hecho o puede mejorarse. Mal hecho es una mala expresión de mi parte. Mejor dicho es que no resulta eficiente para lo que pretendes.

NO USES delay y en cambio todo debes hacer con millis() para que el flujo del programa se ejecute sin demoras ni condiciones que retienen las operaciones.

Mira el ejemplo de alguien que preguntó por un problema del un sersor IR y quería que la presion de sus teclas encendiera algunos leds (supongo) pues bien, puso delays aca y alla y sumados generaban retardos de 250 a 500 mseg. 1/2 seg se siente.. pero he visto gente que pones delays de minutos u horas.. y luego dice se queda colgado el arduino.
Bueno se que no es tu caso, pero quien dice no?

JAJA si, es verdad eso.
no he publicado el codigo, porque aún no lo tengo listo, pero te publico la función de riego para que la veas,
De todas maneras, para ver si entendí. Hasta tanto el riego no finalice su rutina por ejemplo de 5 minutos, el sistema no leerá los demás sensores. es asi?
Por cierto, no uso delays, manejo todo con la funcion millis().
te dejo el codigo.
Los valores de las variables HoraInicio y MinutoInicio los obtengo desde un archivo de texto desde SD

void loop() {
riegoJardin();
alarma_movimiento(); // no desarrollada
portonprincipal(); // no desarrollada
}

void riegoJardin() {
  int durRiego;
  int tiempoDeRiego;
  DateTime horaRiego = rtc.now();
  if (horaRiego.hour() == HoraInicio && horaRiego.minute() == MinutoInicio) {
    durRiego = (5 * 60000) + millis();
    tiempoDeRiego = millis();
    //Inicia Riego Sector 1
    while (durRiego >= tiempoDeRiego) {
     digitalWrite(Puerto2_4, LOW); // Abre EV sector 1
    delay(200);
    digitalWrite(Puerto1_4, LOW); // Enciende Bomba 
    tiempoDeRiego = millis();
    }
    digitalWrite(Puerto1_4, HIGH); // Apaga bomba
    delay(200);
    digitalWrite(Puerto2_4, HIGH); // Cierra EV
  }
}

gracias por tu tiempo

La función while debes considerarla como el núcleo del sketch. Dentro de ella puedes llamar directamente a las funciones que leen sensores dentro del bucle

Te sugiero que la estructura de tu programa la transformes en algo como esto:

void loop() actuará como la función 1

void loop(){
//funciones o variables que no cambian con el tiempo y solo se ejecutan una sola vez, fondos de pantalla, máscaras de presentación, etc.

  while()  
   {
      funcion2(); 
      funcion3();
    }
}

Sin mas palabras, mira el video del controlador que estoy diseñando

Con ayuda de millis(), se pueden tomar las lecturas de todos los sensores que tengas y mostrarlas simultáneamente, en el video se muestran las lecturas de 4 sensores de temperatura, tanto en forma de indicadores analógicos como en gráficas lineales, se puede ajustar individualmente, cada intervalo de captura de datos de cada sensor, sin perder la función táctil y todo practicamente en tiempo real.

me conviene entonces colocar directamente el código de riego dentro de loop y a la vez dentro del while el chequeo de las demas funciones.
a la vez tambien colocar la lectura de las funciones fuera del while una vez que éste termine.

es asi?

tu función de riego aun usando millis() termina actuando de modo análogo a que no usaras millis() y tuvieras un delay, de manera que no sirve.
La solución es la planteada por TFTLCDyg.

gracias una vez mas.

ok, comprendo.

entoces el sketch quedaría sería algo asi?

void loop() {
 while()
{
  riegoJardin();
  alarma_movimiento(); // no desarrollada
  portonprincipal(); // no desarrollada
}
}

puedo llamar las funciones también dentro del while de la funcion riego?
ej:

void loop() {
riegoJardin();
alarma_movimiento(); // no desarrollada
portonprincipal(); // no desarrollada
}

void riegoJardin() {
  int durRiego;
  int tiempoDeRiego;
  DateTime horaRiego = rtc.now();
  if (horaRiego.hour() == HoraInicio && horaRiego.minute() == MinutoInicio) {
    durRiego = (5 * 60000) + millis();
    tiempoDeRiego = millis();
    //Inicia Riego Sector 1
    while (durRiego >= tiempoDeRiego) {
    alarma_movimiento(); // no desarrollada
    portonprincipal(); // no desarrollada 

    digitalWrite(Puerto2_4, LOW); // Abre EV sector 1
    delay(200);
    digitalWrite(Puerto1_4, LOW); // Enciende Bomba 
    tiempoDeRiego = millis();
    }
    digitalWrite(Puerto1_4, HIGH); // Apaga bomba
    delay(200);
    digitalWrite(Puerto2_4, HIGH); // Cierra EV
  }
}

me podrían ayudar un poco con el código?
muchas gracias!

Debes mostrarnos el código que llevas armado para poder darnos una idea de lo que quieres obtener. Además debes indicar los componentes que vas a manipular

Gracias TFTLCDCyg por responder.
basicamente solo tengo hecho lo que mostre, la función de riego.
lo que quiero es manipular ademas un par de sensores de movimiento, mas un par de proximity switch para controlar un porton de acceso.
Aún no he desarrollado esa parte del código, pero al hacer lo del riego, que me pareció lo mas complicado, me topé con la duda del while, por eso el inicio del hilo.
Mi board es una DUE, así que estaba pensando que podría utilizar las interrupciones como opción para realizar eventos con el sensor de movimiento. Se me ocurre esto, porque la bomba la activo a través de Relays, en consecuencia, mientras dure el tiempo de riego, el relay va a estar pegado y tanto la bomba como la electroválvula abierta. No tengo la necesidad de que el tiempo de riego sea exacto, puede extenderse unos segundos.

Pude ver tu video sobre la lectura de sensores en simultaneo, y es a eso a lo que apunto.
Quizá puedas ayudarme un poco como fue que lograste eso.
Aún no tengo claro si colocar dentro del while de la función la llamada a las demás funciones.
Interpreto esto, ya que si en una función tengo un while, y por mas que ésta este dentro del loop dentro de otro while, primero va ejecutar el while de la función y luego ejecutara lo que esta dentro del while del loop.
Esto es correcto?
si es así, debería llamar a las funciones tambien dentro del while de la funcion.

Saludos de nuevo.
bueno hice algunas modificaciones en el código para no depender del while.
en las pruebas funciona, pero quisiera saber sus opiniones.
aquí les dejo el código

void loop() {
  riegoJardin();
  Serial.println("xxxxxxxxxxx");
  Serial.println("aaaaaaaaaaa");
}

void riegoJardin() {
  int tiempoDeRiego;
  if (reloj.hour() == HoraInicio && reloj.minute() == MinutoInicio) {
    riegoON = 1;
    durRiego = (2 * 60000) + millis();
    tiempoDeRiego = millis();
    HoraInicio=0;
    MinutoInicio=0;
  }
  if (riegoON == 1 && durRiego >= tiempoDeRiego) {
    //Inicia Riego Sector 1
    Serial.println("REGANDO.....");
    digitalWrite(Puerto2_4, LOW); // Abre EV sector 1
    delay(300);
    digitalWrite(Puerto1_4, LOW); // Enciende Bomba
    tiempoDeRiego = millis();
    Serial.print(durRiego);
    Serial.print(" - ");
    Serial.println(tiempoDeRiego);
  }
  if (riegoON == 1 && durRiego <= tiempoDeRiego) {
    digitalWrite(Puerto1_4, HIGH); // Abre EV sector 1
    delay(300);
    digitalWrite(Puerto2_4, HIGH); // Enciende Bomba
    Serial.println("Fin del riego");
    riegoON = 0;
  }
}

Pongo en cero las variables HoraInicio y MinutoInicio, porque fue la única forma "elegante" que se me ocurrio de salir del IF.

En las pruebas, todo funcionó bien. No solo se activa el relay, sino que en simultaneo imprime en el serial lo que esta en el loop.

aguardo sus comentarios.
Muchas gracias por su tiempo y predisposición.

Que tal esto

void riegoJardin() {
  int tiempoDeRiego;
  if (reloj.hour() == HoraInicio && reloj.minute() == MinutoInicio && !riegoON) {
     riegoON = 1;
     durRiego = (2 * 60000) + millis();
     tiempoDeRiego = millis();
  }
  
  if (riegoON) {
  	if (durRiego >= millis()) {
	  	//Inicia Riego Sector 1
	    Serial.println("REGANDO.....");
	    digitalWrite(Puerto2_4, LOW); // Abre EV sector 1. Lógica inversa
	    delay(300);
	    digitalWrite(Puerto1_4, LOW); // Enciende Bomba. Lógica inversa
	    tiempoDeRiego = millis();
	    Serial.print(durRiego);
	    Serial.print(" - ");
	    Serial.println(tiempoDeRiego);	
  	}
  	else
  	   digitalWrite(Puerto1_4, HIGH); // Cierra EV sector 1. Lógica inversa
       delay(300);
       digitalWrite(Puerto2_4, HIGH); // Apaga la Bomba. Lógica inversa
       Serial.println("Fin del riego");
       riegoON = 0;
  }
}

Muchas gracias por la ayuda surbyte.
lo pongo en practica hoy y les cuento como me fue!

muchas gracias de nuevo!

Funciono bien hasta ahora.
pero tengo el mismo problema por el cual ponia en cero las variables de HoraInicio y Minuto Inicio.
No sale del primer IF, en consecuencia, me modifica la cuenta durRiego = (2 * 60000) + millis(); hasta que pasa 1 minuto (MinutoInicio cambia).

Necesito que por este IF pase sólo una vez cuando se cumple la condición de iniciar el riego,

 if (relojRiego.hour() == HoraInicio && relojRiego.minute() == MinutoInicio && !riegoON) {
    riegoON = 1;
    durRiego = (2 * 60000) + millis();
    Serial.println("Inicia Riego");

Alguna idea?

ok, lo pude resolver de esta forma

if (relojRiego.hour() == HoraInicio && relojRiego.minute() == MinutoInicio && riegoON == 0) {
    riegoON = 1;
    durRiego = (2 * 60000) + millis();
    Serial.println("Inicia Riego");
 }
  if (riegoON == 1) {
    if (durRiego >= millis()) {
      //Inicia Riego Sector 1
      Serial.println("REGANDO.....");
      digitalWrite(Puerto2_4, LOW); // Abre EV sector 1. Lógica inversa
      delay(300);
      digitalWrite(Puerto1_4, LOW); // Enciende Bomba. Lógica inversa
      Serial.print(durRiego);
      Serial.print(" - ");
      Serial.println(millis());
    } else {
      digitalWrite(Puerto1_4, HIGH); // Cierra EV sector 1. Lógica inversa
      delay(300);
      digitalWrite(Puerto2_4, HIGH); // Apaga la Bomba. Lógica inversa
      Serial.println("Fin del riego");
      riegoON = 0;
    }
  }
}

Espero que esté bien y sea optimo.

desde ya muchas gracias por responder y la paciencia.
He aprendido mucho.....
gracias de nuevo

CharlyBrown:
Funciono bien hasta ahora.
pero tengo el mismo problema por el cual ponia en cero las variables de HoraInicio y Minuto Inicio.
No sale del primer IF, en consecuencia, me modifica la cuenta durRiego = (2 * 60000) + millis(); hasta que pasa 1 minuto (MinutoInicio cambia).

Necesito que por este IF pase sólo una vez cuando se cumple la condición de iniciar el riego,

 if (relojRiego.hour() == HoraInicio && relojRiego.minute() == MinutoInicio && !riegoON) {

riegoON = 1;
    durRiego = (2 * 60000) + millis();
    Serial.println("Inicia Riego");



Alguna idea?

Por ese if pasa 1 sola vez. Preuba de ello es que solo entra cuando riegoOn = false por eso te agregué a las condiciones otro AND !riegoON

Entonces supongamos que no es la hora, no hara nada.
Cuando sea la hora, y ademas como no estas en riego entras, y lo primero que haces es poner riegON = 1
y al ponerlo en 1 ese mismo if tiene el ultimo AND en 0 por lo que hará falso toda la condicion y no la ejecutará mas que una vez.

surbyte, tengo una duda..
primero que nada, todo quedo funcionando bien.
El problema surge cuando abro el monitor serie. Todas las funciones se reinician, y si por ejemplo el la funcion riego esta corriendo, pero la hora de inicio ya paso, digamos que va en el 50% del riego, todo se detiene, y hasta millis() comienza de cero.

esto a que se debe y como lo soluciono?

pd. busque informacion al respecto en el foro pero no pude encontrar nada.

Si mal recuerdo cuando invocas el monitor serie se produce un reset asi que no es bueno llamarlo en medio de algo.. sino al comienzo.
Monitorea todo el tiempo.

Al punto al que has llegado, creo que llegamos todos en algun momento. El monitor serie es solo una herramienta de depuración y no debería emplearse como parte de un proyecto de control.

Podría ser necesario un apoyo extra para tu arduino, con el que puedas independizar tu proyecto de la PC y puedas saber en que zona de control se encuentra el hardware que estas manipulando. Bien puede ser un led RGB, un display-bar, un display de 7 segmentos, una matriz, un lcd e incluso un TFT.

El led RGB me parece la solución mas simple y versátil, ya que con uno solo podrías monitorear tu proyecto mediante una codificación visual basada en cambio de colores.

Te sugiero que vayas directamente por led RGB WS2812b, solo precisa de un pin digital, 5V y GND.

Si quieres un monitoreo mucho mas completo te recomendaría ir directamente por un TFT ILI9341 de 2.4" con pantalla táctil. Para conectarlo al arduino de 5V solo basta con implementar 5 divisores de voltaje, cada uno armado con resistencias de 2k/1k. El costo de una pantalla de estas es bastante bajo.

De esta forma la información que envías al puerto serie, la puedes mandar al TFT, sin que tengas que reiniciar tu proyecto, una vez que lo tengas funcionando al 100%

Todo lo que se ha comentado en el post, conduce directamente a la construcción de un menu simple que vendría muy bien con el TFT-táctil.