#include <PWM.h>
//#define DEBUG
/*
CONFIGURABLE
*/
// which Arduino PWM pins to use (do not use 5 or 6, doing so will literally cause a timewarp...)
const byte BLUES_PIN = 9;
const byte WHITES_PIN = 10;
// how bright the lights are allowed to get
const byte blue_max_level = 255; // 0-255
const byte white_max_level = 50; // 0-255
// cloudy weather
const bool clouds = true;
byte cloud_max_shade = 40; // 1-white_max_level (white_max_level is complete darkness) this is the maximum shadow clouds can cast
const unsigned long cloud_min_duration = 60000; // milliseconds, a cloud will last at least this long
const unsigned long cloud_max_duration = 300000; // milliseconds, this is how long a single cloud can last
const unsigned long cloud_min_between = 10000; // milliseconds, at least this long will pass between clouds
const unsigned long cloud_max_between = 60000; // milliseconds, this is how much time can pass between clouds
// start 7AM, rise until 10AM, peak until 8PM, fall until 9PM
const unsigned long blue_rise_duration = 10800000; // milliseconds
const unsigned long blue_peak_duration = 36000000; // milliseconds
const unsigned long blue_fall_duration = 3600000; // milliseconds
// start 8AM, rise untill 10AM, peak untill 4PM, fall until 5PM
const unsigned long white_rise_start = 3600000; // milliseconds
const unsigned long white_rise_duration = 7200000; // milliseconds
const unsigned long white_peak_duration = 21600000; // milliseconds
const unsigned long white_fall_duration = 3600000; // milliseconds
/*
END CONFIGURABLE
*/
unsigned long now;
unsigned long blue_peak_end, blue_fall_end, blue_duration;
unsigned long white_rise_end, white_peak_end, white_fall_end, white_duration;
unsigned long cloud_start, cloud_end, cloud_middle;
byte blue_level, last_blue_level;
byte white_level, last_white_level;
byte cloud_shade;
void setup()
{
InitTimersSafe();
randomSeed(analogRead(A0));
#ifdef DEBUG
Serial.begin(9600);
#endif
if(SetPinFrequency(BLUES_PIN, 20000) && SetPinFrequency(WHITES_PIN, 20000))
{
pwmWrite(BLUES_PIN, 0);
pwmWrite(WHITES_PIN, 0);
//SetPinFrequency(D3, 20000); SetPinFrequency(11, 20000);
//pwmWrite(3, 255); pwmWrite(11, 255);
pinMode(13, OUTPUT);
digitalWrite(13, HIGH);
}
blue_peak_end = blue_rise_duration + blue_peak_duration;
blue_fall_end = blue_peak_end + blue_fall_duration;
blue_duration = blue_fall_end; // convenience
white_rise_end = white_rise_start + white_rise_duration;
white_peak_end = white_rise_end + white_peak_duration;
white_fall_end = white_peak_end + white_fall_duration;
white_duration = white_fall_end - white_rise_start;
last_blue_level = 0;
last_white_level = 0;
cloud_shade = 0;
cloud_start = 0;
cloud_middle = 0;
cloud_end = 0;
cloud_max_shade = min(cloud_max_shade, white_max_level);
}
void loop()
{
now = millis();
if(now < blue_rise_duration)
{
blue_level = blue_max_level * (1.0 - (((float)blue_rise_duration - (float)now) / (float)blue_rise_duration));
}
else if(now < blue_peak_end)
{
blue_level = blue_max_level;
}
else if(now < blue_fall_end)
{
blue_level = blue_max_level * (float)(((float)blue_fall_end - (float)now) / (float)blue_fall_duration);
}
else
{
blue_level = 0;
}
if((now < white_rise_start) || (now > white_fall_end))
{
white_level = 0;
}
else if(now < white_rise_end)
{
white_level = white_max_level * (1.0 - (float)(((float)white_rise_duration - ((float)now - (float)white_rise_start)) / (float)white_rise_duration));
}
else if(now < white_peak_end)
{
if(clouds)
{
if((now > cloud_start) && (now < cloud_middle))
{
white_level = white_max_level - ((float)cloud_shade * (1.0 - ((float)(cloud_middle - now) / (float)(cloud_middle - cloud_start))));
}
else if((now > cloud_middle) && (now < cloud_end))
{
white_level = white_max_level - ((float)cloud_shade * ((float)(cloud_end - now) / (float)(cloud_end - cloud_middle)));
}
else if(now > cloud_end)
{
cloud_start = now + max(cloud_min_between, ((float)cloud_max_between * (float)((float)random(1, 100000) / 100000.0)));
cloud_end = cloud_start + max(cloud_min_duration, ((float)cloud_max_duration * (float)((float)random(1, 100000) / 100000.0)));
cloud_middle = cloud_start + ((cloud_end - cloud_start) / 2);
cloud_shade = random(1, cloud_max_shade);
}
}
else
{
white_level = white_max_level;
}
}
else if(now < white_fall_end)
{
white_level = white_max_level * (float)(((float)white_fall_duration - ((float)now - (float)white_peak_end)) / (float)white_peak_duration);
}
if(blue_level != last_blue_level)
{
pwmWrite(BLUES_PIN, blue_level);
last_blue_level = blue_level;
}
if(white_level != last_white_level)
{
pwmWrite(WHITES_PIN, white_level);
last_white_level = white_level;
}
#ifdef DEBUG
Serial.print("B"); Serial.println(blue_level);
Serial.print("W"); Serial.println(white_level);
#endif
}