Check if some of the buttons was pressed while executing a "for" loop. HELP!

I need help to check if the button “bt_2” has been pressed while the program executes a for loop, if the button is pressed then it needs to do something if not ir keeps repeating the “void rgb()” function, i already tried to use as many functions as i could understand but nothig solved.
this code is almost doing it but no matter what i do it dont work as well as expected. Please Help me, anything would be appreciated.
P.S: the thing here is, if i press one button it is runnig the rgb function as expected but once it runs it it forget to check if any other button is pressed, i dont know why this is happening, maybe i dont know how to make it keep looking. :~

#define LED1_R 11 
#define LED1_G 10 
#define LED1_B 9  
#define bt_1 digitalRead(2)
#define bt_2 digitalRead(3)
#define bt_3 digitalRead(4)
#define bt_4 digitalRead(5)
#define bt_5 digitalRead(6)
int ledLevel = 25.5;
int WAIT = 40;
int r = 255;
int g = 1;
int b = 1;
boolean lbt_1 = LOW; 
boolean lbt_2 = LOW;
boolean lbt_3 = LOW;
boolean lbt_4 = LOW;
boolean lbt_5 = LOW;
boolean led_red = false;
boolean led_green = false;
boolean led_blue = false;
void setup(){
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  pinMode(4, INPUT);
  pinMode(5, INPUT);
  pinMode(6, INPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
}
void loop(){
    if (bt_1 == HIGH && lbt_1 == LOW){
      lbt_1 = !lbt_1;
      rgb();
    } 
    if (bt_2 == HIGH && lbt_2== LOW){
      lbt_2 = !lbt_2;
    }
    if (bt_2 == LOW && lbt_2 == HIGH){
      if (bt_3 == HIGH && lbt_3 == LOW){
        ledLevel = ledLevel - 25.5; 
      }
      lbt_3 = bt_3;
      if (bt_4 == HIGH && lbt_4 == LOW){
        ledLevel = ledLevel + 25.5;
      }
      lbt_4 = bt_4;
        analogWrite(LED1_R, ledLevel);
        analogWrite(LED1_G, ledLevel);
        analogWrite(LED1_B, ledLevel);
      if (ledLevel > 255)ledLevel = 255;
      if (ledLevel < 25.5)ledLevel = 25.5;
    }
}
void rgb(){
  // Red to Orange to Yellow
  r = ledLevel; g = 1; b = 1;
  for(g = 1; g <= ledLevel; g++) {
    writeLED1();
  }
  // Yellow to Green
  r = ledLevel; g = ledLevel; b = 1;
  for(r = ledLevel; r > 1; r -= 1) {
    writeLED1();
  }
   // Green because blue is bright and a pause for green is good
  r = 1; g = ledLevel; b = 1;
  for(int i = 0; i < 20; i++) {
    writeLED1();
  }
  // Green to Blue
  r = 1; g = ledLevel; b = 1;
  for(g = ledLevel; g > 1; g -= 1) {
    b += 1;
    writeLED1();
  }
  // Blue to Purple
  r = 1; g = 1; b = ledLevel;
  for(r = 1; r < ledLevel; r += 1) {
    writeLED1();
  }
  // Purple to Red
  r = ledLevel; g = 1; b = ledLevel;
  for(b = ledLevel; b > 1; b -= 1) {
    writeLED1();
  }
   rgb();
}
void writeLED1(){
  analogWrite(LED1_R, r);
  analogWrite(LED1_G, g);
  analogWrite(LED1_B, b);
  delay(WAIT);
}

This sort of code is hard to follow:

#define bt_1 digitalRead(2)
#define bt_2 digitalRead(3)
#define bt_3 digitalRead(4)
#define bt_4 digitalRead(5)
#define bt_5 digitalRead(6)
...
void loop(){
    if (bt_1 == HIGH && lbt_1 == LOW){

Hiding away a function call in a define looks confusing. Just write:

void loop(){
    if (digitalRead(2) == HIGH && lbt_1 == LOW){

During delay() everything, except interupts, stops, so you'll not be able to read the switches when you've got a for loop with 40 * 40 millisecond (= 1.6 seconds) delays. Look up 'blink without delay' in the Playground to see how to overcome this.

Henry_Best: During delay() everything, except interupts, stops, so you'll not be able to read the switches when you've got a for loop with 40 * 40 millisecond (= 1.6 seconds) delays. Look up 'blink without delay' in the Playground to see how to overcome this.

Thank you Henry_Best, do you have any idea of how can i do that withou the delay function? I was thinking about using Serial commands. I think i already tried to use interupts but didn't worked. anyway i'll try to do it again. Thanks

the way to do that, as Henry_Best mentioned, is to look at the "Blink without delay()" example. You can find it here: http://arduino.cc/en/Tutorial/BlinkWithoutDelay This way you can achieve a "delay effect" without using the delay() function. When you use the delay() it's kind of like having the arduino "pausing"; it won't read your inputs, so you can't give him new orders (except for the interrupts). If you use the Blink Without Delay method, you will achive this by using the millis() function. The millis() is like a clock that starts counting when you connect (or reset) your arduino. So, let's say you want a 1second "delay" between pressing a button and having a LED light up, you can tell your arduino:

long interval = 1000; // 1 second interval

When I press a button {
  // save the time of press into a variable called pressMillis
  pressMillis = millis();
}

// Check for interval 
if currentMillis - millis() = interval {
   light my LED
}

just to give you a rought idea. check the Blink without delay to really see how it works! ;)

Also, if you explain us what you are trying to achieve with your code, maybe someone will have a different idea of how to do it. Good luck! 8)

boguz: Also, if you explain us what you are trying to achieve with your code, maybe someone will have a different idea of how to do it. Good luck! 8)

I'm trying to us use the millis function right now but seems that when i call the "rgb();" loop it stops working somehow.

My project is basically to make a remote control that control some RGB LED that so something if i press one button. My idea was to make the led to fade between colors if i press bt_1, that was ok until i went to the next step that is meant to whenever i press bt_2 it activates the tree colors and let me control the ledLevel (led brightness control with bt_3 and bt_4 (+ or -)), but the bad thing is: if i press the bt_2 after calling the rgb() loop it does nothing i just stay stucked at rgb loop, i already had to stop using software debouncing in this project because of the delay() function. After solving those errors i still want to make an ON/OFF function that activates/deactivates the whole circuit.

but seems that when i call the "rgb();" loop it stops working somehow.

Well, if it is the "rgb()" you posted above, it is probably because of this delay(WAIT);

RogerioBoscolo: I'm trying to us use the millis function right now but seems that when i call the "rgb();" loop it stops working somehow.

When you have something ready let us take a look at how your doce is looking, maybe we can help you from there...

So, i just made a few adjustments to use the attachInterrupt but it still not working. =( maybe the problem still in the “delay(WAIT);”… i really don’t know how to fix this code, i thought the interrupt would handle the delay and stop that rgb(); loop whenever the button was pressed but seems it doesn’t.

#define red 11
#define green 10 
#define blue 9
#define bt_1 digitalRead(2)
#define bt_3 digitalRead(4)
#define bt_4 digitalRead(5)
#define bt_5 digitalRead(6)
int ledLevel = 25.5;
int modo = 0;
int WAIT = 40;
int r=255;
int g=1;
int b=1;
boolean lbt_1 = LOW;
boolean lbt_2 = LOW;
boolean lbt_3 = LOW;
boolean lbt_4 = LOW;
boolean lbt_5 = LOW;
boolean led_red = LOW;
boolean led_green = LOW;
boolean led_blue = LOW;
void setup(){
  pinMode(2, INPUT); 
  pinMode(4, INPUT);
  pinMode(5, INPUT);
  pinMode(6, INPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  attachInterrupt(1, modo0, RISING);
  
}
void loop(){
    if (bt_1 == HIGH && lbt_1 == LOW){
      lbt_1 = !lbt_1;
    modo=1;
    }
    switch(modo){
      case 0:
      if (bt_3 == HIGH && lbt_3 == LOW){
        ledLevel = ledLevel - 25.5; 
      }
      lbt_3 = bt_3;
      if (bt_4 == HIGH && lbt_4 == LOW){
        ledLevel = ledLevel + 25.5;
      }
      lbt_4 = bt_4;
      analogWrite(red, ledLevel);
      analogWrite(green, ledLevel);
      analogWrite(blue, ledLevel);
      if (ledLevel > 255)ledLevel = 255;
      if (ledLevel < 25)ledLevel = 25.5;
      break;
      case 1:
      rgb();
      break;
    }
}
void rgb() {
  // Red to Orange to Yellow
  r = ledLevel; g = 1; b = 1;
  for(g = 1; g <= ledLevel; g++) {
    writeLED1();
  }
  // Yellow to Green
  r = ledLevel; g = ledLevel; b = 1;
  for(r = ledLevel; r > 1; r -= 1) {
    writeLED1();
  }
   // Green because blue is bright and a pause for green is good
  r = 1; g = ledLevel; b = 1;
  for(int i = 0; i < 20; i++) {
    writeLED1();
  }
  // Green to Blue
  r = 1; g = ledLevel; b = 1;
  for(g = ledLevel; g > 1; g -= 1) {
    b += 1;
    writeLED1();
  }
  // Blue to Purple
  r = 1; g = 1; b = ledLevel;
  for(r = 1; r < ledLevel; r += 1) {
    writeLED1();
  }
  // Purple to Red
  r = ledLevel; g = 1; b = ledLevel;
  for(b = ledLevel; b > 1; b -= 1) {
    writeLED1();
  }
  rgb();
}
void writeLED1(){
  analogWrite(red, r);
  analogWrite(green, g);
  analogWrite(blue, b);
  delay(WAIT);
}
void modo0() { 
  modo = 0;
}

RogerioBoscolo:

So, i just made a few adjustments to use the attachInterrupt but it still not working. =( maybe the problem still in the "delay(WAIT);"

Not maybe. It [u]is[/u] the problem.

unsigned long startTime;  //add this line before setup()

setup(){ startTime = millis();  //add this line } . . . void writeLED1(){ if(millis() - startTime >= WAIT){   analogWrite(red, r);   analogWrite(green, g);   analogWrite(blue, b);   startTime = millis(); //reset startTime for next iteration   } }

r += 1 is one shortcut, another would be r++, same with r -= 1 can be replaced with r--.

int ledLevel = 25.5;

Novel take on an integer.

looks like you are calling rgb(); from within rgb()

AWOL: int ledLevel = 25.5;

Novel take on an integer.

I think it is not the problem because the code was working fine until i put the rgb() functions.

I didn't say it was a problem I said it was novel. Recursion is now your problem.

Henry_Best:

RogerioBoscolo:

So, i just made a few adjustments to use the attachInterrupt but it still not working. =( maybe the problem still in the “delay(WAIT);”

Not maybe. It is the problem.

unsigned long startTime;  //add this line before setup()

setup(){
startTime = millis();  //add this line
}
.
.
.
void writeLED1(){
if(millis() - startTime >= WAIT){
  analogWrite(red, r);
  analogWrite(green, g);
  analogWrite(blue, b);
  startTime = millis(); //reset startTime for next iteration
  }
}

Unfortunately i did that before and did that now, id makes the led to fade a lot faster but still stuck in the rgb loop once inside it. :astonished:
But thank you anyway, any other suggestion would be appreciated

Read the last line of your rgb() function...

It's rgb(), hence, you call the function itself again right before the function ends, hence recursion, and thus resulting in an infinite "loop" (not a loop technically, but the effect is the same in your case since nothing changes from iteration to iteration.)

jackwp: looks like you are calling rgb(); from within rgb()

There is the major problem. rgb() runs rgb() with no escape until the return addresses stack down to overwrite the heap (your variables) after a very long time.

The delay just slows it all down and keeps your code from noticing a pressed button.

Learning BlinkWithoutDelay from your IDE examples (can be reduced to 12 lines of code not counting the comments) is the first step in learning real-time code with Arduino. It's funny how hard less than 20 lines of code can be to follow.

GoForSmoke:

jackwp: looks like you are calling rgb(); from within rgb()

There is the major problem. rgb() runs rgb() with no escape until the return addresses stack down to overwrite the heap (your variables) after a very long time.

The delay just slows it all down and keeps your code from noticing a pressed button.

Learning BlinkWithoutDelay from your IDE examples (can be reduced to 12 lines of code not counting the comments) is the first step in learning real-time code with Arduino. It's funny how hard less than 20 lines of code can be to follow.

Unfortunately if i dont write that down the rgb() will run only once after i press the button, i need it to keep running indefinitely until the button is pressed. The funny thing is that nothing solved it until now, may i give up? That can't be a impossible thing to achieve right?

Take out the rgb() line at the end of your rgb() function to solve the recursive problem, then put in a simple line such as this, and until you push the button, rgb() will continuously run.

while (!digitalRead(myButton)) {
  rgb();
}

Alternatively, if you want it to run while the button is pushed, you can just invert the logic above (by taking out the ! ).

Also, if you want the program to stall until you release the button (which I like to do, prevents multiple things from happening due to one button press), you can do a simple modification to the above code:

while (digitalRead(myButton)) {delay(2);}