/*
Arduino LED controller for reef aquariums
// paramterized LED lighting control for reef aquariums
// use a DS1307 RTC to kick off lighting schedules
// fade up on a given slope
// delay a set amount
// fade back down
// such that the photoperiod lasts the correct amount of time
// Circuit
//
// PWM pins described below connected to dimming circuits on drivers
// ledMaster pin below connected to a 120V AC relay to turn the LED drivers on and off (optional)
// grounds from drivers connected to arduino ground
// DS1307 RTC connected via I2C
//
//
//
*/
// Pins to control LEDs. Change these if you're using different pins.
int blueLed = 9; // LED PWM channel for blues
int whiteLed = 10; // LED PWM channel for whites
// Set up RTC
#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68
// RTC variables
byte second, rtcMins, oldMins, rtcHrs, oldHrs, dayOfWeek, dayOfMonth, month, year;
// Other variables. These control the behavior of lighting. Change these to customize behavoir
int minCounter = 0; // counter that resets at midnight. Don't change this.
int blueStartMins = 480; // minute to start blues. Change this to the number of minutes past
// midnight you want the blues to start.
int whiteStartMins = 480; // minute to start whites. Same as above.
int bluePhotoPeriod = 510; // photoperiod in minutes, blues. Change this to alter the total
// photoperiod for blues.
int whitePhotoPeriod = 510; // photoperiod in minutes, whites. Same as above.
int fadeDuration = 60; // duration of the fade on and off for sunrise and sunset. Change
// this to alter how long the fade lasts.
int blueMax = 255; // max intensity for blues. Change if you want to limit max intensity.
int whiteMax = 255; // max intensity for whites. Same as above.
/****** LED Functions ******/
/***************************/
//function to set LED brightness according to time of day
//function has three equal phases - ramp up, hold, and ramp down
void setLed(int mins, // current time in minutes
int ledPin, // pin for this channel of LEDs
int start, // start time for this channel of LEDs
int period, // photoperiod for this channel of LEDs
int fade, // fade duration for this channel of LEDs
int ledMax // max value for this channel
) {
if (mins > start && mins <= start + fade) {
analogWrite(ledPin, map(mins - start, 0, fade, 0, ledMax));
}
if (mins > start + period && mins <= start + period - fade) {
analogWrite(ledPin, ledMax);
}
if (mins > start + period - fade && mins <= start + period) {
analogWrite(ledPin, map(mins - start + period - fade, 0, fade, ledMax, 0));
}
}
/***** RTC Functions *******/
/***************************/
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}
// 1) Sets the date and time on the ds1307
// 2) Starts the clock
// 3) Sets hour mode to 24 hour clock
// Assumes you're passing in valid numbers.
void setDateDs1307(byte second, // 0-59
byte minute, // 0-59
byte hour, // 1-23
byte dayOfWeek, // 1-7
byte dayOfMonth, // 1-28/29/30/31
byte month, // 1-12
byte year) // 0-99
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.send(0);
Wire.send(decToBcd(second));
Wire.send(decToBcd(minute));
Wire.send(decToBcd(hour));
Wire.send(decToBcd(dayOfWeek));
Wire.send(decToBcd(dayOfMonth));
Wire.send(decToBcd(month));
Wire.send(decToBcd(year));
Wire.endTransmission();
}
// Gets the date and time from the ds1307
void getDateDs1307(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.send(0);
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
*second = bcdToDec(Wire.receive() & 0x7f);
*minute = bcdToDec(Wire.receive());
*hour = bcdToDec(Wire.receive() & 0x3f);
*dayOfWeek = bcdToDec(Wire.receive());
*dayOfMonth = bcdToDec(Wire.receive());
*month = bcdToDec(Wire.receive());
*year = bcdToDec(Wire.receive());
}
void setup() {
// init I2C
Wire.begin();
}
/***** Main Loop ***********/
/***************************/
void loop() {
// get time from RTC and put in hrs and mins variables
getDateDs1307(&second, &rtcMins, &rtcHrs, &dayOfWeek, &dayOfMonth, &month, &year);
minCounter = rtcHrs * 60 + rtcMins;
// determine if it is day or night, and act accordingly
if ((minCounter > blueStartMins || minCounter > whiteStartMins)
&& (minCounter < blueStartMins + bluePhotoPeriod || minCounter < whiteStartMins + whitePhotoPeriod)) { //day
// set LED states
setLed(minCounter, blueLed, blueStartMins, bluePhotoPeriod, fadeDuration, blueMax);
setLed(minCounter, whiteLed, whiteStartMins, whitePhotoPeriod, fadeDuration, whiteMax);
}
else { //night
analogWrite(blueLed, 0);
analogWrite(whiteLed, 0);
}
// Get ready for next iteration of loop
delay(1000);
}