if or while & how to properly use them in my project?

Hello everybody

I have a small basin (250 Liters of water) with two liquid level sensors, one is at fill level X and the other a bit higher at fill level Y. The level sensors are capacitive and can be read with digitalRead(), e.g. digitalRead() returns HIGH if the water has reached the sensors level. Now since i have some other things attached to my Arduino such as a pump and a aeration device, i want to control them according to the liquid level. (e.g. when the water level is high, the aeration device turns on for 30s, and then the pump should pump until the lower water level is reached.)

Now i've tried to get it working with the following code, but i seem to have not understood a basic principle or misunderstood some kind of mechanism.

int pin2 = 2; //pump1, empties the basin
int pin3 = 3; //pump 2, fills the basin 
int pin4 = 4; // meth pump
int pin5 = 5; // aeration device
int pin10 = 10; //stirring device
int pin11 = 11;
int pin12 = 12;
int FS1 = -1; //FS top
int FS2 = -1; //FS bottom (FS stands for fill sensor) 


void setup() {
  pinMode(pin2, OUTPUT);
  pinMode(pin3, OUTPUT);
  pinMode(pin4, OUTPUT);
  pinMode(pin5, OUTPUT);
  pinMode(pin10, OUTPUT); //Declare pin 2-5 & 10 as Output
  pinMode(pin11, INPUT);
  pinMode(pin12, INPUT);  //Declare pin 11 & 12 as input
  Serial.begin(9600);
}

void loop() {
  digitalWrite(pin3, LOW);
  digitalWrite(pin2, LOW);
  digitalWrite(pin4, LOW);
  digitalWrite(pin5, LOW);
  digitalWrite(pin10, LOW); //set all pins LOW just to be sure

  FS1 = digitalRead(pin11);
  FS2 = digitalRead(pin12); //read the two fill sensors
  
  if (FS1 == 0 && FS2 == 0) //when both fill sensors are low 
                                            //pump with pump 2 until first liquid sensor is reached
  { 
    digitalWrite(pin3, HIGH);
  }
  digitalWrite(pin3, LOW); //then turn the pump 2 off
  delay(1000);                //wait for 1 second, (that's not really necessary just for stabilisation)

  FS1 = digitalRead(pin11); //read the fill sensors again
  FS2 = digitalRead(pin12);
  
  if (FS1 == 0 && FS2 == 1) //when the upper fill sensor is low and the lower is high
  {                                         // turn pump 2 on until it's not TRUE anymore = the upper is reached
    digitalWrite(pin3, HIGH);
  }
  digitalWrite(pin3, LOW);          //then again turn the pump off for another second
  delay(1000);

  FS1 = digitalRead(pin11);
  FS2 = digitalRead(pin12);        //read the fill sensors again
  
  if (FS1 == 1 && FS2 == 1) //while both FS are high, execute the following:
  {
    digitalWrite(pin10, HIGH);    // turn device 1 on for 3 seconds
    delay(3000);
    digitalWrite(pin10, LOW);   // turn device 1 off
    delay(1000);                    
    digitalWrite(pin4, HIGH); //turn device 2 on for 5 seconds
    delay(5000);
    digitalWrite(pin4, LOW); // etc.
    delay(1000);
    digitalWrite(pin5, HIGH);
    delay(3000);
    digitalWrite(pin5, LOW); //until the end is reached
    delay(1000);
    digitalWrite(pin3, HIGH); //and pump 1 pumps, until the above state is not true anymore
  }
  digitalWrite(pin3, LOW); //and turn the thing off
  delay(500);

  FS1 = digitalRead(pin11);
  FS2 = digitalRead(pin12); //read the sensors again
  
  if (FS1 == 0 && FS2 == 1); //while the upper is low and the lower high
  {
    digitalWrite(pin3, HIGH); //turn pump 1 on until given statement isn't true anymore
  }
  digitalWrite(pin3, LOW); // turn pump 1 off
  delay(1000);
}

As you can see i thought that the arduino executes this script just as i explained in the code, the problem is now that it seemingly randomly turns things on and off. What i thought might be the problem is, since the second and the last if-condition are the same and the arduino tries to do both at once or doesn't execute the conditions after each other?

Therefore i don't know how to tell the arduino that he should execute all the if(){} blocks after eachother, read the sensors, and then start from the first one again. Also i don't know if it's better to use if or while. You can just substitute the "if" with "while" to get the idea of the same script but with while conditions. Funnily nothing at all works with the while conditions, but with the if conditions the random off and on turning begins.

Any help to solve my problem is greatly apprechiated!

Thank you very much!

Noscope

You do seem to have a basic misunderstand of how the code runs. The processor doesn't look at your code and figure out what you intended. It runs the lines of code one after the other starting at the top and working its way to the bottom one instruction at a time. So for instance here.

  if (FS1 == 0 && FS2 == 0) //when both fill sensors are low 
                                            //pump with pump 2 until first liquid sensor is reached
  { 
    digitalWrite(pin3, HIGH);
  }
  digitalWrite(pin3, LOW); //then turn the pump 2 off

Say if both switches read LOW turn the pump on and immediately turn it off again on the next instruction. It's not going to say to keep the pump as long as those conditions are met. It says if those conditions are met, then turn the pump on and then run the next line which turns it right back off.

And again here:

  if (FS1 == 0 && FS2 == 1); //while the upper is low and the lower high
  {
    digitalWrite(pin3, HIGH); //turn pump 1 on until given statement isn't true anymore
  }
  digitalWrite(pin3, LOW); // turn pump 1 off

Your comments are wrong. That comment should say turn pump 1 on until you get to the next line of code where I told you to turn it right back off.

Interestingly, the comment on the first line seems to suggest a better idea. But note that while in a while loop, only the code inside that while loop runs. Any code outside of it is dead until those conditions aren't true anymore and the code exits the while loop to pick up with the next line.

EDIT: In light of what Groove spotted, these lines actually say, turn the pump on regardless of the state of those two pins and then immediately turn it back off again.

f (FS1 == 0 && FS2 == 1);

Oh dear. That's not how to write an if.

Groove: f (FS1 == 0 && FS2 == 1);

Oh dear. That's not how to write an if.

Man, I copied it too and didn't even see that. Need to get my eyes checked.

I think the others have covered the fundamental misunderstanding of how programs work (this applies to all programming languages, not just Arduino C).

I often do things like this, when checking conditions in loop:

if (FS1 == 0 && FS2 == 1); //if the upper is low and the lower high
  {
    digitalWrite(pin3, HIGH); //turn pump 1 on
  } else {
  digitalWrite(pin3, LOW); // Otherwise turn pump 1 off
}

I often do things like this, when checking conditions in loop:

You mean you can't write a simple if either? ;)

if (FS1 == 0 && FS2 == 1);

The trailing semicolon closes out the if action. Any code in { } then runs everytime. Sometimes hinting at the "error" just isn't enough. The OP hasn't replied tho, so maybe it did sink in.

CrossRoads: if (FS1 == 0 && FS2 == 1);

The trailing semicolon closes out the if action. Any code in { } then runs everytime. Sometimes hinting at the "error" just isn't enough. The OP hasn't replied tho, so maybe it did sink in.

Yes it did, i must have accidently wrote that semicolon while editing the code for the forum. So if i understand right this should fix the whole problem?:

if (FS1 == 0 && FS2 == 1)//NO SEMICOLON HERE!
  {
    digitalWrite(pin3, HIGH); //turn pump 1 on
  } else {
  digitalWrite(pin3, LOW); // Otherwise turn pump 1 off
}

Thanks a lot for your help guys, it's really nice that you spend your time for strangers :)

EDIT because 10min post limit: Goddamit i copied that semicolon aswell :U, Sometimes i should better go to sleep instead of s**tposting on the internet...

No: if (FS1 == 0 && FS2 == 1) // no semicolon here

Ok, i've tried the the following this morning:

int pin2 = 2; //pump2 emptying the basin
int pin3 = 3; // pump1 filling the basin
int pin4 = 4; // device 1
int pin5 = 5; // device 2
int pin10 = 10; //device 3
int pin11 = 11; //read voltage FS1
int pin12 = 12; // read voltage FS2
int FS1 = -1; //FS top
int FS2 = -1; //FS bottom

void setup() {
  pinMode(pin2, OUTPUT);
  pinMode(pin3, OUTPUT);
  pinMode(pin4, OUTPUT);
  pinMode(pin5, OUTPUT);
  pinMode(pin10, OUTPUT);
  pinMode(pin11, INPUT);
  pinMode(pin12, INPUT);
  Serial.begin(9600);
}

void loop() {
  FS1 = digitalRead(pin11);
  FS2 = digitalRead(pin12);
  
  if (FS1 == 0 && FS2 == 0)
  { 
    digitalWrite(pin3, HIGH);
  } else {
    digitalWrite(pin3, LOW);
  }
  
  delay(1000);

  FS1 = digitalRead(pin11);
  FS2 = digitalRead(pin12);
  
  if (FS1 == 0 && FS2 == 1)
  {
    digitalWrite(pin3, HIGH);
  } else {
    digitalWrite(pin3, LOW);
  }
  delay(1000);

  FS1 = digitalRead(pin11);
  FS2 = digitalRead(pin12);
  
  if (FS1 == 1 && FS2 == 1)
  {
    digitalWrite(pin10, HIGH);
    delay(3000);
    digitalWrite(pin10, LOW);
    delay(1000);
    digitalWrite(pin4, HIGH);
    delay(5000);
    digitalWrite(pin4, LOW);
    delay(1000);
    digitalWrite(pin5, HIGH);
    delay(3000);
    digitalWrite(pin5, LOW);
    delay(1000);
    digitalWrite(pin2, HIGH);
  } else {
    digitalWrite(pin10, LOW);
    digitalWrite(pin4, LOW);
    digitalWrite(pin5, LOW);
    digitalWrite(pin3, LOW);
    digitalWrite(pin2, LOW);
  }

  FS1 = digitalRead(pin11);
  FS2 = digitalRead(pin12);
  
  if (FS1 == 0 && FS2 == 1)
  {
    digitalWrite(pin2, HIGH);
  } else {
    digitalWrite(pin2, LOW);
  }
  delay(1000);
}

But it doesn't work that way. The result is that it just turns all pins ON and blinks with pin 3. Although the digitalRead() clearly returns FS1 = 0 and FS2 = 0...

I think i need some kind of function that does check FS1&FS2 continuously and then does something while FS1&2 are e.g. LOW, if they're not LOW anymore, it does something else. When a FULL circle is reached it starts from the beginning e.g.:

when (FS1 == LOW && FS2 == LOW)
    { 
         turn pump2 on 
         until FS1 != LOW && FS2 != HIGH
         then turn pump2 off again
    }
//move to the next thing... etc.

But how do i programm that "until"?

Thanks for your help!

First, let's make it readable...

uint8_t drainPump = 2; //pump2 emptying the basin
uint8_t fillPump = 3; // pump1 filling the basin
uint8_t methPump = 4; // device 1
uint8_t aerationPump = 5; // device 2
uint8_t stirringDevice = 10; //device 3
uint8_t floatSwitch1 = 11; //read voltage topFloatSwitch
uint8_t floatSwitch2 = 12; // read voltage bottomFloatSwitch
uint8_t topFloatSwitch = -1; //FS top
uint8_t bottomFloatSwitch = -1; //FS bottom

void setup() {
  pinMode(drainPump, OUTPUT);
  pinMode(fillPump, OUTPUT);
  pinMode(methPump, OUTPUT);
  pinMode(aerationPump, OUTPUT);
  pinMode(stirringDevice, OUTPUT);
  pinMode(floatSwitch1, INPUT);
  pinMode(floatSwitch2, INPUT);
  Serial.begin(9600);
}

void loop() {
  topFloatSwitch = digitalRead(floatSwitch1);
  bottomFloatSwitch = digitalRead(floatSwitch2);

  if (topFloatSwitch == LOW && bottomFloatSwitch == LOW)
  {
    digitalWrite(fillPump, HIGH);
  } else {
    digitalWrite(fillPump, LOW);
  }

  delay(1000);

  topFloatSwitch = digitalRead(floatSwitch1);
  bottomFloatSwitch = digitalRead(floatSwitch2);

  if (topFloatSwitch == LOW && bottomFloatSwitch == HIGH)
  {
    digitalWrite(fillPump, HIGH);
  } else {
    digitalWrite(fillPump, LOW);
  }
  delay(1000);

  topFloatSwitch = digitalRead(floatSwitch1);
  bottomFloatSwitch = digitalRead(floatSwitch2);

  if (topFloatSwitch == HIGH && bottomFloatSwitch == HIGH)
  {
    digitalWrite(stirringDevice, HIGH);
    delay(3000);
    digitalWrite(stirringDevice, LOW);
    delay(1000);
    digitalWrite(methPump, HIGH);
    delay(5000);
    digitalWrite(methPump, LOW);
    delay(1000);
    digitalWrite(aerationPump, HIGH);
    delay(3000);
    digitalWrite(aerationPump, LOW);
    delay(1000);
    digitalWrite(drainPump, HIGH);
  } else {
    digitalWrite(stirringDevice, LOW);
    digitalWrite(methPump, LOW);
    digitalWrite(aerationPump, LOW);
    digitalWrite(fillPump, LOW);
    digitalWrite(drainPump, LOW);
  }

  topFloatSwitch = digitalRead(floatSwitch1);
  bottomFloatSwitch = digitalRead(floatSwitch2);

  if (topFloatSwitch == LOW && bottomFloatSwitch == HIGH)
  {
    digitalWrite(drainPump, HIGH);
  } else {
    digitalWrite(drainPump, LOW);
  }
  delay(1000);
}

aarg: First, let's make it readable...

Thank you very much. Do you have an idea how i could do what i mentioned above?

Could somebody give me a hint on how to program the following?

when (topFloatSwitch == LOW && bottomFloatSwitch == LOW)
    { 
         turn fillPump on 
         until topFloatSwitch != LOW && bottomFloatSwitch != HIGH
         then turn fillPump off again
    }
//move to the next thing... etc.

Especially how i'd program it so it does that "until" step.

I'd greatly appreciate any tipps and help! Thank you very much

try looking at the pump's owns state too...

if (pumpOff && topFloatSwitch == LOW && bottomFloatSwitch == LOW)
{
  //turn fillPump on
}
if (!pumpOff && topFloatSwitch == HIGH && bottomFloatSwitch != HIGH)
{
  //turn filPump OFF
}