Exiting the for loop after all conditions were satisfied

Hello everyone,

I'm making this code where i'm controlling multiple valves in response to multiple respective load cells (load cell is holding a bottle that is being filled by the valve)
Now I have many valves, however only based on the user input the number of valves and load cells will be activated.
To make it clear here is my code:


//somewhere in void loop()
    digitalWrite(waterpumpA, HIGH); //basically the pump will start here
    for (int i = 0; i < numberofbottles; i++) { 
//numberofbottles is a number that was inserted by the
// user through a numberpad and an lcd
      int loadresult[numberofbottles]; 
//to save the value of the load cell after 
//including the calibration factor
        loadresult[i] = -results[i] / 6250; 
//calibration factor for the rear load cells
        if (loadresult[i] < volumeofwater) { 
//volume of water is basically the desired weight that 
//the user inserted through the numpad previously 
          watervalvestart[i]; //function that will open the valve
        }
        else if (loadresult[i] > volumeofwater) {
          watervalvestop[i]; //function that will close the valve 
        }
// now, here i want to tell the software that AFTER
// all desired valves have been closed to switch off the pump and move to another state. 
// i don't know how much is the total number of valves because every time
// there will be a different input and i want the software to work accordingly 
    }

So basically the software will work like this
1- check every load cell and compare it to the desired input
2- if desired input is achieved at the load cell then close the valve but keep the pump running since other valves might still need to keep working
3- after all load cells reached the desired weight, switch off the pump and move to the next state

I'm just having an issue in structuring that last statement, how would i write that?
Any ideas?

Thanks in advance

You need to use a while structure not a for loop.

1 Like

but in while structure, will i still be able to control each valve individually according to the respective load cell value?

Yes, what is the problem?

1 Like

Moved to programming questions.

I just don't know how to hahaha

Like how will i tell the software to do all that?
Should I place a for loop inside the while loop?
And also how will I tell the software that after ALL the load cells has reached the value then move to the next state

You are already in a loop (loop()), I'm not sure you need another loop at all. Just let loop() loop and do what you need to do in there.

Better still, create a separate function with the code and call it from the loop() function, tidier and easier to understand and debug that way.

1 Like

I did the for loop so that I can use the i, since i don't know total number and it will be based on numberofbottles variable

You're definitely right, i will apply that later

No.

Have you looked up the definition of the while?
https://www.arduino.cc/reference/en/language/structure/control-structure/while/
It has a condition in the brackets next to it and it will continue until that condition is met.

You have a variable that keeps track of what load cell / valve you are using. The condition attached the while will be the number you are using is equal to the number you have. You set this variable to zero before the while, and increment it every time the while loop goes round.

No, to make it clear post ALL your code.

1 Like

An example of a while loop with multiple conditions

#include <PrintBin.h>
/*
  printBin(var);
  printBinln(var);
  printBinBytes(var);
  printBinBytesln(var);
*/

void setup()
{
  Serial.begin(115200);
  byte x = 0;
  byte y = 0;
  while (x < 100 && y < 100)
  {
    x = x + random(8);
    y = y + random(8);
    Serial.print("x = ");
    Serial.println(x);
    Serial.print("y = ");
    Serial.println(y);
    Serial.println();
    delay(200);
  }
  Serial.println("all done");
}

void loop()
{
}

NOTE : This may still not be the best way to do what you want depending on what else your sketch is doing

1 Like

The full code is not complete yet. And i'm afraid it will create some confusion.

So basically, using the while loop I will do this:

int i = 0;
while (i<numderofbottles && loadresult[i] < volumeofwater) 
{
digitalWrite(waterpumpA, HIGH); 
watervalvestart[i]; 
i++;
}

I'm sure this is not how i'm supposed to write it.
Because when it reaches the value of numberofbottles the while loop won't work anymore and i need it to keep working to keep filling until all of the load cells reach the desired value.
I'm still a beginner with arduino, please excuse me.

The for loop was helping me to keep in checking all the load cells and react to their values individually, I'm not sure how to do that in the while loop

Then you write enough of the code to show the problem.

No the while loop will only terminate when i is equal to the numderofbottles AND
the loadresult[i] < volumeofwater, what ever that means.

The big problem here is that you have not explained exactly what you want to do. I get that you have a number of bottles to fill, but what is the other bit with the valves and load cells, what do you want to do here?

1 Like

There is a pump connected to the main tank (water), and connected to several valves (which are connected to nozzles). Each nozzle is placed on top of the load cell.
The user will put a small bottle on each load cell (not necessarily all load cells) to fill and then input the number of bottles he desires to fill. and then he will input the desired weight to be filled (one value).
Now the software will do this:

1- ask about the number of bottles (DONE)
2- ask about the desired weight (DONE)
3- start the pump and open valves according to the number of bottles (In my code above)
4- once any of the activated load cells reaches the desired weight close the valve supplying water to it (in my code above)
5- once I know all the valves have been closed again I want to switch off the pump and move to the next step (Here is my problem)

volumeofwater is basically the desired weight

this is going to be true because the i++ will keep increasing until it reached numberofbottles but that doesn't mean the desired weight have been achieved

You know what I will post my full code in the next comment

here is the full code, (incomplete)

#include <Keypad.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "HX711-multi.h"
LiquidCrystal_I2C lcd(0x27, 16, 2); // Set the LCD address to 0x27 for a 16 chars and 2 line display


const byte ROWS = 4;
const byte COLS = 4;
char hexaKeys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {23, 25, 27, 29};
byte colPins[COLS] = {31, 33, 35, 37};
Keypad kpd = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);



#define CLK 49      // clock pin to the load cell amp
#define DOUT1 A0   // data pin to the first LCA
#define DOUT2 A1  // data pin to the second LCA
#define DOUT3 A2 // data pin to the third LCA
#define DOUT4 A3 // data pin to the forth LCA
#define DOUT5 A4   // data pin to the fifth LCA
#define DOUT6 A5   // data pin to the sixth LCA
#define DOUT7 A6   // seventh 
#define DOUT8 A7   // back load cell 1
#define DOUT9 A8   // back load cell 2

#define BOOT_MESSAGE "MIT_ML_SCALE V0.8" //boot message

#define TARE_TIMEOUT_SECONDS 4 //4 seconds while tare 

byte DOUTS[9] = {DOUT1, DOUT2, DOUT3, DOUT4, DOUT5, DOUT6, DOUT7, DOUT8, DOUT9}; //identify the HX711 modules

#define CHANNEL_COUNT sizeof(DOUTS)/sizeof(byte) //how many hx711 are connected 

long int results[CHANNEL_COUNT]; //number of modules is saved to results

HX711MULTI scales(CHANNEL_COUNT, DOUTS, CLK); //telling the library about number of scales and how are they connected and where is clock connected
/////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
const int waterpumpA = 2; //the pump connected to the water tank
const int waterpumpB = 3;//the pump connected to the water tank
const int methpumpA = 4; //the pump connected to the other tank
const int methpumpB = 5; //the pump connected to the other tank
const int wvalve[] = {13, 14, 15, 16, 17, 18, 19}; //valves connected through a pipe to the water pump at one end and to a nozzle at the other
const int mvalve[] = {6, 7, 8, 9, 10, 11, 12}; //valves connected through a pipe to the other pump at one end and to a nozzle at the other
const int red[] = {28, 30, 32, 34, 36, 38, 40}; //rgb lights (red pins)
const int green[] = {42, 44, 46, 48, 39, 41, 43}; //rgb lights (green pins)
const int blue[] = {43, 45, 47, A14, A13, A12, A11}; //rgb lights (blue pins)



uint8_t state; //state machine
const uint8_t enternumber = 0;
const uint8_t enterwvolume = 1;
const uint8_t methadonevolume = 2;
const uint8_t waterturn = 3;
const uint8_t starting = 4;
const uint8_t bottleplacement = 5;
int numberofbottles = 0;
String volumeofwater; //here might be a potential error for the volume of fluids
String volumeofmethadone; //here might be a potential error for the volume of fluids



boolean startpumpbool;
boolean tankcheck[2]; //we got two tanks to check




void setup() {
  for (int i = 0; i < 7 ; i++) {
    pinMode(wvalve[i], OUTPUT);
    pinMode(mvalve[i], OUTPUT);
    pinMode(red[i], OUTPUT);
    pinMode(green[i], OUTPUT);
    pinMode(blue[i], OUTPUT);
    digitalWrite(wvalve[i], HIGH);
    digitalWrite(mvalve[i], HIGH);
    digitalWrite(red[i], HIGH);
  }
  state = starting;
}


void loop() {

  Serial.print("HI");

  //overhere we check the storage at the back and if it's less than 200 grams then we gotta refill

  if (state == starting) {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Checking storage");
    int loadresult[2];
    for (int i = 8; i < 9; i++) {
      loadresult[i] = -results[i] / 413; //calibration factor for the rear load cells
      if (loadresult[i] > 200) {
        tankcheck[i] = true;
      }
      else {
        tankcheck[i] = false;
      }
      Serial.print("tank" + String(i) + "=" + String(tankcheck[i]));
      Serial.print("  ");
      Serial.print( loadresult[i]);
      Serial.print( (i != scales.get_count() - 1) ? "\t" : "\n");
    }
    if (tankcheck[0] == false || tankcheck[1] == false) {
      refilltankloop();
    }
    else {
      state = enternumber;
    }
  }

  //here we ask the user to input the desired volume and number

  else if (state == enternumber) {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("No. of bottles");
    lcd.setCursor(0, 1);
    char key = kpd.getKey();
    if (key) {
      lcd.print(numberofbottles);
      if (key >= '0' && key <= '9') {
        numberofbottles += key;
      }
      else if (key == '*') {
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("No. of bottles");
        lcd.setCursor(0, 1);
        numberofbottles = "";
      }
      else if (key == '#') {
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Place bottles");
        lcd.setCursor(0, 1);
        lcd.print("Press#to confirm"
                  state = bottleplacement;
      }
    }
  }
  else if (state == bottleplacement) {
    for (int i = 6; i > (numberofbottles - 1); i--) {
      digitalWrite(red[i], LOW);
    }
    char key = kpd.getKey();
    if (key) {
      if (key == '#') {
        for (int i = 0; i < numberofbottles; i++) {
          digitalWrite(blue[i], HIGH);
        }
        tare();
        state = enterwvolume;
      }
    }
  }
  else if (state == enterwvolume) {
    char key = kpd.getKey();
    if (key) {
      lcd.print(volumeofwater);
      if (key >= '0' && key <= '9') {
        volumeofwater += key;
      }
      else if (key == '*') {
        lcd.clear();
        volumeofwater = "";
        lcd.setCursor(0, 0);
        lcd.print("Water volume:");
        lcd.setCursor(0, 1);
      }
      else if (key == '#') {
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Methadone volume:");
        lcd.setCursor(0, 1);
        state = methadonevolume;
      }
    }
  }
  else if (state == methadonevolume) {
    char key = kpd.getKey();
    if (key) {
      lcd.print(volumeofmethadone);
      if (key >= '0' && key <= '9') {
        volumeofmethadone += key;
      }
      else if (key == '*') {
        lcd.clear();
        volumeofmethadone = "";
      }
      else if (key == '#') {
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Dispensing...");
        state = waterturn;
      }
    }
  }
  else if (state == waterturn) {

    digitalWrite(waterpumpA, HIGH);
    for (int i = 0; i < numberofbottles; i++) {
      int loadresult[numberofbottles];
      loadresult[i] = -results[i] / 6250; //calibration factor for the front load cells
      if (loadresult[i] < volumeofwater.toint()) {
        watervalvestart[i];
      }
      else if (loadresult[i] > volumeofwater.toint()) {
        watervalvestop[i];
      }
    }
  }
}




//function for the rear tank is not enogh
void refilltankloop() {
  int loadresult[2];
  for (int i = 8; i < 9; i++) {
    loadresult[i] = -results[i] / 413; //calibration factor for the rear load cells
    if (loadresult[i] > 200) {
      state = enternumber;
    }
    else {
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Refill tank");
      pumpstop();
      valvestopall();
      startpumpbool = false;
      numberofbottles = "";
      volumeofwater = "";
      volumeofmethadone = "";
    }
  }

  //stop all pumps
  void pumpstop() {
    digitalWrite(pump1A, LOW);
    digitalWrite(pump1B, LOW);
    digitalWrite(pump2A, LOW);
    digitalWrite(pump2B, LOW);
  }

  //ensure close all valves
  void valvestopall() {
    for (int i = 0; i < 7; i++) {
      digitalWrite(wvalve[i], HIGH);
      digitalWrite(mvalve[i], HIGH);
    }
  }

  //to open the watervalves
  void watervalvestart(int num) {
    digitalWrite(wvalve[num], LOW);
  }

  //to close the watervalves

  void watervalvestop(int num) {
    digitalWrite(wvalve[num], HIGH);
  }


I have two conditions here

condition one: One is for each valve (When the load cell read the desired weight) To close the valve
condition two: And another one for the pump (When all load cells read the desired weight and the valves on top of them have closed) To switch off the pump and then move to another thing

I have managed to make a code for the first condition as shown in the original post, i'm having a trouble in adding a code to for the second condition

You are on a userforum not in a talk.

What exactly do you mean by "first condition" ? and what by "second condition"?
Without writing more details you force your potential users to invest much more time than nescessary because they have to read through a lot of postings to guess what first condition and second condition means.

best regards Stefan

1 Like

Sorry about that, i editted my comment

So one idea I have is

If I have understood right the user will give the number of bottles to fill at the start.
store this number in a variable.

Each time a valve is closed substract 1 from the variable. If the variable reached value zero
all bottles are filled ==> switch of the pump

best regards Stefan

1 Like

yes this is correct, you have understood the concept correctly

This idea is brilliant!
only small problem is how to write this in code?
I mean if I write a statement like
numberofbottles = numberofbottles-1;
under
the code that says

else if (loadresult[i] > volumeofwater) {
          watervalvestop[i]; //function that will close the valve 
        }

so it becomes

else if (loadresult[i] > volumeofwater) {
          watervalvestop[i]; //function that will close the valve 
numberofbottles = numberofbottles-1; 
        }

I cannot do this because as we loop we will go through all the valves again and the one that has reached the desired weight will still satisfy the condition (loadresult[i] > volumeofwater) so I will be subtracting again

How would I code so that it subtracts only once?