Push button to switching Led effects

Hi guys. I'm learning coding and slowly ,slowly ,slowly start to understand something. But
I've got some issue with the original code from Adafruit NeoPixel. Library called "buttoncycler". The button operate without interrupt in progress. Is it possibble change that function to be operate straight after button is pressed, Led effect is changing??
Thank you for any help

Sorry for code this way . I'm was doing this on my phone and couldn't format that code there.

1 Like

This will prevent you from doing that. You have to completely restructure the program timing to use millis() and never use delay() for anything.

1 Like

Non-blocking timing tutorials:
Blink without delay().
Beginner's guide to millis().
Several things at a time.

Read the forum guidelines to see how to properly post code and some hints on how to get the most from this forum.
Use the IDE autoformat tool (ctrl-t or Tools, Auto format) before posting code in code tags.

Ok thanks for answer. I will try to do it.

Thank you for advice.

BTW

Always:

Show us a good schematic of your proposed circuit. Show us a good image of your ‘actual’ wiring.
Give links to components.


In the Arduino IDE, use Ctrl T or CMD T to format your code then copy the complete sketch.

Use the </> icon from the ‘reply menu’ to attach the copied sketch.

Ok . Trying to use forum on android phone. And still learning.

Aarg so my thinking going this way. If I'll use part of this code

#define BUTTON_PIN   2

#define PIXEL_PIN    6  // Digital IO pin connected to the NeoPixels.

#define PIXEL_COUNT 16  // Number of NeoPixels

// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 3 = Pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   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)

boolean oldState = HIGH;
int     mode     = 0;    // Currently-active animation mode, 0-9

void setup() {
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  strip.begin(); // Initialize NeoPixel strip object (REQUIRED)
  strip.show();  // Initialize all pixels to 'off'
}

void loop() {
  // Get current button state.
  boolean newState = digitalRead(BUTTON_PIN);

  // Check if state changed from high to low (button press).
  if((newState == LOW) && (oldState == HIGH)) {
    // Short delay to debounce button.
    delay(20);
    // Check if button is still low after debounce.
    newState = digitalRead(BUTTON_PIN);
    if(newState == LOW) {      // Yes, still low
      if(++mode > 8) mode = 0; // Advance to next mode, wrap around after #8
      switch(mode) {           // Start the new animation...
        case 0:
          colorWipe(strip.Color(  0,   0,   0), 50);    // Black/off
          break;
        case 1:
          colorWipe(strip.Color(255,   0,   0), 50);    // Red
          break;
        case 2:
          colorWipe(strip.Color(  0, 255,   0), 50);    // Green
          break;
        case 3:
          colorWipe(strip.Color(  0,   0, 255), 50);    // Blue
          break;
        case 4:
          theaterChase(strip.Color(127, 127, 127), 50); // White
          break;
        case 5:
          theaterChase(strip.Color(127,   0,   0), 50); // Red
          break;
        case 6:
          theaterChase(strip.Color(  0,   0, 127), 50); // Blue
          break;
        case 7:
          rainbow(10);
          break;
        case 8:
          theaterChaseRainbow(50);
          break;
      }
    }
  }

  // Set the last-read button state to the old state.
  oldState = newState;
}

And in "case" I'll put any other animation from FastLed library. It should work. Correct me please if I'm wrong.
Thank you.

The concept is so far ok, but handling that button it might become more difficult than expected. Had the same issue some time ago and found some nice coding which can be used to handle several things with in single button:

/* 4-Way Button:  Click, Double-Click, Press+Hold, and Press+Long-Hold Test Sketch

  By Jeff Saltzman
  Oct. 13, 2009

  To keep a physical interface as simple as possible, this sketch demonstrates generating four output events from a single push-button.
  1) Click:  rapid press and release
  2) Double-Click:  two clicks in quick succession
  3) Press and Hold:  holding the button down
  4) Long Press and Hold:  holding the button for a long time
*/
#include <Wire.h>


#define buttonPin 8        // analog input pin to use as a digital input
#define ledPin1 6          // digital output pin for pwr-mosfet
#define ledPin2 3          // digital output pin for LED 2
#define ledPin3 4          // digital output pin for LED 3
#define ledPin4 13          // digital output pin for LED 4

// LED variables
boolean ledVal1 = false;    // state of LED 1
boolean ledVal2 = false;    // state of LED 2
boolean ledVal3 = false;    // state of LED 3
boolean ledVal4 = false;    // state of LED 4


//=================================================

void setup() {
  Serial.begin(115200);

  // Set button input pin
  pinMode(buttonPin, INPUT);
  digitalWrite(buttonPin, HIGH );
  // Set LED output pins
  pinMode(ledPin1, OUTPUT);
  digitalWrite(ledPin1, ledVal1);
  pinMode(ledPin2, OUTPUT);
  digitalWrite(ledPin2, ledVal2);
  pinMode(ledPin3, OUTPUT);
  digitalWrite(ledPin3, ledVal3);
  pinMode(ledPin4, OUTPUT);
  digitalWrite(ledPin4, ledVal4);

} // setup




void loop() {
  // Get button event and act accordingly
  int b = checkButton();
  if (b == 1) clickEvent();
  if (b == 2) doubleClickEvent();
  if (b == 3) holdEvent();
  if (b == 4) longHoldEvent();
}

//=================================================
// Events to trigger

void clickEvent() {
  ledVal1 = !ledVal1;
  digitalWrite(ledPin1, ledVal1);
}
void doubleClickEvent() {
  ledVal2 = !ledVal2;
  digitalWrite(ledPin2, ledVal2);
}
void holdEvent() {
  ledVal3 = !ledVal3;
  digitalWrite(ledPin3, ledVal3);
}
void longHoldEvent() {
  ledVal4 = !ledVal4;
  digitalWrite(ledPin4, ledVal4);
}
//=================================================
//  MULTI-CLICK:  One Button, Multiple Events

// Button timing variables
int debounce = 20;          // ms debounce period to prevent flickering when pressing or releasing the button
int DCgap = 250;            // max ms between clicks for a double click event
int holdTime = 1000;        // ms hold period: how long to wait for press+hold event
int longHoldTime = 3000;    // ms long hold period: how long to wait for press+hold event

// Button variables
boolean buttonVal = HIGH;   // value read from button
boolean buttonLast = HIGH;  // buffered value of the button's previous state
boolean DCwaiting = false;  // whether we're waiting for a double click (down)
boolean DConUp = false;     // whether to register a double click on next release, or whether to wait and click
boolean singleOK = true;    // whether it's OK to do a single click
long downTime = -1;         // time the button was pressed down
long upTime = -1;           // time the button was released
boolean ignoreUp = false;   // whether to ignore the button release because the click+hold was triggered
boolean waitForUp = false;        // when held, whether to wait for the up event
boolean holdEventPast = false;    // whether or not the hold event happened already
boolean longHoldEventPast = false;// whether or not the long hold event happened already

int checkButton() {
  int event = 0;
  buttonVal = digitalRead(buttonPin);
  // Button pressed down
  if (buttonVal == LOW && buttonLast == HIGH && (millis() - upTime) > debounce)
  {
    downTime = millis();
    ignoreUp = false;
    waitForUp = false;
    singleOK = true;
    holdEventPast = false;
    longHoldEventPast = false;
    if ((millis() - upTime) < DCgap && DConUp == false && DCwaiting == true)  DConUp = true;
    else  DConUp = false;
    DCwaiting = false;
  }
  // Button released
  else if (buttonVal == HIGH && buttonLast == LOW && (millis() - downTime) > debounce)
  {
    if (not ignoreUp)
    {
      upTime = millis();
      if (DConUp == false) DCwaiting = true;
      else
      {
        event = 2;
        DConUp = false;
        DCwaiting = false;
        singleOK = false;
      }
    }
  }
  // Test for normal click event: DCgap expired
  if ( buttonVal == HIGH && (millis() - upTime) >= DCgap && DCwaiting == true && DConUp == false && singleOK == true && event != 2)
  {
    event = 1;
    DCwaiting = false;
  }
  // Test for hold
  if (buttonVal == LOW && (millis() - downTime) >= holdTime) {
    // Trigger "normal" hold
    if (not holdEventPast)
    {
      event = 3;
      waitForUp = true;
      ignoreUp = true;
      DConUp = false;
      DCwaiting = false;
      //downTime = millis();
      holdEventPast = true;
    }
    // Trigger "long" hold
    if ((millis() - downTime) >= longHoldTime)
    {
      if (not longHoldEventPast)
      {
        event = 4;
        longHoldEventPast = true;
      }
    }
  }
  buttonLast = buttonVal;
  return event;
}









Maybe it helps you!

2 Likes

Thank you falkgottschalk for your answer. It might be good idea to use it to Led strip. I'll try to use your code to.

It is especially for people who are reading on phones, that code tags are so important.

I believe the animations in that code are themselves blocking. So unless you fix the animations themselves to make them non-blocking, you are wrong.

1 Like

Sorry for lack of brackets. Tried to corrected it but I posted same thing again haha. But other post with a code was ok.

Well . Yes it is blocking. The button must be press to start another animation. So like you answered earlier aarg. If I'll change part where
delay(wait); // Pause for a moment
Or remove delay completely that should working as interrupt. Button pressed, animation changes straight away.

Using an interrupt for a button press, to avoid blocking routines, is a classic mistake. But I will let you find out why, for yourself.

1 Like

Ok . Thank you anyway for your help aarg. I'll try to find it.

The FastLed library can be used with non-blocking techniques. It is only the examples that are crudely constructed as blocking.

Here is a non-blocking effect I wrote:

void shiftRGBStripe(int speed) {
  static int i;
  static int colour = 0;

  switch (colour) {
    case 0 :
      leds[i].setRGB(0, 12, 0);
      break;
    case 1 :
      leds[i].setRGB(0, 0, 12);
      break;
    case 2 :
      leds[i].setRGB(12, 0, 0);
      break;
  }
  i++;
  if (i > NUM_LEDS) {
    i = 0;
    colour++;
  }
  if (colour > 2) colour = 0;
}

... just noticed I didn't use 'speed'. So much work, so little time. :slight_smile:

1 Like

Yes . I understand this. That's why I was asking how it can be change to not be blocked. Which line of the code is responsible for this ,and how this can be reverse. Someone was ssid here about millis().
So will try this. If I managed of course.

Oh thanks mate. You just sent that while I was replying

It isn't about just "changing a line". You have to restructure the logic, which usually involves changing many lines.

1 Like