Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <FastLED.h>
- // This simulates a light rain with some lightning.
- // You still need to add some wind to get a thunderstorm.
- // using a lot of 3rd party code (almost all)
- // For a demo see here: https://www.youtube.com/watch?v=7VH_mzjnUwE
- // Thomas Runge (tom@truwo.de)
- #define DATA_PIN 9
- #define LED_PIN 13
- #define LED_TYPE WS2811
- #define COLOR_ORDER GRB
- #define M_WIDTH 8
- #define M_HEIGHT 8
- #define NUM_LEDS (M_WIDTH*M_HEIGHT)
- #define BRIGHTNESS 180
- #define NUM_DROPLETS (2*M_WIDTH)
- CRGB leds_plus_safety_pixel[ NUM_LEDS + 1 ];
- CRGB* leds(leds_plus_safety_pixel + 1);
- uint16_t XY(uint8_t x, uint8_t y) {
- uint16_t i;
- if(y & 0x01) {
- // Even rows run backwards
- i = (y * M_WIDTH) + x;
- } else {
- // Odd rows run forwards
- uint8_t reverseX = (M_WIDTH - 1) - x;
- i = (y * M_WIDTH) + reverseX;
- }
- return i;
- }
- uint16_t XYsafe(uint8_t x, uint8_t y) {
- if(x >= M_WIDTH) {
- return -1;
- }
- if(y >= M_HEIGHT) {
- return -1;
- }
- return XY(x,y);
- }
- // Original by: Daniel Wilson, 2014
- // Modified by: Andrew Tuline 2015
- // found: https://github.com/atuline/FastLED-Demos/blob/master/lightnings/lightnings.ino
- // modified to run almost non blocking by Thomas Runge
- void lightning(uint8_t firstled, uint8_t num_leds, uint8_t flashchance) {
- static const uint8_t FLASHES = 8;
- static unsigned long flashNext;
- static uint8_t flashCounter = 0, flashMax = 0;
- static uint8_t ledlen, ledstart;
- // (re)init data
- if (flashCounter == flashMax) {
- ledlen = random8(3, num_leds-3); // length of flash, at least 3 LEDs
- ledstart = firstled+random8(num_leds-ledlen); // start of flash
- flashNext = millis()+1000*random8(flashchance); // random start of flash sequence
- flashCounter = 0;
- flashMax = random8(3, FLASHES);
- }
- // show next flash, if it's time has come
- if (millis() >= flashNext) {
- uint8_t dimmer;
- if(flashCounter == 0) {
- // the brightness of the leader is scaled down by a factor of 5
- dimmer = 5;
- } else {
- // return strokes are brighter than the leader
- dimmer = random8(1, 3);
- }
- // Show a section of LED's
- fill_solid(leds+ledstart, ledlen, CHSV(255, 0, 255/dimmer));
- // each flash only lasts 4-10 milliseconds
- FastLED.delay(random8(4, 10));
- // Clear the section of LED's
- fill_solid(leds+ledstart, ledlen, CRGB::Black);
- FastLED.show();
- flashNext = millis()+50+random8(100);
- if (flashCounter == 0) {
- flashNext += 150;
- }
- flashCounter++;
- }
- }
- // algorithm by "danny"
- // found here: http://rurandom.org/justintime/index.php?title=WS2811_%22Water_torture%22
- // or here: https://github.com/DannyHavenith/ws2811/blob/master/src/water_torture.hpp
- // ported to FastLED by Thomas Runge
- /// This class maintains the state and calculates the animations to render a falling water droplet
- /// Objects of this class can have three states:
- /// - inactive: this object does nothing
- /// - swelling: the droplet is at the top of the led strip and swells in intensity
- /// - falling: the droplet falls downwards and accelerates
- /// - bouncing: the droplet has bounced of the ground. A smaller, less intensive droplet bounces up
- /// while a part of the drop remains on the ground.
- /// After going through the swelling, falling and bouncing phases, the droplet automatically returns to the
- /// inactive state.
- class Droplet {
- public:
- Droplet()
- : column(0), color(CRGB::Black), gravity(5),
- position(0), speed(0), state(inactive)
- {}
- void init(uint16_t column) {
- this->column = column;
- reinit();
- }
- void reinit() {
- this->position = 0;
- this->speed = 0;
- this->color = CHSV(144+random8(32), 255, BRIGHTNESS);
- this->start = millis()+1000*random8(5);
- state = swelling;
- }
- /// perform one step and draw.
- void step(CRGB *leds) {
- if (millis() >= start) {
- step();
- draw(leds);
- }
- }
- private:
- /// calculate the next step in the animation for this droplet
- void step() {
- if (state == falling || state == bouncing) {
- position += speed;
- speed += gravity;
- // if we hit the bottom...
- const uint16_t maxpos16 = (M_HEIGHT-1) << 8;
- if (position > maxpos16) {
- if (state == bouncing) {
- // this is the second collision,
- // deactivate.
- state = inactive;
- reinit();
- } else {
- // reverse direction and dampen the speed
- position = maxpos16 - (position - maxpos16);
- speed = -speed/4;
- color.nscale8_video(collision_scaling);
- state = bouncing;
- }
- }
- } else if (state == swelling) {
- ++position;
- if (color.blue <= 10 || color.blue - position <= 10) {
- state = falling;
- position = 0;
- }
- }
- }
- /// Draw the droplet on the led string
- /// This will "smear" the light of this droplet between two leds. The closer
- /// the droplets position is to that of a particular led, the brighter that
- /// led will be
- void draw(CRGB *leds) {
- if (state == falling || state == bouncing) {
- uint8_t position8 = position >> 8;
- uint8_t remainder = position; // get the lower bits
- CRGB tc = color;
- if (position8 < M_HEIGHT) {
- uint8_t lidx = XYsafe(column, M_HEIGHT-1-position8);
- leds[lidx] += tc.nscale8_video(256 - remainder);
- if (remainder && position8+1 < M_HEIGHT) {
- lidx = XYsafe(column, M_HEIGHT-1-position8+1);
- tc = color;
- leds[lidx] += tc.nscale8_video(remainder);
- }
- }
- if (state == bouncing) {
- uint8_t lidx = XYsafe(column, 0);
- leds[lidx] = color;
- }
- } else if (state == swelling) {
- CRGB tc = color;
- uint8_t lidx = XYsafe(column, M_HEIGHT-1);
- leds[lidx] = tc.nscale8_video(position);
- }
- }
- // how much of a color is left when colliding with the floor, value
- // between 0 and 256 where 256 means no loss.
- static const uint16_t collision_scaling = 40;
- uint16_t column;
- CRGB color;
- uint16_t gravity;
- uint16_t position;
- int16_t speed;
- enum stateval {
- inactive,
- swelling,
- falling,
- bouncing
- };
- stateval state;
- unsigned long start;
- };
- Droplet droplets[NUM_DROPLETS];
- void setup() {
- randomSeed(analogRead(0));
- random16_set_seed(1579);
- random16_add_entropy(analogRead(0));
- FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalSMD5050);
- FastLED.setBrightness(BRIGHTNESS);
- for (uint8_t idx = 0; idx < NUM_DROPLETS; ++idx) {
- droplets[idx].init(idx % M_WIDTH);
- }
- }
- void loop() {
- lightning(NUM_LEDS-M_WIDTH, M_WIDTH, 10);
- fill_solid(leds, NUM_LEDS, CRGB::Black);
- for (uint8_t idx = 0; idx < NUM_DROPLETS; ++idx) {
- droplets[idx].step(leds);
- }
- FastLED.delay(15);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement