LED Strip on for a time, then off, and not back on unless door is closed/opened

Hi Folks,

I’ve just started coding with my Arduino, and fairly new to it. I really need a bit of help on part 4 below.

I am attempting to set up an LED strip in a closet with a reed switch (Contact switch, Normally closed).

PART 1: The initial idea would be that when the switch is activated (magnet moved away from switch, and circuit activated/closed contact), the LED’s would go on. That part works.

PART 2: LED’s stay on for set period of time (normally 5 to 10 min, but in my code below it is set for 5 seconds for testing). It would then dim back down to off. This part works.

PART 3: IF the door was closed before the timer runs out, dim LED’s immediately. This part also works.

PART 4: The LED’s would stay off until the door is closed and opened again. This part is not working/coded. Basically, it cycles all over.

I’ve gotten the idea I need to somehow capture the state, and check that, but my logic failing me on how to do this (newbie).

// Light up with contact is closed, stay on for max 10 min or until the door is closed (contact opened).
// NOTE: Status LED LEDDOOROPEN and LEDDOORCLOSE for LED's that give door status (troubleshooting)

#define FADERPIN 3
#define SWITCH 6
#define LEDDOOROPEN 8
#define LEDDOORCLOSE 10
#define FADESPEED1 20   
#define FADESPEED2 10   

void setup()
{                
  pinMode(FADERPIN, OUTPUT);
  pinMode(LEDDOOROPEN, OUTPUT);
  pinMode(LEDDOORCLOSE, OUTPUT);
  pinMode(SWITCH, INPUT);
  digitalWrite(FADERPIN,LOW);
}

void loop() 
{

// Reading status of switch, if HIGH (Door opened), then fade up

if (digitalRead(SWITCH)==HIGH){
    digitalWrite(LEDDOOROPEN, HIGH);
    digitalWrite(LEDDOORCLOSE, LOW);
    int i;
    for (i = 0; i < 70; i++) { 
      analogWrite(FADERPIN, i);
      delay(FADESPEED1);
    }
    for (i = 70; i < 256; i++) { 
      analogWrite(FADERPIN, i);
      delay(FADESPEED2);
    }
    digitalWrite(FADERPIN, HIGH);

    // Now, delay time to stay on if door left open (currently 5 seconds, normally 5 min)
    int t;
    int switchstatus;
    for (t=0; t < 5000; t++){
      // Checking to see if switch went low (Door closed) while counting, if so Break
      switchstatus = digitalRead(SWITCH);
      if (switchstatus ==LOW){
      digitalWrite(LEDDOOROPEN, LOW);
      digitalWrite(LEDDOORCLOSE, HIGH);
      break;
      }

        // Dim the lights back to 0
        int i;
        for (i = analogRead; i > 0; i--) {
        analogWrite(FADERPIN, i);
        delay(FADESPEED2);
        }
      digitalWrite(SWITCH, LOW);
      digitalWrite(LEDDOORCLOSE, HIGH);
      delay (50);
      break;
      }
} // End of first IF statement 

// Switch is not activiated, do nothing
else (digitalRead(SWITCH)==LOW); {
     analogWrite(FADERPIN, 0);
     digitalWrite(FADERPIN, LOW);
    }
}

Note that LEDDOOROPEN and LEDDOORCLOSE I put in to give status lights while troubleshooting.

Thanks for any help and/or guidance.

PART 4: The LED's would stay off until the door is closed and opened again. This part is not working/coded. Basically, it cycles all over.

I've gotten the idea I need to somehow capture the state,

Yes that's exactly what you need to do: only fire up on a "new opening", ie see where the switch becomes open, not is open.

All is revealed here :wink:

Thanks arduin_ologist, I'll start looking into that. Just need to figure out how to add portions of that into my sketch to make it work.

Looks like I need to add another IF statement at the beginning:
if (buttonState != lastButtonState) {

I'll play with it a bit, see if I can get it working. Once I do, PART 5 will be to add the ability to select what color it would display (currently I had tied the RGB's together, but want to break them out). I'm thinking of having the ability to cycle through 10 colors (another switch), use a seven-segment LED to show which current color is tied-to, etc.

Then I'll project board it with some components I purchased previously...

Thanks again.

Do you know you can use compound if statements that test for more than one thing, like

if (buttonState != lastButtonState && buttonState == HIGH) {

The && means AND so you need both cases to be true before the if statement “fires”.

or possibly more clearly:

if (buttonState == HIGH && lastButtonState == LOW ) {

:grinning:

Thanks Mike and Paul on the additional input.

I like the combined statements to clean up the multiple IF statements.

It took me a few to noodle through the logic to finally understand. That part now appears to be working.

What I thought was working but isn’t is the time delay portion of the sketch. The lights do come up to full brightness, but then back down to zero. It is like the delay section is skipped. I am “guessing” that somehow my “break;” is not in the right place, but not sure. I did the for loop for time delay instead of just doing a “delay” as I wanted to capture if the switch status changed.

Revised code as follows:

// Strip Lights up when a door is opened. 
// Lights stay on for max 10 min or until the door is closed (contact opened).
// ButtonState
// NOTE: Status LED LEDDOOROPEN and LEDDOORCLOSE are LED's that give a door status (troubleshooting)

#define FADERPIN 3
#define SWITCH 6
#define LEDDOOROPEN 8
#define LEDDOORCLOSE 10
#define FADESPEED1 20   
#define FADESPEED2 10
// int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button


void setup()
{                
  pinMode(FADERPIN, OUTPUT);
  pinMode(LEDDOOROPEN, OUTPUT);
  pinMode(LEDDOORCLOSE, OUTPUT);
  pinMode(SWITCH, INPUT);
  digitalWrite(FADERPIN,LOW);
}

void loop() 
{
  // Reading status of switch, if HIGH (Door opened), then fade up
  // buttonState captures current digital state (1 or 0)
buttonState = digitalRead(SWITCH);

  // Compare buttonState with lastButtonState.
  // First time Switch went high, so initially buttonState=1, and lastButtonState=0
  // Second time both are equal, and drops out (due to last statement in code)
  //buttonstate goes back high when the door is closed and re-opened.
if (buttonState != lastButtonState && buttonState == HIGH) {
    // Status LEDs. When door is opened, green goes on, Red goes off
    digitalWrite(LEDDOOROPEN, HIGH); // Status LED Green
    digitalWrite(LEDDOORCLOSE, LOW); // Status LED Red
    int i;
    for (i = 0; i < 70; i++) { 
      analogWrite(FADERPIN, i);
      delay(FADESPEED1);
    }
    for (i = 70; i < 256; i++) { 
      analogWrite(FADERPIN, i);
      delay(FADESPEED2);
    }
    digitalWrite(FADERPIN, HIGH);

    // Now, delay time to stay on if door left open (currently 5 seconds, normally 5 min)
    int t;
    int switchstatus;
    for (t=0; t < 15000; t++){
      // Checking to see if switch went low (Door closed) while counting, if so Break
      switchstatus = digitalRead(SWITCH);
      if (switchstatus ==LOW){
      digitalWrite(LEDDOOROPEN, LOW);
      digitalWrite(LEDDOORCLOSE, HIGH);
      break;
      }
      else {
        delay (50);
      }

        // Dim the lights back to 0 from the current brightness (i=analogRead)
        int i;
        for (i = analogRead; i > 0; i--) {
        analogWrite(FADERPIN, i);
        delay(FADESPEED2);
        }
      digitalWrite(SWITCH, LOW);
      digitalWrite(LEDDOORCLOSE, HIGH);
      delay (50);
      break;
      }
} // End of first IF statement 

// Switch is not activiated, do nothing
else (digitalRead(SWITCH)==LOW); {
     analogWrite(FADERPIN, 0);
     digitalWrite(FADERPIN, LOW);
     delay(50);
     lastButtonState = buttonState;
    }
}

Thoughts?

Thanks…

You should use

lastButtonState = buttonState;

as the last statement in the loop function, not as part of the else condition.

Hi Mike,

So, I cleaned up the code quite a bit. I then tried the “lastButtonState = buttonState;” at the end of the void loop section (code attached), outside of the Else. I also placed it at the end of the timer section (end of the if statement section), but didn’t work there (constant cycle of bright to dim after initial turnup of lights)

#define FADERPIN 3
#define SWITCH 6
#define FADESPEED1 20   
#define FADESPEED2 10
int buttonState = 0;
int lastButtonState = 0;

void setup()
{               
  pinMode(FADERPIN, OUTPUT);
  pinMode(SWITCH, INPUT);
  digitalWrite(FADERPIN,LOW);
}

void loop()
{
buttonState = digitalRead(SWITCH);
if (buttonState != lastButtonState && buttonState == HIGH) {
    int i;
    for (i = 0; i < 70; i++) {
      analogWrite(FADERPIN, i);
      delay(FADESPEED1);
    }
    for (i = 70; i < 256; i++) {
      analogWrite(FADERPIN, i);
      delay(FADESPEED2);
    }
    digitalWrite(FADERPIN, HIGH);
// Timer delay section)
    int t;
    int switchstatus;
    for (t=0; t < 15000; t++){
      switchstatus = digitalRead(SWITCH);
      if (switchstatus ==LOW){
      break;
      }

        int i;
        for (i = 255; i > 0; i--) {
        analogWrite(FADERPIN, i);
        delay(FADESPEED2);
        }
      digitalWrite(SWITCH, LOW);
      delay (50);
      break;
      }
}

else (digitalRead(SWITCH)==LOW); {
     analogWrite(FADERPIN, 0);
     digitalWrite(FADERPIN, LOW);
     delay(50);
    }
    lastButtonState = buttonState;
   
}

Thanks for the assist.

This code line is wrong, what are you trying to do?

else (digitalRead(SWITCH)==LOW);

This

pinMode(SWITCH, INPUT);

Are you using an external PULLUP or pull down resistor?

Attached is a quick drawing of the circuit.
I use a MOSFET to drive the 12v needed for the LED strip.

For whatever reason, I thought I would need an If/Else statement. If the switch status was HIGH, the LED’s ramp up to 100%. Else, reset the FADERPIN both logically and physically (analog) to LOW/zero.

EDIT:
And my attempt here is

  1. Switch activates, lights go 100 %
  2. After a period of time, if contact is not closed, lights dim back to zero, and stay off
  3. If contact is closed before period-of-time, lights go out.
  4. Lights will not come back on unless contact is closed and re-opened.

Are you using an external PULLUP or pull down resistor?

So that will be a no then.

In which case you must use this in the setup.

pinMode(SWITCH, INPUT_PULLUP);

This will read a HIGH when no switch is made and LOW when the switch is made, alter your software to suit.
Failure to do this results in the sort of problems you are seeing. See Inputs for the full discussion of why.

I thought I would need an If/Else statement. If the switch status was HIGH, the LED's ramp up to 100%. Else, reset the FADERPIN both logically and physically (analog) to LOW/zero.

Their is no need to test the opposite state in the else part,

if( this == LOW){
  // do stuff
}

else {
// do other stuff
}

// there is no need to do this

if( this == LOW){
// do stuff
}[/code]
else if( this == HIGH) {
// do other stuff
}

Ok, so to clarify from earlier, I was/am using a pull-down resistor, 100k.I read the Arduino site about digitalPins (https://www.arduino.cc/en/Tutorial/DigitalPins), which suggested to normally use 10k ohms.

In the mean time, I swapped it to 10k instead of the 100k, not that it should really matter.

I did read your article as well, which suggests in noisy environments, that the internal resistors may not be sufficient at the nominal 30k average. I might swap back to the 100k later. In the mean time, I updated the drawing (see attached) which just included the 10k resistor on the drawing.

I removed the ELSE statement at the end of the code. Results seem to be the same. The lights fade up, then immediately fade back down, then off. All of this is within the IF statement (fade up part A, fade up part B, Delay for set-period-of-time, Fade back down).

The delay portion seems to get “partially” skipped over. I say that because, if the switch does change states during the delay portion, lights switch immediately off (no dim down, straight off which would infer that the status was read, and that the “break;” occurred). I tried increasing the delay time but that did not seem to make a diff (currently 15000 below, but I even tried 15000000, and no difference)

int t;
int switchstatus;
for (t=0; t < 15000; t++){
switchstatus = digitalRead(SWITCH);
if (switchstatus ==LOW){
break;
}

I have attached the code as well.

#define FADERPIN 3
#define SWITCH 6
#define FADESPEED1 20   
#define FADESPEED2 10
int buttonState = 0;
int lastButtonState = 0;

void setup()
{                
  pinMode(FADERPIN, OUTPUT);
  pinMode(SWITCH, INPUT);
  digitalWrite(FADERPIN,LOW);
}

void loop() 
{
buttonState = digitalRead(SWITCH);

if (buttonState != lastButtonState && buttonState == HIGH) {
    int i;
    for (i = 0; i < 70; i++) { 
      analogWrite(FADERPIN, i);
      delay(FADESPEED1);
    }
    for (i = 70; i < 256; i++) { 
      analogWrite(FADERPIN, i);
      delay(FADESPEED2);
    }
    digitalWrite(FADERPIN, HIGH);

    int t;
    int switchstatus;
    for (t=0; t < 15000; t++){
      switchstatus = digitalRead(SWITCH);
      if (switchstatus ==LOW){
      break;
      }
        int i;
        for (i = 255; i > 0; i--) {
        analogWrite(FADERPIN, i);
        delay(FADESPEED2);
        }
      digitalWrite(SWITCH, LOW);
      delay (50);
      break;
      }
  }
     analogWrite(FADERPIN, 0);
     digitalWrite(FADERPIN, LOW);
     lastButtonState = buttonState;
}

Why are you writing a LOW to an input? This just messes with the pull up options.

Remove the

digitalWrite(SWITCH, LOW);

And as I said before put this in the setup function

pinMode(SWITCH, INPUT_PULLUP);
     analogWrite(FADERPIN, 0);
     digitalWrite(FADERPIN, LOW);

They both do the same thing, only one is needed.

Also wire your switch so that it puts a ground on the input pin not 5V.

So I did the following:

  1. Removed digitalWrite(SWITCH, LOW);
  2. Added the pullup function: pinMode(SWITCH, INPUT_PULLUP); removed the external resistor.
  3. Removed the extra: digitalWrite(FADERPIN, LOW); from the code
  4. Wire switch to ground instead of +5v. Done however, that also required
  • Change the conditional IF statement to check for buttonState to be LOW
  • Change the switchstatus condition to compare to HIGH (instead of low) within the timer section

Amended code attached. Get the same results as before, being that the timer portion is not waiting a period of time before dimming (it still does it immediately after going full brightness).

NOTE: Updated the drawing

#define FADERPIN 3
#define SWITCH 6
#define FADESPEED1 20   
#define FADESPEED2 10
int buttonState = 0;
int lastButtonState = 0;

void setup()
{                
  pinMode(FADERPIN, OUTPUT);
  pinMode(SWITCH, INPUT_PULLUP);
  digitalWrite(FADERPIN,LOW);
}

void loop() 
{
buttonState = digitalRead(SWITCH);

if (buttonState != lastButtonState && buttonState == LOW) {
    int i;
    for (i = 0; i < 70; i++) { 
      analogWrite(FADERPIN, i);
      delay(FADESPEED1);
    }
    for (i = 70; i < 256; i++) { 
      analogWrite(FADERPIN, i);
      delay(FADESPEED2);
    }
    digitalWrite(FADERPIN, HIGH);

    int t;
    int switchstatus;
    for (t=0; t < 15000000; t++){
      switchstatus = digitalRead(SWITCH);
      if (switchstatus ==HIGH){
      break;
      }
        int i;
        for (i = 255; i > 0; i--) {
        analogWrite(FADERPIN, i);
        delay(FADESPEED2);
        }
      delay (50);
      break;
      }
  }
     analogWrite(FADERPIN, 0);
     lastButtonState = buttonState;
}

Get the same results as before, being that the timer portion is not waiting a period of time before dimming

But the code

for (t=0; t < 15000000; t++){
      switchstatus = digitalRead(SWITCH);
      if (switchstatus ==HIGH){
      break;
      }

Does not have a significant delay. These things are fast. You have to put a delay in the loop. Also the loop variable is only an int, the biggest number you can get in an int is 32,767
https://www.arduino.cc/reference/en/language/variables/data-types/int/
I would use

for (int t=0; t < 2000; t++){ // for two seconds
      delay(1);
      switchstatus = digitalRead(SWITCH);
      if (switchstatus ==HIGH){ // check if this is the right way round for communicating your delay.
      break;
      }

So I got it all working. A few things of note.

The reason the timing did not appear to work was because the fade-up section was within the check-for-switch-transition piece, so it would start the count, then fade down.

  1. I pulled that part out of the FOR section, and actually out of the master IF statement. Worked great except for on initial power-up, that section would take the lights to 255, then down to zero. To fix that:
  2. Added another IF statement, and a conditional flag to check against (int currentstate).
  3. Added comments to the code to clarify.

Here is the current code for anyone that wants it.

#define FADERPIN 3          // MOSFET GATE pin
#define SWITCH 6            // The contact switch
#define FULLBRIGHTNESSLED 8 // Indictor LED when full brightness reached- Optional
#define LEDONESEC 9         // LED for timer cycle, one 1 sec, off 1 sec durring timer
#define FADESPEED1 20       // Initial Fade up first half. Larger numbers, slower fade up time
#define FADESPEED2 10       // Second half of Fad up. Larger numbers, slower fade up time
int buttonState = 0;        // Used to check switch status if door has been closed and reopened.
int lastButtonState = 0;    // Used to check switch status if door has been closed and reopened.
int currentState = 0;       // Used so that on powerup  the dimming feature is not activated once.

void setup()
{                
  pinMode(FADERPIN, OUTPUT);
  pinMode(FULLBRIGHTNESSLED, OUTPUT);
  pinMode(LEDONESEC, OUTPUT);
  pinMode(SWITCH, INPUT_PULLUP);
  digitalWrite(FADERPIN,LOW);
}

void loop() 
{
  // Since the switch is set to be tied to ground, LOW state would equal ON when switch is pressed
  // In the mean time, the switch is set with the internal pullup resistor, which could be external
buttonState = digitalRead(SWITCH); // Capturing SWITCH state LOW = ON (button pressed)

if (buttonState != lastButtonState && buttonState == LOW) {
    // Fade up to 70 (about 27%) at a faster speed
    int i;
    int switchstatus;
    for (i = 0; i < 70; i++) { 
      analogWrite(FADERPIN, i);
      delay(FADESPEED1);
    }
    // Fade up to 255 (100%) at a slower speed
    for (i = 70; i < 256; i++) { 
      analogWrite(FADERPIN, i);
      delay(FADESPEED2);
    }
    digitalWrite(FADERPIN, HIGH);
    digitalWrite(FULLBRIGHTNESSLED, HIGH); // Used for testing - Optional

    // The Timer function in a FOR loop.
    for (int t = 0; t < 300; t++){
      // A separate LED is blinked for 1 second on, 1 second off. This status tells us that the
      // loop is running. In this case, the lights will remain on for 10 min. 300 x 2 sec each
      // pass = 600 seconds, or 10 minutes.
      // During each pass, the switchstatus is checked. If the switch went HIGH (button released
      // or door closed in this case), then we break out of loop.
      delay(1000);
      digitalWrite(LEDONESEC, HIGH);
      delay(1000);
      digitalWrite(LEDONESEC, LOW);
      switchstatus = digitalRead(SWITCH);
      if (switchstatus == HIGH){
          // "currentstate" is needed only when first powering up, as the sketch see's the switch
          // HIGH (not pressed) and wants to run the dim-down part below. 
        currentState = 1;
      break;
      }
    }
  }
  // This is the Fade to-off function. It also checks if this is the first time (thus the IF statement
  // , and if so then skip it (only matches this condion on powerup)
 if (currentState == 1 && buttonState == HIGH) {
        int i;
        for (i = 255; i > 0; i--) {
        analogWrite(FADERPIN, i);
        delay(FADESPEED2);
        currentState = 0;
        }
   }
     analogWrite(FADERPIN, 0);
     lastButtonState = buttonState;
     digitalWrite(FULLBRIGHTNESSLED, LOW);
}

My next enhancement to this code will be to choose what color the light strip will default to. Currently it is only white (currently I tied all three pins, RGB, together for the one color).

Mike, thanks again for putting up with my questions and helping me work through all of this.

– James