Exit the infinity while loop by pressing the button and continue with the switch element.

Joined
Apr 21, 2024
Messages
1
Reaction score
0
How can I solve it so that 'rainbowEffect()' function runs smoothly and when I press the button, it exits the while loop and continues in the 'switch' element.

#include <TinyDebug.h>

// Pinek definiálása
#define BUTTON_PIN PB4

#define RED_PIN PB2
#define GREEN_PIN PB1
#define BLUE_PIN PB0

int buttonState = HIGH;
int lastButtonState = HIGH;
int counter = 0;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;

void setup() {
pinMode(RED_PIN, OUTPUT);
pinMode(GREEN_PIN, OUTPUT);
pinMode(BLUE_PIN, OUTPUT);

pinMode(BUTTON_PIN, INPUT_PULLUP);
digitalWrite(RED_PIN, 0);
digitalWrite(GREEN_PIN, 0);
digitalWrite(BLUE_PIN, 0);
}

void loop() {
int reading = digitalRead(BUTTON_PIN);

if (reading != lastButtonState) {
lastDebounceTime = millis();
}

if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) {
buttonState = reading;

if (buttonState == LOW) {
counter++;

if (counter == 6) {
counter = 1;
}

switch (counter) {
case 1:
setColor(255, 0, 0); // Piros
break;
case 2:
setColor(0, 255, 0); // Zöld
break;
case 3:
setColor(0, 0, 255); // Kék
break;
case 4:
rainbowEffect();
break;
case 5:
setColor(0, 0, 0);
break;
}
}
}
}

lastButtonState = reading;
}

// Ez a függvény beállítja az RGB LED színét a megadott értékek alapján
void setColor(int red, int green, int blue) {
analogWrite(RED_PIN, red);
analogWrite(GREEN_PIN, green);
analogWrite(BLUE_PIN, blue);
}

// Ez a függvény létrehozza a szivárvány hatását
void rainbowEffect() {
int delayTime = 10; // Az átmenetek közötti késleltetési idő (milliszekundumban)
int increment = 1; // Színváltozás sebessége

while (digitalRead(BUTTON_PIN) == HIGH) { // Folyamatosan fut a szivárvány hatás
for (int hue = 0; hue < 360; hue += increment) {
float radHue = radians(hue);
int red = int(cos(radHue) * 127 + 128);
int green = int(cos(radHue + radians(120)) * 127 + 128);
int blue = int(cos(radHue + radians(240)) * 127 + 128);

analogWrite(RED_PIN, red);
analogWrite(GREEN_PIN, green);
analogWrite(BLUE_PIN, blue);

delay(delayTime);

if (buttonState == LOW) {
Debug.begin();
Debug.println(digitalRead(BUTTON_PIN));
}

}
}
}
 
Joined
Nov 24, 2022
Messages
80
Reaction score
7
GPT

"To ensure that the rainbowEffect() function runs smoothly and exits when you press the button, you can modify the function to periodically check the button state and exit the loop if the button is pressed. Here's how you can modify the rainbowEffect() function:

Code:
void rainbowEffect() {
    int delayTime = 10; // Transition delay time (in milliseconds)
    int increment = 1; // Color change speed
    
    while (true) { // Continuous rainbow effect loop
        for (int hue = 0; hue < 360; hue += increment) {
            float radHue = radians(hue);
            int red = int(cos(radHue) * 127 + 128);
            int green = int(cos(radHue + radians(120)) * 127 + 128);
            int blue = int(cos(radHue + radians(240)) * 127 + 128);
    
            analogWrite(RED_PIN, red);
            analogWrite(GREEN_PIN, green);
            analogWrite(BLUE_PIN, blue);
    
            delay(delayTime);
            
            // Check button state and exit if pressed
            if (digitalRead(BUTTON_PIN) == LOW) {
                setColor(0, 0, 0); // Turn off LED
                return; // Exit the function
            }
        }
    }
}

In this modified version, I replaced the condition digitalRead(BUTTON_PIN) == HIGH with true in the while loop to ensure the rainbow effect continuously runs. Inside the loop, after setting the LED colors, it checks if the button is pressed. If the button is pressed (digitalRead(BUTTON_PIN) == LOW), it turns off the LED colors using the setColor(0, 0, 0) function and exits the rainbowEffect() function using return. This way, pressing the button will exit the rainbow effect loop and continue executing the rest of the code.
 
Joined
Jul 4, 2023
Messages
368
Reaction score
41
I do not recommend using a delay because this function stops code execution, which makes clicking the button not work smoothly (maybe in this case it does not matter much because delayTime is only set to 10 milliseconds, but IMO it's good to know). Fortunately, a more advanced solution based on the millis function comes to our aid. Thanks to it, Arduino can perform several tasks "simultaneously".

[ Why You Shouldn’t Always Use the Arduino Delay Function ]

Try e.g. like this using millis
C++:
void rainbowEffect() {
  int delayTime = 10; // Transition delay time (in milliseconds)
  int increment = 1; // Color change speed
 
  while (true) { // Continuous rainbow effect loop
    for (int hue = 0; hue < 360; hue += increment) {
      float radHue = radians(hue);
      int red = int(cos(radHue) * 127 + 128);
      int green = int(cos(radHue + radians(120)) * 127 + 128);
      int blue = int(cos(radHue + radians(240)) * 127 + 128);
 
      analogWrite(RED_PIN, red);
      analogWrite(GREEN_PIN, green);
      analogWrite(BLUE_PIN, blue);
 
      // delay(delayTime);
      // Check button state and exit if pressed
      if (delayLoop(delayTime)) {
        setColor(0, 0, 0); // Turn off LED
        return; // Exit the function
      }
    }
  }
}

boolean delayLoop(unsigned int delayInterval) {
  unsigned long startMillis = millis();

  do {
    if (digitalRead(BUTTON_PIN) == LOW) return true;
  } while (millis() - startMillis < delayInterval);

  return false;
}
 
Last edited:

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,117
Latest member
Matilda564
Top