Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include<FastLED.h>
- #define LED_PIN 2
- #define BRIGHTNESS 32
- #define LED_TYPE WS2812B
- #define COLOR_ORDER GRB
- const uint8_t kCubeSize = 8;
- const bool kMatrixSerpentineLayout = false;
- typedef enum {X_LAYER, Y_LAYER, Z_LAYER} LAYER;
- typedef enum {UP, DOWN} DIRECTION;
- // Dictates the direction of the frames
- DIRECTION fillDirection = UP;
- // Which axis are we filling the frames
- LAYER layer = Y_LAYER;
- // Which frame number gets the new noise data
- int nFillFrame;
- #define NUM_LEDS (kCubeSize * kCubeSize * kCubeSize)
- #define MAX_DIMENSION kCubeSize
- // The leds
- CRGB leds[NUM_LEDS];
- // The 16 bit version of our coordinates
- static uint16_t x;
- static uint16_t y;
- static uint16_t z;
- // This example combines two features of FastLED to produce a remarkable range of
- // effects from a relatively small amount of code. This example combines FastLED's
- // color palette lookup functions with FastLED's Perlin/simplex noise generator, and
- // the combination is extremely powerful.
- //
- // You might want to look at the "ColorPalette" and "Noise" examples separately
- // if this example code seems daunting.
- //
- // The basic setup here is that for each frame, we generate a new array of
- // 'noise' data, and then map it onto the LED matrix through a color palette.
- //
- // Periodically, the color palette is changed, and new noise-generation parameters
- // are chosen at the same time. In this example, specific noise-generation
- // values have been selected to match the given color palettes; some are faster,
- // or slower, or larger, or smaller than others, but there's no reason these
- // parameters can't be freely mixed-and-matched.
- //
- // In addition, this example includes some fast automatic 'data smoothing' at
- // lower noise speeds to help produce smoother animations in those cases.
- //
- // The FastLED built-in color palettes (Forest, Clouds, Lava, Ocean, Party) are
- // used, as well as some 'hand-defined' ones, and some proceedurally generated
- // palettes.
- // We're using the x/y dimensions to map to the x/y pixels on the matrix. We'll
- // use the z-axis for "time". speed determines how fast time moves forward. Try
- // 1 for a very slow moving effect, or 60 for something that ends up looking like
- // water.
- uint16_t speed = 1; // speed is set dynamically once we've started up
- // Scale determines how far apart the pixels in our noise matrix are. Try
- // changing these values around to see how it affects the motion of the display. The
- // higher the value of scale, the more "zoomed out" the noise will be. A value
- // of 1 will be so zoomed in, you'll mostly see solid colors.
- uint16_t scale = 30; // scale is set dynamically once we've started up
- // This is the array that we keep our computed noise values in
- uint8_t noise[MAX_DIMENSION][MAX_DIMENSION];
- CRGBPalette16 currentPalette( LavaColors_p );
- uint8_t colorLoop = 1;
- void setup() {
- delay(3000);
- LEDS.addLeds<LED_TYPE,LED_PIN,COLOR_ORDER>(leds,NUM_LEDS);
- LEDS.setBrightness(BRIGHTNESS);
- // Initialize our coordinates to some random values
- x = random16();
- y = random16();
- z = random16();
- if (fillDirection == UP) nFillFrame = 0; else nFillFrame = kCubeSize-1;
- }
- // Fill a frame of the x/y array of 8-bit noise values using the inoise8 function.
- void fillnoise8() {
- // If we're runing at a low "speed", some 8-bit artifacts become visible
- // from frame-to-frame. In order to reduce this, we can do some fast data-smoothing.
- // The amount of data smoothing we're doing depends on "speed".
- uint8_t dataSmoothing = 0;
- if( speed < 50) {
- dataSmoothing = 200 - (speed * 4);
- }
- for(int i = 0; i < MAX_DIMENSION; i++) {
- int ioffset = scale * i;
- for(int j = 0; j < MAX_DIMENSION; j++) {
- int joffset = scale * j;
- uint8_t data = inoise8(x + ioffset,y + joffset,z);
- // The range of the inoise8 function is roughly 16-238.
- // These two operations expand those values out to roughly 0..255
- // You can comment them out if you want the raw noise data.
- data = qsub8(data,16);
- data = qadd8(data,scale8(data,39));
- if( dataSmoothing ) {
- uint8_t olddata = noise[i][j];
- uint8_t newdata = scale8( olddata, dataSmoothing) + scale8( data, 256 - dataSmoothing);
- data = newdata;
- }
- noise[i][j] = data;
- }
- }
- z += speed;
- // apply slow drift to X and Y, just for visual variation.
- x += speed / 8;
- y -= speed / 16;
- }
- void mapNoiseToLEDsUsingPalette()
- {
- static uint8_t ihue=0;
- for(int i = 0; i < kCubeSize; i++) {
- for(int j = 0; j < kCubeSize; j++) {
- // We use the value at the (i,j) coordinate in the noise
- // array for our brightness, and the flipped value from (j,i)
- // for our pixel's index into the color palette.
- uint8_t index = noise[j][i];
- uint8_t bri = noise[i][j];
- // if this palette is a 'loop', add a slowly-changing base value
- if( colorLoop) {
- index += ihue;
- }
- // brighten up, as the color palette itself often contains the
- // light/dark dynamic range desired
- if( bri > 127 ) {
- bri = 255;
- } else {
- bri = dim8_raw( bri * 2);
- }
- CRGB color = ColorFromPalette( currentPalette, index, bri);
- static int nTo;
- switch (layer)
- {
- case X_LAYER:
- nTo = XYZ(nFillFrame, i, j);
- break;
- case Y_LAYER:
- nTo = XYZ(i, nFillFrame, j);
- break;
- case Z_LAYER:
- nTo = XYZ(i, j, nFillFrame);
- break;
- }
- leds[nTo] = color;
- }
- }
- ihue+=1;
- }
- // Copies pixels from one layer to another
- void copyLayer(uint8_t fromLayer, uint8_t toLayer);
- void copyLayer(uint8_t fromLayer, uint8_t toLayer)
- {
- int nFrom; // from pixel
- int nTo; // to pixel
- for (int m = 0; m < kCubeSize; m++)
- for (int n = 0; n < kCubeSize; n++)
- {
- switch (layer)
- {
- case X_LAYER:
- nFrom = XYZ(fromLayer, m, n);
- nTo = XYZ(toLayer, m, n);
- break;
- case Y_LAYER:
- nFrom = XYZ(m, fromLayer, n);
- nTo = XYZ(m, toLayer, n);
- break;
- case Z_LAYER:
- nFrom = XYZ(m, n, fromLayer);
- nTo = XYZ(m, n, toLayer);
- break;
- }
- leds[nTo] = leds[nFrom];
- }
- }
- // Copy frames foward in the plane being used from the fillFrame back
- void moveFrameForward()
- {
- switch (fillDirection)
- {
- case UP:
- {
- for (int nLayer = kCubeSize-1; nLayer > 0; nLayer--)
- copyLayer(nLayer-1, nLayer);
- }
- break;
- case DOWN:
- {
- for (int nLayer = 0; nLayer < kCubeSize; nLayer++)
- copyLayer(nLayer+1, nLayer);
- }
- break;
- }
- }
- void loop() {
- // Periodically choose a new palette, speed, and scale
- //ChangePaletteAndSettingsPeriodically();
- // generate noise data
- fillnoise8();
- // convert the noise data to colors in the LED array
- // using the current palette
- mapNoiseToLEDsUsingPalette();
- LEDS.show();
- delay(10);
- // Copy frames
- moveFrameForward();
- }
- // There are several different palettes of colors demonstrated here.
- //
- // FastLED provides several 'preset' palettes: RainbowColors_p, RainbowStripeColors_p,
- // OceanColors_p, CloudColors_p, LavaColors_p, ForestColors_p, and PartyColors_p.
- //
- // Additionally, you can manually define your own color palettes, or you can write
- // code that creates color palettes on the fly.
- // 1 = 5 sec per palette
- // 2 = 10 sec per palette
- // etc
- #define HOLD_PALETTES_X_TIMES_AS_LONG 5
- void ChangePaletteAndSettingsPeriodically()
- {
- uint8_t secondHand = ((millis() / 1000) / HOLD_PALETTES_X_TIMES_AS_LONG) % 60;
- static uint8_t lastSecond = 99;
- if( lastSecond != secondHand) {
- lastSecond = secondHand;
- if( secondHand == 0) { currentPalette = RainbowColors_p; speed = 1; scale = 30; colorLoop = 1; }
- if( secondHand == 5) { SetupPurpleAndGreenPalette(); speed = 1; scale = 50; colorLoop = 1; }
- if( secondHand == 10) { SetupBlackAndWhiteStripedPalette(); speed = 1; scale = 30; colorLoop = 1; }
- if( secondHand == 15) { currentPalette = ForestColors_p; speed = 1; scale =120; colorLoop = 0; }
- if( secondHand == 20) { currentPalette = CloudColors_p; speed = 1; scale = 30; colorLoop = 0; }
- if( secondHand == 25) { currentPalette = LavaColors_p; speed = 1; scale = 50; colorLoop = 0; }
- if( secondHand == 30) { currentPalette = OceanColors_p; speed = 1; scale = 90; colorLoop = 0; }
- if( secondHand == 35) { currentPalette = PartyColors_p; speed = 1; scale = 30; colorLoop = 1; }
- if( secondHand == 40) { SetupRandomPalette(); speed = 1; scale = 20; colorLoop = 1; }
- if( secondHand == 45) { SetupRandomPalette(); speed = 1; scale = 50; colorLoop = 1; }
- if( secondHand == 50) { SetupRandomPalette(); speed = 1; scale = 90; colorLoop = 1; }
- if( secondHand == 55) { currentPalette = RainbowStripeColors_p; speed = 1; scale = 20; colorLoop = 1; }
- }
- }
- // This function generates a random palette that's a gradient
- // between four different colors. The first is a dim hue, the second is
- // a bright hue, the third is a bright pastel, and the last is
- // another bright hue. This gives some visual bright/dark variation
- // which is more interesting than just a gradient of different hues.
- void SetupRandomPalette()
- {
- currentPalette = CRGBPalette16(
- CHSV( random8(), 255, 32),
- CHSV( random8(), 255, 255),
- CHSV( random8(), 128, 255),
- CHSV( random8(), 255, 255));
- }
- // This function sets up a palette of black and white stripes,
- // using code. Since the palette is effectively an array of
- // sixteen CRGB colors, the various fill_* functions can be used
- // to set them up.
- void SetupBlackAndWhiteStripedPalette()
- {
- // 'black out' all 16 palette entries...
- fill_solid( currentPalette, 16, CRGB::Black);
- // and set every fourth one to white.
- currentPalette[0] = CRGB::White;
- currentPalette[4] = CRGB::White;
- currentPalette[8] = CRGB::White;
- currentPalette[12] = CRGB::White;
- }
- // This function sets up a palette of purple and green stripes.
- void SetupPurpleAndGreenPalette()
- {
- CRGB purple = CHSV( HUE_PURPLE, 255, 255);
- CRGB green = CHSV( HUE_GREEN, 255, 255);
- CRGB black = CRGB::Black;
- currentPalette = CRGBPalette16(
- green, green, black, black,
- purple, purple, black, black,
- green, green, black, black,
- purple, purple, black, black );
- }
- //
- // xyz coordinate mapping code
- //
- uint16_t XYZ( uint8_t x, uint8_t y, uint8_t z)
- {
- uint16_t i;
- i = 8 * ((y * kCubeSize) + x) + z;
- if ((i >= 0) && (i <= 512))
- return i;
- else
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement