Project in progress

Simulated snow on a line of LEDs wrapped around a tree

• 2,086 views
• 0 respects

Components and supplies

 Arduino UNO
×1
×1
 Power Supply 5V 10A
×1
 Capacitor 1000 uF Across the power supply to protect Arduino from spike when turned on
×1

Apps and online services

 Microsoft Visual Studio 2015

This year we put Arduino Uno-powered lights on our tree, and my crowning achievement (so far!) is to make it snow on the tree!

This display creates 'flakes' at the top of the tree, simulates them fluttering down, and piling up in snowdrifts at the bottom. The bottom row slowly melts, making way for more snow!

The hard part was figuring out the ratio of lights in each ring. To do that, I used a temporary bit of code that let me move a 'cursor' around the tree, lighting up one LED at a time. It used Serial.read() so I could use the '-' and '=' keys to move it around, and printed out the current light number so I could record it. This let me create a 'vertical' line up one side of the tree, starting at light 0.

Using those ratios, every time a snowflake needs to 'drop' down, I know how many lights to move it to give the illusion of vertical movement!

Code

doSnow()C/C++
This is the core function that handles the falling snow. Sorry, it's not cleaned up, but hopefully it's documented enough for others to use.
```/**********************************************
*
* doSnow()
*    Let it snow, let it snow!
*
**********************************************/
int lightSpot = 0;
// ringCutoffs is the critical part. Starting with light 0, you need to identify the lights above
// one another in a straight line. If you light these all, you get a vertical line up one side of
// the tree. You need to use the Serial.available if statement at the start to experimentally
// figure out which light numbers those are and adjust the length and contents of the array
// Controls: Send '=' to the serial port to increment to the next light, '-' to go back a light
// You'll need to change your NUM_OF_RINGS to match the number of times your lights go around the tree.
#define NUM_RINGS 11
// Note that the first ring needs to start at 0!
int ringCutoffs[NUM_RINGS] = {0, 54, 95, 135, 167, 196, 218, 240, 262, 281, 295 };
int ringRatios[NUM_RINGS - 1];
char cBuff;
int snowTemp;
float snowPct;
#define SNOW_PWR 50
#define SNOW_MELT_HEAT 1
#define SNOW_MELT_HOW_MANY_RINGS_HIGH 3
#define SNOW_FULL_CUTOFF 230
#define NUM_FLAKES_TO_FALL_PER_FRAME 4
void doSnow() {
// STEP 1 - SET UP YOUR TREE
// THIS IS THE PART YOU USE THE FIRST TIME TO SET UP YOUR TREE
// Uncommend this block (and comment the rest). Use '=' and '-' to
// move your 'cursor' light around and experimentally get the
// values you need to put in the ringCutoffs array.
//if (Serial.available() > 0) {
//	switch (cBuff) {
//		case '=':
//			lightSpot++;
//			break;
//		case '-':
//			lightSpot--;
//			break;
//	}
//	Serial.println(lightSpot);
//}
//fill_solid(leds, NUM_LEDS, CRGB::Black);
//leds[lightSpot] = CRGB::White;
//FastLED.delay(DELAY_TIME_FAST);

// STEP 2 - DOUBLE-CHECK
// When you're done filling in ringCutoffs, uncomment this block and check your line. See if it goes
// fairly straight up the tree.
//fill_solid(leds, NUM_LEDS, CRGB::Black);
//for (ringCounter = 0; ringCounter < NUM_OF_RINGS; ringCounter++) {
//	leds[ringCutoffs[i]] = CRGB::White;
//}
//FastLED.delay(DELAY_TIME_FAST);

// STEP 3 - ENJOY THE SNOW
// Uncomment this code block and it will do the rest!
// Algorithm:
// Generate a random flake
// Start at the bottom ring, and float them all down

for (ring = 0; ring < NUM_RINGS - 1; ring++) {
for (led = ringCutoffs[ring]; led < ringCutoffs[ring + 1]; led++) {
if (snowFlakes[led] > 0) {
if (ring > 0) {
snowTemp = ((float)((float)(led - ringCutoffs[ring]) / (float)(ringCutoffs[ring + 1] - ringCutoffs[ring])) *
(ringCutoffs[ring] - ringCutoffs[ring - 1])) +
ringCutoffs[ring - 1] +
(random8(3) - 1);
if (snowFlakes[snowTemp] < SNOW_FULL_CUTOFF) {
//Serial.print("Going from ");
//Serial.print(led);
//Serial.print(" to ");
//Serial.println(snowTemp);
snowFlakes[snowTemp] = max (snowFlakes[led], min (250, snowFlakes[snowTemp] + SNOW_PWR));
snowFlakes[led] = 0;
}
//Serial.print("ON: ");
}
}
//Serial.println(led);
}
}
for (led = ringCutoffs[NUM_RINGS - 1]; led < NUM_LEDS; led++) {
if (snowFlakes[led] > 0) {
snowTemp = ((float)((float)(led - ringCutoffs[NUM_RINGS - 1]) / (float)(NUM_LEDS - ringCutoffs[NUM_RINGS - 1])) *
(ringCutoffs[NUM_RINGS - 1] - ringCutoffs[NUM_RINGS - 2])) +
ringCutoffs[NUM_RINGS - 2] +
(random8(3) - 1);
//Serial.println(led - ringCutoffs[NUM_RINGS - 1]);
//Serial.println(NUM_LEDS - ringCutoffs[NUM_RINGS - 1]);
//Serial.println((float)((float)(led - ringCutoffs[NUM_RINGS - 1]) / (float)(NUM_LEDS - ringCutoffs[NUM_RINGS - 1])));
//Serial.println(ringCutoffs[NUM_RINGS - 1] - ringCutoffs[NUM_RINGS - 2]);
//Serial.println((float)((float)(led - ringCutoffs[NUM_RINGS - 1]) / (float)(NUM_LEDS - ringCutoffs[NUM_RINGS - 1])) * (ringCutoffs[NUM_RINGS - 1] - ringCutoffs[NUM_RINGS - 2]));
//Serial.println(((float)((float)(led - ringCutoffs[NUM_RINGS - 1]) / (float)(NUM_LEDS - ringCutoffs[NUM_RINGS - 1])) * (ringCutoffs[NUM_RINGS - 1] - ringCutoffs[NUM_RINGS - 2])) + ringCutoffs[NUM_RINGS - 2]);
if (snowFlakes[snowTemp] < SNOW_FULL_CUTOFF) {
//Serial.print("Going from ");
//Serial.print(led);
//Serial.print(" to ");
//Serial.println(snowTemp);
snowFlakes[snowTemp] = min(250, snowFlakes[snowTemp] + SNOW_PWR);
snowFlakes[led] = 0;
}
//Serial.print("ON: ");
}
//Serial.println(led);
}
for (led = 0; led < ringCutoffs[SNOW_MELT_HOW_MANY_RINGS_HIGH]; led++) {
snowFlakes[led] = max(0, snowFlakes[led] - SNOW_MELT_HEAT);
}
for (snowTemp = 0; snowTemp < NUM_FLAKES_TO_FALL_PER_FRAME; snowTemp++) {
led = ringCutoffs[NUM_RINGS - 1] + (random8((NUM_LEDS - ringCutoffs[NUM_RINGS - 1])));
snowFlakes[led] = min (250, snowFlakes[led] + SNOW_PWR);
}
//fill_solid(leds, NUM_LEDS, CRGB::Black);
for (led = 0; led < NUM_LEDS; led++) {
//if (snowFlakes[led] > 0) {
leds[led] = CRGB(snowFlakes[led], snowFlakes[led], snowFlakes[led]);
//}
}
leds[0] = CRGB::Yellow;
FastLED.delay(150);
}
```

Schematics

Simple setup for LED Strings
xmaslights_H5oEYQFQh7.fzz

• 1 project
• 0 followers

Published on

December 22, 2017
See similar projects
you might like

MKR1000 RGB Strip Controller

Project showcase by Keith Mitchell

• 9,881 views
• 14 respects

Alexa-Powered Christmas Tree

Project tutorial by Kay Lerch

• 17,217 views
• 29 respects

DIY Christmas Tree and Christmas Decor Using Arduino

Project tutorial by STEMpedia

• 3,295 views
• 1 comment
• 7 respects

IOT Lighted Xmas Tree

Project tutorial by Sameer

• 1,534 views
• 1 comment
• 2 respects

Thoughts and Prayers

Project showcase by Front404

• 1,885 views