Pause a RGB LED in a loop whit a button

I’ve a small Arduino project. I need to build a color mixer with a RGB led.
That works fine and in the second step of the project I need to add a button.
The first time you push the button the color mixer should stop and when the button is hit for the second time, the mixer should continue where it was stopped.

When I push the button I only get a reaction, after the mixer loop starts again.

So how cab a pause the loop at the first hit and get it started at the second hit.

Can one of you give me some advice?

I use the following code

Code for the RGBLED:
//LED
const int ledPinRed = 9; //Red
const int ledPinGreen = 10; //Green
const int ledPinBlew = 11; //Blew
 
//Button
const int buttonPin = 2;
 
//Variable
boolean red = false;
int buttonStatus = 0;
int lastButtonState = 0;
 
int redIntensity = 0;
int greenIntensity = 0;
int blueIntensity = 0;
 
const int DISPLAY_TIME = 100; // In milliseconds
 
 
void setup()  {
 //DEBUG:
 Serial.begin(9600);
 //LED
 pinMode(ledPinRed, OUTPUT);    
 pinMode(ledPinGreen, OUTPUT);    
 pinMode(ledPinBlew, OUTPUT);      
 //BUTTON
 pinMode(buttonPin, INPUT);   
 //digitalWrite(buttonPin, HIGH);
}
 
 
 
void loop()  {
 buttonStatus = digitalRead(buttonPin);
 //Code for the button:
  if (buttonStatus != buttonStatus ) {
    if (buttonState == HIGH) {
//Pause the LED
    }
 
     for (greenIntensity = 0; greenIntensity <= 255; greenIntensity+=5) {
       redIntensity = 255-greenIntensity;
       analogWrite(ledPinGroen, greenIntensity);
       analogWrite(ledPinRood, redIntensity);
       delay(DISPLAY_TIME);
     }
 
     for (blueIntensity = 0; blueIntensity <= 255; blueIntensity+=5) {
       greenIntensity = 255-blueIntensity;
       analogWrite(ledPinBlauw, blueIntensity);
       analogWrite(ledPinGroen, greenIntensity);
       delay(DISPLAY_TIME);
     }
 
     // Cycle cycle from blue through to red
     // (In this loop we move from 100% blue, 0% red to 0% blue, 100% red)    
     for (redIntensity = 0; redIntensity <= 255; redIntensity+=5) {
       blueIntensity = 255-redIntensity;
       analogWrite(ledPinRood, redIntensity);
       analogWrite(ledPinBlauw, blueIntensity);
       delay(DISPLAY_TIME);
     }
 }
       delay(DISPLAY_TIME);

That line of code and the for loops are the culprits. While the for loops are executing the delay() happens and blocks the program from doing anything else.

So, what to do about it ?
A. The crude method
Read the button input inside the for loops and exit the loop if a button press is detected.

B. The smart method
Use the principle shown in the BlinkWithoutDelay example. It checks every time through loop() whether it is time for something to happen, such as changing the output to an LED and if not goes round loop() again. The smart part is that you can read the button input each time through loop() and act on it without waiting for the LED sequence to finish.

  if (buttonStatus != buttonStatus ) {

Really, now. What are the odds of that statement ever evaluating to true?

It looks like what you are trying to do is compare the current state of the switch to the previous state of the switch, while: 1) not doing it right 2) using crappy names 3) never storing the current state as the previous state

UKHeliBob:
That line of code and the for loops are the culprits. While the for loops are executing the delay() happens and blocks the program from doing anything else.

So, what to do about it ?
A. The crude method
Read the button input inside the for loops and exit the loop if a button press is detected.

B. The smart method
Use the principle shown in the BlinkWithoutDelay example. It checks every time through loop() whether it is time for something to happen, such as changing the output to an LED and if not goes round loop() again. The smart part is that you can read the button input each time through loop() and act on it without waiting for the LED sequence to finish.

Thanks for the answer. I tried the first method and the result is that the button works. The challenge is that the proces is stopped and after the second push the proces should continue.
This is my code for just one color:

//LED
const int ledPinRood = 9; //Rood
const int ledPinGroen = 10; //Groen
const int ledPinBlauw = 11; //Blauw

//Button
const int buttonPin = 2;

//Variable
int buttonStatus = 0;
int lastButtonState = 0;

int redIntensity = 0;
int greenIntensity = 0;
int blueIntensity = 0;

const int DISPLAY_TIME = 100; // In milliseconds


void setup()  { 
  //DEBUG:
  Serial.begin(9600);
  //LED
  pinMode(ledPinRood, OUTPUT);    
  pinMode(ledPinGroen, OUTPUT);    
  pinMode(ledPinBlauw, OUTPUT);      
  //BUTTON
  pinMode(buttonPin, INPUT);   
  //digitalWrite(buttonPin, HIGH); 
} 



void loop()  { 



  for (greenIntensity = 0; greenIntensity <= 255; greenIntensity+=5) {
    redIntensity = 255-greenIntensity;
    analogWrite(ledPinGroen, greenIntensity);
    analogWrite(ledPinRood, redIntensity);
    delay(DISPLAY_TIME);
   
    buttonStatus = digitalRead(buttonPin);
    if (buttonStatus != lastButtonState) {
      if(buttonStatus == HIGH) {  
        Serial.println("Ingedrukt");
        analogWrite(ledPinGroen, LOW);
        analogWrite(ledPinRood, LOW);
        delay(1000);
      } 
      //      else {
      //        analogWrite(ledPinGroen, greenIntensity);
      //        analogWrite(ledPinRood, redIntensity);
      //      }
    }
    lastButtonState = buttonStatus;
  }
}

I understand your description of the smart method, I don’t know how to build that code into the RGB proces.

In your program I don't actually see why pressing the button does anything apart from turning the red and green LEDs off for a second. When the for loop continues the sequence will pick up where it left off.

If you really want to use this method then you need to do a couple of things when the button is pressed. Save the current value of greenIntensity Exit the for loop

Then, outside the for loop, when the button becomes pressed start the loop again with greenIntensity set to the value that it had when you exited the loop.

As you can see this is getting rather messy but could be made to work if you persisted with it.

The smart method may seem complicated at first but it is not. Here is an outline of how it would work to do what your example program does.

intensity = 0
DISPLAY_TIME = 100
startTime = 0
running = true

start of loop()
  if running = true                           //only do this if currently running a sequence
    write to the LEDs based on intensity
    if millis() - startTime >= DISPLAY_TIME  //time to change colour
      startTime = millis()                   //save the start time     
      increment intensity
      if intensity > 255                     //put intensity back to zero
        intensity = 0
      end if    //end of intensity adjustment
    end if      //end of colour change
  end if        //end of test for sequence running
  
  if the button becomes pressed
    running = !running      //stop or start the sequence
  end if
end of loop()

Dear.. Thanks for tips. I’ve them and still have a change lance.

To make it simple I’ve used one color. The first time it works, afterwards the leds starts blinking. Could you give me some advice? Thanks in advance.

My code so far:

//LED
const int ledPinRood = 9; //Rood
const int ledPinGroen = 10; //Groen
const int ledPinBlauw = 11; //Blauw

//Button
const int buttonPin = 2;

//Variable
int buttonStatus = 0;
int lastButtonState = 0;

int intensity = 0;
int startTime = 0;
boolean running = true;

int redIntensity = 0;
int greenIntensity = 0;
int blueIntensity = 0;


const int DISPLAY_TIME = 100; // In milliseconds


void setup()  { 
  //DEBUG:
  Serial.begin(9600);
  //LED
  pinMode(ledPinRood, OUTPUT);    
  pinMode(ledPinGroen, OUTPUT);    
  pinMode(ledPinBlauw, OUTPUT);      
  //BUTTON
  pinMode(buttonPin, INPUT);   
  //digitalWrite(buttonPin, HIGH); 
} 



void loop()  { 
  //only do this if currently running a sequence
  if(running == true) { 
    //write to the LEDs based on intensity
    //time to change colour
    if(millis() - startTime >= DISPLAY_TIME) {  
      //save the start time     
      startTime = millis();        
      intensity = intensity + 5;      
      //intensity+=5;
      Serial.println(intensity);
      if(intensity >= 255) {   
        //put intensity back to zero        
        intensity = 0;
      }
      //How to loop touch the all RGB LED??
      // is this write?
      analogWrite(ledPinGroen, intensity);
    }

  }

  buttonStatus = digitalRead(buttonPin);
  Serial.println(buttonStatus);
  if (buttonStatus != lastButtonState) {
    if(buttonStatus == HIGH) {    
      Serial.println("Ben ingedrukt");
      delay(200);            
      if(running == true) {
        running = false;
      } 
      else {
        running = true;
      }
    }
    lastButtonState = buttonStatus;
  }
}

I've them and still have a change lance.

      // is this write?
      analogWrite(ledPinGroen, intensity);

It is correct.

Hey,

Thanks for your input. I went on holidays and again active with the RGB led. I’ve tried to get everthing in one loop using if statements, to be able the use the button. The challenge I have is how to define the start. I’m using the following code and it almost works. What is wrong with the way I think?

//LED
const int ledPinRood = 9; //Rood
const int ledPinGroen = 10; //Groen
const int ledPinBlauw = 11; //Blauw

//Button
const int buttonPin = 2;

//Variable
int buttonStatus = 0;
int lastButtonState = 0;

//int intensity = 0;
int startTime = 0;
boolean running = true;

int redIntensity = 255;
int greenIntensity = 0;
int blueIntensity = 0;


const int DISPLAY_TIME = 100; // In milliseconds


void setup()  { 
  //DEBUG:
  Serial.begin(9600);
  //LED
  pinMode(ledPinRood, OUTPUT);    
  pinMode(ledPinGroen, OUTPUT);    
  pinMode(ledPinBlauw, OUTPUT);      
  //BUTTON
  pinMode(buttonPin, INPUT);   
  //digitalWrite(buttonPin, HIGH); 
} 



void loop()  { 

  if(running == true) { 
    //write to the LEDs based on intensity
    //time to change colour
    if(millis() - startTime >= DISPLAY_TIME) {  
      //save the start time     
      startTime = millis();        
            
      if(redIntensity <= 255 && greenIntensity >=0 ) {
        greenIntensity+=5;
        redIntensity -=5;
      }
      analogWrite(ledPinGroen, greenIntensity);
      analogWrite(ledPinRood, redIntensity);
      analogWrite(ledPinBlauw, blueIntensity);
      
      
      if(redIntensity <= 0 && greenIntensity >= 255) {
        greenIntensity -= 5;
        blueIntensity += 5;
        redIntensity = 0;
      }
      analogWrite(ledPinGroen, greenIntensity);
      analogWrite(ledPinRood, redIntensity);
      analogWrite(ledPinBlauw, blueIntensity);
      
      if(greenIntensity <= 0 && blueIntensity >= 255) {
        greenIntensity = 0;
        blueIntensity -= 5;
        redIntensity += 5;
      }

      analogWrite(ledPinGroen, greenIntensity);
      analogWrite(ledPinRood, redIntensity);
      analogWrite(ledPinBlauw, blueIntensity);

    }
  }


  buttonStatus = digitalRead(buttonPin);
  //Serial.println(buttonStatus);
  if (buttonStatus != lastButtonState) {
    if(buttonStatus == HIGH) {    
      Serial.println("Ben ingedrukt");
      //delay(200);            
      if(running == true) {
        running = false;
      } 
      else {
        running = true;
      }
    }
    lastButtonState = buttonStatus;
  }
}
      if(redIntensity <= 255 && greenIntensity >=0 ) {
        greenIntensity+=5;
        redIntensity -=5;
      }
      analogWrite(ledPinGroen, greenIntensity);
      analogWrite(ledPinRood, redIntensity);
      analogWrite(ledPinBlauw, blueIntensity);

How long does this take to execute?

As soon as it’s done, a few hundred nanoseconds later you do this:

      if(redIntensity <= 0 && greenIntensity >= 255) {
        greenIntensity -= 5;
        blueIntensity += 5;
        redIntensity = 0;
      }
      analogWrite(ledPinGroen, greenIntensity);
      analogWrite(ledPinRood, redIntensity);
      analogWrite(ledPinBlauw, blueIntensity);

Unless you have super-human eyes, you won’t see the first set of values.

Thanks for the advice. I think I’ve used a delay of 100 ms.

if(millis() - startTime >= DISPLAY_TIME) {  
  //save the start time     
  startTime = millis();

One way of the other not everything is delayed.
Could you give me a hint how to make sure everything has a delay of 100ms.

Could you give me a hint how to make sure everything has a delay of 100ms.

delay(100);

You can't execute instructions in a sequential fashion like that, using the blink without delay philosophy.

You need a state machine. Every time it is time to do something, you determine what state you are in, which defines what you need to do. Your function will be called over and over again. Most times, it will do nothing. When it IS time to do something, it will set the state of the three pins based on what it did last time. If it did the red bit last time, and the end of the red cycle has been reached, it does the green bit. Then, the blue bit.