Break out of while and if function?

I am working on an irrigation system for my home using arduino, my main issue right now, is going out my while loop instantly. because i loop a routine between the 3 sprinkler sections with a minute delay between each. Wich in manual mode will be controlled with a selector or switch. What I am trying to make is to go out my while or if loop instantly when my input goes LOW.

while (digitalRead(manual) == HIGH){
  lcd.clear();
  lcd.setCursor(2,0);
  lcd.print("RIEGO MANUAL");
  lcd.setCursor(4,1);
  lcd.print("ACTIVO");
  digitalWrite(manual_light, HIGH);
  
  digitalWrite(sprinkler_1, HIGH);
  delay(1000);
  digitalWrite(sprinkler_1, LOW);
  digitalWrite(sprinkler_2, HIGH);
  delay(1000);
  digitalWrite(sprinkler_2, LOW);
  digitalWrite(sprinkler_3, HIGH);
  delay(1000);
  digitalWrite(sprinkler_3, LOW);
}

if (digitalRead(manual) == LOW){
  digitalWrite(sprinkler_1, LOW);
  digitalWrite(sprinkler_2, LOW);
  digitalWrite(sprinkler_3, LOW);
  digitalWrite(manual_light, LOW);
}

So, don't do the delay .
(You didn't show that code, BTW)

I cant remove the delay, it is there for water pressure purpose. Thats why I would like to know if there is like an if function but that is constantly veryfying the condition.

#include <RTClib.h>
#include <Wire.h>
RTC_DS3231 rtc;


#include <EEPROM.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(7,6,5,4,3,2); // VSS,GND  VDD,+5V  VO,BRILLO A GND CON RESISTENCIA  RS,7  RW,GND  E,6  D4,5  D5,4  D6,3  D7,2  A,5V 220.Ohm  K,GND

int function = 28;
int automatico = 27;
int vera_confirm = 26;
int vera = 25;
int manual = 24;
int bajar_tiempo = 23;
int subir_tiempo = 22;

int manual_light = 12;
int vera_light = 11;
int sprinkler_1 = 10;
int sprinkler_2 = 9;
int sprinkler_3 = 8;


int minutos = 15; // minutos
int tiempo_restante = minutos;
int vera_repeat = 0;
int hora_auto = 17;
int minuto_auto = 30;
int count_auto = 0;

void setup() {  

  rtc.begin();
  Wire.begin();

  lcd.begin(16,2);

  EEPROM.get(0, minutos);
  EEPROM.get(2, hora_auto);
  EEPROM.get(4, minuto_auto);
  
  pinMode(sprinkler_1, OUTPUT);
  pinMode(sprinkler_2, OUTPUT);
  pinMode(sprinkler_3, OUTPUT);
  pinMode(automatico, INPUT);
  pinMode(vera, INPUT);
  pinMode(manual, INPUT);
  pinMode(subir_tiempo, INPUT);
  pinMode(bajar_tiempo, INPUT);

 // rtc.adjust(DateTime(__DATE__, __TIME__));  //Una vez para setearle la hora al modulo rtc

}

void loop() {

delay(100);
lcd.clear();
lcd.setCursor(3,0);
lcd.print("SELECCIONE");
lcd.setCursor(6,1);
lcd.print("MODO");

//MANUAL

while (digitalRead(manual) == HIGH){
  lcd.clear();
  lcd.setCursor(2,0);
  lcd.print("RIEGO MANUAL");
  lcd.setCursor(4,1);
  lcd.print("ACTIVO");
  digitalWrite(manual_light, HIGH);
  
  digitalWrite(sprinkler_1, HIGH);
  delay(1000);
  digitalWrite(sprinkler_1, LOW);
  digitalWrite(sprinkler_2, HIGH);
  delay(1000);
  digitalWrite(sprinkler_2, LOW);
  digitalWrite(sprinkler_3, HIGH);
  delay(1000);
  digitalWrite(sprinkler_3, LOW);
}

if (digitalRead(manual) == LOW){
  digitalWrite(sprinkler_1, LOW);
  digitalWrite(sprinkler_2, LOW);
  digitalWrite(sprinkler_3, LOW);
  digitalWrite(manual_light, LOW);
}

//VERA
if (digitalRead(vera_confirm) == HIGH){
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("VERA SELECIONADO");
  lcd.setCursor(3,1);
  lcd.print(minutos);
  lcd.print(" MINUTOS");
  digitalWrite(vera_light, HIGH);
  delay(100);
  if (digitalRead(subir_tiempo) == HIGH){
    minutos++;
    minutos++;
    minutos++;
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(minutos);
    lcd.print(" MINUTOS");
    lcd.setCursor(0,1);
    lcd.print("TIEMPO CAMBIADO");
    EEPROM.put(0, minutos);
    delay(100);
}

  if (digitalRead(bajar_tiempo) == HIGH){
    minutos--;
    minutos--;
    minutos--;
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(minutos);
    lcd.print(" MINUTOS");
    lcd.setCursor(0,1);
    lcd.print("TIEMPO CAMBIADO");
    EEPROM.put(0, minutos);
    delay(100);
  }
  
  if (digitalRead(vera) == HIGH and vera_repeat == 0){
    int vera_repeat = 1;
    int tiempo_restante = minutos;
    int ciclos_riego = minutos / 3; //cantidad de ciclos del riego  
    for (int i = 0; i < ciclos_riego; i++){
      delay(100);
      digitalWrite(sprinkler_1, HIGH);
      delay(1000);
    
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print(tiempo_restante--);
      lcd.print(" MINUTOS");
      lcd.setCursor(0,1);
      lcd.print("RESTANTES");
    
      digitalWrite(sprinkler_1, LOW);
      digitalWrite(sprinkler_2, HIGH);
      delay(1000);
    
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print(tiempo_restante--);
      lcd.print(" MINUTOS");
      lcd.setCursor(0,1);
      lcd.print("RESTANTES");
    
      digitalWrite(sprinkler_2, LOW);
      digitalWrite(sprinkler_3, HIGH);
      delay(1000);
    
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print(tiempo_restante--);
      lcd.print(" MINUTOS");
      lcd.setCursor(0,1);
      lcd.print("RESTANTES");
    
      digitalWrite(sprinkler_3, LOW);
  }
}
}

if (digitalRead(vera_confirm) == LOW){
  digitalWrite(vera_light, LOW);
}


//AUTOMATICO
if (digitalRead(automatico) == HIGH){
  int count_auto = 0;
  DateTime fecha = rtc.now();
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("AUTO SELECIONADO");
  lcd.setCursor(0,1);
  lcd.print(fecha.hour());
  lcd.print(":");
  lcd.print(fecha.minute());
  digitalWrite(vera_light, HIGH);
  digitalWrite(manual_light, HIGH);
  delay(100);
  if (digitalRead(subir_tiempo) == HIGH){
    minutos++;
    minutos++;
    minutos++;
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(minutos);
    lcd.print(" MINUTOS");
    lcd.setCursor(0,1);
    lcd.print("TIEMPO CAMBIADO");
    EEPROM.put(0, minutos);
    delay(100);
}

  if (digitalRead(bajar_tiempo) == HIGH){
    minutos--;
    minutos--;
    minutos--;
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(minutos);
    lcd.print(" MINUTOS");
    lcd.setCursor(0,1);
    lcd.print("TIEMPO CAMBIADO");
    EEPROM.put(0, minutos);
    delay(100);
  }

  if (digitalRead(function) == HIGH and count_auto == 0){
    count_auto++;
    while (count_auto == 1){
      delay(300);
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("MODIFICAR HORA");
      lcd.setCursor(0,1);
      lcd.print(hora_auto);
      lcd.print(":");
      lcd.print(minuto_auto);

      if (digitalRead(subir_tiempo) == HIGH){
      hora_auto++;
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("HORA CAMBIADA");
      lcd.setCursor(0,1);
      lcd.print(hora_auto);
      lcd.print(":");
      lcd.print(minuto_auto);
      EEPROM.put(2, hora_auto);
      delay(100);
  }
  
    if (digitalRead(bajar_tiempo) == HIGH){
      hora_auto--;
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("HORA CAMBIADA");
      lcd.setCursor(0,1);
      lcd.print(hora_auto);
      lcd.print(":");
      lcd.print(minuto_auto);
      EEPROM.put(2, hora_auto);
      delay(100);
    }

    if (digitalRead(function) == HIGH){
      count_auto++;
      while (count_auto == 2){
        delay(300);
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("MODIFICAR MINUTOS");
        lcd.setCursor(0,1);
        lcd.print(hora_auto);
        lcd.print(":");
        lcd.print(minuto_auto);
  
        if (digitalRead(subir_tiempo) == HIGH){
        minuto_auto++;
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("MINUTOS CAMBIADOS");
        lcd.setCursor(0,1);
        lcd.print(hora_auto);
        lcd.print(":");
        lcd.print(minuto_auto);
        EEPROM.put(4, minuto_auto);
        delay(100);
    }
    
      if (digitalRead(bajar_tiempo) == HIGH){
        minuto_auto--;
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("MINUTOS CAMBIADOS");
        lcd.setCursor(0,1);
        lcd.print(hora_auto);
        lcd.print(":");
        lcd.print(minuto_auto);
        EEPROM.put(4, minuto_auto);
        delay(100);
      }
      if (digitalRead(function) == HIGH){
        count_auto--;
        count_auto--;
        delay(100);
      }
    }
    
    }
  }
  }

  //Auto con RTC
  if (fecha.hour() == hora_auto and fecha.minute() == minuto_auto){
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("CORRE RUTINA");
    int tiempo_restante = minutos;
    int ciclos_riego = minutos / 3;
    for (int i = 0; i < ciclos_riego; i++){
      delay(100);
      digitalWrite(sprinkler_1, HIGH);
      delay(1000);
    
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print(tiempo_restante--);
      lcd.print(" MINUTOS");
      lcd.setCursor(0,1);
      lcd.print("RESTANTES");
    
      digitalWrite(sprinkler_1, LOW);
      digitalWrite(sprinkler_2, HIGH);
      delay(1000);
    
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print(tiempo_restante--);
      lcd.print(" MINUTOS");
      lcd.setCursor(0,1);
      lcd.print("RESTANTES");
    
      digitalWrite(sprinkler_2, LOW);
      digitalWrite(sprinkler_3, HIGH);
      delay(1000);
    
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print(tiempo_restante--);
      lcd.print(" MINUTOS");
      lcd.setCursor(0,1);
      lcd.print("RESTANTES");
    
      digitalWrite(sprinkler_3, LOW);
    }
  }   
}
}

full code here

You can have the effect of a one minute pause, without a sixty second delay.

Take a look at the IDE's blink without delay example, without delay

So if I make it as you say, the while loop will be interrupted when 'manual' goes LOW?

There won't be a while loop.

Could you please give me an example?
Because I need it to run just while my 'manual' input == HIGH.
And as I see on the arduino IDE example. That is a loop forever.

See Using millis() for timing. A beginners guide, Several things at the same time and the BlinkWithoutDelay example in the IDE

The only loop for ever in the blink without delay example, is the hidden one in the hidden main() that calls loop().

thanks

but if you wish to break loop() you can do it

  //MANUAL

  if (digitalRead(manual) == HIGH) {
    lcd.clear();
    lcd.setCursor(2, 0);
    lcd.print("RIEGO MANUAL");
    lcd.setCursor(4, 1);
    lcd.print("ACTIVO");
    bool weDoneHere = false;
    while (!weDoneHere) {
      digitalWrite(manual_light, HIGH);

      digitalWrite(sprinkler_1, HIGH);
      delay(1000);
      digitalWrite(sprinkler_1, LOW);
      digitalWrite(sprinkler_2, HIGH);
      delay(1000);
      digitalWrite(sprinkler_2, LOW);
      digitalWrite(sprinkler_3, HIGH);
      delay(1000);
      digitalWrite(sprinkler_3, LOW);
      if (digitalRead(manual) == LOW) {
        digitalWrite(sprinkler_1, LOW);
        digitalWrite(sprinkler_2, LOW);
        digitalWrite(sprinkler_3, LOW);
        digitalWrite(manual_light, LOW);
        weDoneHere = true;
      }
    }
  }

Did you mean to say "a 1-second delay"?

With a delay, you can't act on an input "instantly".

The easiest way to insert a delay without delay() is to break the process into steps or 'states'. A state is any part of your sketch that is waiting for an event to happen (button press, operation completed, delay finished) and when the event happens, you go on to the next state. Since there are a limited number of states each process can be in, the process is known as a Finite State Machine.

For example: Let's say you wanted two LEDs to blink at the same time but at different speeds. You can't even do that easily with a simple delay():

void loop()
{
  digitalWrite(LED1, HIGH);
  delay(3000);
  digitalWrite(LED1, LOW);
  delay(2000);

  digitalWrite(LED2, HIGH);
  delay(1000);
  digitalWrite(LED2, LOW);
  delay(2500);
}

This will obviously not do what you want because the 'delay()' calls allow only one LED to be active at a time.

The way to make it work is to make each independent process a separate Finite State Machine. I like to use an 'enum' to give names to each state. In this case the states are the same for both so we can get by with one 'enum' for both:

  enum
  {
    Idle, TurnOn, OnDelay, TurnOff, OffDelay
  } StateLED1 = TurnOn, StateLED2 = TurnOn;

Now you can see that each 'delay()' is spread across two states. The first state starts the delay timer and changes to the second state. The second state checks the timer and, if the timer has expired, goes on to the next state. The process repeats when the "OffDelay" state ends and goes to the "TurnOn" state.

The "Idle" state is there in case you want to turn off either or both blinkers.

const byte LED1 = 4;
const byte LED2 = 5;

enum
  {
    Idle, TurnOn, OnDelay, TurnOff, OffDelay
  } StateLED1 = TurnOn, StateLED2 = TurnOn;

void setup()
{
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
}

void loop()
{
  unsigned long currentMillis = millis();
  static unsigned long Delay1Start;
  static unsigned long Delay2Start;

  switch (StateLED1)
  {
    case Idle:
      digitalWrite(LED1, LOW);
      break;

    case TurnOn:
      digitalWrite(LED1, HIGH);
      Delay1Start = currentMillis;
      StateLED1 = OnDelay;
      break;

    case OnDelay:
      if (currentMillis - Delay1Start >= 3000)
        StateLED1 = TurnOff;
      break;

    case TurnOff:
      digitalWrite(LED1, LOW);
      Delay1Start = currentMillis;
      StateLED1 = OffDelay;
      break;

    case OffDelay:
      if (currentMillis - Delay1Start >= 2000)
        StateLED1 = TurnOn;
      break;
  }
  
  
  switch (StateLED2)
  {
    case Idle:
      digitalWrite(LED2, LOW);
      break;

    case TurnOn:
      digitalWrite(LED2, HIGH);
      Delay2Start = currentMillis;
      StateLED2 = OnDelay;
      break;

    case OnDelay:
      if (currentMillis - Delay2Start >= 1000)
        StateLED2 = TurnOff;
      break;

    case TurnOff:
      digitalWrite(LED2, LOW);
      Delay2Start = currentMillis;
      StateLED2 = OffDelay;
      break;

    case OffDelay:
      if (currentMillis - Delay2Start >= 2500)
        StateLED2 = TurnOn;
      break;
  }
}

And there we go. No delay(). No wait loops.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.