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
}
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);
       }
  • 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. – Jet Propelled Insectivore Aug 19 '15 at 5:30
  • I'm not sure what you mean by "move the return statement to the loop". Can you elaborate? – Nick Gammon Aug 19 '15 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).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.