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);
}
}
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.
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()
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?
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.