FastLED change static gradient patterns and brightness with encoder

I’ve been trying to combine several sketches to use a single Rotary Encoder to both control brightness and scroll between static gradient patterns.

I started with bare bone sketches and tried each of my objectives individually. I have been able to establish a static gradient pattern, change brightness using the encoder, and using this: https://gist.github.com/fasmide/9d820e615ac736501ce0e4c97594bbfd#file-lampe-ino-L160 incorporate both scrolling of scenes as well as changing brightness with the encoder.

However, I have hit a wall that I can’t seem to get through. Using this as a template: https://gist.github.com/kriegsman/8281905786e8b2632aeb

I can’t seem to get it to mesh with what I currently had functioning. I want to be able to define gradient palettes, and scroll between them.

At this point I think I’ve made quite a mess of the code, and though it will compile, it does nothing but log via serial the change in the encoder state and value.

I’ve spent a LONG time on this, hate to ask for help, but I’ve tried SO many different configurations and seem to either have problems compiling, or continue having a blank strip.

#include <FastLED.h>
#include <ClickEncoder.h>
#include <TimerOne.h>

#define DATA_PIN  6  
#define LED_TYPE    WS2812B
#define COLOR_ORDER GRB
#define NUM_LEDS    16
CRGB leds[NUM_LEDS];

#define BRIGHTNESS          96
#define FRAMES_PER_SECOND  120

bool brightnessMode = false;
bool setAccelerationEnabled = true;

ClickEncoder *encoder;
int16_t last, value;

void timerIsr() {
  encoder->service();
}





void setup() {
  delay(3000); // 3 second delay for recovery
  Serial.begin(115200);
  
  // tell FastLED about the LED strip configuration
  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS)
    //.setCorrection(TypicalLEDStrip) // cpt-city palettes have different color balance
    .setDither(BRIGHTNESS < 255);

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

  encoder = new ClickEncoder(2, 3, 4);


  Timer1.initialize(1000);
  Timer1.attachInterrupt(timerIsr);

  last = -1;

}//end of setup




// Forward declarations of an array of cpt-city gradient palettes, and 
// a count of how many there are.  The actual color palette definitions
// are at the bottom of this file.
extern const TProgmemRGBGradientPalettePtr gGradientPalettes[];
extern const uint8_t gGradientPaletteCount;

// Current palette number from the 'playlist' of color palettes
uint8_t gCurrentPaletteNumber = 0;

CRGBPalette16 gCurrentPalette( CRGB::Black);
CRGBPalette16 gTargetPalette( gGradientPalettes[0] );


void loop()
{

  value += encoder->getValue();

  if (value != last) {
    last = value;

if(value > 175)
  value = 175; //prevent encoder from exceeding 255
if(value < 0)
  value = 0;  //prevent encoder from going negative
    
    Serial.print("Encoder Value : ");
    Serial.println(value);
            static uint8_t BRIGHT = value;
        if (brightnessMode == true) {
        FastLED.setBrightness(value);
      }
      else{
      if (last > value) {
        Serial.print("Current Pattern # ");
        Serial.print(value);
        nextPattern();
      } 
      
      else  {
        Serial.print("Current Pattern # ");
        Serial.print(value);
        prevPattern();  
      }  
      }


      
  }

  ClickEncoder::Button b = encoder->getButton();
 if (b != ClickEncoder::Open) {
  switch (b) {
    case ClickEncoder::Clicked:
      Serial.println("Button was clicked");
      brightnessMode = !brightnessMode;
      if (brightnessMode) {
        Serial.println("Knob now controls brightness");
         

      } else {
        Serial.println("Knob now controls color");
      }
      
      break;
  }
 }


  
  palettetest( leds, NUM_LEDS, gCurrentPalette);

  FastLED.show();
  FastLED.delay(20);
}

#define ARRAY_SIZE(A) (gGradientPaletteCount)


void nextPattern()
{
  // add one to the current pattern number, and wrap around at the end
  //gCurrentPaletteNumber = (gCurrentPaletteNumber + 1) % ARRAY_SIZE( gGradientPalettes);
  //gTargetPalette = (gTargetPalette + 1);
 // FastLED.show();


    gCurrentPaletteNumber = addmod8( gCurrentPaletteNumber, 1, gGradientPaletteCount);
    gTargetPalette = gGradientPalettes[ gCurrentPaletteNumber ];
}

void prevPattern()
{
  gCurrentPaletteNumber = (gCurrentPaletteNumber - 1);
  if (gCurrentPaletteNumber > ARRAY_SIZE(gGradientPalettes)) {
    gCurrentPaletteNumber = ARRAY_SIZE(gGradientPalettes)-1;
  }
}





// Alternate rendering function just scrolls the current palette 
// across the defined LED strip.
void palettetest( CRGB* ledarray, uint16_t numleds, const CRGBPalette16& gCurrentPalette)
{
  for (int i=0; i< NUM_LEDS; i++) {
    leds[i] = ColorFromPalette(gCurrentPalette, i*256/NUM_LEDS);
  }
}





// Gradient Color Palette definitions for 33 different cpt-city color palettes.
//    956 bytes of PROGMEM for all of the palettes together,
//   +618 bytes of PROGMEM for gradient palette code (AVR).
//  1,494 bytes total for all 34 color palettes and associated code.

// Gradient palette "ib_jul01_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/ing/xmas/tn/ib_jul01.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 16 bytes of program space.

DEFINE_GRADIENT_PALETTE( ib_jul01_gp ) {
    0, 194,  1,  1,
   94,   1, 29, 18,
  132,  57,131, 28,
  255, 113,  1,  1};

// Gradient palette "es_vintage_57_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/vintage/tn/es_vintage_57.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 20 bytes of program space.

DEFINE_GRADIENT_PALETTE( es_vintage_57_gp ) {
    0,   2,  1,  1,
   53,  18,  1,  0,
  104,  69, 29,  1,
  153, 167,135, 10,
  255,  46, 56,  4};

// Gradient palette "es_vintage_01_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/vintage/tn/es_vintage_01.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 32 bytes of program space.

DEFINE_GRADIENT_PALETTE( es_vintage_01_gp ) {
    0,   4,  1,  1,
   51,  16,  0,  1,
   76,  97,104,  3,
  101, 255,131, 19,
  127,  67,  9,  4,
  153,  16,  0,  1,
  229,   4,  1,  1,
  255,   4,  1,  1};




// Single array of defined cpt-city color palettes.
// This will let us programmatically choose one based on
// a number, rather than having to activate each explicitly 
// by name every time.
// Since it is const, this array could also be moved 
// into PROGMEM to save SRAM, but for simplicity of illustration
// we'll keep it in a regular SRAM array.
//
// This list of color palettes acts as a "playlist"; you can
// add or delete, or re-arrange as you wish.
const TProgmemRGBGradientPalettePtr gGradientPalettes[] = {

  es_vintage_01_gp,
  ib_jul01_gp,
  es_vintage_57_gp,
 };


// Count of how many cpt-city gradients are defined:
const uint8_t gGradientPaletteCount = 
  sizeof( gGradientPalettes) / sizeof( TProgmemRGBGradientPalettePtr );

Building a clear representation of the requirements will help you develop a good code. Patching pieces together leads usually to spaghetti code that is hard to read and maintain, and usually buggy or not performing well.

can you describe in plain English what's expected ? Start by how do you use the Rotary Encoder and what it's supposed to do at high level. Then for each sub-level try to describe what's expected.

You might need a state machine type of code to handle this.

The current milestone I'm trying to achieve is to use a rotary encoder to perform a couple of functions.

Clicking the encoder would toggle between adjusting brightness or scrolling through a playlist of static gradient patterns.

The best I've been able to achieve so far has been the rotary encoder, when clicked will toggle between brightness mode and color modes. When in brightness mode, rotating the encoder will change the brightness, and when in color mode will switch between dynamic patterns.

I've put that version into a pastebin:

The only problem with this version is, rotating the encoder forward the patterns advance forward, rotating the encoder backwards advance the patterns forward as well. The serial monitor is showing increasing/decreasing numbers, so it's not a problem with how the encoder is being read by the arduino.

At the bottom of the code I left an example of what I'm trying to replace each of those patterns with. A static gradient pattern. Unfortunately, I have been unable to compile a script that allows me to have a playlist of those patterns and use the encoder to switch between them.

What the intent of this project is, is a light box with interchangeable silhouettes, backlit by 16 WS2812B leds with static gradients fitting the theme of what's inside.

Once I am able to perform this most basic function, I hope to expand this project by having whatever chosen pattern/brightness level saved to EEPROM for when its turned off, so when it's turned back on it'll resume that current setting, and possibly have it so that if you long press the encoder it sets a timer that would keep the lights turned on for "X" number of hours, turn off, and then turn back on at that time the next day for that number of hours.

Those are all ambitious goals, so for now I just want to make it work in the most basic sense described above.

Add a button with an LED indicator so you can select a mode, and see which mode is selected.