How do I stop an "if piece" looping

Hello, I have a code where I want an led to fade in when a switch is turned on, and fade down when the switch is turned back off.
My code looks like this

void loop () {
    buttonState = digitalRead( buttonPin);
    if (buttonState == HIGH) {
        
          for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) {
          analogWrite(ledPin, fadeValue);
          delay(30);
           } 
    
       }

    if (buttonState == LOW) {
        analogWrite (ledPin, 0);
       } 
    
  }

The problem is that when I turn the switch, the led starts fading on, which is good, but then it, turns off, fades up again and turns off again etc.
I was hoping any of you knew how I could get the “if command” to be executed only once, and then wait until the next “if command” is due to be executed.
All help is much appreciated.

It would seem that, next time through loop() it detects that your switch is still high. Use serial print to add a line to each branch of the if, to display buttonState so you can see what it is.

How is the switch wired?- maybe it's a spurious high.

Maybe you should use a pulldown resistor to ensure it's low when not pressed. Better yet use the internal pullups, but that will reverse your high/low logic to low/high which is no biggy.

BTW, it's better and forum sop to post all the code, not just the bit where you think the problem is.

I will try the serial print when I get access to my computer to see if the problem is as you suspect.
The switch is wired with a pull down resistor, and everything works perfectly in the hardware department.
Here’s the entire piece of code with the two extra leds as well

const int redPin = 5;
const int greenPin = 6;
const int ledPin = 9;
const int buttonPin = 2;
int buttonState = 0;

void setup () {
    pinMode (ledPin, OUTPUT);
    pinMode (redPin, OUTPUT);
    pinMode (greenPin, OUTPUT);
    pinMode (buttonPin, INPUT);
    digitalWrite (redPin, LOW);
    digitalWrite (greenPin, LOW);
   } 

void loop () {
    buttonState = digitalRead( buttonPin);
    if (buttonState == HIGH) {
        digitalWrite (redPin, LOW);
        digitalWrite (greenPin, HIGH);
           for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) {
           analogWrite(ledPin, fadeValue);
           delay(30);
           } 
    
       }
    
    if (buttonState == LOW) {
        digitalWrite (redPin, HIGH);
        digitalWrite (greenPin, LOW);
           for(int fadeValue = 255 ; fadeValue >= 0; fadeValue -=5) { 
           analogWrite(ledPin, fadeValue);
           delay(30);
           } 
      } 
}

You should separate detecting the switch code from the fading up and down code, and then only do the fade when the switch has changed.

So the detect switch change code sets a variable, and the fade up/down code only runs when it is set but clears the variable when it runs.

In your case, make the variable type char which is good for -128 to +127 and fade up if it's +1, fade down when it's -1, don't do either when it is 0.

There is another maybe concern about switch 'bounce' that I think your fade time will cover up nicely.

Switch/button bounce happens with contact-meets-contact switches. In fast-react code it can drive you nuts. For some number of millis the initial contact will have a series of on/off 'bounces'. If you write a short sketch that prints a single character for each on or off then you'll see a few characters for one switch press, but maybe not every switch press. So for those switches/buttons you put in code that waits for the switch to have the same state for as long as it takes (some are better, some are worse) before passing the rest of your code a final state.

Capacitive switches and light-interrupt switches generally don't do this. Switches with hardware debounce built in don't and there will be others that don't. I use jumpers that I ground as switches and they definitely do! Code I write for jumpers as switches will run correctly with just about anything.

Read the sensor with one piece of code and abstract that into a variable value that you action code triggers from and you can do things like one push/release turns it on and the next turns it off or maybe the next makes it faster or some other result. With few buttons you can do many things, limited by your imagination and abilities and hardware only.

I was hoping any of you knew how I could get the “if command” to be executed only once, and then wait until the next “if command” is due to be executed.

if (buttonState == HIGH) {
  for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 5) {
    analogWrite(ledPin, fadeValue);
    delay(30);
  }
  while (buttonState == HIGH);
}

dlloyd:
I was hoping any of you knew how I could get the “if command” to be executed only once, and then wait until the next “if command” is due to be executed.

if (buttonState == HIGH) {

for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 5) {
   analogWrite(ledPin, fadeValue);
   delay(30);
 }
 while (buttonState == HIGH);
}

You make one IF to read the button and set a value in a variable to say if the button has changed state.
You make another IF to do the fade if the variable says state has changed and then clear the variable.
You do NOT control the fade directly from the button unless you like the way it works now.

You make one IF to read the button and set a value in a variable to say if the button has changed state. You make another IF to do the fade if the variable says state has changed and then clear the variable. You do NOT control the fade directly from the button unless you like the way it works now.

Agreed. Just a small baby-step, giving the button full control of program flow (my interpretation of the OP's requirements).

He only wants the fade up/down to happen when the switch changes. The code now fades up/down on switch state which is why it keeps cycling as Jim pointed out.

He only wants the fade up/down to happen when the switch changes.
The code now fades up/down on switch state which is why it keeps cycling as Jim pointed out.

I had already tested the code on the Due using the print monitor to view the fadeValue .
It ramps up just once and stops.

Of course, more code required for fade down … argh … here it is (untested):

if (buttonState == HIGH) {   // fade up once
  for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 5) {
    analogWrite(ledPin, fadeValue);
    delay(30);
  }
  while (buttonState == HIGH);  // wait until LOW
}
if (buttonState == LOW) {   // fade down once
  for (int fadeValue = 255 ; fadeValue > 0; fadeValue -= 5) {
    analogWrite(ledPin, fadeValue);
    delay(30);
  }
  while (buttonState == LOW); // wait until HIGH
}

That's nice if you like blocking code and won't be doing anything else in the sketch. Otherwise......

I don't want to write the code even though it is simple. I'd rather see the OP figure it out.

I got everything working now, thanks to making the arduino read whether the button had been switched, and not which state it was in.
Here´s the final code which works brilliantly

const int redPin = 5;
const int greenPin = 6;
const int ledPin = 9;
const int buttonPin = 2;
int buttonState = 0;
int lastButtonState = 0;
int justPressed = 0;

void setup () {
  pinMode (ledPin, OUTPUT);
  pinMode (redPin, OUTPUT);
  pinMode (greenPin, OUTPUT);
  pinMode (buttonPin, INPUT);
  digitalWrite (redPin, LOW);
  digitalWrite (greenPin, LOW);
}
void loop () {
  buttonState = digitalRead (buttonPin);
  
  if (buttonState != lastButtonState) {
    if (buttonState == HIGH) {
          digitalWrite (redPin, LOW);
          digitalWrite (greenPin, HIGH);
          for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) {
            analogWrite(ledPin, fadeValue);
            delay(30);
          }
        }
        else {
          digitalWrite (redPin, HIGH);
          digitalWrite (greenPin, LOW);
          for(int fadeValue = 255 ; fadeValue >= 0; fadeValue -=5) {
            analogWrite(ledPin, fadeValue);
            delay(30);
    }
    }
  }

  
  lastButtonState = buttonState;
}

Thanks to everyone for their help, solved my problem within hours XD