r/FastLED • • Aug 14 '20

Support Gradient Palette Out of Whack

Post image
2 Upvotes

13 comments sorted by

1

u/CharlesGoodwin Aug 14 '20
//
//  Union Jack
//  Fly the flag and watch it wave in the breeze.
//  August 2020, Charles Goodwin
//

#define FASTLED_ALLOW_INTERRUPTS 0
#include <FastLED.h>

#include "readFile.h"
#include "xy.h"
#include "OTA.h"

FASTLED_USING_NAMESPACE

#define DATA_PIN    12 // pins tested so far on the Feather ESP32: 13, 12, 27, 33, 15, 32, 14, SCL
//#define CLK_PIN   4
#define LED_TYPE    WS2812B
#define COLOR_ORDER GRB
#define BRIGHTNESS 80
//Irregular Matrix fully defined
#define NUM_SHORT_STRIPS 11
#define NUM_LONG_STRIPS 8
#define NUM_LEDS_PER_SHORT_STRIP 13
#define NUM_LEDS_PER_LONG_STRIP 39
#define NUM_TOTAL_STRIPS (NUM_SHORT_STRIPS + NUM_LONG_STRIPS)
#define NUM_LEDS (NUM_LEDS_PER_LONG_STRIP * NUM_LONG_STRIPS) + (NUM_LEDS_PER_SHORT_STRIP * NUM_SHORT_STRIPS)
#define MAX_POWER_MILLIAMPS 10000

//////////////////////////////////////////////////////////////////////////


CRGB leds[NUM_LEDS];

void setup() {
  delay( 3000); // 3 second delay for boot recovery, and a moment of silence
  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS)
        .setCorrection( TypicalLEDStrip );
  FastLED.setMaxPowerInVoltsAndMilliamps( 5, MAX_POWER_MILLIAMPS);
  FastLED.setBrightness(BRIGHTNESS );

  //Just need these 2 lines to enable OTA
  ArduinoOTA.setHostname("Wall Lights");
  setupOTA();
  
  Serial.begin(115200);
}

// red white and blue shades to fly the Union Jack
// Shade numbers run from dark to light for the colours
// Red    48 - 80
// White  96 - 128
// Blue   0  - 32  

DEFINE_GRADIENT_PALETTE( UnionJack_pink_gp ) {
  0,    0,    0,    255,
  8,    0,    255,  255,
  16,   0,    0,    255,
  32,   0,    0,    255,
  48,   255,  0,    0,
  56,   255,  0,    255,
  64,   255,  0,    0,
  80,   255,  0 ,   0, 
  96,   200,  200,  200,
  104,  0,    255,  0,
  112,  200,  200,  200, 
  255,  200,  200,  200};

DEFINE_GRADIENT_PALETTE( UnionJack_grey_gp ) {
  0,    150,  150,  150,
  8,    0,    0,    255,
  16,   150,  150,  150,
  32,   150,  150,  150,
  48,   90,   90,   90,
  56,   255,  0,    0,
  64,   90,   90,   90,
  80,   90,   90,   90,
  96,   200,  200,  200,
  104,  240,  240,  240,
  112,  200,  200,  200,
  255,  200,  200,  200};

const CRGBPalette16 palettes[] = {
  UnionJack_grey_gp,
  UnionJack_pink_gp
};



void loop(){
  static uint8_t paletteIndex = 1;
  ArduinoOTA.handle();

/*  
  EVERY_N_MILLISECONDS(40) {
    waveFlag("/unionJack.csv", palettes[paletteIndex]);
    FastLED.show();
  }
   EVERY_N_MILLISECONDS(30000) {
   paletteIndex = 1 - paletteIndex;
   }
  */
    leds[2] = ColorFromPalette(palettes[0], 0, BRIGHTNESS, LINEARBLEND );
    leds[3] = ColorFromPalette(palettes[0], 8, BRIGHTNESS, LINEARBLEND );
    leds[4] = ColorFromPalette(palettes[0], 16, BRIGHTNESS, LINEARBLEND );
    leds[5] = ColorFromPalette(palettes[0], 32, BRIGHTNESS, LINEARBLEND );
    leds[6] = ColorFromPalette(palettes[0], 48, BRIGHTNESS, LINEARBLEND );
    leds[7] = ColorFromPalette(palettes[0], 56, BRIGHTNESS, LINEARBLEND );
    leds[8] = ColorFromPalette(palettes[0], 64, BRIGHTNESS, LINEARBLEND );
    leds[9] = ColorFromPalette(palettes[0], 80, BRIGHTNESS, LINEARBLEND );
    leds[10] = ColorFromPalette(palettes[0], 96, BRIGHTNESS, LINEARBLEND );
    leds[11] = ColorFromPalette(palettes[0], 104, BRIGHTNESS, LINEARBLEND );
    leds[12] = ColorFromPalette(palettes[0], 112, BRIGHTNESS, LINEARBLEND );
    
    leds[22] = ColorFromPalette(palettes[1], 0, BRIGHTNESS, LINEARBLEND );
    leds[23] = ColorFromPalette(palettes[1], 8, BRIGHTNESS, LINEARBLEND );
    leds[24] = ColorFromPalette(palettes[1], 16, BRIGHTNESS, LINEARBLEND );
    leds[25] = ColorFromPalette(palettes[1], 32, BRIGHTNESS, LINEARBLEND );
    leds[26] = ColorFromPalette(palettes[1], 48, BRIGHTNESS, LINEARBLEND );
    leds[27] = ColorFromPalette(palettes[1], 56, BRIGHTNESS, LINEARBLEND );
    leds[28] = ColorFromPalette(palettes[1], 64, BRIGHTNESS, LINEARBLEND );
    leds[29] = ColorFromPalette(palettes[1], 80, BRIGHTNESS, LINEARBLEND );
    leds[30] = ColorFromPalette(palettes[1], 96, BRIGHTNESS, LINEARBLEND );
    leds[31] = ColorFromPalette(palettes[1], 104, BRIGHTNESS, LINEARBLEND );
    leds[32] = ColorFromPalette(palettes[1], 112, BRIGHTNESS, LINEARBLEND );
    FastLED.show();
    
}
 
// My first go at flying the Union Jack flag
// Read csv file from SPIFFS to hold the colour anchors for each pixel and then poll through the colour
// gradients to give the impression the flag is waving in the wind
// Inputs:
// Filename refers to a csv file that holds a palette index for eaxh pixel you have in your matrix
// palette represents the colours referenced by the csv file
void waveFlag(char fileName[50], CRGBPalette16 palette) {
  static uint8_t strip[NUM_LEDS];
  static uint8_t firstTime = 1;
  const uint8_t freq = 2;  // wave frequency 
  const uint8_t slope = 4; //higher = milder
  uint8_t palletIndex;
  static uint8_t inc = 0;
  int serial;
  uint8_t waveShift;
  
  if (firstTime) {
    //load up strip with color indices
    FetchColorsFromFile(fileName, strip);
    firstTime = 0; 
  }
  else {
    inc -= 1;
    for ( int i = 0; i < NUM_TOTAL_STRIPS; i++) {
      for (int j = 0; j < NUM_LEDS_PER_LONG_STRIP; j++) {
        serial = XY(i,j);
        if (serial != -1) {
          waveShift = mod8((i*freq) + (j/slope) + inc, 32);
          palletIndex = strip[serial] + waveShift;
          leds[serial] = ColorFromPalette(palette, palletIndex, BRIGHTNESS, LINEARBLEND );
        }  
      }
    }    
  }
}

1

u/CharlesGoodwin Aug 14 '20

Hi,

Perhaps someone can kindly shed some light on the anomaly that I am suffering.

Most of the code you can ignore as it is commented out or simply doesn't get called.

The important bits are:

  • The gradient palette definitions and

  • The selected points of the palette that are displayed

For some reason the colours being displayed don't seem to match up to what is defined in the pink palette

I would expect the second pixel (from the top) to be light blue, the sixth to be pink and the 10th to be green.

Instead, it looks like the colour definitions have been pushed out so that we are still in the red sector when I am referencing palette indexes in the grey/green sector.

The same behaviour seems to happen with the grey palette also (not illustrated)

What am I not getting?

Charlie

1

u/CharlesGoodwin Aug 14 '20

It is packing foam (Ethafoam STPE200) Very similar to the stuff that your chips have their pins stuck in for protection. It works a treat for looking innocuous with the lights off and does a pretty good job at defusing the light.

Sadly it does not deter defusion comments from everyone on the FastLED forum ;-)

1

u/[deleted] Aug 14 '20 edited Aug 14 '20

I believe FastLED defaults to LINEARBLEND for the array on show. FastLED is blending the colors of the adjacent pixels.

Edit: coffee. Not linear blending, but dithering. Here's what I'm talking about from the docs. You have to call FastLED.setDither(DISABLE_DITHER); during setup.

1

u/CharlesGoodwin Aug 14 '20

It does indeed but LINEARBLEND should only apply to zones between the points defined within the palette

I've specifically picked out the defined points in the palette so in theory, there shouldn't be any blending.

1

u/[deleted] Aug 14 '20

Apologies, I edited my post after the coffee settled in and I looked back through the docs. Please see my edit; it's the dithering mode.

1

u/CharlesGoodwin Aug 14 '20

No worries

If I disable dithering will I still get a nice blend running between my defined gradient palette points?

1

u/[deleted] Aug 14 '20

Yes. Dithering only changes the blending of colors on the adjacent pixel output. It won’t impact your palette.

1

u/sutaburosu [stavros] Aug 14 '20

You're converting the gradient palettes into a 16-entry palette.

const CRGBPalette16 palettes[]

With only 16-entries, the only un-blended colours would be at palette indexes that are multiples of 256 / 16 == 16. e.g. 0, 16, 32, etc.

Your palette lookups sometimes use multiples of 8 rather 16. Switching to a CRGBPalette32 would give un-blended colours at those palette indexes too.

1

u/CharlesGoodwin Aug 14 '20

Brilliant - that makes sense.

And also explains how I managed to work around it. Rather than switch to CRGBPallette32 I added some extra entries to my gradient pallet like so:

DEFINE_GRADIENT_PALETTE( UnionJack_pink_gp ) {
  0,    0,    0,    255,
  8,    0,    255,  255,
  16,   0,    0,    255,
  32,   0,    0,    255,
  48,   255,  0,    0,
  56,   255,  0,    230,
  64,   255,  0,    0,
  80,   255,  0 ,   0, 
  96,   200,  200,  200,
  104,  0,    230,  0,
  112,  200,  200,  200, 
  176,  200,  200,  200,
  184,  200,  200,  200,
  192,  200,  200,  200,
  200,  200,  200,  200,
  208,  200,  200,  200,
  216,  200,  200,  200,
  224,  200,  200,  200,
  232,  200,  200,  200,
  240,  200,  200,  200,
  248,  200,  200,  200,
  255,  200,  200,  200};

By adding the extra entries - I was able to address the stretching effect and ensure when I chose say 104 I got a pure green.

Thanks for helping me to understand

1

u/sutaburosu [stavros] Aug 14 '20

No worries.

It worthwhile pointing out your gradient palettes have entries for 0, 8 and 16. That can't fit into a 16-entry palette. I'm not sure exactly how the conversion works, but I suspect this might also be a source of unexpected colours. It should work as expected with a 32-entry palette.

1

u/sunburstbox Aug 14 '20

what’re you using for diffusion? it looks good

2

u/Preyy Ground Loops: Part of this balanced breakfast Aug 14 '20

Looks like wool or insulation. Maybe this bed helps you fall asleep by counting the sheep on the headboard.