button press question

Hello! So I seem to be stuck.. I am trying to modify the code from the Adafruit LED strip example (Arduino Code | RGB LED Strips | Adafruit Learning System) to turn off an on when a switch is switched.

I modded it with and if/then statement to test whether the switch was on or off, but if the switch is ON, the sequence runs through the entire code and then won't turn off until it gets to the end. I want it to switch off right when I flip the switch off... what am I doing wrong? :: :~

#define REDPIN 5
#define GREENPIN 6
#define BLUEPIN 3

#define FADESPEED 5     // make this higher to slow down
 
const int buttonPin = 2; 
int buttonState = 0; 

void setup() {
  pinMode(REDPIN, OUTPUT);
  pinMode(GREENPIN, OUTPUT);
  pinMode(BLUEPIN, OUTPUT);
  pinMode(buttonPin, INPUT); 
  }


void loop() {
  buttonState = digitalRead(buttonPin);
  int r, g, b;
 if (buttonState == HIGH)   {     // fade from blue to violet
   for (r = 0; r < 256; r++) { 
   analogWrite(REDPIN, r);
   delay(FADESPEED);
   } 
   // fade from violet to red
   for (b = 255; b > 0; b--) { 
   analogWrite(BLUEPIN, b);
   delay(FADESPEED);
   } 
   // fade from red to yellow
   for (g = 0; g < 256; g++) { 
   analogWrite(GREENPIN, g);
   delay(FADESPEED);
   } 
   // fade from yellow to green
   for (r = 255; r > 0; r--) { 
   analogWrite(REDPIN, r);
   delay(FADESPEED);
   } 
   // fade from green to teal
   for (b = 0; b < 256; b++) { 
   analogWrite(BLUEPIN, b);
   delay(FADESPEED);
   } 
   // fade from teal to blue
   for (g = 255; g > 0; g--) { 
   analogWrite(GREENPIN, g);
   delay(FADESPEED);
   };   
 }
  else {
    analogWrite(REDPIN, 0);
   analogWrite(BLUEPIN, 0);
  analogWrite(GREENPIN, 0); 

}
}

thank you! i love all of you! :smiley:

If you want to make it so that your button press is detected at any point during the sequence you will need to make a lot of changes to that code. Actually, it would be easier just to write a whole new program.

The problem is that the code works as a succession of FOR loops each including a delay() command. As it is written there is no means to detect the button press until the whole sequence is complete.

To detect the button press anywhere it would be necessary to do only one step of each sequence between checking for the button press. And it would also be necessary to replace the use of delay() with the technique in the Blink Without Delay example sketch. The demo several things at a time illustrates these ideas.

...R

hmm ok so I see what you are saying about the delay and I tried to do something similar to the Blink Without Delay demo.

I rewrote the code and tried to make it loop and check if the switch was flipped at the beginning of the loop, but I dont think I have the hang of it yet... can you steer me in the right direction? I am trying to get it to fade in each LED (one step every 100 ms) sequentially. And turn off immediately as soon as the switch is flipped. currently this code just turns on the blue and green leds...no fading or anything. the switch turning it off works though, but thats about it.... =(

#define REDPIN 5
#define GREENPIN 6
#define BLUEPIN 3
 
const int buttonPin = 2; 
int buttonState = 0; 
long previousMillis = 0;
long interval = 100;

void setup() {
  pinMode(REDPIN, OUTPUT);
  pinMode(GREENPIN, OUTPUT);
  pinMode(BLUEPIN, OUTPUT);
  pinMode(buttonPin, INPUT); 
  }


void loop() {
  buttonState = digitalRead(buttonPin);
  int r, g, b;
  unsigned long currentMillis = millis();
  if (buttonState == LOW) {   //checks to see if the button is
    analogWrite(REDPIN, 0);   //pressed. If so, the LEDs turn off.
    analogWrite(BLUEPIN, 0);
    analogWrite(GREENPIN, 0);
  }
  if (currentMillis - previousMillis > interval) {
    //save the last time you dimmed an LED
    previousMillis = currentMillis;
    
  for (r=0; r < 256 ; r++) {        //increments red LED once 
  analogWrite(REDPIN, r);          //everytime through the program
  }                                //until it is at max brightness
    if (r = 255) {    
     for (g=0; g < 256 ; g++){      //brings in green 
      analogWrite(GREENPIN, g);
     }
    }
    if (g = 255) {
     for (b=0; b < 256; b++){      //brings in blue
      analogWrite(BLUEPIN, b);
     }
    }
    if (b = 255){
     for(r=255; r > 0; r--){      //fades out red  
      analogWrite(REDPIN, r);
     }
    }
    if (r=0) {
     for(g=255; g > 0; g--){      //fades out green
      analogWrite(GREENPIN, g);
     }
    }
    if (g=0){
     for(b=255; b > 0; b--){      //fades out blue
      analogWrite(BLUEPIN, b);
     }
    }
    }
  }

thank you!!!

I think this pseudo code may give you some sense of the direction to go

// global variables
redState, blueState, greenState all start at 0
redStep, blueStep, greenStep all 5

void loop() {
   
    buttonPress = digitalRead(buttonPin);
    if (buttonPress == LOW) {
       // set variable such as redState as required
    }

   if (millis() - prevMills > stepInterval) {
        prevMillis += stepInterval;

         redState += redStep;
         if (redState < redStep || redState > 255 - redStep) {
            redStep = - redStep;  // reverse direction 
            // or
            redStep = 0;  // to stop the fade where it is
         }
        // repeat for all the colours
    }
}

You will see that there are no FOR loops. Each step in the fade takes place in an iteration of loop()

...R

ok... so I tried to implement your suggestion. Right now here's what I want to do:

fade the red up and down forever when switch is on
when I flip the switch, the led turns off
when I flip the switch back I want the whole thing to start over.

So my code here will indeed fade the red up and down, but when it fades it all the way down, it then jumps to full brightness and stays that way. When I flip the switch, the led will turn off, but then flicker on and off very dim very fast (at the rate of stepInterval...)

Can you help me? I'm not getting the hang of this yet. sorry im a nooooobie...

int REDPIN = 5;
int GREENPIN = 6;
int BLUEPIN = 3;
int buttonPin = 2;
int buttonPress;      
long previousMillis = 0;
long stepInterval = 100;
int redState = 0;
int blueState = 0;
int greenState = 0;
int redStep = 5;
int blueStep = 5;
int greenStep = 5;

void setup(){
  pinMode(REDPIN, OUTPUT);
  pinMode(BLUEPIN, OUTPUT);
  pinMode(GREENPIN, OUTPUT);
  pinMode(buttonPin, INPUT);
}
 
void loop() {
    buttonPress = digitalRead(buttonPin);
    if (buttonPress == LOW) {
       analogWrite(REDPIN, 0);
       analogWrite(BLUEPIN, 0);
       analogWrite(GREENPIN, 0);
       int redState = 0;          //to reset red back to 0 
  }

   if (millis() - previousMillis > stepInterval) {
       previousMillis += stepInterval;
       analogWrite(REDPIN, redState);
       redState += redStep;
       if (redState < redStep || redState > 255 - redStep) {
            redStep = -redStep;
       }
   }
}

ok I did some debugging with the Serial Monitor and found that when the redState count gets to 0, it subtracts 5 more and then redState goes to -5. Then it gets stuck in a loop and goes from -5 to -10 and back and forth forever.

hmm i know there must be an easy fix for this...

 if (redState < redStep || redState > 255 - redStep) {
            redStep = -redStep;
       }

Maybe there is something silly wrong with this.

What it's meant to do (assuming redStep starts at +5) is to keep adding to redState until it reaches 250 (255 - redStep)
and then redStep changes to -5 and, by continuing to add, counts down.

And now I see the silly mistake - on the way down the test is comparing redState to redStep which happens to be -5. Of course I intended it to test against +5.

The correct code (hopefully) is

 if (redState < abs(redStep) || redState > 255 - redStep) {
            redStep = -redStep;
       }

...R

yep that totally works now. thanks so much! i think the led blinking when it is off is just a weird electrical thing. it is blinking the dimmest it the strip could possibly go ( like analogWrite(ledpin, 1)). There is probably some way to fix it, but the super dim blinking wont even be noticeable in my application.

      analogWrite(GREENPIN, 0);
       int redState = 0;          //to reset red back to 0 
  }

I just noticed this.

redState is defined at the top of the code as a global variable.

The line int redState = 0; creates a local variable with the same name so the 0 that is stored in it has no effect on the global variable.

Drop the int from the line so it refers to the global variable.

...R

Hmm....I seem to be getting a red LED strobe at the what appears to be exactly the same rate as my stepInterval...

Can you help me find the bug in this code?

just a heads up, this is running code for two strips, one is controlled by a pot, the other is an on/off switch.

int REDPIN = 3;
int GREENPIN = 5;
int BLUEPIN = 6;
int RED2PIN = 9;
int GREEN2PIN = 10;
int BLUE2PIN = 11;
int buttonPin = 2;
int ledpot; 
int buttonPress;      
long previousMillis = 0;
long stepInterval = 500;  //make very big for installation
int redState = 100;
int blueState = 0;
int greenState = 0;
int redStep = 4;
int blueStep = 2;    //make the steps small
int greenStep = 3;

void setup(){
  pinMode(REDPIN, OUTPUT);
  pinMode(BLUEPIN, OUTPUT);
  pinMode(GREENPIN, OUTPUT);
  pinMode(buttonPin, INPUT);
  Serial.begin(9600);
}
 
void loop() {
    buttonPress = digitalRead(buttonPin);
    if (buttonPress == LOW) {
      redState = 100;   //reset values back to intial values
      blueState = 0;
      greenState = 0;
       analogWrite(REDPIN, 0);
       analogWrite(BLUEPIN, 0);
       analogWrite(GREENPIN, 0);
  }

   if (millis() - previousMillis > stepInterval) {
       previousMillis += stepInterval;
       redState += redStep;
       analogWrite(REDPIN, redState);
       if (redState < abs(redStep) || redState > 200 - redStep) { 
         redStep = -redStep;  
          }
       greenState += greenStep;
       analogWrite(GREENPIN, greenState);
       if (greenState < abs(greenStep) || greenState > 255){
         greenStep = -greenStep;
       }
       blueState += blueStep;
       analogWrite(BLUEPIN, blueState);
       if (blueState < abs(blueStep) || blueState > 200){
         blueStep = -blueStep;
       }
       
   }
   
  int sensorValue = analogRead(A0);
  ledpot = map(sensorValue, 0, 1023, 0, 255);
 // r = ledpot/2;
 // g = ledpot-100;
  analogWrite(RED2PIN, 255);
  analogWrite(BLUE2PIN, 0);
  analogWrite(GREEN2PIN, ledpot);
  Serial.println("led pot:");
  Serial.println(ledpot);
}

thank you so much for your time and help. it has been such a big help to me!

zumdar:
Hmm....I seem to be getting a red LED strobe at the what appears to be exactly the same rate as my stepInterval...

I've had a look at your code but I don't know which red led is causing you a problem. The code at lines 58 onwards only seems to light the 2nd green led.

By the way thisledpot = map(sensorValue, 0, 1023, 0, 255);
can be replaced by thisledpot =  sensorValue / 4;

Having Serial.print() in loop() may produce an awful lot of output. You probably need code that either prints only 2 or 3 times per second or when the value changes. What value for ledpot is it showing?

...R

yikes sorry I didnt specify earlier, it is the leds from the first part of the code, that detect if the switch is on or off, REDPIN, GREENPIN, and BLUEPIN. I've actually noticed that the usually it is the red led, but sometimes the others will light up too. It is verrry dim, seemingly the brightness of redStep, blueStep, and greenStep. and they definitely strobe at the stepInterval rate.. I feel like it has to be something in this area;

    if (buttonPress == LOW) {
      redState = 100;   //reset values back to intial values
      blueState = 0;
      greenState = 0;
       analogWrite(REDPIN, 0);
       analogWrite(BLUEPIN, 0);
       analogWrite(GREENPIN, 0);
  }

   if (millis() - previousMillis > stepInterval) {
       previousMillis += stepInterval;
       redState += redStep;
       analogWrite(REDPIN, redState);
       if (redState < abs(redStep) || redState > 200 - redStep) { 
         redStep = -redStep;  
          }
       greenState += greenStep;
       analogWrite(GREENPIN, greenState);
       if (greenState < abs(greenStep) || greenState > 255){
         greenStep = -greenStep;
       }
       blueState += blueStep;
       analogWrite(BLUEPIN, blueState);
       if (blueState < abs(blueStep) || blueState > 200){
         blueStep = -blueStep;
       }
       
   }

any thoughts? thank you for the help with the code optimizations by the way! that makes total sense and it's super helpful. thanks!!