Created
November 17, 2012 21:51
-
-
Save bagofarms/4100540 to your computer and use it in GitHub Desktop.
IKEA Dioder Controlled by Time
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <TimeLord.h> // Provides sunrise/sunset information | |
#include <Wire.h> | |
#include <RTClib.h> | |
RTC_DS1307 RTC; | |
// Set the three PWM pins to use for each color. 9,10,11 are the other 3 | |
const int redPin = 9; | |
const int grnPin = 10; | |
const int bluPin = 11; | |
// Set input pin for square wave from RTC | |
//const int swIn = 3; | |
// Color arrays | |
int black[3] = { 0, 0, 0 }; | |
int white[3] = { 255, 255, 255 }; | |
int red[3] = { 255, 0, 0 }; | |
int green[3] = { 0, 255, 0 }; | |
int blue[3] = { 0, 0, 255 }; | |
int ltgreen[3]= { 100, 255, 100 }; | |
int ltblue[3] = { 100, 100, 255 }; | |
int orange[3] = { 255, 101, 0 }; | |
int purple[3] = { 255, 0, 255 }; | |
// Variables that will hold the current color value | |
int redVal; | |
int grnVal; | |
int bluVal; | |
// Sunrise/sunset variables | |
TimeLord timeLord; | |
byte sunRise[6] = {0, 0, 0, 0, 0, 0}; | |
byte sunSet[6] = {0, 0, 0, 0, 0, 0}; | |
// Transistion variables | |
uint32_t cycleTimes[9]; | |
uint32_t cycleOffsets[3] = {1800, 3600, 1800}; | |
int* cycleColors[9] = {purple, red, orange, blue, white, green, orange, red, purple}; | |
uint32_t NOON = 43200; | |
byte prevHour = 0; | |
byte prevDayOfMonth = 0; | |
void setup() { | |
Wire.begin(); | |
RTC.begin(); | |
// Initialize clock with correct time | |
RTC.adjust(DateTime(__DATE__, __TIME__)); | |
// Example initialization with a specific time (useful for debugging) | |
//RTC.adjust(DateTime(__DATE__, "10:59:00")); | |
// Color Pin Setup | |
pinMode(redPin, OUTPUT); // sets the pins as output | |
pinMode(grnPin, OUTPUT); | |
pinMode(bluPin, OUTPUT); | |
// Configure TimeLord for Orlando, FL and GMT-5 (Eastern) | |
timeLord.Position(28.6, -81.2); | |
timeLord.TimeZone(-5 * 60); | |
// Run startup test sequence | |
setToColor(purple); | |
delay(200); | |
setToColor(red); | |
delay(200); | |
setToColor(orange); | |
delay(200); | |
setToColor(blue); | |
delay(200); | |
setToColor(green); | |
delay(200); | |
setToColor(white); | |
delay(500); | |
} | |
void loop() { | |
// Get the current time | |
DateTime now = RTC.now(); | |
// Get sunrise and sunset values and update the cycle times | |
if(now.day() != prevDayOfMonth){ | |
updateSunriseSunset(now); | |
updateCycleTimes(); | |
} | |
prevDayOfMonth = now.day(); //Update the day so that we can compare on the next loop | |
updateColor(now); | |
delay(1000); | |
} | |
void updateSunriseSunset(DateTime now){ | |
sunRise[3] = byte(now.day()); | |
sunRise[4] = byte(now.month()); | |
sunRise[5] = byte(now.year()); | |
timeLord.SunRise((byte*)sunRise); | |
sunSet[3] = byte(now.day()); | |
sunSet[4] = byte(now.month()); | |
sunSet[5] = byte(now.year()); | |
timeLord.SunSet((byte*)sunSet); | |
} | |
void updateCycleTimes(){ | |
uint32_t sunRiseTimestamp = secondsFromMidnight(sunRise[2], sunRise[1], sunRise[0]); | |
uint32_t sunSetTimestamp = secondsFromMidnight(sunSet[2], sunSet[1], sunSet[0]); | |
cycleTimes[0] = sunRiseTimestamp - cycleOffsets[0]; //Before sunrise | |
cycleTimes[1] = sunRiseTimestamp; //Sunrise | |
cycleTimes[2] = sunRiseTimestamp + cycleOffsets[0]; //After sunrise | |
cycleTimes[3] = NOON - cycleOffsets[1]; //Before noon | |
cycleTimes[4] = NOON; //Noon | |
cycleTimes[5] = NOON + cycleOffsets[1]; //After Noon | |
cycleTimes[6] = sunSetTimestamp - cycleOffsets[2]; //Before noon | |
cycleTimes[7] = sunSetTimestamp; //Noon | |
cycleTimes[8] = sunSetTimestamp + cycleOffsets[2]; //After Noon | |
} | |
void updateColor(DateTime now){ | |
// If statements detecting each cycleTime | |
uint32_t curTime = secondsFromMidnight(byte(now.hour()), byte(now.minute()), byte(now.second())); | |
if(curTime <= cycleTimes[0]){ | |
setToColor(black); | |
}else if(curTime > cycleTimes[8]){ | |
setToColor(black); | |
}else{ | |
for(int i=0; i<9; i++){ | |
if(curTime > cycleTimes[i] && curTime <= cycleTimes[i+1]){ | |
calculateColors(curTime, cycleTimes[i], cycleTimes[i+1], cycleColors[i], cycleColors[i+1]); | |
break; | |
} | |
} | |
} | |
} | |
uint32_t secondsFromMidnight(byte in_hour, byte in_min, byte in_sec){ | |
uint32_t hours_in_seconds = uint32_t(in_hour) * 3600; | |
uint32_t minutes_in_seconds = uint32_t(in_min) * 60; | |
uint32_t seconds = uint32_t(in_sec); | |
return hours_in_seconds + minutes_in_seconds + seconds; | |
} | |
void calculateColors(uint32_t curTime, uint32_t startTime, uint32_t endTime, int startColor[3], int endColor[3]){ | |
//Calculate time elapsed per step | |
int dTRed = calculateStep(startTime, endTime, startColor[0], endColor[0]); | |
int dTGrn = calculateStep(startTime, endTime, startColor[1], endColor[1]); | |
int dTBlu = calculateStep(startTime, endTime, startColor[2], endColor[2]); | |
//Calculate current time elapsed in the section of the day | |
uint32_t dTime = curTime - startTime; | |
int setColors[3]; | |
setColors[0] = findColor(startColor[0], redVal, dTRed, dTime); | |
setColors[1] = findColor(startColor[1], grnVal, dTGrn, dTime); | |
setColors[2] = findColor(startColor[2], bluVal, dTBlu, dTime); | |
setToColor(setColors); | |
} | |
// Calculates number of seconds between each step of the color | |
int calculateStep(uint32_t startTime, uint32_t endTime, int startColor, int endColor){ | |
int retVal; | |
int colorDiff = endColor - startColor; | |
// Protect against division by zero | |
if(colorDiff == 0){ | |
retVal = 0; | |
}else{ | |
int32_t timeDiff = int32_t(endTime) - int32_t(startTime); | |
retVal = int(timeDiff / int32_t(colorDiff)); | |
} | |
return retVal; | |
} | |
//Finds the current correct value for the color | |
int findColor(int startColor, int curColor, int dTColor, uint32_t dTime){ | |
int retVal; | |
if(dTColor == 0){ | |
//If the color is already correct, just set it to what the start color was for this segment of the day | |
retVal = startColor; | |
}else if( dTime % dTColor ){ | |
//find out how many steps we've done, add that to starting color for this segment | |
retVal = startColor + int( int32_t(dTime) / int32_t(dTColor) ); | |
}else{ | |
retVal = curColor; | |
} | |
// Check to make sure value is within allowed range | |
// If the color value is negative, it will evaluate to 255. | |
// If it's greater than 255, it will evaluate to 0. | |
if(retVal < 0){ | |
retVal = 0; | |
}else if(retVal > 255){ | |
retVal = 255; | |
} | |
return retVal; | |
} | |
void setToColor(int color[3]){ | |
redVal = color[0]; | |
grnVal = color[1]; | |
bluVal = color[2]; | |
analogWrite(redPin, color[0]); | |
analogWrite(grnPin, color[1]); | |
analogWrite(bluPin, color[2]); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment