Go Down

Topic: Delay problems (BWoD) (SOLVED) (Read 1 time) previous topic - next topic

Samsara_Exit

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()

PaulS

Quote
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:
Code: [Select]
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.

Code: [Select]
  if (DrainValveState == LOW)
Your code would be far easier to read if you had
Code: [Select]
   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.
The art of getting good answers lies in asking good questions.

Samsara_Exit

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.

 

PaulS

Quote
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.

Code: [Select]
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.
The art of getting good answers lies in asking good questions.

Samsara_Exit

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..

Code: [Select]


// --------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?

MorganS

Quote
Code: [Select]
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.
"The problem is in the code you didn't post."

Samsara_Exit

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:

Code: [Select]

// --------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.

MorganS

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.
"The problem is in the code you didn't post."

Samsara_Exit

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:

Code: [Select]


// --------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");
    }
  }
}

Samsara_Exit

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:

Code: [Select]

// --------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");
        }
      }
    }



MorganS

Well you've mastered function pointers which is a pretty advanced concept. You don't need them.

Go back to the piece of paper with the different states written down. Draw a circle around each one. Imagine that the program is stuck inside that circle going around and around and around.  The program checks all the inputs, millis() and makes a decision on where to go next. 

Notice I said "program". It is not just one function. Your whole loop() function is required to run and organize all the other functions thst read inputs, do calculation s and set outputs.

Try looking for tutorials on "state machine". With enough different explanations, one will make sense to you.
"The problem is in the code you didn't post."

Samsara_Exit

Ok. I hope that this is finally starting to look like a state machine, but I´m still doing some things wrong here. I wonder what those mistakes are.

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:

Code: [Select]


// --------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


enum BLOOMWaterStates {IsBLOOMWaterNeeded, BLOOMStep1, BLOOMStep2, BLOOMStep3, BLOOMStep4, BLOOMWaterNotNeeded};
BLOOMWaterStates BLOOMState = IsBLOOMWaterNeeded;

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 BLOOMMachine() {

  switch (BLOOMState) {
    case IsBLOOMWaterNeeded: {
        if (DrainValveState == LOW)
          BLOOMState = BLOOMStep1;
        break;
      }
    case BLOOMStep1:  {
        BLOOMWaterStep1();
        BLOOMState = BLOOMStep2;
        break;
      }
    case BLOOMStep2:  {
        BLOOMWaterStep2();
        BLOOMState = BLOOMStep3;
        break;
      }
    case BLOOMStep3:  {
        BLOOMWaterStep3();
        BLOOMState = BLOOMStep4;
        break;
      }
    case BLOOMStep4:  {
        BLOOMWaterStep4();
        BLOOMState = BLOOMWaterNotNeeded;
        break;
      }
    case BLOOMWaterNotNeeded: {
        BLOOMState = IsBLOOMWaterNeeded;
        break;
      }
  }
}


void loop() {

  BLOOMMachine();

}


void BLOOMWaterStep1()
{
  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");


    }

  }
}

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


    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 BLOOMWaterStep3()

{
  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 BLOOMWaterStep4()

{
  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");

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


    }
  }
}

Samsara_Exit

Finally. Of course the actual problem was in totally different place than I thought. Thats why it took so long to make this watering process go through. The solution looks weird, but the main thing is that it works and thats good enough for me now. I made so many mistakes when solving this, but I don´t feel like those were mistakes actually. That´s because I´ve learned from every mistake I´ve made and that´s good for a beginner like me.

Thanks a lot to everybody who helped me to solve these problems.


So serial monitor gives this:

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
Main Valve Closed
BLOOMWatering Ended


And code is here:

Code: [Select]


// --------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


enum BLOOMWaterStates {IsBLOOMWaterNeeded, BLOOMStep1, BLOOMStep2, BLOOMStep3, BLOOMStep4, BLOOMWaterNotNeeded};
BLOOMWaterStates BLOOMState = IsBLOOMWaterNeeded;

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 PumpABPeriod = 5000;  //Fertilizer Pump 1 GROW ON BLOOMMIX period
const int PumpBBPeriod = 5000;  //Fertilizer Pump 2 BLOOM ON BLOOMMIX period
const int PumpCBPeriod = 5000;  //Fertilizer Pump 3 MICRO ON BLOOMMIX period

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

byte MainValveState = LOW;
byte DrainValveState = LOW;
byte PumpAState = LOW;
byte PumpBState = LOW;
byte PumpCState = LOW;

unsigned long DrainValveStartMillis;

unsigned long PumpABStartMillis;
unsigned long PumpBBStartMillis;
unsigned long PumpCBStartMillis;

unsigned long DrainValveCurrentMillis = 0;

unsigned long PumpABCurrentMillis = 0;
unsigned long PumpBBCurrentMillis = 0;
unsigned long PumpCBCurrentMillis = 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 BLOOMMachine() {

  switch (BLOOMState) {


    case IsBLOOMWaterNeeded: {


        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 {
         

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

            DrainValveStartMillis = DrainValveCurrentMillis;  //IMPORTANT to save the start time of the current RELAY state.

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

            BLOOMState = BLOOMStep1;
            break;
          }



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

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


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

              if (BLOOMState == BLOOMStep1)
              {
                if (millis() - PumpABStartMillis >= PumpABPeriod)  //test whether the period has elapsed
                {
                  digitalWrite(RELAY3, LOW);  //if so, change the state of the Drain Valve to Closed
                  PumpABStartMillis = PumpABCurrentMillis;  //IMPORTANT to save the start time of the current RELAY state.
                  DrainValveState = LOW;
                  PumpAState = LOW;
                  Serial.println("Fertilizer Pump 1 (GROW) Closed");

                  BLOOMState = BLOOMStep2;
                  break;
                }
              }

            case BLOOMStep2:  {

                if (DrainValveState == LOW)
                {

                  digitalWrite(RELAY4, HIGH);  //change the state of the Fertilizer Pump 2 (BLOOM) to Open
                  Serial.println("Fertilizer Pump 2 (BLOOM) Open");
                  DrainValveState = HIGH;
                  PumpBState = HIGH;
                  PumpBBStartMillis = millis();
                } else {
                 

                  if (BLOOMState == BLOOMStep2)
                  {

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

                      break;
                    }
                  }



                case BLOOMStep3:  {

                    if (DrainValveState == LOW)
                    {

                      digitalWrite(RELAY5, HIGH);  //change the state of the Fertilizer Pump 3 (MICRO) to Open
                      Serial.println("Fertilizer Pump 3 (MICRO) Open");
                      DrainValveState = HIGH;
                      PumpCState = HIGH;
                      PumpCBStartMillis = millis();


                    } else {
                     

                      if (BLOOMState == BLOOMStep3)
                      {

                        if (millis() - PumpCBStartMillis >= PumpCBPeriod)  //test whether the period has elapsed
                        {

                          digitalWrite(RELAY5, LOW);  //if so, change the state of the Fertilizer Pump 3 (MICRO) to Closed
                          DrainValveState = LOW;
                          PumpCState = LOW;
                          Serial.println("Fertilizer Pump 3 (MICRO) Closed");

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


                          BLOOMState = BLOOMStep4;

                          break;
                        }
                      }



                    case BLOOMStep4:  {

                        if (BLOOMState == BLOOMStep4) {
                          BLOOMState = BLOOMWaterNotNeeded;
                          Serial.println("BLOOMWatering Ended");
                         
                          break;
                        }
                      }

                    }
                  }

                }
              }
            }
          }
        }
      }
  }
}

void loop() {

  BLOOMMachine();

}


MorganS

Sorry, I wrote a long reply yesterday and it got lost in the system. It looks like you've already covered some of the things I was going to say. So, commenting on your code in reply #43...

1. You declare your periods as int. That is not going to work when you try to enter a period longer than 32 seconds. Use const unsigned long instead.

2. You put a { after every case. That's not necessary. In fact I'm surprised that the compiler accepted the code that you entered. Remove those, and their matching }.

3. Make sure there's a break; above every case which always gets hit - don't put it inside the else{} block.

If you follow the first run through the switch(), you should see that it first sets the drain valve to HIGH and there is no break after that. It will go through to the next case which checks if the drain valve is LOW. Since it isn't, it checks if the PumpABStartMillis has expired, which it hasn't so it does nothing and doesn't break. So it goes to the next one, doing this all the way to the bottom of the switch().

That explains why you had to write if (BLOOMState == BLOOMStep3) inside case(BLOOMStep3). If your switch was working properly, you would not need that.

Alternatively, remove the whole switch() construct. Just add a couple more if() to the top ones which didn't already check the current state.

4. What happens when something goes wrong? If the drain valve is not LOW when you start the sequence, it will never complete properly. Now that you have the main procedure worked out, look at it again and consider what might go wrong. Most importantly, if you add a "stop" or "pause" button in the future, how would that work? How can you restart from a stop in the middle of the process?

Make your first state BloomWaterNeeded set all the valves and everything to a known starting condition. Then move onto step zero which opens the drain valve.

5. You have a relatively complex set of state variables. In each of the watering steps you check if the corresponding valve is open or closed. I would actually remove all of those and make them states of their own.

So the thing starts with setting everything to a known condition . Then the first state after that opens the drain valve and records the time. That instantly moves to the next state. That next state is the one which waits until it is time to close the valve. That will remove basically all of the if() statements inside each of your states, making the whole thing simpler and more readable. (or remove the switch like I suggested in 3.)
"The problem is in the code you didn't post."

Samsara_Exit

Thanks again MorganS. Good points to think about. This is bit more easier to read and switch does actually work now. I´ll take a closer look one more time, but this is how it looks now. Serial monitor gives this:

Starting
All Fertilizer Pumps + Drain & Main Valves Closed
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
Main Valve Closed
BLOOMWatering Ended


Code: [Select]


// --------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


enum BLOOMWaterStates {IsBLOOMWaterNeeded, BLOOMStep1, BLOOMStep2, BLOOMStep3, BLOOMStep4, BLOOMWaterNotNeeded, BLOOMWaterNeeded};
BLOOMWaterStates BLOOMState = IsBLOOMWaterNeeded;

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 unsigned long DrainValvePeriod = 5000;  //Drain Valve period
const unsigned long PumpABPeriod = 5000;  //Fertilizer Pump 1 GROW ON BLOOMMIX period
const unsigned long PumpBBPeriod = 5000;  //Fertilizer Pump 2 BLOOM ON BLOOMMIX period
const unsigned long PumpCBPeriod = 5000;  //Fertilizer Pump 3 MICRO ON BLOOMMIX period

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

byte MainValveState = LOW;
byte DrainValveState = LOW;
byte PumpAState = LOW;
byte PumpBState = LOW;
byte PumpCState = LOW;

unsigned long DrainValveStartMillis;

unsigned long PumpABStartMillis;
unsigned long PumpBBStartMillis;
unsigned long PumpCBStartMillis;

unsigned long DrainValveCurrentMillis = 0;

unsigned long PumpABCurrentMillis = 0;
unsigned long PumpBBCurrentMillis = 0;
unsigned long PumpCBCurrentMillis = 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 BLOOMMachine() {

  switch (BLOOMState) {

    case IsBLOOMWaterNeeded:

      digitalWrite(RELAY6, LOW);  //change the state of the Drain Valve to Closed
      DrainValveState = LOW;

      digitalWrite(RELAY1, LOW);  //change the state of the Main Valve to Closed
      MainValveState = LOW;

      digitalWrite(RELAY3, LOW);  //change the state of the Fertilizer Pump 1 (GROW) to Closed
      PumpAState = LOW;

      digitalWrite(RELAY4, LOW);  //change the state of the Fertilizer Pump 2 (BLOOM) to Closed
      PumpBState = LOW;

      digitalWrite(RELAY5, LOW);  //change the state of the Fertilizer Pump 3 (MICRO) to Closed
      PumpCState = LOW;

      Serial.println("All Fertilizer Pumps + Drain & Main Valves Closed");

      BLOOMState = BLOOMWaterNeeded;
      break;

    case BLOOMWaterNeeded:

      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 {

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

          DrainValveStartMillis = DrainValveCurrentMillis;  //IMPORTANT to save the start time of the current RELAY state.

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

          BLOOMState = BLOOMStep1;
        }
      }
      break;

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

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

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

        if (millis() - PumpABStartMillis >= PumpABPeriod)  //test whether the period has elapsed
        {
          digitalWrite(RELAY3, LOW);  //if so, change the state of the Drain Valve to Closed
          PumpABStartMillis = PumpABCurrentMillis;  //IMPORTANT to save the start time of the current RELAY state.
          DrainValveState = LOW;
          PumpAState = LOW;
          Serial.println("Fertilizer Pump 1 (GROW) Closed");

          BLOOMState = BLOOMStep2;
        }
      }
      break;

    case BLOOMStep2:

      if (DrainValveState == LOW)
      {

        digitalWrite(RELAY4, HIGH);  //change the state of the Fertilizer Pump 2 (BLOOM) to Open
        Serial.println("Fertilizer Pump 2 (BLOOM) Open");
        DrainValveState = HIGH;
        PumpBState = HIGH;
        PumpBBStartMillis = millis();
      } else {

        if (millis() - PumpBBStartMillis >= PumpBBPeriod)  //test whether the period has elapsed
        {
          digitalWrite(RELAY4, LOW);  //if so, change the state of the Fertilizer Pump 2 (BLOOM) to Closed
          DrainValveState = LOW;
          PumpBState = LOW;
          Serial.println("Fertilizer Pump 2 (BLOOM) Closed");
          BLOOMState = BLOOMStep3;
        }
      }
      break;

    case BLOOMStep3:

      if (DrainValveState == LOW)
      {

        digitalWrite(RELAY5, HIGH);  //change the state of the Fertilizer Pump 3 (MICRO) to Open
        Serial.println("Fertilizer Pump 3 (MICRO) Open");
        DrainValveState = HIGH;
        PumpCState = HIGH;
        PumpCBStartMillis = millis();

      } else {

        if (millis() - PumpCBStartMillis >= PumpCBPeriod)  //test whether the period has elapsed
        {

          digitalWrite(RELAY5, LOW);  //if so, change the state of the Fertilizer Pump 3 (MICRO) to Closed
          DrainValveState = LOW;
          PumpCState = LOW;
          Serial.println("Fertilizer Pump 3 (MICRO) Closed");

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

          BLOOMState = BLOOMStep4;

        }
      }
      break;

    case BLOOMStep4:

      BLOOMState = BLOOMWaterNotNeeded;
      Serial.println("BLOOMWatering Ended");
      break;
  }
}


void loop() {

  BLOOMMachine();

}


Go Up