Delay problems (BWoD) (SOLVED)

OK..

I cutted the watering process to small steps and I made it as simple as I can. Only the watering process. Serial monitor gives me this all at once without any delays.. after this nothing happens. What is wrong with the delays here?

Starting
Drain Valve Open
Drain Valve Closed
Main Valve Open
Fertilizer Pump 1 (GROW) Open
Fertilizer Pump 1 (GROW) Closed
Fertilizer Pump 2 (BLOOM) Open
Fertilizer Pump 2 (BLOOM) Closed
Fertilizer Pump 3 (MICRO) Open
Fertilizer Pump 3 (MICRO) Closed
Drain Valve Open

// --------CONSTANTS (won't change)---------------

#define DHTPIN 0  //D3
#define DHTPIN 2  //D4
#define DHTPIN 14 //D5
#define DHTPIN 12 //D6
#define DHTPIN 13 //D7
#define DHTPIN 15 //D8
#define DHTPIN 16  //D0

const int RELAY1 = D3; //Main Valve
const int RELAY2 = D4; //Lights ON/OFF
const int RELAY6 = D8; //Drain Valve
const int RELAY3 = D5; //Fertilizer Pump 1 GROW
const int RELAY4 = D6; //Fertilizer Pump 2 BLOOM
const int RELAY5 = D7; //Fertilizer Pump 3 MICRO

const int DrainValvePeriod = 5000;  //Drain Valve period
const int FertilizerPump1BLOOMPeriod = 5000;  //Fertilizer Pump 1 GROW ON BLOOMMIX period
const int FertilizerPump2BLOOMPeriod = 5000;  //Fertilizer Pump 2 BLOOM ON BLOOMMIX period
const int FertilizerPump3BLOOMPeriod = 5000;  //Fertilizer Pump 3 MICRO ON BLOOMMIX period

////------------ VARIABLES (will change)---------------------



byte MainValveState = LOW;
byte DrainValveState = LOW;
byte FertilizerPump1State = LOW;
byte FertilizerPump2State = LOW;
byte FertilizerPump3State = LOW;

unsigned long DrainValveStartMillis;
unsigned long FertilizerPump1BLOOMStartMillis;
unsigned long FertilizerPump2BLOOMStartMillis;
unsigned long FertilizerPump3BLOOMStartMillis;

unsigned long DrainValveCurrentMillis = 0;
unsigned long FertilizerPump1BLOOMCurrentMillis = 0;
unsigned long FertilizerPump2BLOOMCurrentMillis = 0;
unsigned long FertilizerPump3BLOOMCurrentMillis = 0;

//========================================

void setup() {

  Serial.begin(115200);
  delay (2000);
  Serial.println("\Starting");

  pinMode(RELAY1, OUTPUT);
  pinMode(RELAY2, OUTPUT);
  pinMode(RELAY3, OUTPUT);
  pinMode(RELAY4, OUTPUT);
  pinMode(RELAY5, OUTPUT);
  pinMode(RELAY6, OUTPUT);


  digitalWrite(RELAY1, LOW); // set Main Valve OFF
  digitalWrite(RELAY2, LOW); // set LIGHTS OFF
  digitalWrite(RELAY3, LOW); // set Fertilizer Pump 1 GROW OFF
  digitalWrite(RELAY4, LOW); // set Fertilizer Pump 2 BLOOM OFF
  digitalWrite(RELAY5, LOW); // set Fertilizer Pump 3 MICRO OFF
  digitalWrite(RELAY6, LOW); // set Drain Valve OFF

}


//========================================

void loop() {

  DrainValveCurrentMillis = millis();
  DrainValveBLOOM();

}


void DrainValveBLOOM()

{

  if (DrainValveState == LOW)

  {
    digitalWrite(RELAY6, HIGH);  //change the state of the Drain Valve to Open
    Serial.println("Drain Valve Open");
    DrainValveState = HIGH;

    if (DrainValveCurrentMillis - DrainValveStartMillis >= DrainValvePeriod)  //test whether the period has elapsed
    {
      digitalWrite(RELAY6, LOW);  //if so, change the state of the Drain Valve to Closed

      DrainValveState = LOW;
      Serial.println("Drain Valve Closed");
      DrainValveStartMillis = DrainValveCurrentMillis;  //IMPORTANT to save the start time of the current RELAY state.

      MainValveBLOOM();
    }
  }

}

void MainValveBLOOM()

{
  if (DrainValveState == LOW)
  {
    digitalWrite(RELAY1, HIGH);  //change the state of the Main Valve to Open
    Serial.println("Main Valve Open");
    MainValveState = HIGH;

    FertilizerPump1BLOOMCurrentMillis = millis();
    Fert1BLOOM();
  }
}



void Fert1BLOOM()

{
  digitalWrite(RELAY3, HIGH);  //change the state of the Fertilizer Pump 1 (GROW) to Open
  Serial.println("Fertilizer Pump 1 (GROW) Open");
  FertilizerPump1State = HIGH;

  if (FertilizerPump1BLOOMCurrentMillis - FertilizerPump1BLOOMStartMillis >= FertilizerPump1BLOOMPeriod)  //test whether the period has elapsed
  {
    digitalWrite(RELAY3, LOW);  //if so, change the state of the Fertilizer Pump 1 (GROW) to Closed
    FertilizerPump1State = LOW;

    FertilizerPump1BLOOMStartMillis = FertilizerPump1BLOOMCurrentMillis;  //IMPORTANT to save the start time of the current RELAY state.
    Serial.println("Fertilizer Pump 1 (GROW) Closed");

    FertilizerPump2BLOOMCurrentMillis = millis();
    Fert2BLOOM();
  }
}

void Fert2BLOOM()

{
  if (FertilizerPump1State == LOW)
  {
    digitalWrite(RELAY4, HIGH);  //change the state of the Fertilizer Pump 2 (BLOOM) to Open
    Serial.println("Fertilizer Pump 2 (BLOOM) Open");
    FertilizerPump2State = HIGH;

    if (FertilizerPump2BLOOMCurrentMillis - FertilizerPump2BLOOMStartMillis >= FertilizerPump2BLOOMPeriod)  //test whether the period has elapsed
    {
      digitalWrite(RELAY4, LOW);  //if so, change the state of the Fertilizer Pump 2 (BLOOM) to Closed

      FertilizerPump2State = LOW;

      FertilizerPump2BLOOMStartMillis = FertilizerPump2BLOOMCurrentMillis;  //IMPORTANT to save the start time of the current RELAY state.
      Serial.println("Fertilizer Pump 2 (BLOOM) Closed");

      FertilizerPump3BLOOMCurrentMillis = millis();
      Fert3BLOOM();
    }
  }
}


void Fert3BLOOM()

{
  if (FertilizerPump2State == LOW)
  {
    digitalWrite(RELAY5, HIGH);  //change the state of the Fertilizer Pump 3 (MICRO) to Open
    Serial.println("Fertilizer Pump 3 (MICRO) Open");
    FertilizerPump3State = HIGH;

    if (FertilizerPump3BLOOMCurrentMillis - FertilizerPump3BLOOMStartMillis >= FertilizerPump3BLOOMPeriod)  //test whether the period has elapsed
    {
      digitalWrite(RELAY5, LOW);  //if so, change the state of the Fertilizer Pump 3 (MICRO) to Closed

      FertilizerPump3State = LOW;

      FertilizerPump3BLOOMStartMillis = FertilizerPump3BLOOMCurrentMillis;  //IMPORTANT to save the start time of the current RELAY state.
      Serial.println("Fertilizer Pump 3 (MICRO) Closed");
    }
  }
}

#define doesnt warn you when you re-define something. The top 7 lines have the same effect as just one #define DHTPIN 16 //D0

Most of those global variables only have meanings inside one function. Get into the habit of making most variables local. Make them static if they need to retain their values after the function exits.

Looking at DrainValveBloom() I see that it checks if the drain valve state is LOW then it makes it HIGH and does some other stuff. But once it is HIGH then calling this function again does nothing. So it is stuck at high and nothing else happens.

So let's get that part working...

void DrainValveBLOOM()
{
  if (DrainValveState == LOW)
  {
    digitalWrite(RELAY6, HIGH);  //change the state of the Drain Valve to Open
    Serial.println("Drain Valve Open");
    DrainValveState = HIGH;
    DrainValveStartMillis = millis(); //record when we opened the valve
  } else {
    //drain valve is open. Is it time to turn it off?

    if (millis() - DrainValveStartMillis >= DrainValvePeriod)  //test whether the period has elapsed
    {
      digitalWrite(RELAY6, LOW);  //if so, change the state of the Drain Valve to Closed

      DrainValveState = LOW;
      Serial.println("Drain Valve Closed");
    }
  }
}

(oops, I hit "post" too soon...)

So that code will turn the valve on for 5 seconds because your loop() will call it thousands and thousands of times every second. Then when the valve goes off, it will immediately turn it on again. You should see offon (5 sec) offon (5sec) offon (5sec)....

That isn't very useful. You want it to do something else after. So you might get it to turn on the main valve. Then the main valve function can do its timing.

But there is a prblem with that too...

The thing with Drain turning on Main at the time that it turns off Drain is that then Drain is off. What does Drain do when it's off? Well it turns it right back on again. It doesn't remember that it is now the time for Main to run and Drain needs to wait for that.

You have gone tpo far making all these independent functions. They aren't independent. There is a series of states, from Start to Drain to Main ....

Bingo! It is a state.machine.

Draw your states on paper. Most of them will say "after 5 seconds go to state X" but you will discover there are a lot more states that your system will need.

Hey thanks a lot.. I´m finally somehow on the right track.. BUT :slight_smile:

I feel so stupid cause I just don´t get why the Drain turns back open again as you said..

Serial monitor gives this now:

Starting
Drain Valve Open
Drain Valve Closed
Main Valve Open
Fertilizer Pump 1 (GROW) Open
Drain Valve Open
Drain Valve Closed
Main Valve Open
Fertilizer Pump 1 (GROW) Open
Drain Valve Open

Code is like this now:

// --------CONSTANTS (won't change)---------------

#define DHTPIN 0  //D3
#define DHTPIN 2  //D4
#define DHTPIN 14 //D5
#define DHTPIN 12 //D6
#define DHTPIN 13 //D7
#define DHTPIN 15 //D8
#define DHTPIN 16  //D0

const int RELAY1 = D3; //Main Valve
const int RELAY2 = D4; //Lights ON/OFF
const int RELAY6 = D8; //Drain Valve
const int RELAY3 = D5; //Fertilizer Pump 1 GROW
const int RELAY4 = D6; //Fertilizer Pump 2 BLOOM
const int RELAY5 = D7; //Fertilizer Pump 3 MICRO

const int DrainValvePeriod = 5000;  //Drain Valve period
const int FertilizerPump1BLOOMPeriod = 5000;  //Fertilizer Pump 1 GROW ON BLOOMMIX period
const int FertilizerPump2BLOOMPeriod = 5000;  //Fertilizer Pump 2 BLOOM ON BLOOMMIX period
const int FertilizerPump3BLOOMPeriod = 5000;  //Fertilizer Pump 3 MICRO ON BLOOMMIX period

////------------ VARIABLES (will change)---------------------

byte DrainValveState = LOW;
byte FertilizerPump1State = LOW;
byte FertilizerPump2State = LOW;
byte FertilizerPump3State = LOW;

unsigned long DrainValveStartMillis;

unsigned long FertilizerPump1BLOOMStartMillis;
unsigned long FertilizerPump2BLOOMStartMillis;
unsigned long FertilizerPump3BLOOMStartMillis;

unsigned long DrainValveCurrentMillis = 0;

unsigned long FertilizerPump1BLOOMCurrentMillis = 0;
unsigned long FertilizerPump2BLOOMCurrentMillis = 0;
unsigned long FertilizerPump3BLOOMCurrentMillis = 0;

//========================================

void setup() {

  Serial.begin(115200);
  delay (2000);
  Serial.println("\Starting");

  pinMode(RELAY1, OUTPUT);
  pinMode(RELAY2, OUTPUT);
  pinMode(RELAY3, OUTPUT);
  pinMode(RELAY4, OUTPUT);
  pinMode(RELAY5, OUTPUT);
  pinMode(RELAY6, OUTPUT);


  digitalWrite(RELAY1, LOW); // set Main Valve OFF
  digitalWrite(RELAY2, LOW); // set LIGHTS OFF
  digitalWrite(RELAY3, LOW); // set Fertilizer Pump 1 GROW OFF
  digitalWrite(RELAY4, LOW); // set Fertilizer Pump 2 BLOOM OFF
  digitalWrite(RELAY5, LOW); // set Fertilizer Pump 3 MICRO OFF
  digitalWrite(RELAY6, LOW); // set Drain Valve OFF

}


//========================================

void loop() {


  DrainValveBLOOM();

}


void DrainValveBLOOM()
{
  if (DrainValveState == LOW)
  {
    digitalWrite(RELAY6, HIGH);  //change the state of the Drain Valve to Open
    Serial.println("Drain Valve Open");
    DrainValveState = HIGH;
    DrainValveStartMillis = millis(); //record when we opened the valve
  } else {
    //drain valve is open. Is it time to turn it off?

    if (millis() - DrainValveStartMillis >= DrainValvePeriod)  //test whether the period has elapsed
    {
      digitalWrite(RELAY6, LOW);  //if so, change the state of the Drain Valve to Closed

      DrainValveState = LOW;
      Serial.println("Drain Valve Closed");

      MainValveFert1BLOOM();
    }

  }
}

void MainValveFert1BLOOM()
{
  if (DrainValveState == LOW)
  {
    digitalWrite(RELAY1, HIGH);  //change the state of the Main Valve to Open
    Serial.println("Main Valve Open");

    digitalWrite(RELAY3, HIGH);  //change the state of the Fertilizer Pump 1 (GROW) to Open
    Serial.println("Fertilizer Pump 1 (GROW) Open");
    FertilizerPump1State = HIGH;
    FertilizerPump1BLOOMStartMillis = millis(); //record when we opened the valve
  } else {


    if (millis() - FertilizerPump1BLOOMStartMillis >= FertilizerPump1BLOOMPeriod)  //test whether the period has elapsed
    {
      digitalWrite(RELAY3, LOW);  //if so, change the state of the Fertilizer Pump 1 (GROW) to Closed

      FertilizerPump1State = LOW;
      Serial.println("Fertilizer Pump 2 (BLOOM) Closed");
      Fert2BLOOM();
    }

  }
}
 
void Fert2BLOOM()

{
  if (FertilizerPump1State == LOW)
  {
    digitalWrite(RELAY4, HIGH);  //change the state of the Fertilizer Pump 2 (BLOOM) to Open
    Serial.println("Fertilizer Pump 2 (BLOOM) Open");
    FertilizerPump2State = HIGH;
    FertilizerPump2BLOOMCurrentMillis = millis();

  } else {

    if (millis() - FertilizerPump2BLOOMStartMillis >= FertilizerPump2BLOOMPeriod)  //test whether the period has elapsed
    {
      digitalWrite(RELAY4, LOW);  //if so, change the state of the Fertilizer Pump 2 (BLOOM) to Closed

      FertilizerPump2State = LOW;
      Serial.println("Fertilizer Pump 2 (BLOOM) Closed");
      Fert3BLOOM();
    }

  }
}

void Fert3BLOOM()

{
  if (FertilizerPump2State == LOW)
  {
    digitalWrite(RELAY5, HIGH);  //change the state of the Fertilizer Pump 3 (MICRO) to Open
    Serial.println("Fertilizer Pump 3 (MICRO) Open");
    FertilizerPump3State = HIGH;
    FertilizerPump3BLOOMCurrentMillis = millis();

  } else {

    if (millis() - FertilizerPump3BLOOMStartMillis >= FertilizerPump3BLOOMPeriod)  //test whether the period has elapsed
    {
      digitalWrite(RELAY3, LOW);  //if so, change the state of the Fertilizer Pump 3 (MICRO) to Closed

      FertilizerPump3State = LOW;
      Serial.println("Fertilizer Pump 3 (MICRO) Closed");

    }
  }
}
#define DHTPIN 0  //D3
#define DHTPIN 2  //D4
#define DHTPIN 14 //D5
#define DHTPIN 12 //D6
#define DHTPIN 13 //D7
#define DHTPIN 15 //D8
#define DHTPIN 16  //D0

You still haven't fixed this mess.

Hmm.. can I just fix it like this? Or "const int"? Or what should I do to fix those?

const byte DHTPIN3 = 0;  //D3
const byte DHTPIN4 = 2;  //D4
const byte DHTPIN5 = 14; //D5
const byte DHTPIN6 = 12; //D6
const byte DHTPIN7 = 13; //D7
const byte DHTPIN8 = 15; //D8
const byte DHTPIN0 = 16;  //D0

The "Drain Valve open"-problem I understand, that the Drain has to wait till "Main Valve" is closed again (In the whole code when Ultrasound sensor gives number 1300 or less) or I can maybe add "MainValveState" wich needs to be "LOW" until Drain Valve is allowed to open again. But wondering how should I do that?

I tried to add "MainValveState HIGH/LOW" like this, but it doesn´t seem to work:

// --------CONSTANTS (won't change)---------------

const byte DHTPIN3 = 0;  //D3
const byte DHTPIN4 = 2;  //D4
const byte DHTPIN5 = 14; //D5
const byte DHTPIN6 = 12; //D6
const byte DHTPIN7 = 13; //D7
const byte DHTPIN8 = 15; //D8
const byte DHTPIN0 = 16;  //D0

const int RELAY1 = D3; //Main Valve
const int RELAY2 = D4; //Lights ON/OFF
const int RELAY6 = D8; //Drain Valve
const int RELAY3 = D5; //Fertilizer Pump 1 GROW
const int RELAY4 = D6; //Fertilizer Pump 2 BLOOM
const int RELAY5 = D7; //Fertilizer Pump 3 MICRO

const int DrainValvePeriod = 5000;  //Drain Valve period
const int FertilizerPump1BLOOMPeriod = 5000;  //Fertilizer Pump 1 GROW ON BLOOMMIX period
const int FertilizerPump2BLOOMPeriod = 5000;  //Fertilizer Pump 2 BLOOM ON BLOOMMIX period
const int FertilizerPump3BLOOMPeriod = 5000;  //Fertilizer Pump 3 MICRO ON BLOOMMIX period

////------------ VARIABLES (will change)---------------------

byte MainValveState = LOW;
byte DrainValveState = LOW;
byte FertilizerPump1State = LOW;
byte FertilizerPump2State = LOW;
byte FertilizerPump3State = LOW;

unsigned long DrainValveStartMillis;

unsigned long FertilizerPump1BLOOMStartMillis;
unsigned long FertilizerPump2BLOOMStartMillis;
unsigned long FertilizerPump3BLOOMStartMillis;

unsigned long DrainValveCurrentMillis = 0;

unsigned long FertilizerPump1BLOOMCurrentMillis = 0;
unsigned long FertilizerPump2BLOOMCurrentMillis = 0;
unsigned long FertilizerPump3BLOOMCurrentMillis = 0;

//========================================

void setup() {

  Serial.begin(115200);
  delay (2000);
  Serial.println("\Starting");

  pinMode(RELAY1, OUTPUT);
  pinMode(RELAY2, OUTPUT);
  pinMode(RELAY3, OUTPUT);
  pinMode(RELAY4, OUTPUT);
  pinMode(RELAY5, OUTPUT);
  pinMode(RELAY6, OUTPUT);


  digitalWrite(RELAY1, LOW); // set Main Valve OFF
  digitalWrite(RELAY2, LOW); // set LIGHTS OFF
  digitalWrite(RELAY3, LOW); // set Fertilizer Pump 1 GROW OFF
  digitalWrite(RELAY4, LOW); // set Fertilizer Pump 2 BLOOM OFF
  digitalWrite(RELAY5, LOW); // set Fertilizer Pump 3 MICRO OFF
  digitalWrite(RELAY6, LOW); // set Drain Valve OFF

}


//========================================

void loop() {


  DrainValveBLOOM();

}


void DrainValveBLOOM()
{
  if (MainValveState == LOW)
  {
    digitalWrite(RELAY6, HIGH);  //change the state of the Drain Valve to Open
    Serial.println("Drain Valve Open");
    DrainValveState = HIGH;
    MainValveState = HIGH;
    DrainValveStartMillis = millis(); //record when we opened the valve
  } else {
    //drain valve is open. Is it time to turn it off?

    if (millis() - DrainValveStartMillis >= DrainValvePeriod)  //test whether the period has elapsed
    {
      digitalWrite(RELAY6, LOW);  //if so, change the state of the Drain Valve to Closed

      DrainValveState = LOW;
      Serial.println("Drain Valve Closed");

      MainValveFert1BLOOM();
    }

  }
}

void MainValveFert1BLOOM()
{
  if (DrainValveState == LOW)
  {
    digitalWrite(RELAY1, HIGH);  //change the state of the Main Valve to Open
    Serial.println("Main Valve Open");
    

    digitalWrite(RELAY3, HIGH);  //change the state of the Fertilizer Pump 1 (GROW) to Open
    Serial.println("Fertilizer Pump 1 (GROW) Open");
    FertilizerPump1State = HIGH;
    FertilizerPump1BLOOMStartMillis = millis(); //record when we opened the valve
  } else {


    if (millis() - FertilizerPump1BLOOMStartMillis >= FertilizerPump1BLOOMPeriod)  //test whether the period has elapsed
    {
      digitalWrite(RELAY3, LOW);  //if so, change the state of the Fertilizer Pump 1 (GROW) to Closed

      FertilizerPump1State = LOW;
      Serial.println("Fertilizer Pump 2 (BLOOM) Closed");
      Fert2BLOOM();
    }

  }
}
 
void Fert2BLOOM()

{
  if (FertilizerPump1State == LOW)
  {
    digitalWrite(RELAY4, HIGH);  //change the state of the Fertilizer Pump 2 (BLOOM) to Open
    Serial.println("Fertilizer Pump 2 (BLOOM) Open");
    FertilizerPump2State = HIGH;
    FertilizerPump2BLOOMCurrentMillis = millis();

  } else {

    if (millis() - FertilizerPump2BLOOMStartMillis >= FertilizerPump2BLOOMPeriod)  //test whether the period has elapsed
    {
      digitalWrite(RELAY4, LOW);  //if so, change the state of the Fertilizer Pump 2 (BLOOM) to Closed

      FertilizerPump2State = LOW;
      Serial.println("Fertilizer Pump 2 (BLOOM) Closed");
      Fert3BLOOM();
    }

  }
}

void Fert3BLOOM()

{
  if (FertilizerPump2State == LOW)
  {
    digitalWrite(RELAY5, HIGH);  //change the state of the Fertilizer Pump 3 (MICRO) to Open
    Serial.println("Fertilizer Pump 3 (MICRO) Open");
    FertilizerPump3State = HIGH;
    FertilizerPump3BLOOMCurrentMillis = millis();

  } else {

    if (millis() - FertilizerPump3BLOOMStartMillis >= FertilizerPump3BLOOMPeriod)  //test whether the period has elapsed
    {
      digitalWrite(RELAY3, LOW);  //if so, change the state of the Fertilizer Pump 3 (MICRO) to Closed

      FertilizerPump3State = LOW;
      Serial.println("Fertilizer Pump 3 (MICRO) Closed");
      MainValveState = LOW;
    }
  }
}

Is using "MainValveState" the right approach at all? Am I totally lost again?

Or what should I do to fix those?

A #define statement defines a name and a value. How you define the names is up to you. Giving the same name a different value 7 times is not a useful thing to do.

I tried to add "MainValveState HIGH/LOW" like this, but it doesn´t seem to work:

"It doesn't work", or any variation on that theme, is the most useless thing you can say here. The code DOES work, exactly as you have written it. If what it ACTUALLY does, which you haven't said, is not what you expect, then your expectations are wrong.

PaulS:
"It doesn't work", or any variation on that theme, is the most useless thing you can say here. The code DOES work, exactly as you have written it. If what it ACTUALLY does, which you haven't said, is not what you expect, then your expectations are wrong.

It didn´t help. Happy now?

The code i did paste there (where i added MainValveState HIGH/LOW) gives this to serial monitor:

Starting
Drain Valve Open
Drain Valve Closed
Main Valve Open
Fertilizer Pump 1 (GROW) Open
Drain Valve Closed
Main Valve Open
Fertilizer Pump 1 (GROW) Open
Drain Valve Closed
Main Valve Open
Fertilizer Pump 1 (GROW) Open
Drain Valve Closed
Main Valve Open
Fertilizer Pump 1 (GROW) Open
Drain Valve Closed
Main Valve Open
Fertilizer Pump 1 (GROW) Open
Drain Valve Closed
Main Valve Open
Fertilizer Pump 1 (GROW) Open

And that´s it. Anybody know how to fix this?

Anybody know how to fix this?

So, now we know what the code does. Your expectations are still a mystery.

PaulS:
Your expectations are still a mystery.

Really? Are they? To get through the whole watering process of course. In this order:

  1. DrainValveBLOOM()
  2. MainValveFert1BLOOM()
  3. Fert2BLOOM()
  4. Fert3BLOOM()

Really? Are they? To get through the whole watering process of course. In this order:

  1. DrainValveBLOOM()
  2. MainValveFert1BLOOM()
  3. Fert2BLOOM()
  4. Fert3BLOOM()

Given the last code you posted, where loop() looks like:

void loop() {


  DrainValveBLOOM();

}

those expectations seem unrealistic.

Why are those last three functions not called from loop()? On any given pass through loop(), at most one of the functions will do something. On most passes, no function will do anything.

  if (DrainValveState == LOW)

Your code would be far easier to read if you had

   if(IsDrainValveClosed())

where IsDrainValveClosed() returned true if DrainValveState == LOW and false otherwise.

Actually, rather than maintaining state variables, like DrainValveState, IsDrainValveClosed() should read the state of the pin. That way, there can never be a disconnect between DrainValveState and the actual state of the pin.

I suspect that the issue is WHEN you call the last three functions. Calling them all from loop(), unconditionally or conditionally, based on the state of the system (Draining, Filling, etc.) would be better, IMHO.

I can´t put them to the loop, cause this is only a part of the whole code. In the whole code (wich can be found in the earlier posts from me) the loop does other things. This watering process I try to solve here is only used when water level droppes to the lowest level. That´s why I need to keep the loop-part clear from the actual watering process stuff.

I hope this answered your question.

This watering process I try to solve here is only used when water level droppes to the lowest level. That´s why I need to keep the loop-part clear from the actual watering process stuff.

Nonsense.

void loop()
{
   if(IsWateringNeeded())
   {
      AddWater();
   }

   DoOtherStuff();
}

The loop() function is very clean, but it can STILL do lots of stuff. It simply hands off responsibility to other functions to make that happen.

AddWater() can STILL be called on every pass through loop(), as long as watering is needed and the watering process is not complete.

Thanks PaulS you´re absolutely right in this. Answer to this problem is somewhere really really close, but feels like it´s been too long day at work that this beginner brain could solve this problem now. I´ve ended up totally lost in this IF/ELSE-jungle and made some really stupid mistakes. What those are would be really nice to know.

I tried this and serial monitor gives this result:

Starting
Drain Valve Open
Fertilizer Pump 2 (BLOOM) Closed
Fertilizer Pump 2 (BLOOM) Open
Fertilizer Pump 3 (MICRO) Closed
Drain Valve Open
Fertilizer Pump 2 (BLOOM) Closed
Fertilizer Pump 2 (BLOOM) Open
Fertilizer Pump 3 (MICRO) Closed
Drain Valve Open
Fertilizer Pump 2 (BLOOM) Closed
Fertilizer Pump 2 (BLOOM) Open
Fertilizer Pump 3 (MICRO) Closed
Drain Valve Open

and goes on and on..

// --------CONSTANTS (won't change)---------------

#define DHTPIN3 = 0;  //D3
#define DHTPIN4 = 2;  //D4
#define DHTPIN5 = 14; //D5
#define DHTPIN6 = 12; //D6
#define DHTPIN7 = 13; //D7
#define DHTPIN8 = 15; //D8
#define DHTPIN0 = 16;  //D0

const int RELAY1 = D3; //Main Valve
const int RELAY2 = D4; //Lights ON/OFF
const int RELAY6 = D8; //Drain Valve
const int RELAY3 = D5; //Fertilizer Pump 1 GROW
const int RELAY4 = D6; //Fertilizer Pump 2 BLOOM
const int RELAY5 = D7; //Fertilizer Pump 3 MICRO

const int DrainValvePeriod = 5000;  //Drain Valve period
const int FertilizerPump1BLOOMPeriod = 5000;  //Fertilizer Pump 1 GROW ON BLOOMMIX period
const int FertilizerPump2BLOOMPeriod = 5000;  //Fertilizer Pump 2 BLOOM ON BLOOMMIX period
const int FertilizerPump3BLOOMPeriod = 5000;  //Fertilizer Pump 3 MICRO ON BLOOMMIX period

////------------ VARIABLES (will change)---------------------

byte IsBLOOMWaterNeeded = LOW;
byte IsMainValveOpen = LOW;
byte IsDrainValveOpen = LOW;
byte IsFertPumpBLOOM1Open = LOW;
byte IsFertPumpBLOOM2Open = LOW;
byte IsFertPumpBLOOM3Open = LOW;

byte WaterBLOOMStep1 = LOW;
byte WaterBLOOMStep2 = LOW;
byte WaterBLOOMStep3 = LOW;


unsigned long DrainValveStartMillis;

unsigned long FertilizerPump1BLOOMStartMillis;
unsigned long FertilizerPump2BLOOMStartMillis;
unsigned long FertilizerPump3BLOOMStartMillis;

unsigned long DrainValveCurrentMillis = 0;

unsigned long FertilizerPump1BLOOMCurrentMillis = 0;
unsigned long FertilizerPump2BLOOMCurrentMillis = 0;
unsigned long FertilizerPump3BLOOMCurrentMillis = 0;

//========================================

void setup() {

  Serial.begin(115200);
  delay (2000);
  Serial.println("\Starting");

  pinMode(RELAY1, OUTPUT);
  pinMode(RELAY2, OUTPUT);
  pinMode(RELAY3, OUTPUT);
  pinMode(RELAY4, OUTPUT);
  pinMode(RELAY5, OUTPUT);
  pinMode(RELAY6, OUTPUT);


  digitalWrite(RELAY1, LOW); // set Main Valve OFF
  digitalWrite(RELAY2, LOW); // set LIGHTS OFF
  digitalWrite(RELAY3, LOW); // set Fertilizer Pump 1 GROW OFF
  digitalWrite(RELAY4, LOW); // set Fertilizer Pump 2 BLOOM OFF
  digitalWrite(RELAY5, LOW); // set Fertilizer Pump 3 MICRO OFF
  digitalWrite(RELAY6, LOW); // set Drain Valve OFF

}


//========================================

void loop()

{
  if (IsBLOOMWaterNeeded = LOW);
  {
    DrainValveBLOOM();
  }

  if (WaterBLOOMStep1 = HIGH)

  {
    MainValveFert1BLOOM();
  }

  if (WaterBLOOMStep2 = HIGH)
  {
    Fert2BLOOM();
  }

  if (WaterBLOOMStep3 = HIGH)
  {
    Fert3BLOOM();
  }
}

void DrainValveBLOOM()
{
  if (IsBLOOMWaterNeeded == LOW)
  {
    digitalWrite(RELAY6, HIGH);  //change the state of the Drain Valve to Open
    Serial.println("Drain Valve Open");

    IsBLOOMWaterNeeded = HIGH;
    WaterBLOOMStep1 = HIGH;
    IsDrainValveOpen = HIGH;


    DrainValveStartMillis = millis(); //record when we opened the valve
  } else {
    //drain valve is open. Is it time to turn it off?

    if (millis() - DrainValveStartMillis >= DrainValvePeriod)  //test whether the period has elapsed
    {
      digitalWrite(RELAY6, LOW);  //if so, change the state of the Drain Valve to Closed
      Serial.println("Drain Valve Closed");

      IsDrainValveOpen = LOW;

    }
  }
}

void MainValveFert1BLOOM()
{
  if (IsDrainValveOpen == LOW)
  {
    digitalWrite(RELAY1, HIGH);  //change the state of the Main Valve to Open
    Serial.println("Main Valve Open");

    digitalWrite(RELAY3, HIGH);  //change the state of the Fertilizer Pump 1 (GROW) to Open
    Serial.println("Fertilizer Pump 1 (GROW) Open");

    WaterBLOOMStep1 = LOW;
    IsFertPumpBLOOM1Open = HIGH;
    WaterBLOOMStep2 = HIGH;

    FertilizerPump1BLOOMStartMillis = millis(); //record when we opened the valve
  } else {

    if (millis() - FertilizerPump1BLOOMStartMillis >= FertilizerPump1BLOOMPeriod)  //test whether the period has elapsed
    {
      digitalWrite(RELAY3, LOW);  //if so, change the state of the Fertilizer Pump 1 (GROW) to Closed

      Serial.println("Fertilizer Pump 2 (BLOOM) Closed");

      IsFertPumpBLOOM1Open = LOW;

    }
  }
}

void Fert2BLOOM()

{
  if (IsFertPumpBLOOM1Open == LOW)
  {
    digitalWrite(RELAY4, HIGH);  //change the state of the Fertilizer Pump 2 (BLOOM) to Open
    Serial.println("Fertilizer Pump 2 (BLOOM) Open");

    WaterBLOOMStep2 = LOW;
    IsFertPumpBLOOM2Open = HIGH;
    WaterBLOOMStep3 = HIGH;

    FertilizerPump2BLOOMCurrentMillis = millis();

  } else {

    if (millis() - FertilizerPump2BLOOMStartMillis >= FertilizerPump2BLOOMPeriod)  //test whether the period has elapsed
    {
      digitalWrite(RELAY4, LOW);  //if so, change the state of the Fertilizer Pump 2 (BLOOM) to Closed
      Serial.println("Fertilizer Pump 2 (BLOOM) Closed");

      IsFertPumpBLOOM2Open = LOW;

    }
  }
}

void Fert3BLOOM()

{
  if (IsFertPumpBLOOM2Open == LOW)
  {
    digitalWrite(RELAY5, HIGH);  //change the state of the Fertilizer Pump 3 (MICRO) to Open
    Serial.println("Fertilizer Pump 3 (MICRO) Open");

    WaterBLOOMStep3 = LOW;
    IsFertPumpBLOOM3Open = HIGH;

    FertilizerPump3BLOOMCurrentMillis = millis();

  } else {

    if (millis() - FertilizerPump3BLOOMStartMillis >= FertilizerPump3BLOOMPeriod)  //test whether the period has elapsed
    {
      digitalWrite(RELAY3, LOW);  //if so, change the state of the Fertilizer Pump 3 (MICRO) to Closed

      Serial.println("Fertilizer Pump 3 (MICRO) Closed");

      IsFertPumpBLOOM3Open = LOW;
      IsBLOOMWaterNeeded == LOW;
      IsMainValveOpen = LOW;
    }
  }
}

What I´ve done wrong this time?

if (IsBLOOMWaterNeeded = LOW);

Two mistakes:

  1. = is the assignment operator. You would normally use the equality operator ==

  2. The trailing semicolon ends the if statement here. The following block is just an anonymous block that always executes.

Thanks MorganS.. I´ve really been too tired yesterday. So stupid those mistakes you said were. But after correcting those the serial monitor gives this without any 5 sec delays:

Starting
Drain Valve Open
Fertilizer Pump 2 (BLOOM) Closed
Fertilizer Pump 2 (BLOOM) Closed
Fertilizer Pump 2 (BLOOM) Closed
Fertilizer Pump 2 (BLOOM) Closed
Fertilizer Pump 2 (BLOOM) Closed

Code is now:

// --------CONSTANTS (won't change)---------------

#define DHTPIN3 = 0;  //D3
#define DHTPIN4 = 2;  //D4
#define DHTPIN5 = 14; //D5
#define DHTPIN6 = 12; //D6
#define DHTPIN7 = 13; //D7
#define DHTPIN8 = 15; //D8
#define DHTPIN0 = 16;  //D0

const int RELAY1 = D3; //Main Valve
const int RELAY2 = D4; //Lights ON/OFF
const int RELAY6 = D8; //Drain Valve
const int RELAY3 = D5; //Fertilizer Pump 1 GROW
const int RELAY4 = D6; //Fertilizer Pump 2 BLOOM
const int RELAY5 = D7; //Fertilizer Pump 3 MICRO

const int DrainValvePeriod = 5000;  //Drain Valve period
const int FertilizerPump1BLOOMPeriod = 5000;  //Fertilizer Pump 1 GROW ON BLOOMMIX period
const int FertilizerPump2BLOOMPeriod = 5000;  //Fertilizer Pump 2 BLOOM ON BLOOMMIX period
const int FertilizerPump3BLOOMPeriod = 5000;  //Fertilizer Pump 3 MICRO ON BLOOMMIX period

////------------ VARIABLES (will change)---------------------

byte IsBLOOMWaterNeeded = LOW;
byte IsMainValveOpen = LOW;
byte IsDrainValveOpen = LOW;
byte IsFertPumpBLOOM1Open = LOW;
byte IsFertPumpBLOOM2Open = LOW;
byte IsFertPumpBLOOM3Open = LOW;

byte WaterBLOOMStep1 = LOW;
byte WaterBLOOMStep2 = LOW;
byte WaterBLOOMStep3 = LOW;


unsigned long DrainValveStartMillis;

unsigned long FertilizerPump1BLOOMStartMillis;
unsigned long FertilizerPump2BLOOMStartMillis;
unsigned long FertilizerPump3BLOOMStartMillis;

unsigned long DrainValveCurrentMillis = 0;

unsigned long FertilizerPump1BLOOMCurrentMillis = 0;
unsigned long FertilizerPump2BLOOMCurrentMillis = 0;
unsigned long FertilizerPump3BLOOMCurrentMillis = 0;

//========================================

void setup() {

  Serial.begin(115200);
  delay (2000);
  Serial.println("\Starting");

  pinMode(RELAY1, OUTPUT);
  pinMode(RELAY2, OUTPUT);
  pinMode(RELAY3, OUTPUT);
  pinMode(RELAY4, OUTPUT);
  pinMode(RELAY5, OUTPUT);
  pinMode(RELAY6, OUTPUT);


  digitalWrite(RELAY1, LOW); // set Main Valve OFF
  digitalWrite(RELAY2, LOW); // set LIGHTS OFF
  digitalWrite(RELAY3, LOW); // set Fertilizer Pump 1 GROW OFF
  digitalWrite(RELAY4, LOW); // set Fertilizer Pump 2 BLOOM OFF
  digitalWrite(RELAY5, LOW); // set Fertilizer Pump 3 MICRO OFF
  digitalWrite(RELAY6, LOW); // set Drain Valve OFF

}


//========================================

void loop()

{
  if (IsBLOOMWaterNeeded == LOW)
  {
    DrainValveBLOOM();
  }

  if (WaterBLOOMStep1 == HIGH)

  {
    MainValveFert1BLOOM();
  }

  if (WaterBLOOMStep2 == HIGH)
  {
    Fert2BLOOM();
  }

  if (WaterBLOOMStep3 == HIGH)
  {
    Fert3BLOOM();
  }
}

void DrainValveBLOOM()
{
  if (IsBLOOMWaterNeeded == LOW)
  {
    digitalWrite(RELAY6, HIGH);  //change the state of the Drain Valve to Open
    Serial.println("Drain Valve Open");

    IsBLOOMWaterNeeded = HIGH;
    WaterBLOOMStep1 = HIGH;
    IsDrainValveOpen = HIGH;


    DrainValveStartMillis = millis(); //record when we opened the valve
  } else {
    //drain valve is open. Is it time to turn it off?

    if (millis() - DrainValveStartMillis >= DrainValvePeriod)  //test whether the period has elapsed
    {
      digitalWrite(RELAY6, LOW);  //if so, change the state of the Drain Valve to Closed
      Serial.println("Drain Valve Closed");

      IsDrainValveOpen = LOW;

    }
  }
}

void MainValveFert1BLOOM()
{
  if (IsDrainValveOpen == LOW)
  {
    digitalWrite(RELAY1, HIGH);  //change the state of the Main Valve to Open
    Serial.println("Main Valve Open");

    digitalWrite(RELAY3, HIGH);  //change the state of the Fertilizer Pump 1 (GROW) to Open
    Serial.println("Fertilizer Pump 1 (GROW) Open");

    WaterBLOOMStep1 = LOW;
    IsFertPumpBLOOM1Open = HIGH;
    WaterBLOOMStep2 = HIGH;

    FertilizerPump1BLOOMStartMillis = millis(); //record when we opened the valve
  } else {

    if (millis() - FertilizerPump1BLOOMStartMillis >= FertilizerPump1BLOOMPeriod)  //test whether the period has elapsed
    {
      digitalWrite(RELAY3, LOW);  //if so, change the state of the Fertilizer Pump 1 (GROW) to Closed

      Serial.println("Fertilizer Pump 2 (BLOOM) Closed");

      IsFertPumpBLOOM1Open = LOW;

    }
  }
}

void Fert2BLOOM()

{
  if (IsFertPumpBLOOM1Open == LOW)
  {
    digitalWrite(RELAY4, HIGH);  //change the state of the Fertilizer Pump 2 (BLOOM) to Open
    Serial.println("Fertilizer Pump 2 (BLOOM) Open");

    WaterBLOOMStep2 = LOW;
    IsFertPumpBLOOM2Open = HIGH;
    WaterBLOOMStep3 = HIGH;

    FertilizerPump2BLOOMCurrentMillis = millis();

  } else {

    if (millis() - FertilizerPump2BLOOMStartMillis >= FertilizerPump2BLOOMPeriod)  //test whether the period has elapsed
    {
      digitalWrite(RELAY4, LOW);  //if so, change the state of the Fertilizer Pump 2 (BLOOM) to Closed
      Serial.println("Fertilizer Pump 2 (BLOOM) Closed");

      IsFertPumpBLOOM2Open = LOW;

    }
  }
}

void Fert3BLOOM()

{
  if (IsFertPumpBLOOM2Open == LOW)
  {
    digitalWrite(RELAY5, HIGH);  //change the state of the Fertilizer Pump 3 (MICRO) to Open
    Serial.println("Fertilizer Pump 3 (MICRO) Open");

    WaterBLOOMStep3 = LOW;
    IsFertPumpBLOOM3Open = HIGH;

    FertilizerPump3BLOOMCurrentMillis = millis();

  } else {

    if (millis() - FertilizerPump3BLOOMStartMillis >= FertilizerPump3BLOOMPeriod)  //test whether the period has elapsed
    {
      digitalWrite(RELAY3, LOW);  //if so, change the state of the Fertilizer Pump 3 (MICRO) to Closed

      Serial.println("Fertilizer Pump 3 (MICRO) Closed");

      IsFertPumpBLOOM3Open = LOW;
      IsBLOOMWaterNeeded == LOW;
      IsMainValveOpen = LOW;
    }
  }
}

I wonder who is this "qweiczz" who has copy/pasted my earlier post there? strange.

So I'm debugging this by just following the code execution. We start at the top of loop() and check if IsBLOOMWaterNeeded==LOW. Yes it is, so we go into the first function. That also checks IsBLOOMWaterNeeded==LOW and then immediately sets it HIGH.

Now a few other things get set to HIGH, but I'm ignoring them for the moment. Lets return to loop(). Guess what? IsBLOOMWaterNeeded is HIGH so it never goes into that first function again. You never give that function an opportunity to look at the clock.

So the first fix is to remove that check IsBLOOMWaterNeeded==LOW from the loop. It should always enter the first function, to give that function a chance to check IsBLOOMWaterNeeded for itself.

Your logic is still too fragmented. It's like that game with the plastic monkeys that hang off each other hand-to-hand. You try to pick up a chain of monkeys by grabbing one monkey and using it to pick up the next monkey's hand, then hook that monkey onto the next one...

Instead of a chain where each valve is waiting for the previous valve to close, why not make it a list? At step 3 of the list, which valves should be open and which should be closed? How long do you wait while you're in step 3?

Then add a couple of extra steps to the list. Like "watering not needed" and "please start this cycle". Your waterlevel sensor that calls for a cycle to start can kick it into the first step and then the automatic timing takes over from there.

Very interesting thanks again. I understand now that why this "IsBLOOMWaterNeeded==LOW" has to be removed from the loop. Thats simple and clear.

But not quite sure what you mean by making a "list"? I guess that this "list" is again pretty simple thing, but only after you know what it actually means. How should I do it? If it isn´t too hard to explain.. for a beginner like me.

And what should these "watering not needed" and "please start this cycle" actually contain?

Yeah there were more stupid mistakes. I somehow made errors in wich valves should be open and wich closed. I double checked them now and those should be correct. Like in step 3. "Fert2BLOOM()" the main valve (RELAY1) + Fertilizer pump 2 (BLOOM) (RELAY4) should be open.. all others closed.

How long do I wait till I´m in step 3? Till Drain Valve (RELAY6) opens+closes and Fertilizer pump 1 (GROW) (RELAY3) opens+closes. Should I really know the exact time for that process or isn´t that "wait till Fertilizer pump 1 (GROW) (RELAY3)" closes enough to start the step 3. "Fert2BLOOM()"?

Thanks for having patience with me.. I appreciate that.

I fixed those stupid mistakes in relay numbers and serial monitor gives this:

Starting
Drain Valve Open
Fertilizer Pump 1 (GROW) Closed
Fertilizer Pump 1 (GROW) Closed
Fertilizer Pump 1 (GROW) Closed
Fertilizer Pump 1 (GROW) Closed
Fertilizer Pump 1 (GROW) Closed
Fertilizer Pump 1 (GROW) Closed

And code is like this now:

// --------CONSTANTS (won't change)---------------

#define DHTPIN3 = 0;  //D3
#define DHTPIN4 = 2;  //D4
#define DHTPIN5 = 14; //D5
#define DHTPIN6 = 12; //D6
#define DHTPIN7 = 13; //D7
#define DHTPIN8 = 15; //D8
#define DHTPIN0 = 16;  //D0

const int RELAY1 = D3; //Main Valve
const int RELAY2 = D4; //Lights ON/OFF
const int RELAY6 = D8; //Drain Valve
const int RELAY3 = D5; //Fertilizer Pump 1 GROW
const int RELAY4 = D6; //Fertilizer Pump 2 BLOOM
const int RELAY5 = D7; //Fertilizer Pump 3 MICRO

const int DrainValvePeriod = 5000;  //Drain Valve period
const int FertilizerPump1BLOOMPeriod = 5000;  //Fertilizer Pump 1 GROW ON BLOOMMIX period
const int FertilizerPump2BLOOMPeriod = 5000;  //Fertilizer Pump 2 BLOOM ON BLOOMMIX period
const int FertilizerPump3BLOOMPeriod = 5000;  //Fertilizer Pump 3 MICRO ON BLOOMMIX period

////------------ VARIABLES (will change)---------------------

byte IsBLOOMWaterNeeded = LOW;
byte IsMainValveOpen = LOW;
byte IsDrainValveOpen = LOW;
byte IsFertPumpBLOOM1Open = LOW;
byte IsFertPumpBLOOM2Open = LOW;
byte IsFertPumpBLOOM3Open = LOW;

byte WaterBLOOMStep1 = LOW;
byte WaterBLOOMStep2 = LOW;
byte WaterBLOOMStep3 = LOW;


unsigned long DrainValveStartMillis;

unsigned long FertilizerPump1BLOOMStartMillis;
unsigned long FertilizerPump2BLOOMStartMillis;
unsigned long FertilizerPump3BLOOMStartMillis;

unsigned long DrainValveCurrentMillis = 0;

unsigned long FertilizerPump1BLOOMCurrentMillis = 0;
unsigned long FertilizerPump2BLOOMCurrentMillis = 0;
unsigned long FertilizerPump3BLOOMCurrentMillis = 0;

//========================================

void setup() {

  Serial.begin(115200);
  delay (2000);
  Serial.println("\Starting");

  pinMode(RELAY1, OUTPUT);
  pinMode(RELAY2, OUTPUT);
  pinMode(RELAY3, OUTPUT);
  pinMode(RELAY4, OUTPUT);
  pinMode(RELAY5, OUTPUT);
  pinMode(RELAY6, OUTPUT);


  digitalWrite(RELAY1, LOW); // set Main Valve OFF
  digitalWrite(RELAY2, LOW); // set LIGHTS OFF
  digitalWrite(RELAY3, LOW); // set Fertilizer Pump 1 GROW OFF
  digitalWrite(RELAY4, LOW); // set Fertilizer Pump 2 BLOOM OFF
  digitalWrite(RELAY5, LOW); // set Fertilizer Pump 3 MICRO OFF
  digitalWrite(RELAY6, LOW); // set Drain Valve OFF

}


//========================================

void loop()

{

  DrainValveBLOOM();


  if (WaterBLOOMStep1 == HIGH)

  {
    MainValveFert1BLOOM();
  }

  if (WaterBLOOMStep2 == HIGH)
  {
    Fert2BLOOM();
  }

  if (WaterBLOOMStep3 == HIGH)
  {
    Fert3BLOOM();
  }
}

void DrainValveBLOOM()
{
  if (IsBLOOMWaterNeeded == LOW)
  {
    digitalWrite(RELAY6, HIGH);  //change the state of the Drain Valve to Open
    Serial.println("Drain Valve Open");

    IsBLOOMWaterNeeded = HIGH;
    WaterBLOOMStep1 = HIGH;
    IsDrainValveOpen = HIGH;


    DrainValveStartMillis = millis(); //record when we opened the valve
  } else {
    //drain valve is open. Is it time to turn it off?

    if (millis() - DrainValveStartMillis >= DrainValvePeriod)  //test whether the period has elapsed
    {
      digitalWrite(RELAY6, LOW);  //if so, change the state of the Drain Valve to Closed
      Serial.println("Drain Valve Closed");

      IsDrainValveOpen = LOW;

    }
  }
}

void MainValveFert1BLOOM()
{
  if (IsDrainValveOpen == LOW)
  {
    digitalWrite(RELAY1, HIGH);  //change the state of the Main Valve to Open
    Serial.println("Main Valve Open");

    digitalWrite(RELAY3, HIGH);  //change the state of the Fertilizer Pump 1 (GROW) to Open
    Serial.println("Fertilizer Pump 1 (GROW) Open");

    WaterBLOOMStep1 = LOW;
    IsFertPumpBLOOM1Open = HIGH;
    WaterBLOOMStep2 = HIGH;

    FertilizerPump1BLOOMStartMillis = millis(); //record when we opened the valve
  } else {

    if (millis() - FertilizerPump1BLOOMStartMillis >= FertilizerPump1BLOOMPeriod)  //test whether the period has elapsed
    {
      digitalWrite(RELAY3, LOW);  //if so, change the state of the Fertilizer Pump 1 (GROW) to Closed

      Serial.println("Fertilizer Pump 1 (GROW) Closed");

      IsFertPumpBLOOM1Open = LOW;

    }
  }
}

void Fert2BLOOM()

{
  if (IsFertPumpBLOOM1Open == LOW)
  {
    digitalWrite(RELAY4, HIGH);  //change the state of the Fertilizer Pump 2 (BLOOM) to Open
    Serial.println("Fertilizer Pump 2 (BLOOM) Open");

    WaterBLOOMStep2 = LOW;
    IsFertPumpBLOOM2Open = HIGH;
    WaterBLOOMStep3 = HIGH;

    FertilizerPump2BLOOMCurrentMillis = millis();

  } else {

    if (millis() - FertilizerPump2BLOOMStartMillis >= FertilizerPump2BLOOMPeriod)  //test whether the period has elapsed
    {
      digitalWrite(RELAY4, LOW);  //if so, change the state of the Fertilizer Pump 2 (BLOOM) to Closed
      Serial.println("Fertilizer Pump 2 (BLOOM) Closed");

      IsFertPumpBLOOM2Open = LOW;

    }
  }
}

void Fert3BLOOM()

{
  if (IsFertPumpBLOOM2Open == LOW)
  {
    digitalWrite(RELAY5, HIGH);  //change the state of the Fertilizer Pump 3 (MICRO) to Open
    Serial.println("Fertilizer Pump 3 (MICRO) Open");

    WaterBLOOMStep3 = LOW;
    IsFertPumpBLOOM3Open = HIGH;

    FertilizerPump3BLOOMCurrentMillis = millis();

  } else {

    if (millis() - FertilizerPump3BLOOMStartMillis >= FertilizerPump3BLOOMPeriod)  //test whether the period has elapsed
    {
      digitalWrite(RELAY5, LOW);  //if so, change the state of the Fertilizer Pump 3 (MICRO) to Closed

      Serial.println("Fertilizer Pump 3 (MICRO) Closed");

      IsFertPumpBLOOM3Open = LOW;
      IsBLOOMWaterNeeded == LOW;
      IsMainValveOpen = LOW;

      digitalWrite(RELAY1, LOW);  //change the state of the Main Valve to Closed
      Serial.println("Main Valve Closed");
    }
  }
}

I tried this kind of approach, but I still have problems with this code. I´m not sure did you MorganS ment this when you talked about making a list? Is this idea totally wrong again or is there some possibility to make those delays finally work.

Serial monitor gives this without any delays:

Starting..
Drain Valve Open
Fertilizer Pump 1 (GROW) Closed
Fertilizer Pump 2 (BLOOM) Open
Fertilizer Pump 3 (MICRO) Closed
Main Valve Closed

Code is like this:

// --------CONSTANTS (won't change)---------------

#define DHTPIN3 = 0;  //D3
#define DHTPIN4 = 2;  //D4
#define DHTPIN5 = 14; //D5
#define DHTPIN6 = 12; //D6
#define DHTPIN7 = 13; //D7
#define DHTPIN8 = 15; //D8
#define DHTPIN0 = 16;  //D0

const int RELAY1 = D3; //Main Valve
const int RELAY2 = D4; //Lights ON/OFF
const int RELAY6 = D8; //Drain Valve
const int RELAY3 = D5; //Fertilizer Pump 1 GROW
const int RELAY4 = D6; //Fertilizer Pump 2 BLOOM
const int RELAY5 = D7; //Fertilizer Pump 3 MICRO

const int DrainValvePeriod = 5000;  //Drain Valve period
const int FertilizerPump1BLOOMPeriod = 5000;  //Fertilizer Pump 1 GROW ON BLOOMMIX period
const int FertilizerPump2BLOOMPeriod = 5000;  //Fertilizer Pump 2 BLOOM ON BLOOMMIX period
const int FertilizerPump3BLOOMPeriod = 5000;  //Fertilizer Pump 3 MICRO ON BLOOMMIX period

////------------ VARIABLES (will change)---------------------

byte MainValveState = LOW;
byte DrainValveState = LOW;
byte FertilizerPump1State = LOW;
byte FertilizerPump2State = LOW;
byte FertilizerPump3State = LOW;

unsigned long DrainValveStartMillis;

unsigned long FertilizerPump1BLOOMStartMillis;
unsigned long FertilizerPump2BLOOMStartMillis;
unsigned long FertilizerPump3BLOOMStartMillis;

unsigned long DrainValveCurrentMillis = 0;

unsigned long FertilizerPump1BLOOMCurrentMillis = 0;
unsigned long FertilizerPump2BLOOMCurrentMillis = 0;
unsigned long FertilizerPump3BLOOMCurrentMillis = 0;

//========================================


void BLOOMStep1(void);
void BLOOMStep2(void);
void BLOOMStep3(void);
void BLOOMStep4(void);

void (*myPointer[])(void) = {
  BLOOMStep1,
  BLOOMStep2,
  BLOOMStep3,
  BLOOMStep4
};

void setup() {
  Serial.begin(115200);
  delay (2000);
  Serial.println ("Starting..");
  for (uint8_t i = 0; i < 4; i++) {
    (*myPointer[i])();
  }
}

void loop() {
}

void BLOOMStep1()
{
  if (DrainValveState == LOW)
  {
    digitalWrite(RELAY6, HIGH);  //change the state of the Drain Valve to Open
    Serial.println("Drain Valve Open");
    DrainValveState = HIGH;
    MainValveState = HIGH;

    DrainValveStartMillis = millis(); //record when we opened the valve
  } else {
    //drain valve is open. Is it time to turn it off?

    if (millis() - DrainValveStartMillis >= DrainValvePeriod)  //test whether the period has elapsed
    {
      digitalWrite(RELAY6, LOW);  //if so, change the state of the Drain Valve to Closed

      DrainValveState = LOW;
      Serial.println("Drain Valve Closed");

    }
  }
}

void BLOOMStep2()
{
  if (DrainValveState == LOW)
  {
    digitalWrite(RELAY1, HIGH);  //change the state of the Main Valve to Open
    Serial.println("Main Valve Open");


    digitalWrite(RELAY3, HIGH);  //change the state of the Fertilizer Pump 1 (GROW) to Open
    Serial.println("Fertilizer Pump 1 (GROW) Open");
    FertilizerPump1State = HIGH;
    FertilizerPump1BLOOMStartMillis = millis(); //record when we opened the valve
  } else {


    if (millis() - FertilizerPump1BLOOMStartMillis >= FertilizerPump1BLOOMPeriod)  //test whether the period has elapsed
    {
      digitalWrite(RELAY3, LOW);  //if so, change the state of the Fertilizer Pump 1 (GROW) to Closed

      FertilizerPump1State = LOW;
      Serial.println("Fertilizer Pump 1 (GROW) Closed");

    }

  }
}

void BLOOMStep3()
{
  if (FertilizerPump1State == LOW)
  {
    digitalWrite(RELAY4, HIGH);  //change the state of the Fertilizer Pump 2 (BLOOM) to Open
    Serial.println("Fertilizer Pump 2 (BLOOM) Open");
    FertilizerPump2State = HIGH;
    FertilizerPump2BLOOMCurrentMillis = millis();

  } else {

    if (millis() - FertilizerPump2BLOOMStartMillis >= FertilizerPump2BLOOMPeriod)  //test whether the period has elapsed
    {
      digitalWrite(RELAY4, LOW);  //if so, change the state of the Fertilizer Pump 2 (BLOOM) to Closed

      FertilizerPump2State = LOW;
      Serial.println("Fertilizer Pump 2 (BLOOM) Closed");

    }

  }
}

void BLOOMStep4()
{
      if (FertilizerPump2State == LOW)
      {
        digitalWrite(RELAY5, HIGH);  //change the state of the Fertilizer Pump 3 (MICRO) to Open
        Serial.println("Fertilizer Pump 3 (MICRO) Open");
        FertilizerPump3State = HIGH;
        FertilizerPump3BLOOMCurrentMillis = millis();

      } else {

        if (millis() - FertilizerPump3BLOOMStartMillis >= FertilizerPump3BLOOMPeriod)  //test whether the period has elapsed
        {
          digitalWrite(RELAY5, LOW);  //if so, change the state of the Fertilizer Pump 3 (MICRO) to Closed

          FertilizerPump3State = LOW;
          Serial.println("Fertilizer Pump 3 (MICRO) Closed");
          MainValveState = LOW;
          digitalWrite(RELAY1, LOW);  //change the state of the Main Valve to Closed
          Serial.println("Main Valve Closed");
        }
      }
    }