|
#include "FastLED.h" |
|
|
|
#define NUM_LEDS 60 |
|
#define TIME_BUTTON_PIN 3 |
|
#define WEATHER_BUTTON_PIN 2 |
|
#define BUTTON_PINC 4 |
|
#define DATA_PIN 6 |
|
|
|
|
|
#define LATCH_PIN 8 |
|
//Pin connected to SH_CP of 74HC595 |
|
#define CLOCK_PIN 12 |
|
////Pin connected to DS of 74HC595 |
|
#define SHIFT_DATA_PIN 11 |
|
|
|
CRGB leds[NUM_LEDS]; |
|
CRGB lastLeds[NUM_LEDS]; |
|
CRGB targetLeds[NUM_LEDS]; |
|
|
|
void setup() { |
|
FastLED.addLeds<WS2812, 6, GRB>(leds, NUM_LEDS); |
|
FastLED.setBrightness(255); |
|
|
|
pinMode(TIME_BUTTON_PIN, INPUT); |
|
pinMode(WEATHER_BUTTON_PIN, INPUT); |
|
pinMode(BUTTON_PINC, INPUT); |
|
Serial.begin(9600); |
|
|
|
for(int i = 0; i < NUM_LEDS; i++) { |
|
leds[i] = CRGB::Red; |
|
lastLeds[i] = CRGB::Red; |
|
targetLeds[i] = CRGB::Red; |
|
} |
|
|
|
pinMode(LATCH_PIN, OUTPUT); |
|
pinMode(CLOCK_PIN, OUTPUT); |
|
pinMode(SHIFT_DATA_PIN, OUTPUT); |
|
} |
|
|
|
int lightState = 0; |
|
int lastButtonAState = LOW; |
|
int lastButtonBState = LOW; |
|
int lastButtonCState = LOW; |
|
|
|
int maximumState = 1; |
|
|
|
void setLed(int ledIndex, CRGB targetColor) { |
|
targetLeds[ledIndex] = CRGB(0, 0, 255); |
|
} |
|
|
|
long lastChange = millis(); |
|
|
|
void setLastLeds() { |
|
for(int i = 0; i < NUM_LEDS; i++) { |
|
lastLeds[i] = leds[i]; |
|
} |
|
} |
|
|
|
#define SUNRISE 0 |
|
#define MIDDAY 1 |
|
#define SUNSET 2 |
|
#define NIGHTTIME 3 |
|
|
|
int timeOfDay = SUNRISE; |
|
|
|
#define CLEARSKIES 0 |
|
#define OVERCAST 1 |
|
#define RAIN 2 |
|
|
|
int weather = CLEARSKIES; |
|
|
|
int layerLeds[][2] = {{0, 9}, {10, 19}, {20, 29}, {30, 39}, {40, 49}, {50, 59}, {60, 60}}; |
|
|
|
#define SUN 5 |
|
#define MOUNTAIN1 0 |
|
#define MOUNTAIN2 1 |
|
#define MOUNTAIN3 2 |
|
#define MOUNTAIN4 3 |
|
#define SKY 4 |
|
|
|
CRGB mountain1Color = CRGB::White; |
|
CRGB mountain2Color = CRGB::Chartreuse;//;// CRGB(28, 148, 173); |
|
CRGB mountain3Color = CRGB(90, 166, 181); |
|
CRGB mountain4Color = CRGB::Coral;//CRGB(228, 176, 168); |
|
CRGB skyColor = CRGB::DeepSkyBlue; |
|
CRGB sunColor = CRGB(249, 171, 136); |
|
|
|
CRGB fadeColorByWeather(CRGB color, int weather) { |
|
switch(weather) { |
|
case OVERCAST: |
|
return color.fadeLightBy(255/2); |
|
case RAIN: |
|
return color.fadeLightBy(255*3/4); |
|
default: |
|
return color; |
|
} |
|
} |
|
|
|
|
|
CRGB paintColorByTimeOfDay(CRGB color, int timeOfDay) { |
|
switch(timeOfDay) { |
|
case SUNSET: |
|
return CRGB::Red; |
|
case SUNRISE: |
|
return CRGB::OrangeRed; |
|
case NIGHTTIME: |
|
return CRGB::Blue; |
|
default: |
|
return color; |
|
} |
|
} |
|
|
|
CRGB getLayerColor(int layer, int timeOfDay, int weather) { |
|
//Serial.println(layer); |
|
if(layer == SUN) { |
|
CRGB color; |
|
switch(timeOfDay) { |
|
case SUNRISE: |
|
color = CRGB::Orange; |
|
case MIDDAY: |
|
color = CRGB::Yellow; |
|
case SUNSET: |
|
color = CRGB::Yellow; |
|
default: |
|
color = CRGB::MintCream; |
|
break; |
|
} |
|
color.fadeLightBy(200); |
|
return color; |
|
} else if(layer == MOUNTAIN1) { |
|
CRGB color = mountain1Color; |
|
color = paintColorByTimeOfDay(color, timeOfDay); |
|
color = fadeColorByWeather(color, weather); |
|
return color; |
|
|
|
} else if(layer == MOUNTAIN2) { |
|
if (timeOfDay == NIGHTTIME) |
|
return CRGB::Black; |
|
CRGB color = mountain2Color; |
|
color = paintColorByTimeOfDay(color, timeOfDay); |
|
color = fadeColorByWeather(color, weather); |
|
return color; |
|
|
|
} else if(layer == MOUNTAIN3) { |
|
if (timeOfDay == NIGHTTIME) |
|
return CRGB::Black; |
|
CRGB color = mountain3Color; |
|
color = paintColorByTimeOfDay(color, timeOfDay); |
|
color = fadeColorByWeather(color, weather); |
|
return color; |
|
|
|
} else if(layer == MOUNTAIN4) { |
|
if (timeOfDay == NIGHTTIME) |
|
return CRGB::Black; |
|
CRGB color = mountain4Color; |
|
color = paintColorByTimeOfDay(color, timeOfDay); |
|
color = fadeColorByWeather(color, weather); |
|
return color; |
|
|
|
} else if (layer == SKY) { |
|
CRGB color; |
|
switch(timeOfDay) { |
|
case SUNRISE: |
|
return CRGB::DeepPink; |
|
case MIDDAY: |
|
color = CRGB::SkyBlue; |
|
color.fadeLightBy(100); |
|
return color; |
|
case SUNSET: |
|
return CRGB::Red; |
|
default: |
|
return CRGB::LightGoldenrodYellow; |
|
} |
|
|
|
} |
|
else { |
|
return CRGB::White; |
|
} |
|
} |
|
|
|
void setConditions(int timeOfDay, int weather) { |
|
|
|
setLastLeds(); |
|
lastChange = millis(); |
|
|
|
byte statusData = 0; |
|
bitSet(statusData, weather); |
|
bitSet(statusData, timeOfDay + 3); |
|
digitalWrite(LATCH_PIN, LOW); |
|
// shift out the bits: |
|
shiftOut(SHIFT_DATA_PIN, CLOCK_PIN, MSBFIRST, statusData); |
|
|
|
//take the latch pin high so the LEDs will light up: |
|
digitalWrite(LATCH_PIN, HIGH); |
|
|
|
for(int i = 0; i <= 5; i++) { |
|
CRGB color = getLayerColor(i, timeOfDay, weather); |
|
for(int j = layerLeds[i][0]; j <= layerLeds[i][1]; j++) { |
|
targetLeds[j] = color; |
|
} |
|
} |
|
} |
|
|
|
#define TRANSITION_DURATION 1000.0 |
|
void advanceAnimation() { |
|
float percentage = constrain((millis() - lastChange * 1.) / TRANSITION_DURATION, 0., 0.9999); |
|
fract8 fract = floor(percentage * 256); |
|
|
|
if (fract <= 256) { |
|
for(int i = 0; i < NUM_LEDS; i++) { |
|
leds[i] = blend(lastLeds[i], targetLeds[i], fract); |
|
} |
|
} |
|
if (timeOfDay == NIGHTTIME) { |
|
animateNightStars(); |
|
} |
|
FastLED.show(); |
|
delay(20); |
|
} |
|
|
|
#define SPARKLE_DURATION 1000 |
|
long lastStarChange = millis(); |
|
void animateNightStars() { |
|
|
|
int firstSkyLed = layerLeds[MOUNTAIN3][0]; |
|
int lastSkyLed = layerLeds[SKY][1]; |
|
|
|
if(millis() - lastStarChange > SPARKLE_DURATION) { |
|
Serial.println("sparkling"); |
|
lastStarChange = millis(); |
|
|
|
for(int i = firstSkyLed; i <= lastSkyLed; i++) { |
|
lastLeds[i] = leds[i]; |
|
targetLeds[i] = CRGB::Blue; |
|
} |
|
|
|
for(int i = 0; i < 10; i++) { |
|
int randomStarOn = random(firstSkyLed, lastSkyLed + 1); |
|
Serial.print(randomStarOn); |
|
Serial.print(" "); |
|
targetLeds[randomStarOn] = CRGB::White; |
|
targetLeds[randomStarOn].fadeLightBy(200); |
|
} |
|
Serial.println(""); |
|
|
|
lastStarChange = millis(); |
|
} |
|
|
|
|
|
float percentage = constrain((millis() - lastStarChange * 1.) / SPARKLE_DURATION, 0., 0.9999); |
|
fract8 fract = floor(percentage * 256); |
|
for(int i = firstSkyLed; i <= lastSkyLed; i++) { |
|
leds[i] = blend(lastLeds[i], targetLeds[i], fract); |
|
} |
|
} |
|
|
|
void loop() { |
|
// read the state of the pushbutton value: |
|
int currentButtonAState = digitalRead(TIME_BUTTON_PIN); |
|
int currentButtonBState = digitalRead(WEATHER_BUTTON_PIN); |
|
int currentButtonCState = digitalRead(BUTTON_PINC); |
|
|
|
if (currentButtonAState == HIGH && lastButtonAState == LOW) { |
|
timeOfDay++; |
|
if (timeOfDay >NIGHTTIME) |
|
timeOfDay = 0; |
|
Serial.print("time of day: "); |
|
Serial.println(timeOfDay); |
|
setConditions(timeOfDay, weather); |
|
// for(int i = 0; i < NUM_LEDS; i++) { |
|
// targetLeds[i] = CRGB::Green; |
|
// } |
|
} |
|
if (currentButtonBState == HIGH && lastButtonBState == LOW) { |
|
weather++; |
|
if (weather > RAIN) |
|
weather = 0; |
|
Serial.print("weather: "); |
|
Serial.println(weather); |
|
setConditions(timeOfDay, weather); |
|
// for(int i = 0; i < NUM_LEDS; i++) { |
|
// targetLeds[i] = CRGB::Blue; |
|
// } |
|
} |
|
if (currentButtonCState == HIGH && lastButtonCState == LOW) { |
|
Serial.println("getWeather"); |
|
} |
|
|
|
lastButtonAState = currentButtonAState; |
|
lastButtonBState = currentButtonBState; |
|
lastButtonCState = currentButtonCState; |
|
|
|
advanceAnimation(); |
|
|
|
if (Serial.available() > 0) { |
|
// read the incoming byte: |
|
String incomingMessage = Serial.readString(); |
|
int commaIndex = incomingMessage.indexOf(','); |
|
timeOfDay = incomingMessage.substring(0, commaIndex).toInt(); |
|
weather = incomingMessage.substring(commaIndex + 1, incomingMessage.length()).toInt(); |
|
|
|
setConditions(timeOfDay, weather); |
|
Serial.print("weather received: "); |
|
Serial.print(timeOfDay); |
|
Serial.print(" "); |
|
Serial.println(weather); |
|
|
|
|
|
} |
|
} |