Button to exit a running loop

Hi!

I have a very basic circuit setup:

  • A button connected to pin 2
  • An LED connected to pin 9

Desired Functionality:

When the button is pressed, the user can toggle through 4 LED patterns.

The Problem:

Once the first fade pattern begins, the user has to wait until it has finished running before the button can toggle to the next pattern. What I want is that the button push will move to pattern 2, even if pattern 1 has already started.

Attempted Solutions:

I’ve tried to insert a while function in a couple of places i.e while buttonstate =lastbuttonstate, but that doesn’t seem to work.

Here’s the code: (I realize all the fadeloops are the same right now, they will different in the working model)

//PROBLEM: The fade function has to complete a full loop before allowing toggle to next one


const int  buttonPin = 2;    // the pin that the pushbutton is attached to
const int ledPin = 9;       // the pin that the LED is attached to

// Variables will change:
int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

int brightness = 0;    // how bright the LED is
int firstFadeAmount = 5;    // how many points to fade the LED by
int secondFadeAmount = 5;    // how many points to fade the LED by


void setup() {
  // initialize the button pin as a input:
  pinMode(buttonPin, INPUT);
  // initialize the LED as an output:
  pinMode(ledPin, OUTPUT);
  // initialize serial communication:
  Serial.begin(9600);
}


void loop() {
  // read the pushbutton input pin:
  buttonState = digitalRead(buttonPin);

  if (buttonState != lastButtonState) {
    if (buttonState == HIGH) {
      buttonPushCounter++;
    } 
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  lastButtonState = buttonState;
  
  while (buttonPushCounter = lastButtonState) {
  if (buttonPushCounter == 1 && buttonState == HIGH) {
    fadeLoop1(); 
    delay(50);//JP Edit 
  } 
  
  else if (buttonPushCounter == 2 && buttonState == HIGH) {
    fadeLoop2(); 
    delay(50); 
  } 
  
  else if (buttonPushCounter == 3 && buttonState == HIGH) {
    fadeLoop3(); 
    delay(50); 
  } 
  
  else if (buttonPushCounter == 4 && buttonState == HIGH) {
    fadeLoop4(); 
    delay(50); 
  } 
  
  }
  if (buttonPushCounter == 4) {  //Resets back to zero after 4 presses
     buttonPushCounter = 0;
  }
     
     
}

void fadeLoop1()  
  {
  for (int i = 0; i < 100; i++) {  //Set the length of the first fading cycle 
  analogWrite(ledPin, brightness);
  brightness = brightness + firstFadeAmount;
  if (brightness <= 0 || brightness >= 255) {
    delay(1000);                  //Sets the hold at the top and bottom of the cycle 
    firstFadeAmount = -firstFadeAmount;
  }
    delay(100);
  }
  for (int i = 0; i < 100; i++) {  //Set the length of second fading cycle
  analogWrite(ledPin, brightness);
  brightness = brightness + secondFadeAmount;
  if (brightness <= 0 || brightness >= 255) {
    secondFadeAmount = -secondFadeAmount;
  }
    delay(30);
  }

  digitalWrite(ledPin, LOW);
  }




void fadeLoop2()  
  {
  for (int i = 0; i < 100; i++) {  //Set the length of the first fading cycle 
  analogWrite(ledPin, brightness);
  brightness = brightness + firstFadeAmount;
  if (brightness <= 0 || brightness >= 255) {
    delay(1000);                  //Sets the hold at the top and bottom of the cycle 
    firstFadeAmount = -firstFadeAmount;
  }
    delay(100);
  }
  for (int i = 0; i < 100; i++) {  //Set the length of second fading cycle
  analogWrite(ledPin, brightness);
  brightness = brightness + secondFadeAmount;
  if (brightness <= 0 || brightness >= 255) {
    secondFadeAmount = -secondFadeAmount;
  }
    delay(30);
  }

  digitalWrite(ledPin, LOW);
  }



void fadeLoop3()  
  {
  for (int i = 0; i < 100; i++) {  //Set the length of the first fading cycle 
  analogWrite(ledPin, brightness);
  brightness = brightness + firstFadeAmount;
  if (brightness <= 0 || brightness >= 255) {
    delay(1000);                  //Sets the hold at the top and bottom of the cycle 
    firstFadeAmount = -firstFadeAmount;
  }
    delay(100);
  }
  for (int i = 0; i < 100; i++) {  //Set the length of second fading cycle
  analogWrite(ledPin, brightness);
  brightness = brightness + secondFadeAmount;
  if (brightness <= 0 || brightness >= 255) {
    secondFadeAmount = -secondFadeAmount;
  }
    delay(30);
  }

  digitalWrite(ledPin, LOW);
  }



void fadeLoop4()  
  {
  for (int i = 0; i < 100; i++) {  //Set the length of the first fading cycle 
  analogWrite(ledPin, brightness);
  brightness = brightness + firstFadeAmount;
  if (brightness <= 0 || brightness >= 255) {
    delay(1000);                  //Sets the hold at the top and bottom of the cycle 
    firstFadeAmount = -firstFadeAmount;
  }
    delay(100);
  }
  for (int i = 0; i < 100; i++) {  //Set the length of second fading cycle
  analogWrite(ledPin, brightness);
  brightness = brightness + secondFadeAmount;
  if (brightness <= 0 || brightness >= 255) {
    secondFadeAmount = -secondFadeAmount;
  }
    delay(30);
  }

  digitalWrite(ledPin, LOW);
  }

I've tried to insert a while function in a couple of places i.e while buttonstate =lastbuttonstate, but that doesn't seem to work.

Why? In if statement, to exit the loop would have been far more appropriate.

I realize all the fadeloops are the same right now, they will different in the working model

Correct. They will be non-existent.

You, like everyone else that has painted themselves into a corner by writing blocking functions, need to start over, and use a state machine and write non-blocking code. The ONLY loop you will have is loop().

You, like everyone else that has painted themselves into a corner by writing blocking functions, need to start over, and use a state machine and write non-blocking code. The ONLY loop you will have is loop().

Thank you, but that is way too advanced for me.

Can anyone offer a more basic solution?

NelsonRRR:
Can anyone offer a more basic solution?

No, there are only more complex ways. There are plenty of examples and tutorials for this technique. Start with:

Arduino IDE: File --> Examples --> 02.Digital --> BlinkWithoutDelay
Demonstration code for several things at the same time
Using millis() for timing. A beginners guide

Read those and attempt to implement the technique in your project. If you have problems, post complete code here along with description of what's going wrong. Folks here will help you out.

Thanks, this is similar to the advice I've found elsewhere.

I was hoping I could just edit a line or two, but the advice seems to be to use miilis ().

Check your while() syntax again.

Right...

Good spot.

Will give it a try when back in the office.