0

I am trying to use different buttons to activate different methods for an LED strip. However, when one button is pressed after another has been pressed, I want it to interrupt the first buttons method and begin the second. For example: one button sends a rainbow pattern through the LED strip when pressed, however, while it is cycling through the rainbow, the second button is pressed which sends a white cycle through the LED strip. There will be 24 buttons total. I have gotten this to work with 2 buttons but am having trouble getting it to work for a third. The code is below:

 void loop(){
 if (digitalRead(inPin(1)) == HIGH && lastState == LOW){//if button has just been pressed
 stopCycle();
 theaterChaseRainbow(50);
 }
 if (digitalRead(inPin(2)) == HIGH){
 stopCycle();
 theaterChase(strip.Color(127, 127, 127), 50); // White
 }
 if (digitalRead(inPin(3)) == HIGH){
 stopCycle();
 rainbowCycle(0); 
 }
 }
 //Theatre-style crawling lights.
void theaterChase(uint32_t c, uint8_t wait) {
 for (int j=0; j<100; j++) { //do 100 cycles of chasing
 if (digitalRead (inPin(1)) == LOW) { //checks that other button(s) have not been pressed
 if (digitalRead (inPin(3) == LOW)){
 for (int q=0; q < 3; q++) {
 for (int i=0; i < strip.numPixels(); i=i+3) {
 strip.setPixelColor(i+q, c); //turn every third pixel on
 }
 strip.show();
 delay(wait);
 for (int i=0; i < strip.numPixels(); i=i+3) {
 strip.setPixelColor(i+q, 0); //turn every third pixel off
 }
 }
 }
 }
 }
}
void rainbow(uint8_t wait) {
 int i, j;
 for (j=0; j < 384; j++) { 
 if (digitalRead (inPin(2)) == LOW) { // 3 cycles of all 384 colors in the wheel
 if (digitalRead (inPin(3) == LOW)){
 for (i=0; i < strip.numPixels(); i++) {
 strip.setPixelColor(i, Wheel( (i + j) % 384));
 } 
 strip.show(); // write all the pixels out
 delay(wait);
 }
 } 
 }
}
uint32_t Wheel(uint16_t WheelPos)
{
 byte r, g, b;
 switch(WheelPos / 128)
 {
 case 0:
 r = 127 - WheelPos % 128; //Red down
 g = WheelPos % 128; // Green up
 b = 0; //blue off
 break; 
 case 1:
 g = 127 - WheelPos % 128; //green down
 b = WheelPos % 128; //blue up
 r = 0; //red off
 break; 
 case 2:
 b = 127 - WheelPos % 128; //blue down 
 r = WheelPos % 128; //red up
 g = 0; //green off
 break; 
 }
 return(strip.Color(r,g,b));
}
void rainbowCycle(uint8_t wait) {
 uint16_t i, j;
 for (j=0; j < 384 * 5; j++) { // 5 cycles of all 384 colors in the wheel
 if (inPin(1) == LOW) {
 if (inPin(2) == LOW) {
 for (i=0; i < strip.numPixels(); i++) {
 // tricky math! we use each pixel as a fraction of the full 384-color wheel
 // (thats the i / strip.numPixels() part)
 // Then add in j which makes the colors go around per pixel
 // the % 384 is to make the wheel cycle around
 strip.setPixelColor(i, Wheel( ((i * 384 / strip.numPixels()) + j) % 384) );
 } 
 strip.show(); // write all the pixels out
 delay(wait);
 }
 }
 }
}
void stopCycle(){
 int i;
 for (i=0; i < strip.numPixels(); i++) {
 strip.setPixelColor(i, 0);
 } 
 strip.show(); // write all the pixels out
}
asked Aug 19, 2015 at 4:16

2 Answers 2

0

Inside each inner loop, just test the switches and return if they are pressed.

eg.

//Theatre-style crawling lights.
void theaterChase(uint32_t c, uint8_t wait) {
 for (int j=0; j<100; j++) { //do 100 cycles of chasing
 for (int q=0; q < 3; q++) {
 for (int i=0; i < strip.numPixels(); i=i+3)
 {
 strip.setPixelColor(i+q, c); //turn every third pixel on
 }
 strip.show();
 delay(wait);
 // give up if switches pressed
 if (digitalRead (inPin(1)) == HIGH || 
 digitalRead (inPin(2)) == HIGH ||
 digitalRead (inPin(3)) == HIGH )
 return;
 for (int i=0; i < strip.numPixels(); i=i+3) {
 strip.setPixelColor(i+q, 0); //turn every third pixel off
 }
 }
 }
}

am having trouble getting it to work for a third

If that doesn't help please explain the nature of this "trouble".


You may need to debounce the switch presses. And you may need to wait for them to release the switch, eg.

 if (digitalRead(inPin(1)) == HIGH && lastState == LOW){//if button has just been pressed
 stopCycle();
 while (digitalRead(inPin(1)) == HIGH)
 { } // wait for switch release
 delay (10); // debounce
 theaterChaseRainbow(50);
 }
answered Aug 19, 2015 at 5:13
2
  • This is an excellent solution but is there a way to move the return statement to the loop? This way, I could call theatreChase multiple times with different buttons at different paramenters. Commented Aug 19, 2015 at 5:30
  • I'm not sure what you mean by "move the return statement to the loop". Can you elaborate? Commented Aug 19, 2015 at 9:11
0

I would normally do this (pseudocode):

void loop() {
 static state=state_off;
 if (button_1_pushed) {
 state=state_1;
 } elseif (button_2_pushed) {
 state=state_2;
 }
 if (state==state_off) {
 turn_all_leds_off();
 } elseif (state==state_2) {
 shownextframe_rainbow();
 } elseif (state==state_2) {
 shownextframe_chaser();
 }
 delay(1);
}

In shownextframe_chaser/shownextframe_rainbow, I would probably work out what should be shown based on the current millis() - e.g. if your chaser has 10 lights, and you want it to pulse over 1 second, then each led should be on for 100 millis, so at any instant, the led that should be on is (millis()/100)%10 (assuming the led's are numbered for 0 to 9).

answered Aug 19, 2015 at 5:13

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.