Help with Code to turn off Neopixel LEDs and start timer to turn back on

I'm hoping that anyone can help me figure out my code for this project I'm working on. I have my code, Neopixel Strip LEDs, and Arduino set up to make the LEDs glow by raising and lowering their brightness. The only issue with my code is when I'm trying to make my button code work. I tested it to make sure that I wired it correctly and it is, but the code is where I'm having problems. I tried different variations of my code. I want my code to start a 15 second timer where the LEDs are off until the timer hits 0. I'm running out of ideas as to how to fix my code. My code for LEDs work, it's just the button function that is the problem. Any help would be greatly appreciated.

#include "Adafruit_NeoPixel.h"
 
#define PIN 5
#define LEDS 12
 
// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
//   NEO_RGBW    Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(LEDS, PIN, NEO_GRB + NEO_KHZ800);

int red=265;
int green=165;
int blue=0;
int timer=0;
int buttonState=0;

void setup() {
  pinMode(2, INPUT);
  pinMode(PIN, OUTPUT);
  strip.begin();
  strip.show();
}

void loop() {
  while(timer>0){
    timer--;
    delay(1000);
  }
  FadeInOut(255,165,0);
}


void showStrip() {
 #ifdef ADAFRUIT_NEOPIXEL_H
   // NeoPixel
   strip.show();
 #endif
}

void setPixelColor(int Pixel,int red,int green,int blue) {
 #ifdef ADAFRUIT_NEOPIXEL_H
   // NeoPixel
   strip.setPixelColor(Pixel, strip.Color(red, green, blue));
 #endif
}

void setAll(byte red, byte green, byte blue) {
  for(int i = 0; i < LEDS; i++ ) {
    setPixelColor(i, red, green, blue);
  }
  showStrip();
}

void FadeInOut(int red,int green,int blue){
  float r, g, b;
  if (timer==0){
  for(int k = 165; k < 256; k=k+1) {
    buttonState=digitalRead(2);
    if(buttonState == HIGH){
      break;
      timer=15;
    }
    r = (k/256.0)*red; 
    g = (k/256.0)*green; 
    b = (k/256.0)*blue; 
    setAll(r,g,b); 
    showStrip();
    delay(10);
    } 
  delay(1000);
  for(int k = 255; k >= 165; k=k-1) {
    buttonState=digitalRead(2);
    if(buttonState == HIGH){
      break;
      timer=15;
    }
    r = (k/256.0)*red;
    g = (k/256.0)*green;
    b = (k/256.0)*blue;
    setAll(r,g,b);
    showStrip();
    delay(10);
  }
  delay(1000);
  }
  else if(timer>0){
   r = 0; 
   g = 0; 
   b = 0; 
   setAll(r,g,b); 
   showStrip();
  }
}

        break;
        timer = 15;

I have not looked closely at your code so there may be other problems, but the line that sets timer to 15 will never be executed because of the break; that ends the conditional code

strip.clear();
strip.show();

I'm not yet sure what you wanted functionality is:

You have functions that fade in / fade out the LED strip

all and every "code" starts executing as soon as you connect the microcontroller to power.

I assume you mean the fade in / fade out shall start only if

a button is pressed
and
15 seconds have passed by since the button was pressed.

This means your loop is checking all the time
is button pressed?

if button is pressed start a timer that counts down 15 seconds
if timer reaches zero start fadeInOut

As long as it is sufficient to do these steps as a fixed sequence and you want the FadeInOut-sequence to run down completely you can keep the delays in your code

As soon as you want more "reponsiveness" to button presses
Your code must be totally re-designed with non-blocking timing.
It is no exaggeration if I say totally re-designed.

Be the change you want to see in the world
best regards Stefan

byte red=255; // it is no sense to try more then 255
byte green=165;
byte blue=0;
#include "Adafruit_NeoPixel.h"

#define PIN 5
#define LEDS 12
Adafruit_NeoPixel strip(LEDS, PIN, NEO_GRB + NEO_KHZ800);

byte red = 255; // it is no sense to try more then 255
byte green = 165;
byte blue = 0;
int timer = 0;
int buttonState = 0;

void setup() {
  pinMode(2, INPUT);
  pinMode(PIN, OUTPUT);
  strip.begin();
  strip.show();
}

void loop() {
  while (timer > 0) {
    strip.clear();
    strip.show();
    timer--;
    delay(1000);
  }
  FadeInOut(255, 165, 0);
}

void setAll(byte red, byte green, byte blue) {
  for (byte i = 0; i < LEDS; i++ )strip.setPixelColor(i, red, green, blue);
  strip.show();
}

void FadeInOut(byte red, byte green, byte blue) {
  static int r, g, b = 0;
  if (timer == 0) {
    for (byte k = 165; k < 255; k = k + 1) {
      if  ( digitalRead(2) == HIGH) {
        timer = 15;
        break;
      }
      r = (k * red ) / 255;
      g = (k * green ) / 255;
      b = (k * blue) / 255;
      setAll((byte)r, (byte)g, (byte)b);
      delay(10);
    }
    delay(1000);
    for (byte k = 255; k >= 165; k = k - 1) {
      if  ( digitalRead(2) == HIGH) {
        timer = 15;
        break;
      }
      r = (k / 256.0) * red;
      g = (k / 256.0) * green;
      b = (k / 256.0) * blue;
      setAll((byte)r, (byte)g, (byte)b);
      delay(10);
    }
    delay(1000);
  }
}

Thank you so much for your help. I have been stumped on this for a while and C++ hasn't been my strongest coding language.

Hi @salxaphone

The solution that kolaha posted works. This solution requires to press the button for around one second because the code still has these delay(1000); at various places.

As long as one of the delay(1000) is executed the button-press is not detected.
This means if the begin and end of the button-press occurs while executing the delay(1000)
the button-press is not detected.

If the code should have even more responsiveness then nonblocking timing based on function millis() would be nescessary.

Be the change you want to see in the world
best regards Stefan

I had this working for a week and now when I tried reuploading the code to my arduino it's cycling through three colors. I have no clue why. I didn't even touch the code that Kolaha sent.

Now can you please use the Startrek-transporter to give me back the real working glas-sphere so I can look into it to find the change?
Not possible?

So at least could you post exact that code-version that you tried to upload?
You can post code by using this method that adds the code-tags
There is an automatic function for doing this in the Arduino-IDE
just three steps

  1. press Ctrl-T for autoformatting your code
  2. do a rightclick with the mouse and choose "copy for forum"
  3. paste clipboard into write-window of a posting

best regards Stefan

Here's the code. The only thing I changed was increasing the number of LEDS since I'm using a bigger strip and removed the 1 second delay. I thought that it was possible that the LEDs or the Arduino malfunctioned. I tried testing with two different Arduinos and got the same effect. I tried with different LEDs and I was getting the same 3 colors cycling. I checked to see if the NeoPixel library got updated, but that was last updated on January 31st. I even tried two different computers to see if it was the Arduino application or uploading weirdly. I probably gotta rewrite the whole code.

#include "Adafruit_NeoPixel.h"

#define PIN 5
#define LEDS 30
Adafruit_NeoPixel strip(LEDS, PIN, NEO_GRB + NEO_KHZ800);

byte red = 255;
byte green = 165;
byte blue = 0;
int timer = 0;
int buttonState = 0;

void setup() {
  pinMode(2, INPUT);
  pinMode(PIN, OUTPUT);
  strip.begin();
  strip.show();
}

void loop() {
  while (timer > 0) {
    strip.clear();
    strip.show();
    timer--;
    delay(1000);
  }
  FadeInOut(255, 165, 0);
}

void setAll(byte red, byte green, byte blue) {
  for (byte i = 0; i < LEDS; i++ )strip.setPixelColor(i, red, green, blue);
  strip.show();
}

void FadeInOut(byte red, byte green, byte blue) {
  static int r, g, b = 0;
  if (timer == 0) {
    for (byte k = 165; k < 255; k = k + 1) {
      if  ( digitalRead(2) == HIGH && timer == 0) {
        timer = 15;
        break;
      }
      r = (k * red ) / 255;
      g = (k * green ) / 255;
      b = (k * blue) / 255;
      setAll((byte)r, (byte)g, (byte)b);
      delay(10);
    }
    for (byte k = 255; k >= 165; k = k - 1) {
      if  ( digitalRead(2) == HIGH && timer == 0) {
        timer = 15;
        break;
      }
      r = (k / 256.0) * red;
      g = (k / 256.0) * green;
      b = (k / 256.0) * blue;
      setAll((byte)r, (byte)g, (byte)b);
      delay(10);
    }
  }
}

Also, I've been using Tinkercad to test my code. It still works correctly on the program, so I'm a bit lost.

The code that you posted some minutes ago and the code kolaha posted in post #7
have

four substantial differencies.

I guess if you copy the code from kolaha new and upload it it will run again

How did I find the differencies? By using a software that can compare textfiles by content.
You should find such a software yourself. I will not give any hints about that because you are a little bit lazy. You did not remember that you made changes to your code.

Edit: You described the differencies you made in the posting.
Well there you got it: You did touch the code from kolaha. But claimed that you

from this example you can see:
Even the smallest change in the code can cause a change of the behaviour of the code.

As I have previously written:
To get your wanted functionality and highest responsivness your code must be fundamentally re-written using non-blocking timing.

If I say

fundamentally

i mean
fundamentally re-written.
non-blocking timing is

not

a small deviation from delay()
it is a way of thinking and coding that is

completely different

As long as you are not ready to learn something

completely new

you should stay away from it.

If you are not ready to learn something completely new you would scratch your head for hours trying to press it into the delay-thing but non-blocking timing does not fit into the delay-scheme.

As soon as you say:
OK let's learn this completely different approach it will become easy to learn.

Be the change you want to see in the world
best regards Stefan

I even tried it with the original code from Kolaha and it's doing the same thing that my code is doing with the cycling colors.

did you really do a new click on the copy-icon in the upper-right corner of the forum-posting and then pasting the clip-board-content into your Arduino-IDE?

I would check the wiring of the button

best regards Stefan

I did. I event tried it with a third Arduino and it still isn't giving me the right results. The wiring is still the same as my original wiring when the code from Kolaha worked.

I managed to fix it. I had to rewrite the for loop code.

#include <Adafruit_NeoPixel.h>

#define PIN 5
#define LEDS 60
Adafruit_NeoPixel strip(LEDS, PIN, NEO_GRB + NEO_KHZ800);

byte red = 255;
byte green = 50;
byte blue = 0;
int timer = 0;
int buttonState = 0;

void setup() {
  pinMode(2, INPUT);
  pinMode(PIN, OUTPUT);
  strip.begin();
  strip.show();
}

void loop() {
  while (timer > 0) {
    strip.clear();
    strip.show();
    timer--;
    delay(1000);
  }
  FadeInOut(255, 50, 0);
}

void setAll(byte red, byte green, byte blue) {
  for (byte i = 0; i < LEDS; i++ )strip.setPixelColor(i, red, green, blue);
  strip.show();
}

void FadeInOut(byte red, byte green, byte blue) {
  static int r, g, b = 0;
  if (timer == 0) {
    for (byte k = 55; k < 255; k = k + 1) {
      if  ( digitalRead(2) == HIGH && timer == 0) {
        timer = 15;
        break;
      }
      strip.setBrightness(k);
      setAll(red, green, blue);
      delay(10);
    }
    delay (1000);
    for (byte k = 255; k >= 55; k = k - 1) {
       if  ( digitalRead(2) == HIGH && timer == 0) {
        timer = 15;
        break;
      }
      strip.setBrightness(k);
      setAll(red, green, blue);
      delay(10);
    }
    delay (1000);
  }
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.