FastLED: Problems with rainbow cycle

Hi everybody, this is my first topic in this website. My question is: how can I put rainbow cycle inside a switch-case? I use FastLED library and switch case for change the color of my leds. If I use only static colors, I don't have any problem, but when I put the rainbowcycle or other effect like that, my leds show also static effect. I red many articles about the troubleshooting of FastLED library, but I didn't find nothing about my question.
ProvaStaticColor.ino (1.9 KB)

Welcome to the forum

Please follow the advice given in the link below when posting code, in particular the section entitled 'Posting code and common code problems'

Use code tags (the </> icon above the compose window) to make it easier to read and copy for examination

1 Like

Hi,
I think your problem is that "startShow" is only getting called once when the button is pressed
If you put it directly in LOOP then the colours start cycling as expected :slight_smile:

I tried your solution, but the result didn't change

Please post the revised code here so that we can see what you have done

ProvaStaticColor.ino (1.9 KB)

#include "FastLED.h"

//FIXED GLOBAL VARS
#define BRIGHTNESS 15
#define DATA_PIN 11  //Define led data pin in
#define LED_TYPE NEOPIXEL  //define type of led
#define NUM_LEDS 4  //num of leds in strip
#define Button 8

bool oldState = HIGH;
int showType = 0;

CRGB leds[NUM_LEDS];  // Initialize LED array
CRGBPalette16 currentPalette;

uint8_t hue = 0;

void setup() {
  FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  pinMode(Button, INPUT_PULLUP);
  // put your setup code here, to run once:
  delay(2000); //for safe startup
  FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setBrightness(50);
}

void loop() {

bool newState = digitalRead(Button);

  // 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);
    if (newState == LOW) {
      showType++;
      if (showType > 8)
        showType=0;
      startShow(showType);
    }
  }

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

void startShow(int g){

  EVERY_N_MILLISECONDS(50){
    hue++;
  }
      
for (int i = 0; i < NUM_LEDS; i++) {  

switch(g){

case 0: leds[i] = CRGB::Black;
        break;
case 1: leds[i] = CRGB::Red;
        break;
case 2: leds[i] = CRGB::Green;
        break;
case 3: leds[i] = CRGB::Yellow;
        break;
case 4: leds[i] = CRGB::Blue;
        break;
case 5: leds[i] = CRGB::Purple;
        break;
case 6: leds[i] = CHSV(hue + (i * 200), 255, 255);
        break;
case 7: leds[i] = CRGB::Aqua;
        break;
case 8: leds[i] = CRGB::HotPink;
        break;       
}
}
FastLED.show();
}

If I understand what you are trying to achieve, when case 6 is active you want the LEDs to cycle through colours rather than just a static display?
For this to happen "startShow(showType);" needs to be called each time LOOP runs, but at the moment this only happens once when the button is pressed

Thanks for your answare. You have understand my question. So, what can I do?

1 Like

do you have a working sketch with the desired "rainbow cycle"?
Just this only effect without any other buttons.
Can you provide such a sketch?

1 Like

My sketch is based on this:

#include <FastLED.h>

#define NUM_LEDS  4
#define LED_PIN   11

CRGB leds[NUM_LEDS];

//has to be uint8_t so it starts at 0 after it reached 256
uint8_t hue = 0;

void setup() {
  FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setBrightness(50);
}

void loop() {
  
  for (int i = 0; i < NUM_LEDS; ++i) {
    leds[i] = CHSV(hue + (i * 10), 255, 255);
  }

  //You can change the pattern speed here
  EVERY_N_MILLISECONDS(15){
    hue++;
  }
  
  FastLED.show();
}

This sketch show the rainbow effect on my Ws2812b without problems

if you make the next line after: void loop() {
startShow(showType);

I think that will get the display doing something

1 Like

@ Andrea_Bonato
and the other "modes" should be fixed colours or do you like that flickering?

1 Like

Other case have static colours

It doesn't work

I had to change some pins, but you should be able to find the change.

#include "FastLED.h"

//FIXED GLOBAL VARS
#define BRIGHTNESS 15
#define LED_TYPE NEOPIXEL  //define type of led
#define NUM_LEDS 4  //num of leds in strip
//#define DATA_PIN 11  //Define led data pin in
//#define Button 8

#define DATA_PIN 6  //for noiasca
#define Button A0


bool oldState = HIGH;
int showType = 0;

CRGB leds[NUM_LEDS];  // Initialize LED array
CRGBPalette16 currentPalette;

uint8_t hue = 0;

void setup() {
  Serial.begin(115200);
  FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  pinMode(Button, INPUT_PULLUP);
  // put your setup code here, to run once:
  delay(2000); //for safe startup
  FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setBrightness(50);
}

void loop() {

  bool newState = digitalRead(Button);

  // 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);
    if (newState == LOW) {
      showType++;
      if (showType > 8)
        showType = 0;
      Serial.print(F("new showType=")); Serial.println(showType);
      startShow(showType);
    }
  }

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

  if (showType == 6) rainbowCycle(); // needs to be called permanentely
}

void fill(CRGB newColor)   // there might be an built function in FASTled also...
{
  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i] = newColor;
  }
  FastLED.show();
}

void startShow(int g) {
  switch (g) {
    case 0: fill(CRGB::Black);
      break;
    case 1: fill(CRGB::Red);
      break;
    case 2: fill(CRGB::Green);
      break;
    case 3: fill(CRGB::Yellow);
      break;
    case 4: fill(CRGB::Blue);
      break;
    case 5: fill(CRGB::Purple);
      break;
    case 6:
      // leds[i] = CHSV(hue + (i * 200), 255, 255);
      //rainbowCycle();
      break;
    case 7: fill(CRGB::Aqua);
      break;
    case 8: fill(CRGB::HotPink);
      break;
  }
}

void rainbowCycle() {
  for (int i = 0; i < NUM_LEDS; ++i) {
    leds[i] = CHSV(hue + (i * 10), 255, 255);
  }
  EVERY_N_MILLISECONDS(15) {
    hue++;
  }

  FastLED.show();
}

basically what I did:
take the loop from rainbow,
copy it to a new function
and call that function in loop if we are in state == 6.

cleanup the for loop
Todo for your: I guess there is even a built in function in FASTled to fill a strip, but I was to lazy to look for it

1 Like

Thanks. Now it works!

Ok, thanks for this tips

1 Like