Hey crew,  I am trying to use a button to cycle through effects and

Hey crew, I am trying to use a button to cycle through effects and everything is working fine, but I can’t figure out how to make this rainbow fade effect I am using in cases 4 & 5 continue to loop while still retaining the ability to interrupt it with a button push. Right now it just cycles through the spectrum once and then stops. However, if I do something like: for(hue=755; hue>10; hue–), I can’t make the button switch to the next case. Here’s the code: http://pastebin.com/ybcPZm3b

Any suggestions? Thanks in advance!

The delay() in the rainbow code is a blocking delay. You won’t be able to do anything during your delay(). Try inserting myBtn.read(); in the rainbow() function somewhere so you read the button during the animation and remove the delay and replace it with LEDS.delay().

By switching any call to the library from FastLED.whatever to LEDS.whatever you can save a few bytes every time you call it FYI.

Jeez… tried that in a few different ways and still no luck. Again, it will cycle through the rainbow, but it wont recognize the button press. Here’s the code as it stands now: http://pastebin.com/XkTCVnYe

I was thinking more along the lines of this:

void rainbow(uint8_t wait){
static byte hue = 0;
fill_rainbow( leds, NUM_LEDS, hue );
myBtn.read();
LEDS.show();
LEDS.delay(wait);
myBtn.read();
hue++;
}
return;
}

The hue is in range of 255, the for loop you had going on was confusing, because the LED library will automatically correct for over numbers that are too large.

The type of LED you use requires that all interrupts be disabled while you are writing data to the leds, so if the button library is working on interrupts, you can see why your missing a press.

Still no luck… can’t believe this is giving me so much trouble. Using the code you suggested, the strip will cycle through the rainbow once, but still will not recognize the button push until hue has reached 255. Even if the button did work, would I just continue the rainbow by using an if(hue=255) {hue = 0} statement?

What happens if you change your pooling of the button to IS PRESSED rather than WAS PRESSED

This is why I don’t use for loops in my functions. I keep the hue variable outside, as a global variable, and increment it inside of the function as it’s being used. So something like:


// maxEffects is the maximum number of effects available, for example 5 effects
const uint8_t maxEffects = 5;

// state defines which effect is currently being displayed and is a number between 1 to maxEffects
volatile uint8_t state = 1;

// global hue variable
volatile uint8_t hue = 0;

void setup() {
// FastLED setup
// Other setup stuff
}

void loop() {
// This loop will run as fast as it can, always checking the button with every loop. If you need it slower, add an appropriate millis() check - never use a blocking delay()

// check button state

if (button has changed) {
// increment state
state++;
if (state > maxEffects) state = 1;
}
displayEffect(state);
}

static displayEffect(uint8_t effect) {
switch (effect) {
case 1: effectOne(); break;
case 2: effectTwo(); break;
case 3: effectThree(); break;
// etc., etc.
default: LEDS.showColors(CRGB::Black); break;
}
}

// effectOne - Rainbow
static void effectOne() {
FastLED.clear();
fill_rainbow( &(leds[0]), NUM_LEDS /led count/, hue /starting hue/);
hue++;
FastLED.show();
}

Now if you need to run the rainbow slower, stick a millis() check in the function (make sure you initialize patternLastRun and pause accordingly):

// effectOne - Rainbow
static void effectOne() {
if (millis() - patternLastRun > pause) {
FastLED.clear(); // why are you clearing it?
fill_rainbow( &(leds[0]), NUM_LEDS /led count/, hue /starting hue/);
hue++;
FastLED.show();
patternLastRun = millis();
}
}

Jon: Thank you - the IS PRESSED worked as far as recognizing the button push, but I was still stuck inside of the rainbow effect - every time I pushed the button it would start the rainbow fade over.

Ashley: I believe that is how my current sketch is set up. (see, e.g. ,http://pastebin.com/muBeQ3Gh ). However, for some reason the hue++ doesn’t increment the leds - so I just see a solid, unchanging red in all of the leds.

Thank you both for taking the time to reply to this stuff - I’m sure you have far better things to do than fix the problems with my code =\

I’ll have to set up a test rig to see where or why it’s doing that. It should work, but maybe something else is causing that behavior. Unfortunately my test rig has been torn apart as I’m working on my oven and I needed the space. If you can’t figure it out, I’ll set up a rig and see if I can figure it out.

@Ashley_M_Kirchner_No What kind of cookies are you baking in that oven of yours?

None. Just working on the layout on the new TFT LCD. Then adding remaining code. Oven itself, stock configuration, works like shit.

@Ashley_M_Kirchner_No is this a oven you are converting to a reflow oven or was it already a reflow oven when you purchased it?

Cheap Chinese oven, T962.

As I believe Ashley mentions before, use timers for you delay. This allows you to multitask and get more work done while you are waiting. Definitely have to not do to much as you will affect your timing if what you are doing takes longer than your delay…

if (millis()>mydelay)
{
do rainbow();
mydelay = millis()+rainbowdelaytime;
}else
{
checkbutton();
}

Still stuck on this… for some reason I can’t get the rainbow_fill statement to work without using a for() function…i.e. the hue++ doesn’t work here:

int patternLastRun = 0;
uint8_t hue = 0;

static void rainbow(int pause){
if(millis() - patternLastRun > pause) {
fill_rainbow(&(leds[0]), NUM_LEDS, hue);
hue++;
FastLED.show();
patternLastRun=millis();
}
}

Am I doing something wrong here?

Where are you initializing that variable? If you’re putting it inside of the function, it needs to be “static uint8_t hue;”. Otherwise it needs to be at the top of your program, outside of the function.

It is outside of the function - just as shown in my last comment. Here is the full code: http://pastebin.com/pKYpkKgj

Right now, when I get to case 4, I just get a solid, static red on all LEDs.

You don’t need a for loop, the library does it for you. This shippet is from the colorutils.cpp file of the lib:

void fill_rainbow( struct CRGB * pFirstLED, int numToFill,
uint8_t initialhue,
uint8_t deltahue )
{
CHSV hsv;
hsv.hue = initialhue;
hsv.val = 255;
hsv.sat = 255;
for( int i = 0; i < numToFill; i++) {
hsv2rgb_rainbow( hsv, pFirstLED[i]);
hsv.hue += deltahue;
}
}

I have no idea. I just copied the relevant code from yours and uploaded it to my UNO and I get a rainbow that’s moving. One thing you need to change is the patternLastRun, it needs to be a long, not int. But even as an int, it should be working.

Let me add the remaining pieces from your code and see where it fails.

Jon, yes, that does increase the color of each consecutive led by deltahue, but I am wanting the strip to “fade” through the hue values - in other words, every LED on the strip would be the same color at the same time, but the strip is continuously changing hue values