Last active
April 6, 2022 18:31
-
-
Save StefanPetrick/96574043d6425cc4f3ee39a2245ac965 to your computer and use it in GitHub Desktop.
Proof of concept for smooth fading
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
A FastLED matrix example: | |
A simplex noise field fully modulated and controlled by itself | |
written by | |
Stefan Petrick 2017 | |
Do with it whatever you like and show your results to the FastLED community | |
https://plus.google.com/communities/109127054924227823508 | |
*/ | |
#include "FastLED.h" | |
// matrix size | |
uint8_t Width = 16; | |
uint8_t Height = 16; | |
uint8_t CentreX = (Width / 2) - 1; | |
uint8_t CentreY = (Height / 2) - 1; | |
// NUM_LEDS = Width * Height | |
#define NUM_LEDS 256 | |
#define BRIGHTNESS 255 | |
CRGB leds[NUM_LEDS]; | |
CRGB buffer1[NUM_LEDS]; | |
CRGB buffer2[NUM_LEDS]; | |
// parameters and buffer for the noise array | |
#define NUM_LAYERS 2 | |
uint32_t x[NUM_LAYERS]; | |
uint32_t y[NUM_LAYERS]; | |
uint32_t z[NUM_LAYERS]; | |
uint32_t scale_x[NUM_LAYERS]; | |
uint32_t scale_y[NUM_LAYERS]; | |
uint16_t noise[NUM_LAYERS][16][16]; | |
// colortables | |
uint8_t a[1024]; | |
uint8_t b[1024]; | |
uint8_t c[1024]; | |
//control parameters | |
uint8_t ctrl[6]; | |
void setup() { | |
setup_tables(); | |
Serial.begin(115200); | |
// Adjust this for you own setup. Use the hardware SPI pins if possible. | |
// On Teensy 3.1/3.2 the pins are 11 & 13 | |
// Details here: https://github.com/FastLED/FastLED/wiki/SPI-Hardware-or-Bit-banging | |
// In case you see flickering / glitching leds, reduce the data rate to 12 MHZ or less | |
LEDS.addLeds<APA102, 11, 13, BGR, DATA_RATE_MHZ(12)>(leds, NUM_LEDS); | |
FastLED.setBrightness(BRIGHTNESS); | |
FastLED.setDither(DISABLE_DITHER); | |
randomSeed(analogRead(5)); | |
x[0] = random(60000); | |
y[0] = random(60000); | |
z[0] = random(60000); | |
x[1] = random(60000); | |
y[1] = random(60000); | |
z[1] = random(60000); | |
} | |
void loop() { | |
//show_palette(); | |
noise_noise2(); | |
//monitor(); | |
show_fps(); | |
} | |
void setup_tables() { | |
/* | |
for (uint16_t i = 0; i < 1024; i++) { | |
a[i] = sin8(i/4) ; | |
b[i] = 0; | |
c[i] = cubicwave8( i/2) ; | |
} | |
*/ | |
for (uint16_t i = 256; i < 768; i++) { | |
a[i] = triwave8(127 + (i / 2)) ; | |
//b[i] = 0; | |
//c[i] = triwave8(127 + (i / 2)) ; | |
} | |
} | |
// whatch the serial plotter | |
void monitor() { | |
EVERY_N_MILLIS(50) { | |
Serial.print(ctrl[0]); | |
Serial.print(" "); | |
Serial.print(ctrl[1]); | |
Serial.print(" "); | |
Serial.print(ctrl[2]); | |
Serial.print(" "); | |
Serial.print(ctrl[3]); | |
Serial.print(" "); | |
Serial.print(ctrl[4]); | |
Serial.print(" "); | |
Serial.print(ctrl[5]); | |
Serial.print(" "); | |
Serial.println(noise[0][0][0]); | |
} | |
} | |
// check the "palette" | |
void show_palette() { | |
for (uint8_t y = 0; y < Height; y++) { | |
for (uint8_t x = 0; x < Width; x++) { | |
leds[XY(x, y)] = CRGB( a[ ((x * 16) + y) * 4], b[ ((x * 16) + y) * 4], c[ ((x * 16) + y) * 4]); | |
} | |
} | |
adjust_gamma(); | |
FastLED.show(); | |
} | |
// check the Serial Monitor to see how many fps you get | |
void show_fps() { | |
EVERY_N_MILLIS(100) { | |
Serial.println(LEDS.getFPS()); | |
} | |
} | |
// this finds the right index within a serpentine matrix | |
uint16_t XY( uint8_t x, uint8_t y) { | |
uint16_t i; | |
if ( y & 0x01) { | |
uint8_t reverseX = (Width - 1) - x; | |
i = (y * Width) + reverseX; | |
} else { | |
i = (y * Width) + x; | |
} | |
return i; | |
} | |
/* | |
// for a line by line matrix it should be | |
uint16_t XY( uint8_t x, uint8_t y) | |
{ | |
uint16_t i; | |
i = (y * Width) + x; | |
return i; | |
} | |
*/ | |
// cheap correction with gamma 2.0 | |
void adjust_gamma() | |
{ | |
// minimal brightness you want to allow | |
// make sure to have the global brightnes on maximum and run no other color correction | |
// a minimum of min = 1 might work fine for you and allow more contrast | |
uint8_t min = 3; | |
for (uint16_t i = 0; i < NUM_LEDS; i++) | |
{ | |
leds[i].r = dim8_video(leds[i].r); | |
leds[i].g = dim8_video(leds[i].g); | |
leds[i].b = dim8_video(leds[i].b); | |
if (leds[i].r < min) leds[i].r = min; | |
if (leds[i].g < min) leds[i].g = min; | |
if (leds[i].b < min) leds[i].b = min; | |
} | |
} | |
// highly experimental | |
// note that the noise values are in the range of 0-1023 when using them | |
void noise_noise2() { | |
// LAYER ONE | |
//top left | |
ctrl[0] = (ctrl[0] + noise[0][0][0] + noise[0][1][0] + noise [0][0][1] + noise[0][1][1]) / 20; | |
//top right | |
ctrl[1] = (ctrl[1] + noise[0][Width - 1][0] + noise[0][Width - 2][0] + noise [0][Width - 1][1] + noise[0][Width - 2][1]) / 20; | |
//down left | |
ctrl[2] = (ctrl[2] + noise[0][0][Height - 1] + noise[0][0][Height - 2] + noise [0][1][Height - 1] + noise[0][1][Height - 2]) / 20; | |
//middle left | |
ctrl[3] = (ctrl[3] + noise[0][0][CentreY] + noise[0][1][CentreY] + noise [0][0][CentreY + 1] + noise[0][1][CentreY + 1]) / 20; | |
//center | |
ctrl[4] = (ctrl[4] + noise[0][Width - 1][CentreY] + noise[0][Width - 2][CentreY] + noise [0][Width - 1][CentreY + 1] + noise[0][Width - 2][CentreY + 1]) / 20; | |
ctrl[5] = (ctrl[5] + ctrl[0] + ctrl[1]) / 12; | |
x[0] = x[0] + (ctrl[0]) - 127; | |
y[0] = y[0] + (ctrl[1]) - 127; | |
z[0] += 1 + (ctrl[2] / 4); | |
scale_x[0] = 8000 + (ctrl[3] * 16); | |
scale_y[0] = 8000 + (ctrl[4] * 16); | |
//calculate the noise data | |
uint8_t layer = 0; | |
for (uint8_t i = 0; i < Width; i++) { | |
uint32_t ioffset = scale_x[layer] * (i - CentreX); | |
for (uint8_t j = 0; j < Height; j++) { | |
uint32_t joffset = scale_y[layer] * (j - CentreY); | |
uint16_t data = inoise16(x[layer] + ioffset, y[layer] + joffset, z[layer]); | |
if (data < 11000) data = 11000; | |
if (data > 51000) data = 51000; | |
data = data - 11000; | |
data = data / 41; | |
noise[layer][i][j] = (noise[layer][i][j] + data) / 2; | |
} | |
} | |
//map the colors | |
//here the red layer | |
for (uint8_t y = 0; y < Height; y++) { | |
for (uint8_t x = 0; x < Width; x++) { | |
uint16_t i = noise[0][x][y]; | |
buffer1[XY(x, y)] = CRGB(a[i], 0, 0); | |
} | |
} | |
// LAYER TWO | |
//top left | |
ctrl[0] = (ctrl[0] + noise[1][0][0] + noise[1][1][0] + noise [1][0][1] + noise[1][1][1]) / 20; | |
//top right | |
ctrl[1] = (ctrl[1] + noise[1][Width - 1][0] + noise[1][Width - 2][0] + noise [1][Width - 1][1] + noise[1][Width - 2][1]) / 20; | |
//down left | |
ctrl[2] = (ctrl[2] + noise[1][0][Height - 1] + noise[1][0][Height - 2] + noise [1][1][Height - 1] + noise[1][1][Height - 2]) / 20; | |
//middle left | |
ctrl[3] = (ctrl[3] + noise[1][0][CentreY] + noise[1][1][CentreY] + noise [1][0][CentreY + 1] + noise[1][1][CentreY + 1]) / 20; | |
//center | |
ctrl[4] = (ctrl[4] + noise[1][Width - 1][CentreY] + noise[1][Width - 2][CentreY] + noise [1][Width - 1][CentreY + 1] + noise[1][Width - 2][CentreY + 1]) / 20; | |
ctrl[5] = (ctrl[5] + ctrl[0] + ctrl[1]) / 12; | |
x[1] = x[1] + (ctrl[0]) - 127; | |
y[1] = y[1] + (ctrl[1]) - 127; | |
z[1] += 1 + (ctrl[2] / 4); | |
scale_x[1] = 8000 + (ctrl[3] * 16); | |
scale_y[1] = 8000 + (ctrl[4] * 16); | |
//calculate the noise data | |
layer = 1; | |
for (uint8_t i = 0; i < Width; i++) { | |
uint32_t ioffset = scale_x[layer] * (i - CentreX); | |
for (uint8_t j = 0; j < Height; j++) { | |
uint32_t joffset = scale_y[layer] * (j - CentreY); | |
uint16_t data = inoise16(x[layer] + ioffset, y[layer] + joffset, z[layer]); | |
if (data < 11000) data = 11000; | |
if (data > 51000) data = 51000; | |
data = data - 11000; | |
data = data / 41; | |
noise[layer][i][j] = (noise[layer][i][j] + data) / 2; | |
} | |
} | |
//map the colors | |
//here the blue layer | |
for (uint8_t y = 0; y < Height; y++) { | |
for (uint8_t x = 0; x < Width; x++) { | |
uint16_t i = noise[1][x][y]; | |
buffer2[XY(x, y)] = CRGB(0, 0, a[i]); | |
} | |
} | |
// blend | |
//for (uint16_t i = 0; i < NUM_LEDS; i++) {leds[i] = buffer1[i] + buffer2[i];} | |
for (uint8_t y = 0; y < Height; y++) { | |
for (uint8_t x = 0; x < Width; x++) { | |
leds[XY(x, y)] = blend(buffer1[XY(x, y)], buffer2[XY(x, y)], noise[1][y][x] / 4); | |
// you could also just add them: | |
// leds[XY(x, y)] = buffer1[XY(x, y)] + buffer2[XY(x, y)]; | |
} | |
} | |
//make it looking nice | |
adjust_gamma(); | |
//and show it! | |
FastLED.show(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I am using noise_noise.ino for a small art project and I do get some jitters and flickers with my WS2812B (which don't have clock control) and IstsyBitsy 32u4 5V 16MHz. So I was really curious about this smooth noise sketch. However, it seems to break my itsybitsy... i.e. I lose the port and then have to reset. Any ideas what could be going on?