Go Down

Topic: FastLED and Button Library question (Read 816 times) previous topic - next topic

sokbok

Hello.

Simply, I am trying to use 4 buttons to control a strip of Ws2812 LEDs.

Each button should trigger a different pattern, Ive been using the FastLED Demo reel and modifying some of those patterns.

I am trying to make 3 patterns that resemble water and rainbow.

I am using JChristensen's Button Library which I have renamed button (different then the button library found using the library manager).

I think I have declared my buttons correctly, its just in the read button function, I dont know what to put to trigger the patterns.

Any help is greatly appreciated.

Link to my current code:

https://gist.github.com/slurrybowl/53177ff1c70de8959c8aab514d159505


Grumpy_Mike

Post your code do not link to it.

Read the button, then use an if statement to test if it is pushed, if it is then call the appropriate pattern function.

You will not be able to look at the button again and so change the pattern until the current pattern ends. Given that your use of a debounce library is totally unnecessary.

borland

I haven't used FastLED before, but it seems like you're going to need to add a Timer2 overflow interrupt to handle the button check by Christensen's button library.  The readbutton() function call won't take but a fraction of processor's time, so the button check can be done during/between any delay's needed by FastLED, and FastLED performance won't be noticeably impacted.

Take a look at Paul Stoffregen's MSTimer2 library on github.com.  His library includes an overflow interrupt routine, so very easy to implement within your Sketch.

Grumpy_Mike

Look at the context of the application. NO DEBOUNCE IS NEEDED
Forget it. Remove it. Do not do it.

borland

That should work!  Just don't push the wrong button.  Otherwise you'll have to comeback later, after the pattern function finishes, then push the right button.  Ops, wrong button again.  Darn, hate when that happens.
That wait could be all night for all we know.  Oh, wait a minute, there that reset button on the Arduino board.  Cool!

Grumpy_Mike

#5
Jul 09, 2017, 07:54 am Last Edit: Jul 09, 2017, 07:55 am by Grumpy_Mike
Sure what will happen if you are crap at programming. Their is no way a debounced button is going to help you with that is their?

Using an interrupt for a push button is a waste of time in this application, their is no way an interrupt is going to get you out of a pattern when you are writing code in C.

borland


You still have access to processor hardware registers in C/C++.  Software Reset by using Interrupt Reset Vector can be accessed via Watchdog System Reset.  Or call a pointer function to address 0.
Code: [Select]

 void(* resetFunc) (void) = 0;



Grumpy_Mike

So?

You seem to be missing the point here big time.

sokbok

#8
Jul 09, 2017, 06:18 pm Last Edit: Jul 18, 2017, 04:21 pm by sokbok Reason: proper code formatting
Thanks for the discussion.  :)

My understanding of interrupts and debouncing is very poor....BUT

Below is some code that I started with. It uses 1 button to scroll through a pattern list and
the patterns can be changed "on the fly". I am attempting to use 4 buttons (each button has its own pattern) and change the strip "on the fly".

Code: [Select]
//***************************************************************
// This is Mark Kriegsman's FastLED DemoReel100 example with
// a modificaiton to use a button for changing patterns.  The
// timer used for picking a new pattern has been commented out
// and there is a button check inside the main loop now.
//
// Search for "BUTTON STUFF" to find the various button releated
// code additions.
//
// Marc Miller, March 2017
//***************************************************************

#include "FastLED.h"
#define DATA_PIN    11
#define CLK_PIN   13
#define LED_TYPE    LPD8806
#define COLOR_ORDER GRB
#define NUM_LEDS    32
CRGB leds[NUM_LEDS];
#define BRIGHTNESS          128
#define FRAMES_PER_SECOND  120


//---------------------------------------------------------------
//BUTTON STUFF
// This uses JChristensen's Button Library from:
//   https://github.com/JChristensen/Button
#include "Button.h"    // Include Button library
const int buttonPin = 4;  // Set digital pin used with debounced pushbutton
Button myButton(buttonPin, true, true, 50);  // Declare the button


//---------------------------------------------------------------
void setup() {
 Serial.begin(115200);  // Allows serial monitor output (check baud rate)
 delay(3000); // 3 second delay for recovery
 //FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
 FastLED.addLeds<LED_TYPE,DATA_PIN,CLK_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
 FastLED.setBrightness(BRIGHTNESS);
}


// List of patterns to cycle through.  Each is defined as a separate function below.
typedef void (*SimplePatternList[])();
SimplePatternList gPatterns = { rainbow, confetti, sinelon, juggle };

uint8_t gCurrentPatternNumber = 0; // Index number of which pattern is current
uint8_t gHue = 0; // rotating "base color" used by many of the patterns


//---------------------------------------------------------------
void loop()
{
 // Call the current pattern function once, updating the 'leds' array
 gPatterns[gCurrentPatternNumber]();

 // send the 'leds' array out to the actual LED strip
 FastLED.show();  
 // insert a delay to keep the framerate modest
 FastLED.delay(1000/FRAMES_PER_SECOND);

 // do some periodic updates
 EVERY_N_MILLISECONDS( 20 ) { gHue++; } // slowly cycle the "base color" through the rainbow

 // BUTTON STUFF
 //   Not using this timer to change patterns any more.  Instead check the button.
 //     EVERY_N_SECONDS( 10 ) { nextPattern(); } // change patterns periodically
 //
 readbutton();  // check for button press

}//end_main_loop

#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))


//---------------------------------------------------------------
void nextPattern()
{
 // add one to the current pattern number, and wrap around at the end
 gCurrentPatternNumber = (gCurrentPatternNumber + 1) % ARRAY_SIZE( gPatterns);
}

void rainbow()
{
 // FastLED's built-in rainbow generator
 fill_rainbow( leds, NUM_LEDS, gHue, 12);
}

void confetti()
{
 // random colored speckles that blink in and fade smoothly
 fadeToBlackBy( leds, NUM_LEDS, 20);
 int pos = random16(NUM_LEDS);
 leds[pos] += CHSV( gHue + random8(64), random8(128,200), random8(48,255));
}

void sinelon()
{
 // a colored dot sweeping back and forth, with fading trails
 fadeToBlackBy( leds, NUM_LEDS, 12);
 int pos = beatsin16( 13, 0, NUM_LEDS-1 );
 leds[pos] += CHSV( gHue, 255, 192);
}

void juggle() {
 // four colored dots, weaving in and out of sync with each other
 fadeToBlackBy( leds, NUM_LEDS, 20);
 byte dothue = 0;
 for( int i = 0; i < 4; i++) {
   leds[beatsin16( i+5, 0, NUM_LEDS-1 )] |= CHSV(dothue, 200, 255);
   dothue += 32;
 }
}


//BUTTON STUFF
//---------Function to read the button and do something----------
void readbutton() {
 myButton.read();
 if(myButton.wasPressed()) {
   Serial.println("Button pressed!  Next pattern...   ");
   nextPattern();  // Change to the next pattern

   //Flash pixel zero white as a visual that button was pressed.
   leds[0] = CHSV(0,0,255);  //Set first pixel color white
   FastLED.show();  //Update display
   delay(100);  //Short pause so we can see leds[0] flash
   leds[0] = CRGB::Black;  //Set first pixel off
   FastLED.show();  //Update display
   delay(100);  //Short pause so we can see leds[0] flash
 }
}//end_readbutton


//---------------------------------------------------------------

Grumpy_Mike

It looks way way too complex for what you want.

Please read this:-
How to use this forum
Because your post is breaking the rules about posting code.

sokbok

sigh....thanks for the reminder to post code correctly.

now, any insight for how to do this more efficiently?

thanks very much.

Qdeathstar

it's hard to tell. Go back and edit your post so we can see it clearly.
A creaking creeping shadow
stiff against the freezing fog
glares at a tickless watch.

Time has failed him -- all things shall pass.

Grumpy_Mike

#12
Jul 16, 2017, 08:28 am Last Edit: Jul 16, 2017, 08:31 am by Grumpy_Mike
sigh....thanks for the reminder to post code correctly.

now, any insight for how to do this more efficiently?
Even bigger sigh!

Go back, edit that post and post the code correctly. Then I can look at the code and maybe even try it out on my system.

But it would be so much better if you post your attempt at making this a four button job. Then we could tell you what you are getting wrong.

sokbok

Thanks for the clarification.

So....

One important thing is that I was recommended to use a button library I found here:
https://github.com/JChristensen/Button

I renamed it Button, which is different than another library with the same name that can be found in the library manager.

I have gotten the code below to successfully work, it scrolls through the pattern list and just uses 1 button.
Code: [Select]

#include "FastLED.h"


FASTLED_USING_NAMESPACE

// FastLED "100-lines-of-code" demo reel, showing just a few
// of the kinds of animation patterns you can quickly and easily
// compose using FastLED. 
//
// This example also shows one easy way to define multiple
// animations patterns and have them automatically rotate.
//
// -Mark Kriegsman, December 2014

#if FASTLED_VERSION < 3001000
#error "Requires FastLED 3.1 or later; check github for latest code."
#endif

#define DATA_PIN    6
//#define CLK_PIN   4
#define LED_TYPE    WS2811
#define COLOR_ORDER GRB
#define NUM_LEDS    12
CRGB leds[NUM_LEDS];

#define BRIGHTNESS          96
#define FRAMES_PER_SECOND  120

#include "Button.h"    // Include Button library
const int buttonPin = 4;  // Set digital pin used with debounced pushbutton
Button myButton(buttonPin, true, true, 50);  // Declare the butto

void setup() {
  Serial.begin(115200);
  delay(3000); // 3 second delay for recovery
 
  // tell FastLED about the LED strip configuration
  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  //FastLED.addLeds<LED_TYPE,DATA_PIN,CLK_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);

  // set master brightness control
  FastLED.setBrightness(BRIGHTNESS);
}


// List of patterns to cycle through.  Each is defined as a separate function below.
typedef void (*SimplePatternList[])();
SimplePatternList gPatterns = { confetti_GB, sinelon_B, juggle_B, rainbow};

uint8_t gCurrentPatternNumber = 0; // Index number of which pattern is current
uint8_t gHue = 0; // rotating "base color" used by many of the patterns
 
void loop()
{
  // Call the current pattern function once, updating the 'leds' array
  gPatterns[gCurrentPatternNumber]();

  // send the 'leds' array out to the actual LED strip
  FastLED.show(); 
  // insert a delay to keep the framerate modest
  FastLED.delay(1000/FRAMES_PER_SECOND);

  // do some periodic updates
  EVERY_N_MILLISECONDS( 20 ) { gHue++; } // slowly cycle the "base color" through the rainbow
  //EVERY_N_SECONDS( 10 ) { nextPattern(); } // change patterns periodically
 
  readbutton();  // check for button press

 
}

#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))

void nextPattern()
{
  // add one to the current pattern number, and wrap around at the end
  gCurrentPatternNumber = (gCurrentPatternNumber + 1) % ARRAY_SIZE( gPatterns);
}

void rainbow()
{
  // FastLED's built-in rainbow generator
  fill_rainbow( leds, NUM_LEDS, gHue, 7);
}

void rainbowWithGlitter()
{
  // built-in FastLED rainbow, plus some random sparkly glitter
  rainbow();
  addGlitter(80);
}

void addGlitter( fract8 chanceOfGlitter)
{
  if( random8() < chanceOfGlitter) {
    leds[ random16(NUM_LEDS) ] += CRGB::White;
  }
}

void confetti()
{
  // random colored speckles that blink in and fade smoothly
  fadeToBlackBy( leds, NUM_LEDS, 10);
  int pos = random16(NUM_LEDS);
  leds[pos] += CHSV( gHue + random8(64), 200, 255);
}

void sinelon_B()
{
  // a colored dot sweeping back and forth, with fading trails
  int Hue = 155;
  fadeToBlackBy( leds, NUM_LEDS, 20);
  int pos = beatsin16(40,0,NUM_LEDS);
  leds[pos] += CHSV( Hue, 255, 200);
}

void bpm()
{
  // colored stripes pulsing at a defined Beats-Per-Minute (BPM)
  uint8_t BeatsPerMinute = 62;
  CRGBPalette16 palette = PartyColors_p;
  uint8_t beat = beatsin8( BeatsPerMinute, 64, 255);
  for( int i = 0; i < NUM_LEDS; i++) { //9948
    leds[i] = ColorFromPalette(palette, gHue+(i*2), beat-gHue+(i*10));
  }
}

void juggle_B() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds, NUM_LEDS, 20);
  byte dothue = 155;
  for( int i = 0; i < 8; i++) {
    leds[beatsin16(i+7,0,NUM_LEDS)] |= CHSV(dothue, 200, 255);
    //dothue += 32;
  }
}

void confetti_GB()
{
  // random colored speckles, Green and Blue hues only
  // Green = 96, Blue = 160
  uint8_t p = 60;  // What percentage of the time to make speckles.  [Range 0-100]
 
  fadeToBlackBy( leds, NUM_LEDS, 10);
  if (random8(100) < p) {
    int pos = random16(NUM_LEDS);
    uint8_t hue = random8(2);  // randomly chooses a 0 or 1
    if (hue == 0) {
      hue = random8(92,111);  // pick a hue somewhere in the green zone
    } else {
      hue = random8(156,165);  // pick a hue somewhere in the blue zone
    }
    leds[pos] += CHSV( hue, random8(200,240), 255);
  }
}//end confetti_GB

//BUTTON STUFF
//---------Function to read the button and do something----------
void readbutton() {
  myButton.read();
  if(myButton.wasPressed()) {
    Serial.println("Button pressed!  Next pattern...   ");
    nextPattern();  // Change to the next pattern

    //Flash pixel zero white as a visual that button was pressed.
    leds[0] = CHSV(0,0,255);  //Set first pixel color white
    FastLED.show();  //Update display
    delay(100);  //Short pause so we can see leds[0] flash
    leds[0] = CRGB::Black;  //Set first pixel off
    FastLED.show();  //Update display
    delay(100);  //Short pause so we can see leds[0] flash
  }
}//end_readbutton



sokbok

My attempt to modify the above posted code to use 4 buttons is below. I have not gotten it to work properly.

What I think needs to be fixed is at the bottom of the code, where I specify what to do with myButtonA-D.read();

I need to call a command within the FastLED library to execute the command.

I think Im close, any help extremely appreciated.
Code: [Select]

#include "FastLED.h"

FASTLED_USING_NAMESPACE

// FastLED "100-lines-of-code" demo reel, showing just a few
// of the kinds of animation patterns you can quickly and easily
// compose using FastLED. 
//
// This example also shows one easy way to define multiple
// animations patterns and have them automatically rotate.
//
// -Mark Kriegsman, December 2014

#if FASTLED_VERSION < 3001000
#error "Requires FastLED 3.1 or later; check github for latest code."
#endif

#define DATA_PIN    6
//#define CLK_PIN   4
#define LED_TYPE    WS2811
#define COLOR_ORDER GRB
#define NUM_LEDS    12
CRGB leds[NUM_LEDS];

#define BRIGHTNESS          96
#define FRAMES_PER_SECOND  120

#include "Button.h"  // Include Button library

int i = 0;


const int buttonPinA = 1;  // Set digital pin 4 for button A
Button myButtonA(buttonPinA, true, true, 50);

const int buttonPinB = 2;  // Set digital pin 5 for button B
Button myButtonB(buttonPinB, true, true, 50);

const int buttonPinC = 3;  // Set digital pin 4 for button C
Button myButtonC(buttonPinC, true, true, 50);

const int buttonPinD = 4;  // Set digital pin 5 for button D
Button myButtonD(buttonPinD, true, true, 50);


void setup() {
  Serial.begin(115200);
  delay(3000); // 3 second delay for recovery
 
  // tell FastLED about the LED strip configuration
  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  //FastLED.addLeds<LED_TYPE,DATA_PIN,CLK_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);

  // set master brightness control
  FastLED.setBrightness(BRIGHTNESS);
}


// List of patterns to cycle through.  Each is defined as a separate function below.
//typedef void (*SimplePatternList[])();
//SimplePatternList gPatterns = { confetti_GB, sinelon_B, juggle_B, rainbow};

uint8_t gCurrentPatternNumber = 0; // Index number of which pattern is current
uint8_t gHue = 0; // rotating "base color" used by many of the patterns
 
void loop()
{
  // Call the current pattern function once, updating the 'leds' array
 // gPatterns[gCurrentPatternNumber]();

  // send the 'leds' array out to the actual LED strip
  FastLED.show(); 
  // insert a delay to keep the framerate modest
  FastLED.delay(1000/FRAMES_PER_SECOND);

  // do some periodic updates
  EVERY_N_MILLISECONDS( 20 ) { gHue++; } // slowly cycle the "base color" through the rainbow
  //EVERY_N_SECONDS( 10 ) { nextPattern(); } // change patterns periodically
 
  readbutton();  // check for button press

 
}

#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))

void nextPattern()
{
  // add one to the current pattern number, and wrap around at the end
 // gCurrentPatternNumber = (gCurrentPatternNumber + 1) % ARRAY_SIZE( gPatterns);
}

void rainbow()
{
  // FastLED's built-in rainbow generator
  fill_rainbow( leds, NUM_LEDS, gHue, 7);
}

void rainbowWithGlitter()
{
  // built-in FastLED rainbow, plus some random sparkly glitter
  rainbow();
  addGlitter(80);
}

void addGlitter( fract8 chanceOfGlitter)
{
  if( random8() < chanceOfGlitter) {
    leds[ random16(NUM_LEDS) ] += CRGB::White;
  }
}

void confetti()
{
  // random colored speckles that blink in and fade smoothly
  fadeToBlackBy( leds, NUM_LEDS, 10);
  int pos = random16(NUM_LEDS);
  leds[pos] += CHSV( gHue + random8(64), 200, 255);
}

void sinelon_B()
{
  // a colored dot sweeping back and forth, with fading trails
  int Hue = 155;
  fadeToBlackBy( leds, NUM_LEDS, 20);
  int pos = beatsin16(40,0,NUM_LEDS);
  leds[pos] += CHSV( Hue, 255, 200);
}

void bpm()
{
  // colored stripes pulsing at a defined Beats-Per-Minute (BPM)
  uint8_t BeatsPerMinute = 62;
  CRGBPalette16 palette = PartyColors_p;
  uint8_t beat = beatsin8( BeatsPerMinute, 64, 255);
  for( int i = 0; i < NUM_LEDS; i++) { //9948
    leds[i] = ColorFromPalette(palette, gHue+(i*2), beat-gHue+(i*10));
  }
}

void juggle_B() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds, NUM_LEDS, 20);
  byte dothue = 155;
  for( int i = 0; i < 8; i++) {
    leds[beatsin16(i+7,0,NUM_LEDS)] |= CHSV(dothue, 200, 255);
    //dothue += 32;
  }
}

void confetti_GB()
{
  // random colored speckles, Green and Blue hues only
  // Green = 96, Blue = 160
  uint8_t p = 60;  // What percentage of the time to make speckles.  [Range 0-100]
 
  fadeToBlackBy( leds, NUM_LEDS, 10);
  if (random8(100) < p) {
    int pos = random16(NUM_LEDS);
    uint8_t hue = random8(2);  // randomly chooses a 0 or 1
    if (hue == 0) {
      hue = random8(92,111);  // pick a hue somewhere in the green zone
    } else {
      hue = random8(156,165);  // pick a hue somewhere in the blue zone
    }
    leds[pos] += CHSV( hue, random8(200,240), 255);
  }
}//end confetti_GB

//BUTTON STUFF
//---------Function to read the buttons and do something----------
void readbutton() {
  myButtonA.read();
    if(myButtonA.wasPressed()) {
    confetti_GB ; 
      FastLED.show(); 
       FastLED.delay(1000 / FRAMES_PER_SECOND);

      //A was pressed so set a variable or do something
    }
  myButtonB.read();
    if(myButtonB.wasPressed()) {
       confetti_GB ; 
         FastLED.show(); 
          FastLED.delay(1000 / FRAMES_PER_SECOND);

      //B was pressed so set a variable or do something
    }
  myButtonC.read();
    if(myButtonC.wasPressed()) {
      confetti_GB ; 
         FastLED.show();
      //C was pressed so set a variable or do something
    }
myButtonD.read();
    if(myButtonD.wasPressed()) {
       leds[1].setRGB( 0, 255, 225);
       FastLED.show();
        delay(30);
      //D was pressed so set a variable or do something
    }
}



Go Up