Skip to content

Instantly share code, notes, and snippets.

@bagofarms
Created November 17, 2012 21:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bagofarms/4100540 to your computer and use it in GitHub Desktop.
Save bagofarms/4100540 to your computer and use it in GitHub Desktop.
IKEA Dioder Controlled by Time
#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