Delay problems (BWoD) (SOLVED)

Hi,

Pretty novice question, but does anyone know how I should code my hydroponic watering? I´m using Blunk to control this. All the Blynk code and some orther has been removed, otherwise too long message.

What i´m trying to do here and where the problem is:

(The actual problem is in “void watermixBLOOM()”)

  1. Open Drain valve for 5 secs if ultrasound sensor gives number 1900 or more
  2. Close Drain valve
  3. Check if Drain valve is closed and if so open Main valve (no time) and Fertilizer Pump 1 (GROW) (for 5 secs and close it)
  4. Check if Fertilizer Pump 1 (GROW) is closed and if so, open Fertilizer Pump 2 (BLOOM) (for 5 secs and close it)
  5. Check if Fertilizer Pump 2 (GROW) is closed and if so, open Fertilizer Pump 3 (BLOOM) (for 5 secs and close it)
  6. Close Main Valve if ultrasound sensor gives number 1300 or less.
/**************************************************************

   Samsara Exit Hydroponics V1.0

   01.12.2018

   Hydroponics System for NodeMCU 0.9

 * ************************************************************



 **************************************************************/

#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <SimpleTimer.h>
#include <TimeLib.h>
#include <WidgetRTC.h>
#include <SPI.h>


SimpleTimer timer;


unsigned long WaterPumpStartMillis;
unsigned long DrainValveStartMillis;


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

unsigned long CurrentMillis;

unsigned long DrainValveCurrentMillis;
unsigned long FertilizerPump1BLOOMCurrentMillis;
unsigned long FertilizerPump2BLOOMCurrentMillis;
unsigned long FertilizerPump3BLOOMCurrentMillis;


const unsigned long WaterPumpPeriod = 5000;  //Water Pump ON/OFF period
const unsigned long DrainValvePeriod = 5000;  //Drain Valve ON period



const unsigned long FertilizerPump1BLOOMPeriod = 5000;  //Fertilizer Pump 1 GROW ON BLOOMMIX period
const unsigned long FertilizerPump2BLOOMPeriod = 5000;  //Fertilizer Pump 2 BLOOM ON BLOOMMIX period
const unsigned long FertilizerPump3BLOOMPeriod = 5000;  //Fertilizer Pump 3 MICRO ON BLOOMMIX period


#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


int DrainValveState = 0;
int FertilizerPump1State = 0;
int FertilizerPump2State = 0;
int FertilizerPump3State = 0;

int RELAY1 = D3; //Main Valve
int RELAY2 = D4; //Lights ON/OFF

const byte RELAY6 = D8; //Drain Valve
const byte RELAY3 = D5; //Fertilizer Pump 1 GROW
const byte RELAY4 = D6; //Fertilizer Pump 2 BLOOM
const byte RELAY5 = D7; //Fertilizer Pump 3 MICRO
const byte RELAY7 = D0; //Water Pump



//-------------------
//ultrasound sensor:

unsigned long echo = 0;
int ultraSoundSignal = 5; // Ultrasound trig signal pin D1
int ultraSoundSignalIN = 4; // Ultrasound echo signal pin D2

unsigned long ultrasoundValue = 0;
//-------------------

void setup()
{
  pinMode(RELAY1, OUTPUT);
  pinMode(RELAY2, OUTPUT);
  pinMode(RELAY3, OUTPUT);
  pinMode(RELAY4, OUTPUT);
  pinMode(RELAY5, OUTPUT);
  pinMode(RELAY6, OUTPUT);
  pinMode(RELAY7, OUTPUT);


  digitalWrite(RELAY2, LOW); // set LIGHTS OFF


  pinMode(ultraSoundSignal, OUTPUT);
  pinMode(ultraSoundSignalIN, INPUT);

  Serial.begin(115200);
  Serial.println("\Starting");
  Blynk.begin(auth, ssid, pass, IPAddress(139, 59, 206, 133), 80);
  int mytimeout = millis() / 1000;

  WaterPumpStartMillis = millis();  //initial start time of Water Pump
  DrainValveStartMillis = millis();  //initial start time of Drain Valve


  FertilizerPump1BLOOMStartMillis = millis(); //initial start time of Fertilizer Pump 1 BLOOMMIX GROW
  FertilizerPump2BLOOMStartMillis = millis(); //initial start time of Fertilizer Pump 2 BLOOMMIX BLOOM
  FertilizerPump3BLOOMStartMillis = millis(); //initial start time of Fertilizer Pump 3 BLOOMMIX MICRO

  while (Blynk.connect() == false) { // try to connect to server for 10 seconds
    if ((millis() / 1000) > mytimeout + 8) { // try local server if not connected within 9 seconds
      break;
    }
  }
  rtc.begin();
}

//-------------------
//ultrasound sensor:

unsigned long ping()
{


  if (echo >= 1900 && echo < 2500)

  {
    Blynk.syncVirtual(V8);
  }

  return ultrasoundValue;


}

//-------------------


BLYNK_WRITE (V8) {

  switch (param.asInt())
  {

    case 1: // Vegetative Mix
       watermixVEG();
      break;



    case 2: // Bloom Mix
      watermixBLOOM();
      break;



    case 3: // Plain Water Mix
      watermixPLAIN();
      break;

    default:
      // if nothing else matches, do the default
      // default is optional
      watermixVEG();
      break;
  }
}

void ultrasoundsensor_send()
{
  int x = 0;
  x = ping();
}



void watermixBLOOM()
{
  if (echo >= 1900 && echo < 2500)
  {
    Blynk.virtualWrite(V1, "Watering BLOOM-mix");

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

    if (DrainValveCurrentMillis - 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.
      Serial.println("Drain Valve Closed");
    }
    DrainValveState = digitalRead(RELAY6);     // read the input pin (Drain Valve)

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

      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
        FertilizerPump1BLOOMStartMillis = FertilizerPump1BLOOMCurrentMillis;  //IMPORTANT to save the start time of the current RELAY state.
        Serial.println("Fertilizer Pump 1 (GROW) Closed");
      }
      FertilizerPump1State = digitalRead(RELAY3);     // read the input pin (FertilizerPump1)

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

        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
          FertilizerPump2BLOOMStartMillis = FertilizerPump2BLOOMCurrentMillis;  //IMPORTANT to save the start time of the current RELAY state.
          Serial.println("Fertilizer Pump 2 (BLOOM) Closed");
        }

        FertilizerPump2State = digitalRead(RELAY4);     // read the input pin (FertilizerPump2)

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

          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
            FertilizerPump3BLOOMStartMillis = FertilizerPump3BLOOMCurrentMillis;  //IMPORTANT to save the start time of the current RELAY state.
            Serial.println("Fertilizer Pump 3 (MICRO) Closed");
          }
        }
      }
    }

  }
}







// All the Blynk coding has been removed



void WaterPump()  //function to ON/OFF Water Pump
{
  if (CurrentMillis - WaterPumpStartMillis >= WaterPumpPeriod)  //test whether the period has elapsed
  {
    digitalWrite(RELAY7, !digitalRead(RELAY7));  //if so, change the state of the Water Pump
    WaterPumpStartMillis = CurrentMillis;  //IMPORTANT to save the start time of the current RELAY state.
    //Serial.println("Water Pump ON/OFF");
  }
}

void loop()
{

  if (Blynk.connected()) {
    Blynk.run();
  }
  timer.run();

  CurrentMillis = millis();  //get the current time
  WaterPump();

}

What does the code ACTUALLY do? You can't get from point A to point B without knowing where points A and B are.

  FertilizerPump1BLOOMStartMillis = millis(); //initial start time of Fertilizer Pump 1 BLOOMMIX GROW
  FertilizerPump2BLOOMStartMillis = millis(); //initial start time of Fertilizer Pump 2 BLOOMMIX BLOOM
  FertilizerPump3BLOOMStartMillis = millis(); //initial start time of Fertilizer Pump 3 BLOOMMIX MICRO

Are you actually starting anything here? What value does using BLOOM in the names add?

void ultrasoundsensor_send()
{
  int x = 0;
  x = ping();
}

ping() does not return an int. This function is NOT sending anything.

ok I try to explain this bit more. Theres a waterpump in the background wich turns ON/OFF continuosly (5 secs ON ans 5 secs OFF.. All these times are now 5 secs, but I will change them to actual times when code works) . That works fine. Then theres a Ultrasound distance sensor wich checkes the water level.. that works also just fine.

When water level droppes to lowest level (ultrasound value 1900 and more), it starts "void watermixBLOOM()". That works also. There will be also Water mix Vegetative and thats why i´m using that "BLOOM" in the name. Other one will be "watermixVEG()", cause I need 2 different fertilizer mixes for vegetative- and bloom-state.

So problems starts when the "void watermixBLOOM()" starts. First I need to open the Drain Valve (RELAY6) to get out all the water that is left there (Now only 5 secs on). After that drain is finished I need to open the Main Valve (RELAY1) to get new water in (in main valve theres no time, cause it´s controlled by the Ultrasound distance sensor).. and also start adding those 3 different fertilizers (RELAYS 3,4 and 5). 1 at the time (now 5 secs each).

When waterlevel is back to 100% (ultrasound sensor value 1300 and less), it should close the Main Valve and continue the normal progress. I know that this closing the main valve part is missing from the code still.

This is what i get from serial monitor when waterlevel (ultrasound value) goes over that 1900:

[28227] Connecting to 139.59.206.133
[28325] Ready (ping: 48ms).
[28506] Time sync: OK
1358
1392
1466
1667
1829
1938
Drain Valve Open
Drain Valve Closed
1981

So it just opens and closes and thats it.. no 5 secs there. Doesn´t go to the fertilizer relays at all.. Why so?

I hope this explaining is not too hard to understand.

    if (DrainValveState = LOW)

You are assigning the value LOW to DrainValveState, not testing whether the value in DrainValveState is LOW.

This is what i get from serial monitor when waterlevel (ultrasound value) goes over that 1900:

Not with the code you posted...

Well thats because theres parts removed that were working fine, and thats because it was too long message otherwise. This is not the whole code. That is the exact Serial Monitor output what i get with the whole code included. I can send the whole code if needed, but it´s not possible via this forum seems so.

But hey thanks for this tip you gave. I´m still so novice as you can see, so how should I write that part in the code? ..in case it´s easy to explain?

I can send the whole code if needed, but it´s not possible via this forum seems so.

If you use the Reply button, NOT the Quick Reply field, you can attach your code - far more than the 9500 character limit.

so how should I write that part in the code?

What part? Following your post is like trying to follow a murder mystery by reading every third page.

Murder mystery! Hah! I believe that… cause I´m a total beginner actually. My first real project actually… yeah could have been easier maybe, but I just need this. Thinking about this for too long already. Theres no turning back anymore.

I ment this tip of course: "if (DrainValveState = LOW)

You are assigning the value LOW to DrainValveState, not testing whether the value in DrainValveState is LOW."

Code is still too long to copy here, so I included an attachment. Hopefully it helps.

Btw… Theres also Lights control added there, with timer or manual ON/OFF. Thats works fine also. So all controlled by Blynk.

kasvihuone66.ino (21 KB)

The assignment operator is =. The equality (test) operator is ==. Your statement should be:

if (DrainValveState == LOW)

You've made that same mistake in many places.

Samsara_Exit:
but I just need this. Thinking about this for too long already. Theres no turning back anymore.

That kind of thinking has burned up trillions of dollars. Look up the story of the FBI Virtual Case File for one example.

Your idea seems well-thought out but it is missing an important concept from BWoD. The Arduino processor is fast and physical processes are slow. So don't stop the processor waiting for a valve to close. Go back to the main loop, read all the inputs, look at the clock and do any calculation required. If the conditions are satisfied to move to the next state then do so.

I like to draw out the state macine on paper with bubbles for states and arrows for state transitions. Doing it this way discovers a lot of states you did not think of. For example, what should your system do if a valve fails to open or close in a reasonable time? It may do something different depending on which valve it was.

This blinking (BWoD) is so new to me, but so important to understand. Somehow i thought that it should use the loop all the time already, but seems like the case isn´t so. Again… Is it easy to explain in concrete way that how do i jump to the loop from the middle of the watering process? Also that tip earlier you gave interests me still.

You´re question: "if valve fails to open or close in a reasonable time). Hmm… Did I get the question right, but I know that Fertilizing pumps have plenty of time to do their thing before Main Valve closes and water level is 100% again. And if something really strange happens and water comes over the edges, I will add just in case a moisture sensor to the floor. That adds one more “emergency valve” to the main water input. If that sensor notices water on the floor it will shut down the Main Water input totally (And send warning to my phone).

Not sure did I answered your question at all now but…

Oh hey thanks PaulS for this help, I almost didnt notice it"

"The assignment operator is =. The equality (test) operator is ==. Your statement should be:
Code: [Select]

if (DrainValveState == LOW)"

That helped the code go through all the watering process, but all valves without that 5 secs delays.

But it does that only once now. Second time I try to start the watering process it gives this to serial monitor:

[29564] Ready (ping: 49ms).
[29745] Time sync: OK
1753
1578
1920
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
2118
Drain Valve Open
2164
Drain Valve Open
1910
Drain Valve Open
1519
1527

Leaves Drain valve only open… nothing else happens.

Read up about the concept of a "state machine". That's a rather hi'falutin name for a program in which one or more variables is used to keep track of the state of your system. For example some of the states might be WATER_LOW, DRAINING, FILLING ete etc.

The program can move from one state to the next either when time elapses (based on millis() or when something happens such as a float switch identifying the water level.

...R
Planning and Implementing a Program
Several Things at a Time

Try this explanation to see if it clicks for you... State Machine

Hey thanks a lot for these links. Seems like theres very usefull info for me. So back to studying…

Nothing comes easy when you are doing your first project. Good thing that at least I learn a lot while strugeling with this code:)

Still wondering why it runs watering process (void watermixBLOOM()) only ones? Second time only leaving drain valve open. Strange.

I added the code one more time. To a version where I´ve been corrected those “if (DrainValveState == LOW)” mistakes.

kasvihuone6temp.ino (21 KB)

    if (DrainValveCurrentMillis - 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.
      Serial.println("Drain Valve Closed");
    }

Where does DrainValveCurrentMillis get assigned a value?

You have WAY too much code for someone just learning. Dump the Blynk crap. Get a value from the Serial object (send it using the Serial Monitor app). If the value is ‘0’, call the ONLY function, outside of loop() and setup(), waterMixBLOOM(). Pay extremely close attention to the variables used in the function, and where they are initialized and where they are updated.

Determine whether those variables need to be global. For instance, I can’t see that DrainValveState needs to be global.

Sorry but the Blynk crap is needed, cause it´s important that I can control this via phone. From where ever I might be. And all the Blynk crap does work so far, so theres no turning back as I said. I know this is not an easy project for sure. Of course I´ve done some tests before this, but this is the first "real" project for me. I have no deadline with this, so I have time to study these things.

I try to understand those links you gave. hopefully solving the problems.

I have this there:

"unsigned long DrainValveCurrentMillis;"

Should it be like:

"unsigned long DrainValveCurrentMillis = 0;"? I guess not actually.. need to study this also it seems

And should i use byte instead of int? like this:

byte DrainValveState = 0;
byte FertilizerPump1State = 0;
byte FertilizerPump2State = 0;
byte FertilizerPump3State = 0;

The choice of byte or int is not important unless you have hundreds of them and need to save memory.

Unlike regular C, on the Arduino global variables always start at zero. So it makes no difference if you assign zero when declaring the variable. However it is good to get used to doing it that way as you might forget in other places.

If you write your code with good functions then you can test a complex function inside a simple framework without other complex stuff getting in the way. There are probably 100 times that I have trimmed out a function that was causing me problems so I could post it here when I discovered the problem during the trimming.

Samsara_Exit:
I added the code one more time.

How could you have got to the point of having 21K of code before you discovered you have a problem.

Learn about new techniques in short programs of 10 or 20 lines. Don't incorporate stuff into a large program unless you that it works.

Can you go back to the immediately previous working version of the large program? What changes did you then make that cause the problem?

Test early and often.

...R

Sorry but the Blynk crap is needed, cause it´s important that I can control this via phone.

Sure. AFTER you get the part of the code that you are having trouble with working properly. NOT now.

Ookey…

I managed to fix everything else, but only those 5 secs delays are still missing.

I moved those “****StartMillis = millis()” from the setup to the “void watermixBLOOM()”. Also moved all those “byte *****State = HIGH/LOW;” to there. Like this:

void watermixBLOOM()
{

  if (echo >= 1900 && echo < 2500)
  {
    Blynk.virtualWrite(V1, "Watering BLOOM-mix");

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

    byte DrainValveState = HIGH;
    DrainValveStartMillis = millis();  //initial start time of Drain Valve



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

      byte DrainValveState = LOW;

      DrainValveStartMillis = DrainValveCurrentMillis;  //IMPORTANT to save the start time of the current RELAY state.
      Serial.println("Drain Valve Closed");
    }
    DrainValveState = digitalRead(RELAY6);     // read the input pin (Drain Valve)

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

      byte FertilizerPump1State = HIGH;
      FertilizerPump1BLOOMStartMillis = millis();  //initial start time of Fertilizer Pump 1 (GROW)

      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
        FertilizerPump1BLOOMStartMillis = FertilizerPump1BLOOMCurrentMillis;  //IMPORTANT to save the start time of the current RELAY state.

        byte FertilizerPump1State = LOW;

        Serial.println("Fertilizer Pump 1 (GROW) Closed");
      }
      FertilizerPump1State = digitalRead(RELAY3);     // read the input pin (FertilizerPump1)

      if (FertilizerPump1State == LOW)
      {

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

        byte FertilizerPump2State = HIGH;
        FertilizerPump2BLOOMStartMillis = millis();  //initial start time of Drain Valve


        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
          FertilizerPump2BLOOMStartMillis = FertilizerPump2BLOOMCurrentMillis;  //IMPORTANT to save the start time of the current RELAY state.

          byte FertilizerPump2State = LOW;

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

        FertilizerPump2State = digitalRead(RELAY4);     // read the input pin (FertilizerPump2)

        if (FertilizerPump2State == LOW)
        {

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

          byte FertilizerPump3State = HIGH;
          FertilizerPump3BLOOMStartMillis = millis();  //initial start time of  Fertilizer Pump 3 (MICRO)


          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
            FertilizerPump3BLOOMStartMillis = FertilizerPump3BLOOMCurrentMillis;  //IMPORTANT to save the start time of the current RELAY state.

            byte FertilizerPump3State = LOW;

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

}

Yeah I probaply should cut the watering process to many different “void”-stages. Could that help to get those 5 sec delays somehow?

Main Valve closing when ultrasound sensor gives 1300 or less works now too. “loop” is still the same:

void loop()
{

  if (Blynk.connected()) {
    Blynk.run();
  }
  timer.run();

  WaterPumpCurrentMillis = millis();  //get the current time of Water Pump
  WaterPump();

}

Should there be something more in the loop or what is wrong with those 5 secs delays?

Serial monitor gives this now when I move the Ultrasound sensor:

[27221] Ready (ping: 48ms).
[27402] Time sync: OK
1623
1627
1767
1857
1946
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
1855
1569
1398
1315
1295
Main Valve Closed
1295

And this happens now every time when I move the sensor to the lowest/highest point. I also attach the whole code if someone is interested in it.

Yeah I haven´t used that “state machine” still like it should be used… Seems like its necessary?

kasvihuone666temp.ino (22.1 KB)

It is necessary for the code to remember where it is up to and calculate what happens next. You can choose to call that a "state machine" or call it anything else. The state machine concept is just a convenient way to organize your own thought process.

Your latest snippets don't contain enough of the program for me to see which delays are supposed to be 5 seconds. So I can't even look for your problem.