Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // reddit user /u/Procupine 4/7/2019
- //the time between transitions is hardcoded (sorry), but the color of the "rain" and speed of the rainbow should be easy to edit
- // This code is intended for three rows of LEDs
- // I tried my best to comment everything but feel free to pm if you have more questions
- #include <FastLED.h>
- #define LED_PIN 5 //digital pin 5
- #define NUM_LEDS 579
- #define BRIGHTNESS 255
- #define LED_TYPE WS2812
- #define COLOR_ORDER GRB
- CRGB leds[NUM_LEDS];
- CRGB colorsArray[NUM_LEDS]; //pregenerated rainbow to make the acutal rainbow less laggy
- #define FRAMES_PER_SECOND 50 //it takes ~20ms to push all the data to all 579 LEDs so the hard limit is ~50fps
- #define animationLength 15000 //milliseconds
- #define rainbowSpeed 100 //bigger = faster rainbow
- const int size = NUM_LEDS / 3; //size of the rainbow, divided by 3 for 3 rows of leds
- int frequency = 10; //frequency of rain and glitter flashes
- int rainColor[3] = {110,20,255}; //make sure each value is at least 1, that's how the program distinguishes between the rain and the rainbow
- void setup() {
- delay(50); //because life sucks
- FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
- FastLED.setBrightness( BRIGHTNESS );
- //initial bias is arbitary and then normalized to the rainbow size. More bias will make the respective section of the rainbow larger
- int BRsize = 90; //section between 100% blue and 100% red
- int RGsize = 100; //section between 100% red and 100% green
- int GBsize = 80; //section between 100% green and 100% blue
- int biasSum = BRsize + RGsize + GBsize;
- BRsize = size * (float(BRsize) / float(biasSum)); //normalize bias
- RGsize = size * (float(RGsize) / float(biasSum)); //normalize bias
- GBsize = size * (float(GBsize) / float(biasSum)); //normalize bias
- biasSum = BRsize + RGsize + GBsize;
- //makes the sum of the bias the same size as the rainbow, fixes "holes" caused by rounding
- if (biasSum < size) {
- BRsize ++;
- biasSum ++;
- if (biasSum < size) {
- RGsize ++;
- biasSum ++;
- if (biasSum < size) {
- GBsize ++;
- biasSum ++;
- }
- }
- }
- else if (biasSum > size) {
- BRsize --;
- biasSum --;
- if (biasSum > size) {
- RGsize --;
- biasSum --;
- if (biasSum > size) {
- GBsize --;
- biasSum --;
- }
- }
- }
- //generate the rainbow. Uses linear interpolations between points set by the bias
- for (int i = 0; i < BRsize; i++) {
- colorsArray[i] = CRGB( int(round(255 * float(i) / float(BRsize))) ,
- 0 ,
- int(round(255 - 255 * float(i) / (BRsize) )));
- }
- for (int i = 0; i < RGsize; i++) {
- colorsArray[i + BRsize] = CRGB(int(round(255 - 255 * float(i) / float(RGsize))) , int(round(255 * (float(i) / float(RGsize)))) , 0 );
- }
- for (int i = 0; i < GBsize; i++) {
- colorsArray[i + BRsize + RGsize] = CRGB(0, int(round(255 - 255 * float(i) / float(GBsize))) , int(round(255 * (float(i) / float(GBsize)))));
- }
- //copy first row onto next two rows
- for (int i = 0; i < NUM_LEDS / 3; i++) {
- colorsArray[i + NUM_LEDS / 3] = colorsArray[i];
- colorsArray[i + 2 * NUM_LEDS / 3] = colorsArray[i];
- }
- }
- void loop() {
- //a timer is used to set a maximum fps
- unsigned long start = millis(); //start timer
- FastLED.show();
- if (millis() % animationLength < 5000) {
- rain(); //not really rain, just some LEDs that converge to the bottom and fade away
- }
- else if (millis() % animationLength < 10000) {
- glitter(); //randomly lights up LEDs in different colors
- }
- else {
- rainbow(); //generic scrolling rainbow
- }
- unsigned long delta = millis() - start; //end of timer
- if ( 1000 / FRAMES_PER_SECOND > delta) { //adds pause to ensure that fps is at or below the defined fps
- FastLED.delay(1000 / FRAMES_PER_SECOND - delta);
- }
- }
- //not really rain, just some LEDs that converge to the bottom and fade away
- void rain() {
- //generates random LEDs to turn on
- frequency = 0.001 * (millis() % animationLength) + 7 ; //how many LEDs per update turn on, starts slow and builds up
- int topRow[frequency];
- for (int i = 0; i < frequency; i++) {
- topRow[i] = random16(2 * NUM_LEDS / 3, NUM_LEDS);
- }
- // fades bottom row
- for (int i = 0; i < NUM_LEDS / 3; i++) {
- if (leds[i].red + leds[i].green + leds[i].blue != 255) { // make the rainbow now fade initially
- leds[i].fadeToBlackBy( 35 );
- }
- }
- //turns off middle row and moves LEDs that were on down
- for (int i = NUM_LEDS / 3; i < 2 * NUM_LEDS / 3; i++) {
- if (i < 2 * NUM_LEDS / 3 && leds[i].red > 0 && leds[i].green > 0 && leds[i].blue > 0) {
- leds[i - NUM_LEDS / 3] = CRGB(rainColor[0], rainColor[1], rainColor[2]);
- leds[i] = CRGB(0, 0, 0);
- }
- }
- //turns off top row, moves LEDs that were on down, turns on new random LEDs
- for (int i = 2 * NUM_LEDS / 3; i < NUM_LEDS; i++) { //toprow, turns random LEDs on, turns other LEDs off
- //turns off LEDs in the top row that were not just turned on, turns on LEDs in the second row below the LEDs that are being turned off
- if (leds[i].red > 0 && leds[i].green > 0 && leds[i].blue > 0) {
- leds[i - NUM_LEDS / 3] = CRGB(rainColor[0], rainColor[1], rainColor[2]);
- leds[i] = CRGB(0, 0, 0);
- }
- }
- for (int i = 0; i < frequency; i++) {
- leds[topRow[i]] = CRGB(rainColor[0], rainColor[1], rainColor[2]);
- }
- }
- //randomly lights up LEDs in different colors
- void glitter() {
- frequency = 2 * pow(float(millis() % animationLength - 5000) / 1000, 4) + 10; //frequency is how much "glitter" there is. Starts out at basically 10 and then grows exponentially (^4)
- int ledOffset = millis() * rainbowSpeed / FRAMES_PER_SECOND / 100 % NUM_LEDS ; // 0 - NUM_LEDS, calculates how far the generated table should be offset from the starting position for the given cycle count
- int lightToTurnOn[frequency]; //randomly generates which LEDs to turn on
- for (int i = 0; i < frequency; i++) {
- lightToTurnOn[i] = random16(0, NUM_LEDS);
- }
- int fade = 35 - pow((((millis() % animationLength) / 1000) - 5), 1.25); //lights fade less quickly over time to more smoothly transition to the full rainbow
- for (int i = 0; i < NUM_LEDS; i++) {
- leds[i].fadeToBlackBy(fade);
- }
- for (int i = 0; i < frequency; i++) { //turns on LEDs that were selected
- if (random8() + 60 > (millis() % animationLength - 5000) * 0.09 ) { //initial glitter will be rain colored, then quickly become rainbow colored
- leds[lightToTurnOn[i]] = CRGB(rainColor[0], rainColor[1], rainColor[2]); //rain colored
- }
- else {
- leds[lightToTurnOn[i]] = colorsArray[(lightToTurnOn[i] + ledOffset) % NUM_LEDS]; //rainbow colored
- }
- }
- }
- //generic scrolling rainbow
- void rainbow() {
- int ledOffset = millis() * rainbowSpeed / FRAMES_PER_SECOND / 100 % NUM_LEDS ; // 0 - NUM_LEDS, calculates how far the generated table should be offset from the starting position for the given time
- //writes the led array based on the pre-generated table
- for (int i = 0; i < NUM_LEDS; i++) {
- leds[i] = colorsArray[(i + ledOffset) % NUM_LEDS];
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment