kitesurfer1404 / WS2812FX

WS2812 FX Library for Arduino and ESP8266

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Switching patterns by button presses

neopolygnath opened this issue · comments

Hello, found the WS2812FX library recently as I'm working on a lighting project that would require me to switch between complex segment patterns by pushing two buttons. I'm not a programmer and unsure if WS2812FX is even adaptable for my scenario. My issue:
I have two to patterns with two modes that I want to modify by button presses. I'm not a programmer myself (sadly) but I try to describe what I want to achieve and maybe someone here can help me with an example or give some hints:

Pressing the first button is intended to switch between the main patterns 1 and 2. Patterns 3 and 4 are color inverted versions of the two main patterns. So pressing the second button is intended to switch between patterns 1 and 3 and 2 and 4 (depending upon the previously selected pattern). To my understanding I would have to stop, swap and then re-initialize the activated pattern by "ws2812fx.start();". Is it even technically possible with the library (or could another library be more helpful here)? My patterns look like the following:

Pattern 1:

 ws2812fx.init();
 //ws2812fx.setBrightness(200);

 // parameters: index, start, stop, mode, color, speed, reverse
 ws2812fx.setSegment(0,  0,  9, FX_MODE_FIRE_FLICKER, 0xFF0000, 1000, false); // segment 0 is leds 0 - 9
 ws2812fx.setSegment(1,  10,  19, FX_MODE_BLINK, 0xFFFFFF, 1000, false); // segment 0 is leds 0 - 9
 ws2812fx.setSegment(2,  20,  29, FX_MODE_FIRE_FLICKER, 0x00FF00, 1000, false); // segment 0 is leds 0 - 9
 ws2812fx.setSegment(3,  30,  39, FX_MODE_BLINK, 0xFFFFFF, 1000, false); // segment 0 is leds 0 - 9
 ws2812fx.setSegment(4,  40,  49, FX_MODE_FIRE_FLICKER, 0x0000FF, 1000, false); // segment 0 is leds 0 - 9
 ws2812fx.start();
}

Pattern 2:

 ws2812fx.init();
 //ws2812fx.setBrightness(200);

 // parameters: index, start, stop, mode, color, speed, reverse
 ws2812fx.setSegment(0,  0,  9, FX_MODE_BLINK, 0xFF0000, 1000, false); // segment 0 is leds 0 - 9
 ws2812fx.setSegment(1,  10,  19, FX_MODE_FIRE_FLICKER, 0xFFFFFF, 1000, false); // segment 0 is leds 0 - 9
 ws2812fx.setSegment(2,  20,  29, FX_MODE_BLINK, 0x00FF00, 1000, false); // segment 0 is leds 0 - 9
 ws2812fx.setSegment(3,  30,  39, FX_MODE_FIRE_FLICKER, 0xFFFFFF, 1000, false); // segment 0 is leds 0 - 9
 ws2812fx.setSegment(4,  40,  49, FX_MODE_BLINK, 0x0000FF, 1000, false); // segment 0 is leds 0 - 9
 ws2812fx.start();
}

Pattern 3:

ws2812fx.init();
 //ws2812fx.setBrightness(200);

 // parameters: index, start, stop, mode, color, speed, reverse
 ws2812fx.setSegment(0,  0,  9, FX_MODE_FIRE_FLICKER, 0xFFFFFF, 1000, false); // segment 0 is leds 0 - 9
 ws2812fx.setSegment(1,  10,  19, FX_MODE_BLINK, 0xFF0000, 1000, false); // segment 0 is leds 0 - 9
 ws2812fx.setSegment(2,  20,  29, FX_MODE_FIRE_FLICKER, 0xFFFFFF, 1000, false); // segment 0 is leds 0 - 9
 ws2812fx.setSegment(3,  30,  39, FX_MODE_BLINK, 0x00FF00, 1000, false); // segment 0 is leds 0 - 9
 ws2812fx.setSegment(4,  40,  49, FX_MODE_FIRE_FLICKER, 0xFFFFFF, 1000, false); // segment 0 is leds 0 - 9
 ws2812fx.start();
}

Pattern 4:

 ws2812fx.init();
 //ws2812fx.setBrightness(200);

 // parameters: index, start, stop, mode, color, speed, reverse
 ws2812fx.setSegment(0,  0,  9, FX_MODE_BLINK, 0xFFFFFF, 1000, false); // segment 0 is leds 0 - 9
 ws2812fx.setSegment(1,  10,  19, FX_MODE_FIRE_FLICKER, 0xFF0000, 1000, false); // segment 0 is leds 0 - 9
 ws2812fx.setSegment(2,  20,  29, FX_MODE_BLINK, 0xFFFFFF, 1000, false); // segment 0 is leds 0 - 9
 ws2812fx.setSegment(3,  30,  39, FX_MODE_FIRE_FLICKER, 0x00FF00, 1000, false); // segment 0 is leds 0 - 9
 ws2812fx.setSegment(4,  40,  49, FX_MODE_BLINK, 0xFFFFFF, 1000, false); // segment 0 is leds 0 - 9
 ws2812fx.start();
}

Seems like you're using button1 to change the effect of each segment, and button2 to change the color of each segment. You don't need to reconfigure each segment whenever a button is pressed. You can just use setSegment() to initialize the segments, then use setMode() and setColor() to update the segments in response to a button press. This is what I came up with:

#include <WS2812FX.h>

#define LED_PIN   D2  // digital pin used to drive the LED strip
#define LED_COUNT 50  // number of LEDs on the strip

#define BUTTON1_PIN   D0 // digital pin for button 1
#define BUTTON2_PIN   D1 // digital pin for button 2

boolean button1 = HIGH; // initial state of the buttons
boolean button2 = HIGH;

boolean modeState = false;  // initial state of the effect mode
boolean colorState = false; // initial state of the color palette

WS2812FX ws2812fx = WS2812FX(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

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

  pinMode(BUTTON1_PIN, INPUT_PULLUP); // config buttons as inputs with pullup resistors
  pinMode(BUTTON2_PIN, INPUT_PULLUP);

  ws2812fx.init();
  ws2812fx.setBrightness(128);

  // parameters: index, start, stop, mode, color, speed, reverse
  ws2812fx.setSegment(0,   0,   9, FX_MODE_FIRE_FLICKER, RED,   1000, false);
  ws2812fx.setSegment(1,  10,  19, FX_MODE_BLINK,        WHITE, 1000, false);
  ws2812fx.setSegment(2,  20,  29, FX_MODE_FIRE_FLICKER, GREEN, 1000, false);
  ws2812fx.setSegment(3,  30,  39, FX_MODE_BLINK,        WHITE, 1000, false);
  ws2812fx.setSegment(4,  40,  49, FX_MODE_FIRE_FLICKER, BLUE,  1000, false);
  ws2812fx.start();
}

void loop() {
  ws2812fx.service();

  // Check button 1 (controls the effect mode)
  boolean newState = digitalRead(BUTTON1_PIN);
  if((newState == LOW) && (button1 == HIGH)) { // button 1 toggled high to low
    if(modeState) {
      ws2812fx.setMode(0, FX_MODE_FIRE_FLICKER);
      ws2812fx.setMode(1, FX_MODE_BLINK);
      ws2812fx.setMode(2, FX_MODE_FIRE_FLICKER);
      ws2812fx.setMode(3, FX_MODE_BLINK);
      ws2812fx.setMode(4, FX_MODE_FIRE_FLICKER);
    } else {
      ws2812fx.setMode(0, FX_MODE_BLINK);
      ws2812fx.setMode(1, FX_MODE_FIRE_FLICKER);
      ws2812fx.setMode(2, FX_MODE_BLINK);
      ws2812fx.setMode(3, FX_MODE_FIRE_FLICKER);
      ws2812fx.setMode(4, FX_MODE_BLINK);
    }
    modeState = !modeState;
  }
  button1 = newState;

  // Check button 2 (controls the color scheme)
  newState = digitalRead(BUTTON2_PIN);
  if((newState == LOW) && (button2 == HIGH)) { // button 2 toggled high to low
    if(colorState) {
      ws2812fx.setColor(0, RED);
      ws2812fx.setColor(1, WHITE);
      ws2812fx.setColor(2, GREEN);
      ws2812fx.setColor(3, WHITE);
      ws2812fx.setColor(4, BLUE);
    } else {
      ws2812fx.setColor(0, WHITE);
      ws2812fx.setColor(1, RED);
      ws2812fx.setColor(2, WHITE);
      ws2812fx.setColor(3, GREEN);
      ws2812fx.setColor(4, WHITE);
    }
    colorState = !colorState;
  }
  button2 = newState;
}

Wow, that was fast (and it's working like a charm). Many thanks for your input and your example :-) It depicts capabilities of this library I had not even thought possible. Especially the solution to decouple the segment description from the rest and your way to set the modes and colors - that's just elegant - I raise my virtual hat to your programming skills. Thank you and best wishes