Testing for a condition in a while loop

So I have this code that runs in two while loops. When a certain sensor (analog pin 4) is on one loop runs, when it's off another loop runs. Seen here-

int gatePin = 2;
int clampPin = 4;
int machinePin = 6;
int threshold = 500;
int threshold2 = 600;
int analogPin1 = A0;
int analogPin2 = A2;
int analogPin3 = A4;
int analogPin4 = A5;
int val = 0;
int x = 0;
void setup() {
  // defines each piin as an input or output
 pinMode (gatePin, OUTPUT);
 pinMode (clampPin, OUTPUT);
 pinMode (machinePin, OUTPUT);
 pinMode (analogPin1, INPUT);
 pinMode (analogPin2, INPUT);
 pinMode (analogPin3, INPUT);
 pinMode (analogPin4, INPUT);
  Serial.begin(9600);
}
void loop() {
 int analogValue4 = analogRead(analogPin4);
 //this loop is started when analog pin 4 is on
 while (analogValue4 >= threshold){
  
  int analogValue1 = analogRead(analogPin1);

  // if the analog value is high enough, turn on gate
  if (analogValue1 < threshold2) {
    digitalWrite(gatePin, HIGH);
  } else {
    digitalWrite(gatePin, LOW);
  }
  delay(1);

 {

  int analogValue2 = analogRead(analogPin2);

  // if the analog value is high enough, turn on clamp
   if (analogValue2 > threshold) {
    delay(1);
    digitalWrite(clampPin, HIGH);
  } else {
    digitalWrite(clampPin, LOW);
  }
  delay(1);
}
{

  int analogValue3 = analogRead(analogPin3);
  // if the analog value is high enough, turn on machine
  if (analogValue3 > threshold) {
    digitalWrite(machinePin, HIGH);  //this machine is turned on by the didital output, but turned off by an outsde timer.
  } else {
    digitalWrite(machinePin, LOW);
  }
  delay(1);
}
break;
 }
// this while loop is started when analog pin 4 is off
while (analogValue4 < threshold){
  delay(1000);
  digitalWrite(gatePin, LOW);
  digitalWrite(clampPin, LOW);
  digitalWrite(machinePin, LOW);
  break;
}
}

What i need to get this to do is to wait in the second while loop while analog pin 4 is low, but then set all of the other digital pins to low when analog pin 4 goes back to high (something that the machine will do on it's own without the code.). The second while loop I have replicates this because the delay happens to match up with the timing of the machine, but I want to make this work without the delay so that the machine timing doesn't matter. The problem is that to put that pin reset in the first while loop violates the IF statements within the loop.

Anybody have any advice? -Thanks

You should avoid waiting in the Loop. Without running the loop, you cant figure out any change in the pin state.

I'm not sure I know what you mean.

  int analogValue4 = analogRead(analogPin4);
  //this loop is started when analog pin 4 is on
  while (analogValue4 >= threshold) {
  }

Since you don't change analogValue4 inside the while loop, once you enter the while loop with a value >= threshold the loop will never end. You would get better results with:

  // this loop will continue as long as analog pin 4 is 'on'
  while (analogRead(analogPin4) >= threshold) {
  }

It seems to work just as well with that change as without. Basically this analog pin 4 goe from on to off to on again. When it goes to on again I need to reset my whole process. I don't care how this happens, but I'm really new to programming so I don't really know what mechanic to use to do this. I thought maybe I could enter this second loop and then test for that condition to switch back, the problem is when it switches back it also puts me back in the other loop. needless to say I'm pretty stuck.

If there was a way to make the arduino perform a function when pin 4 goes from low to high that could work, but I don't know how to define that change of state.

erogbass:
If there was a way to make the arduino perform a function when pin 4 goes from low to high that could work, but I don't know how to define that change of state.

You do know that you can use A0-A5 as digital pins, right?

void loop() {
    static boolean previousState = digitalRead(A4);
    boolean state = digitalRead(A4)
    if (state == HIGH && previousState == LOW)  {
       // Do stuff when A4 goes from LOW to HIGH
    }
    previousState = state;
}

Haha no I did not! Wow that is really good to know. Let me seen what I can come up with here.

Ok so that did compile, but I think the problem is that that IF statement then conflicts with the previous IF statements since those are still true at the point where that transition happens. Here is what it looks like now (pleas ignore what I've commented out).

int gatePin = 2;
int clampPin = 4;
int machinePin = 6;
int threshold = 500;
int threshold2 = 600;
int analogPin1 = A0;
int analogPin2 = A2;
int analogPin3 = A4;
int analogPin4 = A5;
int val = 0;
int x = 0;
void setup() {
  // defines each piin as an input or output
 pinMode (gatePin, OUTPUT);
 pinMode (clampPin, OUTPUT);
 pinMode (machinePin, OUTPUT);
 pinMode (analogPin1, INPUT);
 pinMode (analogPin2, INPUT);
 pinMode (analogPin3, INPUT);
 pinMode (analogPin4, INPUT);
  Serial.begin(9600);
}
void loop() {
   int analogValue2 = analogRead(analogPin2);
 int analogValue4 = analogRead(analogPin4);
 //this loop is started when analog pin 4 is on
 //while (analogValue4 >= threshold){
  
  int analogValue1 = analogRead(analogPin1);

  // if the analog value is high enough, turn on gate
  if (analogValue1 < threshold2) {
    digitalWrite(gatePin, HIGH);
  } else {
    digitalWrite(gatePin, LOW);
  }
  delay(1);

 {

  // if the analog value is high enough, turn on clamp
   if (analogValue2 > threshold) {
    delay(1);
    digitalWrite(clampPin, HIGH);
  } else {
    digitalWrite(clampPin, LOW);
  }
  delay(1);
}
{

  int analogValue3 = analogRead(analogPin3);
  // if the analog value is high enough, turn on machine
  if (analogValue3 > threshold) {
    digitalWrite(machinePin, HIGH);  //this machine is turned on by the didital output, but turned off by an outsde timer.
  } else {
    digitalWrite(machinePin, LOW);
  }
  delay(1);
  /*if (analogValue3 > threshold && analogValue4 > threshold && analogValue2 > threshold && analogValue1 < threshold2) {
    delay(1);
  digitalWrite(gatePin, LOW);
  digitalWrite(clampPin, LOW);
  digitalWrite(machinePin, LOW);
  }*/
}
//break;
 //}
// this while loop is started when analog pin 4 is off
/*while (analogValue4 < threshold){
  delay(1000);
  digitalWrite(gatePin, LOW);
  digitalWrite(clampPin, LOW);
  digitalWrite(machinePin, LOW);
  break;
}*/
static boolean previousState = digitalRead(A4);
    boolean state = digitalRead(A4);
    if (state == HIGH && previousState == LOW)  {
       // Do stuff when A4 goes from LOW to HIGH
  digitalWrite(gatePin, LOW);
  digitalWrite(clampPin, LOW);
  digitalWrite(machinePin, LOW);
    }
    previousState = state;
}

The first half works, but the reset still does not.

Regarding your original code

Your while loops are only executed once because you use break to break out of them; you could just as well have used an if statement.

With the code from reply #8

  static boolean previousState = digitalRead(A4);
  boolean state = digitalRead(A4);
  if (state == HIGH && previousState == LOW)  {
    ...
    ...

How big do you think that the chances are that state and previousState are different? previousState should not be read from the pin but initially be set to the 'default' value; low in this case.

What you may be missing here is that the current state through the first half of the process is HIGH, it's only LOW for a short time (maybe 4 seconds) before going back to HIGH. So if this reads the way i think it does then previous state will at times be LOW and at times be HIGH. If it was the case that it was only at high when the process was over then this would all be very simple.

You read the pin in very quick succession. If the button does not bounce, both readings will be the same (either high or low); else there is a small chance that they differ.

You should not assign the result of the read to the previousState. Looking at your code, your button is wired to Vcc (and hopefully has a pull-down resistor).

  static boolean previousState = LOW;
  boolean state = digitalRead(A4);
  if (state == HIGH && previousState == LOW)  {
    ...
    ...
  }
  previousState = state;
}

The initial previousState is LOW; when you press the button state goes high and the if statement will see the difference and act accordingly.
Next previousState and state will be made the same (high).

Next iteration, previousState will still be high, state will be whatever and the if condition will not be satisfied.

Eventually the button will be released and previousState will become low.

Next iteration, previousState will still be low, state will be whatever and the if condition will or will not be satisfied.

sterretje:
With the code from reply #8

static boolean previousState = digitalRead(A4);

boolean state = digitalRead(A4);
 if (state == HIGH && previousState == LOW)  {
   ...



How big do you think that the chances are that state and previousState are different?

Note the 'static' keyword. I couldn't be sure if the state at sketch start would likely be HIGH or LOW. If I picked one and got it wrong then some code will execute. This way it picks up the current value when the static variable is initialized.

@johnwasser
I was aware of the static keyword. I did not expect it to be dynamically assigned once-off at run time when functions come into play. I had to test it (used below sketch); learned something this morning :wink:

void setup()
{
  Serial.begin(9600);
  pinMode(2, INPUT_PULLUP);
}

void loop()
{
  static byte buttonState = digitalRead(2);
  Serial.println(buttonState);
  delay(500);
}

To my surprise, it always prints the initial state of the button.

@erogbass
Apologies for misinforming you.