LED Strip Button looping code issue

I've looked at the video. I don't actually see what you mean, the fading might be fast since there is no pause, counting to 255 is like 123 cycles.
Remember also that code goes to dark, make a quick pause, and then fade again from full bright.

In any case, here is a version with a small state machine, it's cleaner

#include <FastLED.h>
#define NUM_LEDS 30
#define DATA_PIN 5
CRGB leds[NUM_LEDS];

const byte buttonPin = 7;

enum : byte {STOPPED, RUNNING, PAUSING} currentState = PAUSING;

const int deltaStep = 5;
const int startingColor = 255;
int colorStep = startingColor;

unsigned long pauseStartTime;
const unsigned long pauseDuration = 1000; // in ms ie 1 second

void fillStrip(byte c) {
  for (byte px = 0; px < NUM_LEDS; px++) leds[px] = CRGB(0, c, 0);
  FastLED.show();
}

void black() {
  FastLED.clear();
  FastLED.show(); // not sure if this is neeed after clear
}

void manageStrip() {
  if (digitalRead(buttonPin) == HIGH) {     // button not pressed
    if (currentState != STOPPED) {
      black();
      currentState = STOPPED;
    }
  } else {                                  // button pressed
    switch (currentState) {
      case STOPPED:  // we were stopped and button got pressed, start running
        fillStrip(colorStep); // start where we left off
        currentState = RUNNING;
        break;

      case RUNNING:
        fillStrip(colorStep);
        colorStep -= deltaStep;
        if (colorStep <= 0) {
          colorStep = startingColor;
          pauseStartTime = millis();
          currentState = PAUSING;
        }
        break;

      case PAUSING:
        if (millis() - pauseStartTime >= pauseDuration) {
          currentState = RUNNING;
        }
        break;
    }
  }
}

void setup() {
  pinMode(buttonPin, INPUT_PULLUP); // wire pin D7 --- button --- GND
  FastLED.addLeds<WS2811, DATA_PIN, RGB>(leds, NUM_LEDS);
  black();
}

void loop() {
  manageStrip();
}

if you want to slow things down to see what's going on, change the fillStrip() function into

void fillStrip(byte c) {
  for (byte px = 0; px < NUM_LEDS; px++) leds[px] = CRGB(0, c, 0);
  FastLED.show();
  delay(100); // 10 Hz update
}

Hi Jean-Marc,

Thank so much for the re-write. Much cleaner :+1:
Still can't get the desired effect unfortunately.

If I only tap the switch it only light on for brief moment - no fade.

If I hold the switch I get the desired effect.

I really need it to do one light up the fade every if the switch is only tapped.

Hope that makes sense.

I'm going to keep battling now but let me know if you have any other ideas. I've attached code how it stands right now.

Thanks again for all your ongoing help. Do you code for work or just for your own projects?

#include <FastLED.h>
#define NUM_LEDS 30
#define DATA_PIN 5
CRGB leds[NUM_LEDS];

const byte buttonPin = 7;

enum : byte {STOPPED, RUNNING, PAUSING} currentState = PAUSING;

const int deltaStep = 1;
const int startingColor = 255;
int colorStep = startingColor;

unsigned long pauseStartTime;
const unsigned long pauseDuration = 300; // in ms ie 1 second

void fillStrip(byte c) {
  for (byte px = 0; px < NUM_LEDS; px++) leds[px] = CRGB(0, 0, c);
  FastLED.show();
  //delay(10);
}

void black() {
  FastLED.clear();
  FastLED.show(); // not sure if this is neeed after clear
}

void manageStrip() {
  if (digitalRead(buttonPin) == HIGH) {     // button not pressed
    if (currentState != STOPPED) {
      black();
      currentState = STOPPED;
    }
  } else {                                  // button pressed
    switch (currentState) {
      case STOPPED:  // we were stopped and button got pressed, start running
        fillStrip(colorStep); // start where we left off
        currentState = RUNNING;
        break;

      case RUNNING:
        fillStrip(colorStep);
        colorStep -= deltaStep;
        if (colorStep <= 0) {
          colorStep = startingColor;
          pauseStartTime = millis();
          currentState = PAUSING;
        }
        break;

      case PAUSING:
        if (millis() - pauseStartTime >= pauseDuration) {
          currentState = RUNNING;
        }
        break;
    }
  }
}

void setup() {
  pinMode(buttonPin, INPUT_PULLUP); // wire pin D7 --- button --- GND
  FastLED.addLeds<WS2811, DATA_PIN, RGB>(leds, NUM_LEDS);
  black();
}

void loop() {
  manageStrip();
}

Hi

You mean a simple touch would do a full cycle even if you don’t hold?

(I’m retired - software engineering background)

Hi Jean-Marc,

I'm Rob by the way :slight_smile:

Yes! That's exactly what I mean. I'm trying to add debounce to the code as we speak but no luck so far...

Hope you're enjoying your own projects now you're retired :slight_smile: Wish I'd started learning to program years ago..

Hi Rob

I’ll have a look tomorrow if you don’t solve it by then.

Cool, thank you. Wish me luck!

so no luck?

I would go for a modification of the state machine to only check for button state when you have completed a cycle

#include <FastLED.h>
#define NUM_LEDS 30
#define DATA_PIN 5
CRGB leds[NUM_LEDS];

const byte buttonPin = 7;

enum : byte {STOPPED, RUNNING, PAUSING} currentState = STOPPED;

const int deltaStep = 5;
const int startingColor = 255;
int colorStep = startingColor;

unsigned long pauseStartTime;
const unsigned long pauseDuration = 1000; // in ms ie 1 second

void fillStrip(byte c) {
  for (byte px = 0; px < NUM_LEDS; px++) leds[px] = CRGB(0, c, 0);
  FastLED.show();
}

void black() {
  FastLED.clear();
  FastLED.show(); // not sure if this is neeed after clear
}

void manageStrip() {
  switch (currentState) {
    case STOPPED:  // we are stopped, if there is one button press, start running
      if (digitalRead(buttonPin) == LOW) {
        colorStep = startingColor;
        currentState = RUNNING;
      }
      break;

    case RUNNING: // run a complete cycle, at the end check for button still pressed
      fillStrip(colorStep);
      colorStep -= deltaStep;
      if (colorStep <= 0) {
        black();
        if (digitalRead(buttonPin) == LOW) { // button is still pressed, pause for a bit
          colorStep = startingColor;
          pauseStartTime = millis();
          currentState = PAUSING;
        } else { // button is no longer pressed, stop
          currentState = STOPPED;
        }
      }
      break;

    case PAUSING:
      if (millis() - pauseStartTime >= pauseDuration) {
        currentState = RUNNING;
      }
      break;
  }
}

void setup() {
  pinMode(buttonPin, INPUT_PULLUP); // wire pin D7 --- button --- GND
  FastLED.addLeds<WS2811, DATA_PIN, RGB>(leds, NUM_LEDS);
  black();
}

void loop() {
  manageStrip();
}

(typed here, fully untested)

Hiya, battled with it till late last night to no avail...

I’m at work right now and the circuit is at home so I can’t test.

I’ll give it a go and let you know later :slight_smile:

Do you think I could use a capacitor for this function as a hardware add on? Just wondering...

Thanks for the code! I’ll let you know how I get on :+1:

I don't get the question. Where would you put a cap?

I thought that the issue may be with debouncing and read that you can use caps for debouncing...

Cap goes between switch pins...

ah - OK sure you could, it does not hurt but is an extra part.

I don't think it's really needed, one "flash" will probably last longer than 15/20 ms which is usually more than the bounce time of those small momentary buttons and we don't check the state again before one cycle is completed.

This works great! I just modified the deltaStep and the pause duration to suit my needs but absolutely brilliant!

I will study the last code and this to try and understand the differences.

Thank you so much for all your help! :smiley: Couldn't have done it without you :slight_smile:

Here's the final code I've used - just so it's up on here.

#include <FastLED.h>
#define NUM_LEDS 30
#define DATA_PIN 5
CRGB leds[NUM_LEDS];

const byte buttonPin = 7;

enum : byte {STOPPED, RUNNING, PAUSING} currentState = STOPPED;

const int deltaStep = 1;
const int startingColor = 255;
int colorStep = startingColor;

unsigned long pauseStartTime;
const unsigned long pauseDuration = 300; // in ms ie 1 second

void fillStrip(byte c) {
  for (byte px = 0; px < NUM_LEDS; px++) leds[px] = CRGB(0, 0, c);
  FastLED.show();
}

void black() {
  FastLED.clear();
  FastLED.show(); // not sure if this is neeed after clear
}

void manageStrip() {
  switch (currentState) {
    case STOPPED:  // we are stopped, if there is one button press, start running
      if (digitalRead(buttonPin) == LOW) {
        colorStep = startingColor;
        currentState = RUNNING;
      }
      break;

    case RUNNING: // run a complete cycle, at the end check for button still pressed
      fillStrip(colorStep);
      colorStep -= deltaStep;
      if (colorStep <= 0) {
        black();
        if (digitalRead(buttonPin) == LOW) { // button is still pressed, pause for a bit
          colorStep = startingColor;
          pauseStartTime = millis();
          currentState = PAUSING;
        } else { // button is no longer pressed, stop
          currentState = STOPPED;
        }
      }
      break;

    case PAUSING:
      if (millis() - pauseStartTime >= pauseDuration) {
        currentState = RUNNING;
      }
      break;
  }
}

void setup() {
  pinMode(buttonPin, INPUT_PULLUP); // wire pin D7 --- button --- GND
  FastLED.addLeds<WS2811, DATA_PIN, RGB>(leds, NUM_LEDS);
  black();
}

void loop() {
  manageStrip();
}

great news (I want to see the video :slight_smile: )

have fun

Here ya go! So happy with this just wanna learn quicker! Thanks again :slight_smile:

jean480.mov.zip (3.4 MB)

Hi,
Good to see its working;
@Eleventy3 LED strip, frame shot.

Tom... :grinning: :+1: :coffee: :australia:

Nice ! thanks for the video

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