DIY LED lighting

The friendliest place on the web for anyone with an interest in aquariums or fish keeping!
If you have answers, please help by responding to the unanswered posts.

AdamHorton

Aquarium Advice FINatic
Joined
Aug 12, 2009
Messages
581
Location
Cincinnati, OH
I'm planning a 55G freshwater tank, and I have sort of a rough idea in my head of what I want, part of that vision is lighting...

First, I'll say that I have no desire to keep live plants in this tank, the lights will be used for viewing purposes only, and I'll be getting my FW plant fix from a different tank.

Second, the decor for this tank will probably consist mostly of rocks and driftwood. I may end up with a few fake plants in there for color, but I'm not sure. I'm leaning towards using a darker substrate, maybe Tahitian Moon Sand?

Third, I want there to be LED lights on this tank. This is mostly because I have a vision of providing lots of color to this tank through lighting. I'd like to be able to provide more than just white and blue light, sort of like a sunrise/sunset effect. My inspiration right now is the following: (if anyone else even understands this reference I'll be shocked)

Episode 8 of Season 21 of Survivor, there was a scene where there was this brilliant sunset and this strong, orange light was coming from one side, making the lighting of everything just strong. Here's a link to some pictures of it: Ep2108_0495 There are a bunch of other nearby pictures of it too.

Kind of obscure, I know, but I'd like to be able to have an LED setup that can give me white, blue, and red/orange light. I suppose the more colors, the better, though.

Building it:

So it doesn't look like there are any lighting systems out there that are pre-made to include any colors of light other than white and blue. What I'd really like to happen is to have a "sunrise" in the morning, starting out with red/orange light and going into white light during the day. A "sunset" at the end of the day, where the white fades out, then red light, which fades into blue light, then that fades out.

Each color of light would have to have a separate timer on it. I realize that I'm going to have to do some DIY here, but I don't have much confidence in my ability to make the final setup look good. I'm hoping to get some suggestions to make my life easier in this thread, or if not, at least I can document a lot of my ideas and if any of them actually work in case it helps anyone else.

Ideas:

So, what I'm thinking right now: I get a cheap LED canopy light that has fade in/fade out capabilities with a timer that can control all of that, and that has only white light.

EDIT: The closest thing I can find to that is something like this: http://premiumaquatics.com/aquatic-supplies/ML-32992.html
I'd really like to have a gradual fade in/fade out feature, and this appears to just be on/off. I have a sinking feeling that if I want fade in/fade out white light I'll have to make the same as the colored light. If I do it that way, then making it pretty might be difficult...

Then, I'll use something like these:

Radiantz Sidewinderz LED Light Strip - RED - 3 Lights RTI04

and I'd have to make my own 12V custom circuit that would control the voltage with a timer. I could just stick these on the white light system, or even on the sides of the tank -- one side for sunrise, the other side for sunset. This makes the "hard part" the controlling circuit for the colored lights, which conveniently falls close to (but not quite within) my area of expertise (I write software for a living, but I've had some hardware background). It's been a while, but I've made a microcontroller-based circuit before that could do this kind of thing.

If there's something I can buy to use for part of this circuit I'd rather do that than DIY that part, even if it costs more.

Anyways, I'll probably do some more research on this and stick it in this thread, but I welcome suggestions/constructive criticism here. If there's a way I can do this better, I'd certainly like to know about it.

Time Frame:
I haven't bought anything for this tank yet, I think I might get the tank, stand, substrate, heater, and filter this weekend at the earliest, but even then I have 5-6 weeks while the tank fishless cycles before I have to have anything done for lighting purposes.
 
You can achieve the fade in and out with a controller DIY an Arduino or something off the shelf from digital aquatics. The controller though is going to be spend unless you do something like an Arduino. As far as the LEDs go if you want to go with all DIY LEDs i would use something from the CREE line. Buck pucks are dimmable and run off of DC. I have been working on a very simalar project thus far I have my arduino wired up to the pucks and i can fade in and out. for your application you would need 3 separate channels and possible 4-6 pucks depending on the number of LEDs you want to have.

On a 55 it may be quite spendy... but i would use 1 channel of 15 whites 1 channel of 15 blues and one channel with your reds.

The algorithm would go something like
AM Ramp up reds over an hour
half way through reds begin to ramp whites
as white make 50% hold whites and begin to fade reds
as reds fade ramp blues to 50%
reds off ramp whites and blues to full intensity
reverse for sunset.

my .02$

I can certainly help with the hardware side if you can handle the programming... i may even need some help with my programming for my controller.
 
those leds you linked will only give a small color to the tank without any benefit to the corals... for the reds maybe ok since those will be more for show than anything else. But for the main lights the small 12mm leds just dont create enough PAR for plants and such and really arent bright enough for viewing unless you go CRAZY with the number of them... cheaper to use something like CREES in the long run if you decide to come to the dark side and do a reef or even a planted FW tank
 
To clarify, this lighting setup is for a freshwater tank, where I won't be keeping live plants. The lights here are for show only, and the only purpose is to give some color to the tank, which is why I chose the LEDs that I did. I have a planted FW tank and a SW tank that will be a reef one day, so I guess I'm sort of already on the dark side.

Those LEDs I linked to, they don't have many technical details, it just says that they will work on any 12V system. You mentioned using Buck Pucks, and those seem to be big on keeping the current to the LED constant. If I remember correctly, isn't the brightness of an LED proportional to its current? You said you were able to fade in/out using your controller (a brief look at Arduino's website doesn't show much for what those controllers are able to do). How exactly do you have it set up, and what kind of LEDs are you using? My guess is that you're using some type of PWM going out of your Arduino controller, then that goes to the Buck Puck, which drives your LED. If you're having success with this, then it may be the best path for me.

I think I want to have one channel of blue light, one channel of white light, and two channels of red light. I'm still holding onto the vision that sunrise will come from one side of the tank and sunset from the other... Does the Arduino have four PWM channels (or whatever you're using to get your fade effect)?
 
Hi Adam

I've been looking at similar systems
If you're not looking at planted tanks and it's just for visual purposes then a system like this might be something you're after
AquaFX LED Aquarium Lighting System

I'm considering one as part of my setup and it's fully programmable
I have had some feedback about it that may be of help to you
here


Cheers
Andy
 
spama -- interesting link, I haven't see anything like that yet. It's certainly expensive, but it's right along the lines of what I'm looking for... I'll look into it more closely. I already had this post typed up before you added yours.

Jnam -- I've done a little more digging. I'm pretty sure the Arduino is the controller I'm going to use. As far as hardware goes, my only questions left are related to the Buck Puck. Are you using that to drive the LED, using the output of your controller as the switch? Are you able to drive your LEDs this way using PWM to achieve the fade effect? If I'm understanding correctly, this should be how you're doing it...

Here are the LED strips I'm looking at (I've changed since last time because those other ones had an adhesive already on them and I didn't want that near my fish tank)

Orange LEDs for sunrise/sunset effect, one of these for each side:
WFLB96 series Waterproof Flexible Light Bar

White/blue LEDs, probably four warm white and two blue (the 24-LED strips):
WFLB series Waterproof Flexible Light Bar

So, for example, if I wanted to drive the four white strips, which together draw 456 mA, it looks like I can use the 500mA "E" BuckPuck (3021-D-E-500 BuckPuck - LED Supply.com) to drive them in parallel as long as I use at least a 12V power supply, as long as I adjust the output current to be 450 mA or so.

If I end up using these LED strips, I'm thinking I won't have any kind of canopy over the tank, just a glass cover. What I want to do is hot-glue the LED strips underneath the rim of the tank, just below the top. I'll do the white and blue on the front and back edges (blue in the middle, two whites on the ends, on both the front and back edges of the tank). Then, I can do the orange strips on the left and right sides. I haven't decided the exact placement of the orange lights yet, but the strips I'm looking at are long and they can be cut down so that gives me some flexibility.

This is pretty exciting, I think I have all of the hardware picked out, and I think it will all work! I was worried this would be the hardest part, since I'm sure the software side will be a breeze for me (I'd be ashamed and looking for a new career if it wasn't)

If anyone has any comments or suggestions (or NO THIS WON'T WORK!), I'm hoping to order hardware by tomorrow at the latest.
 
Yes I use PWM and the buck, you are correct current is proportionate to the brightness of the LED. 12V doesnt mean much when it comes to LEDs as voltage isnt the driving factor. Looking at the data sheets for the LEDs I cant tell what the forwad voltage of the string is nor can I see how they are wired series paralell... Its hard to give an opinion. From the website it looks like the just depend on some internal circuitry? to regulate the LEDs... It says 640mA at 12 Volts is the current draw that would indicate to me some kind of current limiting resistor wired in there someplace... Its worth testing out for sure I just dont know.

Yes you are right with your ideas on the driving the LEDs. Cant wait to see the project move forward!
 
I got the LEDS and the Buck Pucks in today and I've been playing around with them. It seems that there are current-limiting resistors in the LED strips, and it also seems that the Buck Pucks are pretty good about not frying the LEDs. Once the Arduino comes in I should be able to get things set up pretty quickly.

I had a quick question about they way you're controlling the brightness: are you using the CTL input on the Buck Puck for your PWM? If so, are you just hooking the output of your PWM directly to that input of the Buck Puck, or are you using a pull-up resistor or anything else in between?

The software side of things shouldn't be too hard for me. Once I get it working I'll post my code and I shouldn't have much trouble debugging if you're having a problem.
 
I got the last of the supplies in the mail today, and I couldn't stop myself from working on it. I have the software all written, and the hardware is all set up on my breadboard. All that's left to do is move it to a different breadboard (one that's dedicated to this project), attach the LEDs to the tank, and tweak a couple of numbers in the program until I like the way it looks. Once I'm happy with the code, I'll start uploading stuff.

I bought an LCD screen because I wanted to have that interface to set the clock with, but something's wrong with the LCD and I don't know what it is. It just doesn't work. So, I'm using the serial interface with the computer to set the clock. It's not as pretty, but at least it works. The problem with that is that every time I plug it in to start, I have to hook it up to my computer to set the clock and that's kind of a pain.

If today is any indication, I'll probably work on it all day tomorrow and be done with it.
 
Question for everyone, I have wanted to do something very similar to your set up. I wanted to make an LED system that mimics real life. Blue lights at night that progressively gets stronger to normal light then recedes back to blue. How strong do you need to make it if you want a decently planted aquarium. I know the creator of the post didn't want plants but it is feasible with LEDs to have a planted aquarium?
 
what RTC are you using with your arduino? or are you using the internal timers from the millis() function?

i use a one wire ds1307 with batter backup it has a couple cool features like usable eeprom and a square wave generator. It keeps its own time and with a 3v battery it should be good for 9 years. I set the time once and then in the code turn the setting into a fuction that i can call to update the time if i want.

Which LCD did you get?

I have a planted tank with LEDs just started it though. The coolest thing though is that HC I have pearls already... If LEDs can sustain a light demanding reef its just a matter of matching spectrums and PAR requirements for a planted freshwater tank.
 
For my clocking, I'm using the millis() function with this fix for the rollover problem:

Arduino playground - TimingRollover

Here's a link to the LCD I bought.

Amazon.com: LCD Module for Arduino 20 x 4, White on Blue: Everything Else

I've gotten the backlight to work, just nothing on the display. I'm planning to post about it on the Arduino forums so I can try and figure out what's wrong with it, but I haven't been feeling well so it may be a few days before I can get to it.

The system is basically done. I plan on commenting my code and posting it soon. I took a couple of videos but the quality isn't very good and I need to re-do them. I'll link to the crappy videos here, but again, I don't feel so good so it may be a while before I get a chance to do that.

YouTube - DIY LED lighting
YouTube - DIY LED lighting - how it works

Besides, I kind of wanted to finish the aquascaping before I took videos like this, and right now I'm dealing with a piece of driftwood that won't sink so it might be a while before it decides to sink for me.
 
I've commented my source code. Here it is:

Code:
static unsigned long lWaitMillis;
int inByte = 0;
int ValidTime;

int Time_hrs;
int Time_mins;
int Time_secs;

//These #defines allow me to quickly change the lighting schedule.
//Right now they're in a test setup, I'll change it eventually to
//match a more realistic lighting schedule

//Sunrise = 1: From 0:00 to 1:00, fade in orange lights 0-100%
//             From 1:00 to 2:00, fade in white lights 0-100%
//             From 2:00 to 3:00, fade out orange lights 100-0%
#define SUNRISE  1

//Sunset = 5:  From 4:00 to 5:00, fade in orange lights 0-100%
//             From 5:00 to 6:00, fade out white lights 100-0%
//             From 6:00 to 7:00, fade out orange lights 100-0%
#define SUNSET   5

//The moon is independant from the sun at the moment. I think this
//is the way I like it, where the moon rises while the sun is still
//out. I have the ability to change it though.

//Moonrise = 3: From 3:00-4:00, fade in blue lights 0-100%
#define MOONRISE 3
//Moonset = 7:  From 7:00-8:00, fade out blue lights 100-0%
#define MOONSET  7

//This is #defined for test purposes. It really should be 1000, but I
//can make the number smaller so that I don't have to wait so long to
//see the complete light cycle.
#define MILLIS_SEC 10

//This function will calculate the intensity desired for the current
//minute, when we're in the middle of fading in/out a certain light.
//Start_hrs and Start_mins dictate the beginning of the fade
//duration dictates the length of the fade
//Start_intensity and End_intensity dictate how intense the light will
//                                          be at the ends of the fade.
//                                          These values range from
//                                          0 to 0xFF.
int Ramp(int Start_hrs, int Start_mins, int duration,
         int Start_intensity, int End_intensity) {
 int mins_in;
 int intensity;

 //First, calculate how many minutes we are into the fade.
 mins_in = 60*(Time_hrs - Start_hrs);
 mins_in += Time_mins - Start_mins;

 if (Start_intensity < End_intensity) {
   intensity = (End_intensity - Start_intensity) * mins_in / duration;
   intensity += Start_intensity;
 } else {
   intensity = Start_intensity;
   intensity -= (Start_intensity - End_intensity) * mins_in / duration;
 }

 return intensity;
}

//These schedule functions are where I can adjust each individual LED
//channel according to when the sunrise/sunset are set to be. Currently,
//they are set to the schedule described above (near the #defines).
void WhiteSchedule() {
 int intensity;
 if (Time_hrs < SUNRISE) {
   intensity = 0;
 }
 if (Time_hrs == SUNRISE) {
   //I've found that the differences in intensity are more noticeable
   //when the duty cycle is low. Instead of just doing one ramp from
   //0 to 0xFF, doing the ramp like this makes it seem more like a "linear"
   //fade. I may still tweak this, though.
   if (Time_mins < 30) {
     intensity = Ramp(SUNRISE, 0 , 30, 0 , 30  );
   } else {
     intensity = Ramp(SUNRISE, 30, 30, 30, 0xFF);
   }
 }
 if ((Time_hrs > SUNRISE) && (Time_hrs < SUNSET)) {
   intensity = 0xFF;
 }
 if (Time_hrs == SUNSET) {
   if (Time_mins < 30) {
     intensity = Ramp(SUNSET, 0 , 30, 0xFF, 30);
   } else {
     intensity = Ramp(SUNSET, 30, 30, 30  , 0 );
   }
 }
 if (Time_hrs > SUNSET) {
   intensity = 0;
 }

 //The Buck Pucks turn on the LEDs when the voltage is low (0V) which
 //is why I need to invert the intensity value here.
 analogWrite(3, 0xFF - intensity);
}

void BlueSchedule() {
 int intensity;
 if (Time_hrs < MOONRISE) {
   intensity = 0;
 }
 if (Time_hrs == MOONRISE) {
   if (Time_mins < 30) {
     intensity = Ramp(MOONRISE, 0 , 30, 0 , 30  );
   } else {
     intensity = Ramp(MOONRISE, 30, 30, 30, 0xFF);
   }
 }
 if ((Time_hrs > MOONRISE) && (Time_hrs < MOONSET)) {
   intensity = 0xFF;
 }
 if (Time_hrs == MOONSET) {
   if (Time_mins < 30) {
     intensity = Ramp(MOONSET, 0 , 30, 0xFF, 30);
   } else {
     intensity = Ramp(MOONSET, 30, 30, 30  , 0 );
   }
 }
 if (Time_hrs > MOONSET) {
   intensity = 0;
 }

 analogWrite(5, 0xFF - intensity);
}

void OrangeSchedule1() {
 int intensity;
 if (Time_hrs < SUNRISE-1) {
   intensity = 0;
 }
 if (Time_hrs == SUNRISE-1) {
   if (Time_mins < 30) {
     intensity = Ramp(SUNRISE-1, 0 , 30, 0 , 30  );
   } else {
     intensity = Ramp(SUNRISE-1, 30, 30, 30, 0xFF);
   }
 }
 if (Time_hrs == SUNRISE) {
   intensity = 0xFF;
 }
 if (Time_hrs == SUNRISE+1) {
   if (Time_mins < 30) {
     intensity = Ramp(SUNRISE+1, 0 , 30, 0xFF, 30);
   } else {
     intensity = Ramp(SUNRISE+1, 30, 30, 30  , 0 );
   }
 }
 if (Time_hrs > SUNRISE+1) {
   intensity = 0;
 }

 analogWrite(6, 0xFF - intensity);
}

void OrangeSchedule2() {
 int intensity;
 if (Time_hrs < SUNSET-1) {
   intensity = 0;
 }
 if (Time_hrs == SUNSET-1) {
   if (Time_mins < 30) {
     intensity = Ramp(SUNSET-1, 0 , 30, 0 , 30  );
   } else {
     intensity = Ramp(SUNSET-1, 30, 30, 30, 0xFF);
   }
 }
 if (Time_hrs == SUNSET) {
   intensity = 0xFF;
 }
 if (Time_hrs == SUNSET+1) {
   if (Time_mins < 30) {
     intensity = Ramp(SUNSET+1, 0 , 30, 0xFF, 30);
   } else {
     intensity = Ramp(SUNSET+1, 30, 30, 30  , 0 );
   }
 }
 if (Time_hrs > SUNSET+1) {
   intensity = 0;
 }

 analogWrite(9, 0xFF - intensity);
}

void UpdateBrightness() {
 WhiteSchedule();
 BlueSchedule();
 OrangeSchedule1();
 OrangeSchedule2();
}

void setup() {
 // initialize serial communications at 9600 bps:
 Serial.begin(9600);

 lWaitMillis = millis() + MILLIS_SEC;

 //Turn off the LEDs to begin.
 analogWrite(3, 0xFF);
 analogWrite(5, 0xFF);
 analogWrite(6, 0xFF);
 analogWrite(9, 0xFF);
 Time_hrs = 0;
 Time_mins = 0;
 Time_secs = 0;

}

void loop() {
 if ( (long)(millis() - lWaitMillis ) >= 0) {
   lWaitMillis += MILLIS_SEC;

   // The rest of this if loop will only execute once every second.
   Time_secs++;
   if (Time_secs == 60) {
     Time_secs = 0;
     Time_mins++;
     if (Time_mins == 60) {
       Time_mins = 0;
       Time_hrs++;
       if (Time_hrs == 24) {
         Time_hrs = 0;
       }
     }
     //every minute, update the brightess of each channel
     UpdateBrightness();
   }

   // print the time to the serial monitor:
   Serial.print(Time_hrs, DEC);
   Serial.print(":");
   Serial.print(Time_mins, DEC);
   Serial.print(":");
   Serial.println(Time_secs, DEC);
//    Serial.println(" ");

   //analogWrite(analogOutPin, sensorValue);

 } else {

   //If anything has been input on the serial port, it means we
   //want to set the clock.
   if (Serial.available() > 0) {
     inByte = Serial.read();
     //Serial.println(inByte, DEC);

     //set the time
     ValidTime = 0;
     while (ValidTime == 0) {
       Serial.println("Enter time in format AB:CD");
       Serial.println("Enter ABCD");
       while (Serial.available() <= 0) {
         delay(1);
       }
       inByte = Serial.read();
       Serial.println(inByte, DEC);
       Time_hrs = 10*(inByte-0x30);
       inByte = Serial.read();
       Serial.println(inByte, DEC);
       Time_hrs += inByte-0x30;
       inByte = Serial.read();
       Serial.println(inByte, DEC);
       Time_mins = 10*(inByte-0x30);
       inByte = Serial.read();
       Serial.println(inByte, DEC);
       Time_mins += inByte-0x30;
       Time_secs = 0;

       //make sure it's a valid time
       if ((Time_hrs >= 0)  && (Time_hrs < 24) &&
           (Time_mins >= 0) && (Time_mins < 60)) {
         ValidTime = 1;
       } else {
         Serial.println("Invalid time!");
       }
     }

     lWaitMillis = millis() + MILLIS_SEC;
   }

   delay(1);
 }
}
 
millis() works but it makes it a pain to set. I skimmed through your code but i didnt see where you initilize the lights? From the looks of it you need to do a resest at the time you want to start counting form on the millis()? I have the same display but i use an i2C expander to save pins on the arduino
 
I initialize the lights in my setup function, at least if I correctly understand what you're asking. Right under the "//Turn off the LEDs to begin." comment.

You're right that it is a pain to set, but without a working LCD at the moment I can't think of any other way to do it. I originally wanted to use the LCD screen along with something like a potentiometer/button input to set the time, but I can't see any realistic way of doing it without the display. I'm not exactly hurting for pins on the Arduino, but no matter what I do, I can't get any display on the LCD. Hopefully this weekend I'll be feeling up to posting pictures/videos of what I'm doing with the LCD and getting some help debugging it. My soldering isn't good but it looks OK to me...

How are you setting your clock? I would think you use the LCD screen to provide some output, right?

As far as what I'm using for millis(), the math behind it is pretty sound and makes sense to me. I haven't run it for long enough to make the millis() counter loop over, so it hasn't *officially* been tested yet, but that takes over a month to happen so it's not exactly on the top of my list.
 
I use an I2C realtime clock to impliement time it uses a dallas chip ds1307 to keep track of the real time. You set the time once and it keeps it in a 24 mode including day and month and year. For you this could be pretty cool as you could program to change the paterns based on the time of year say longer in summer month shorter in winter. Or you could program moon phases and vary the intensity of your "moonlight" based on date.

I will take some pics of my project tonight and show you.

here is the code I am using, this is extremely rough and remember I am an EE not a software guy so my coding is awful.

Code:
/* First controller project sketch
first functions display temp and time and date
needs reset function to turn extPumps back to 1
*/
/*
TODO LIST
clean up code and organize
LCD import and run
Create voltage diveder code for contol buttons X 5 on analog pin 2
Organized PIN OUT
pin 0 serial use
pin 1 serial us
Inputs
pin 3 open input
pin 2 Leak detection 
pin 4 ATO float switch
pin 5 One wire bus
 
Outputs
pin 6 alarm speaker
pin 7 External pumps relay
pin 8 Feeding pumps relay
pin 9 ATO Relay
pin 10 Daylight relay
pin 11 Actinic relay
pin 12 Unused
pin 13 unused may be used for LCD dimming or additional interupt currently used as reset pin.
 
Analog pins
A1
A2 Control buttons
A3 i2c
A4 i2c
I2C address
LCD
EEPROM  
RTC  0x68
 
*/
// this section to include libraries
 
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include <PCFCrystal.h>
// #include LCD LIBRARY
 
//definitions for 1wire and I2C
#define ONE_WIRE_BUS 5 //set one wire bus to pin 5
#define DS1307_I2C_ADDRESS 0x68 //set I2C address for RTC on A4 and A5
 
 
//Contstants
const int atoPin = 4;
const int leakDetectionPin = 2;//assinged as the second interuptpin
//const int leakDetectPin = ; //
//pin 5 is for the onewire bus
const int resetPin = 13;  //reset button for now then menu buttons wit LCD
const int alarmSpeaker = 6;
const int extPumpPin = 7;
const int feedPumpPin = 8;
const int atoPumpPin = 9;
const int dayLightPin = 10;
const int actinicPin = 11;
 
//Global variables
int tHour;
int extPumps = 1; //this pump is for HOB skimmer or any external pump
int atoPump = 0;  //this pump needs to be normally off or 0
int feedpump = 1; //This will be for all powerheads for feeding or cleaning time
int resetState = 0; //global for the state of the reset button on alarm 
int waterDetectState = 0; //global for water detection
int atoState = 0;
int atoHour = 30; //this number must be above 23 or a false ATo error will trigger
int atoAlarm = 0;
int atoCounter ;
int leakDetected = 0;
int currentTemp;
int tempHighAlarm;
//user changeable variables in menu
int aTone = 1000; //frequency of the alert 1000 is pretty annoying
int atoInterval = 180; //max amount of time to run ATO in seconds 
int actinicOn = 0;
int actinicOff = 21;
int dayLightOn = 0;
int dayLightOff = 22;
int alarmTemp = 87;
int feedTime = 180; //this value is in seconds 
//PCFCrystal Variabls
byte buffer = 0;
byte data = 0;
// initialize the library with the numbers of the interface pins
// rs, en, d0, d1, d2, d3, address, buffer
// 4 bits
PCFCrystal lcd(B00100000, B00010000, B00000001, B00000010, B00000100, B00001000, 0x38, &buffer);
// 8 bits
//PCFCrystal lcd(B00100000, B00010000, B10000000, B01000000, B00100000, B00010000, B00000001, B00000010, B00000100, B00001000, 0x21, 0x20, &data, &buffer);
 
// RTC functions
// Convert normal decimal number to binary coded decimal
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
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));    // 0 to bit 7 starts the clock
  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.send(00010000); // sends 0x10 (hex) 00010000 (binary) to control register - turns on square wave
  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)
{
  // Reset the register pointer
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0);
  Wire.endTransmission();
  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
  // A few of these need masks because certain bits are control bits
  *second     = bcdToDec(Wire.receive() & 0x7f);
  *minute     = bcdToDec(Wire.receive());
  *hour       = bcdToDec(Wire.receive() & 0x3f);  // Need to change this if 12 hour am/pm
  *dayOfWeek  = bcdToDec(Wire.receive());
  *dayOfMonth = bcdToDec(Wire.receive());
  *month      = bcdToDec(Wire.receive());
  *year       = bcdToDec(Wire.receive());
}
//END of Rtc functions
//Start ONEWIRE temps
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);
//End onewire temps
void setup() //runs once for all setup functions
{
  //Pin Mode declaring inputs
  pinMode(resetPin, INPUT); //this pin will be made free with kepad or analog
  pinMode(atoPin, INPUT);
  //attachInterrupt(leakDetectionPin, waterDetection, RISING);  //assigns atoPin as an interupt on digital pin 3 interupt pin 1
  pinMode(leakDetectionPin, INPUT);
 
  pinMode(alarmSpeaker, OUTPUT);
  pinMode(extPumpPin, OUTPUT); 
  pinMode(feedPumpPin, OUTPUT); 
  pinMode(atoPumpPin, OUTPUT);
  pinMode(dayLightPin, OUTPUT); 
  pinMode(actinicPin, OUTPUT); 
 
//Setup for Clock
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  //starts the library for RTC
  Wire.begin();
  // Start up the library for temps
  sensors.begin();
  // start serial port so you can see whats going on replace with LCD
  Serial.begin(9600);
  // set up the LCD's number of rows and columns: 
  lcd.begin(20, 4);
  // Open Message
  lcd.print("Reef Controller v .2");
 
  // Change these values to what you want to set your clock to.
  // You probably only want to set your clock once and then remove
  // the setDateDs1307 call.
  //ADD BACK IN TO CHANGE TIME
  /*
  second = 0;
  minute = 54;
  hour = 21;
  dayOfWeek = 1;
  dayOfMonth = 7;
  month = 3;
  year = 11;
setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
*/
 
}
void lightTimer()
{
if(dayLightOn == hour)
  {
   digitalWrite(dayLightPin, HIGH); 
  }
if(dayLightOff == hour)
  {
  digitalWrite(dayLightPin, LOW);
  }
if(actinicOn == hour)
  {
  digitalWrite(actinicPin, HIGH);  
  }
if(actinicOff == hour)
  {
  digitalWrite(actinicPin, LOW);
  }
 
return;
}
 
void ATO()
{
 /*this function when called runs the ATO for a 180 seconds
   which can be changed by the user via an ATO menu, eventually
   the function will also enter the alarm state for the ATO and 
   and sound the alarm if the ato trys to run more than 5 times
   in an hour.
*/
 
 
 
 
 atoState = digitalRead(atoPin); //set the state of the ato to whatever the pin is 
 if(atoState == HIGH)
 {
 int thisHour = hour;
        //Serial.println("this hour is ");
        //Serial.println(thisHour);
        //Serial.println(hour, DEC);
        //delay(2000); //for debug
        lcd.clear();
        lcd.print("ATO MODE Filling");
 delay(1000); //must pause to allow float to stabilize
 if(atoHour == thisHour)//checks to see if the last time the ato ran is the same hour as now
  {
  atoCounter++; //if it is the counter is increased
  }
 if(atoHour == thisHour  && atoCounter == 5)
  {
  atoAlarm = 1; 
  alarmCall(); //need to have atoAlarm done in Alarm section and on reset it must change atoHour back to 30
  } 
 if(atoState == HIGH && atoHour != thisHour) //hour should be in military time and should be called from RTC
  {
  atoHour = thisHour;
                digitalWrite(atoPumpPin, HIGH);//turn the pump on
                for(int x = 0; atoState == HIGH && x != atoInterval; x++)//fill loop; x++)//continually checks for pump to float to be on up to interval
                  {
                  lcd.print("filling");
    delay(1000);
    atoState = digitalRead(atoPin);
    lcd.clear();   
                  if(x == atoInterval)
         {
          digitalWrite(atoPumpPin, LOW);
         }
                  }  
  digitalWrite(atoPumpPin, LOW);
  }
 }
 else
 {
 
        return;
 } 
}
void waterDetection()
{
  //water detection function needs to be moved here
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Water detected");
 lcd.setCursor(0, 1);
        lcd.print("Please check area");
 waterDetectState = 1;
 digitalWrite(extPumpPin, LOW);
        delay(2000);
 alarmCall();
  //int buttonState = 0;
  /*
  for (int y = 0; buttonState == HIGH; y++) {
 
    Serial.println(y);
    delay(1000);
    buttonState = digitalRead(leakDetectPin); //exits for loop after tow trys if false water reading
    Serial.println("Water sensed waiting 5 seconds");
    delay(5000);
    if (y > 0)
    {
      Serial.println("ALARM!!!"); 
 
      extPumps = 0;
      leakDetected = 1;
      alarmCall();
  }
 
  }*/
}
void mainDisplay()
{
  sensors.requestTemperatures();
 
  getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  lcd.setCursor(0, 0);
  lcd.print("Reef Controller v .2");
  lcd.setCursor(0, 1);
  //lcd.print(" ");
  if(hour > 12)
    {
    tHour = hour - 12;  
    }
  else
  {
    tHour = hour;
    if(tHour == 0)
    {
      tHour = 12;
    }
  }
  lcd.print(tHour, DEC);
  lcd.print(":");
  if (minute<10)
  {
      lcd.print("0");
  }
  lcd.print(minute, DEC);
  if(hour >=12 )
    {
      lcd.print("PM");
    }
    else
    {lcd.print("AM");
    }
  //lcd.print(":");
  //if (second<10)
  //{
      //lcd.print("0");
  //}
  //lcd.print(second, DEC);
  //lcd.print("  ");
  lcd.setCursor(14, 1);
  lcd.print(month, DEC);
  lcd.print("/");
  lcd.print(dayOfMonth, DEC);
  lcd.print("/");
  lcd.print(year, DEC);
 
  lcd.setCursor(0, 2);
  lcd.print("Temp: ");
  lcd.print(sensors.getTempFByIndex(0));
  lcd.print("F");
  /*lcd.print("  ");
  switch(dayOfWeek){
  case 1: 
    lcd.println("Mon");
    break;
  case 2: 
    lcd.println("Tue");
    break;
  case 3: 
    lcd.println("Wed");
    break;
  case 4: 
    lcd.println("Thur");
    break;
  case 5: 
    lcd.println("Fri");
    break;
  case 6: 
    lcd.println("Sat");
    break;
  case 7: 
    lcd.println("Sun");
    break;
  }
  */
 
  /*add this back in for debugging
  Serial.println(" ");
  Serial.print(hour, DEC);
  Serial.print(":");
  if (minute<10)
  {
      Serial.print("0");
  }
  Serial.print(minute, DEC);
  Serial.print(":");
  if (second<10)
  {
      Serial.print("0");
  }
  Serial.print(second, DEC);
  Serial.print("  ");
  Serial.print(month, DEC);
  Serial.print("/");
  Serial.print(dayOfMonth, DEC);
  Serial.print("/");
  Serial.print(year, DEC);
  Serial.print("  ");
  switch(dayOfWeek){
  case 1: 
    Serial.println("Mon");
    break;
  case 2: 
    Serial.println("Tue");
    break;
  case 3: 
    Serial.println("Wed");
    break;
  case 4: 
    Serial.println("Thur");
    break;
  case 5: 
    Serial.println("Fri");
    break;
  case 6: 
    Serial.println("Sat");
    break;
  case 7: 
    Serial.println("Sun");
    break;
  }
  //  Serial.println(dayOfWeek, DEC);
  //Send command to get temps
  Serial.print("Temperature : ");
 
  Serial.println(sensors.getTempFByIndex(0));
  */
}
void safetyFunctions()
{
if(digitalRead(leakDetectionPin) == HIGH)
{
  waterDetection();
  return;
}
 
if(currentTemp >= alarmTemp)
  {
  digitalWrite(actinicPin, LOW);
  digitalWrite(dayLightPin, LOW);
  tempHighAlarm = 1;
  alarmCall();
  }
}
void alarmCall() //call in the event of an alarm state 
{
/*  when atoAlarm is high run the atoAlarm subroutine
    if the atoAlarm is on ensure the ato gets turned off
    until its reset.
*/  
 //noInterrupts();
        int resetState = 0;
        if (atoAlarm == 1)
   {
   digitalWrite(atoPumpPin, LOW);
   lcd.setCursor(0, 2);
          lcd.print("PRESS RESET TO STOP");
   for(int x = 0 ; x < 1  ;  )
            {
            x = digitalRead(resetPin);
            digitalWrite (alarmSpeaker, HIGH);
            delayMicroseconds(aTone / 2);
            digitalWrite (alarmSpeaker, LOW);
            delayMicroseconds(aTone / 4);
            }
   lcd.clear();
          lcd.setCursor(1, 1);
          lcd.print("ATO alarm Active");
          lcd.setCursor(4, 2);
          lcd.print("check Float");
   lcd.setCursor(1, 3);
          lcd.print("Press Reset if safe");
          do
          {
            resetState = digitalRead(resetPin);
              if(resetState == HIGH)
              {
                atoHour = 30;//comment out
                atoAlarm = 0;
                break;
              }
          }while(resetState == LOW);
        return;  
        }
 
 
  //Water detection
  //sound beeper urgently until reset is hit once
 
  if(waterDetectState == 1)
    {
    extPumps = 0;
    lcd.setCursor(0, 3);
    lcd.print("PRESS RESET TO STOP");
 
    for(int x = 0 ; x < 1  ;  )
      {
      x = digitalRead(resetPin);
      digitalWrite (alarmSpeaker, HIGH);
      delayMicroseconds(aTone / 2);
      digitalWrite (alarmSpeaker, LOW);
      delayMicroseconds(aTone / 4);
      }
    if(extPumps == 0)
      {
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("External pumps off");
        lcd.setCursor(0, 1);
        lcd.print("leak detected");
        delay(5000);
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Reset? Hold reset");
        lcd.setCursor(0, 1);
        lcd.print("for 5 seconds");
        delay(3000);
        if(digitalRead(resetPin) == HIGH)
        {
        extPumps =1;
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Pumps reset to on");
        waterDetectState = 0;
        lcd.setCursor(0, 1);
        lcd.print("Water detect reset");
        delay(1000);
        lcd.clear();
        return;
        }
        else
          {
          alarmCall();
          }
      }
    }
//temp alarm
//interrupts();
}    
void feedingTime()
{
 
 for(int startTime = millis(); millis() - startTime <= feedTime * 1000; )
 {
   int sinceStart = millis() - startTime;
   int feedCountDown = feedTime - sinceStart/1000;
   digitalWrite(feedPumpPin, LOW);
   lcd.clear();
   lcd.setCUrsor(0, 0);
   lcd.print("FEED MODE ACTIVE");
   lcd.setCursor(8, 1);
   lcd.print(feedCountDown);
 }
        lcd.clear();
 lcd.setCursor(1, 0);
 lcd.print(Feed Time complete);
 delay(2000);
 lcd.clear();
 return;
}
 
//BEGIN MAIN PROGRAM HERE
void loop()
{
  currentTemp = sensors.getTempFByIndex(0);
  if(extPumps == 1)
  {
    digitalWrite(extPumpPin, HIGH);
  }  
  mainDisplay();
  lightTimer();
  safetyFunctions();
  ATO();
  Wire.beginTransmission(0x38);
    Wire.send(buffer);
    Wire.endTransmission();
 
  //comment this in for debug
  //Serial.println("dump");
  //Serial.print("ATO STATE");
  //Serial.print("  ");
  //Serial.print(atoPump);
  //Serial.print("Exteriour pump");
  //Serial.print("  ");
  //Serial.print(extPumps);
  //delay(5000);  
}
 
Most of the aquarium-related Arduino projects I've seen do a whole bunch of stuff, like yours is doing. Kind of strange that I'm only controlling lighting with mine. I do have an extra float switch lying around, so I've thought about doing ATO along with my lighting, but for freshwater, it just doesn't seem worth it. Oh well. Maybe if I get ambitious I'll buy a smaller Arduino and make an ATO system for my SW tank some day, that might save me a little stress when I get corals.

I'd be interested to see how your feeding system works. I don't remember if you said you needed help with anything, but I understand pretty much everything that's going on in your code so I could help if you need it.

I tried to edit my post above with the videos but it won't let me. Those videos will just be broken eventually, I guess... I've taken a new video and some still pictures that aren't terrible, so I'll post them here:

YouTube - DIY LED Lighting (HQ)

http://www.adamhorton.com/files/flog/good/diyled01.jpg
http://www.adamhorton.com/files/flog/good/diyled02.jpg
http://www.adamhorton.com/files/flog/good/diyled03.jpg

My mission for this weekend is to put together some pictures/video of me attempting to get my LCD to work and see if I can get some help debugging it. I'll post it on the Arduino forum but I'll probably post it here just for posterity.
 
Yeah I would like to see it. That code is sans the LCD I was using Serial.print to get a visual. Feeding mode just counts down from a pre designated time. Turns off all the pumps for feeding so i can target feed my corals without risk of the food blowing away.
 
Of course, that makes sense. I'm planning on having a reef in my SW tank but I haven't gotten there yet.

I managed to get my LCD screen to work. It turns out that my soldering was the problem.

http://www.adamhorton.com/files/flog/good/diyled04.jpg

I can now set the time using a button and a potentiometer, so I don't have to connect it to my computer to set the time. I'll upload my code at some point.

I'm thinking the next thing I want to do is to try and have the time saved in a non-volatile part of memory. It would be nice if I had a power hit if the time didn't reset back to midnight, but rather the last time it had before the power hit. I'll be looking into that this week. I've tweaked the lighting schedule a couple of times as well.

The tank will probably be ready for fish in 2-3 weeks, at least that's my guess...
 
I've added the EEPROM so that the time is stored even if the power is turned off, and I fixed a couple of minor bugs and tweaked the lighting schedule a bit. Here's my code.

Code:
#include <LiquidCrystal.h>
#include <Bounce.h>
#include <EEPROM.h>

static unsigned long lWaitMillis;
int inByte = 0;
int ValidTime;

int Time_hrs;
int Time_mins;
int Time_secs;

LiquidCrystal lcd(4, 7, 10, 11, 12, 13);
Bounce bouncer = Bounce(2, 5);

#define SUNRISE  9
#define SUNSET   21
#define MOONSET  23

//#define FAST
#define MILLIS_SEC 1000

int Ramp(int Start_hrs, int Start_mins, int duration, int Start_intensity, int End_intensity) {
  int mins_in;
  int intensity;
  mins_in = 60*(Time_hrs - Start_hrs);
  mins_in += Time_mins - Start_mins;
  
  if (Start_intensity < End_intensity) {
    intensity = (End_intensity - Start_intensity) * mins_in / duration;
    intensity += Start_intensity;
  } else {
    intensity = Start_intensity;
    intensity -= (Start_intensity - End_intensity) * mins_in / duration;
  }
  
  return intensity;  
}

void WhiteSchedule() {
  int intensity;
  if (Time_hrs < SUNRISE) {
    intensity = 0;
  }
  if (Time_hrs == SUNRISE) {
    if (Time_mins < 30) {
      intensity = Ramp(SUNRISE, 0 , 30, 0 , 30  );
    } else {
      intensity = Ramp(SUNRISE, 30, 30, 30, 0xFF);
    }
  }
  if ((Time_hrs > SUNRISE) && (Time_hrs < SUNSET)) {
    intensity = 0xFF;
  }
  if (Time_hrs == SUNSET) {
    if (Time_mins < 30) {
      intensity = Ramp(SUNSET, 0 , 30, 0xFF, 30);
    } else {
      intensity = Ramp(SUNSET, 30, 30, 30  , 0 );
    }
  }
  if (Time_hrs > SUNSET) {
    intensity = 0;
  }
  
  analogWrite(3, 0xFF - intensity);
}

void BlueSchedule() {
  int intensity;
  if (Time_hrs < SUNRISE) {
    intensity = 0;
  }
  if (Time_hrs == SUNRISE) {
    if (Time_mins < 30) {
      intensity = Ramp(SUNRISE, 0 , 30, 0 , 30  );
    } else {
      intensity = Ramp(SUNRISE, 30, 30, 30, 0xFF);
    }
  }
  if ((Time_hrs > SUNRISE) && (Time_hrs < SUNSET)) {
    intensity = 0xFF;
  }
  if (Time_hrs == SUNSET) {
    intensity = Ramp(SUNSET, 0, 60, 0xFF, 0x80);
  }
  if ((Time_hrs > SUNSET) && (Time_hrs < MOONSET)) {
    intensity = 0x80;
  }
  if (Time_hrs == MOONSET) {
    if (Time_mins < 30) {
      intensity = Ramp(MOONSET, 0 , 30, 0xFF, 0x80);
    } else {
      intensity = Ramp(MOONSET, 30, 30, 30  , 0 );
    }
  }
  if (Time_hrs > MOONSET) {
    intensity = 0;
  }
  
  analogWrite(5, 0xFF - intensity);
}

void OrangeSchedule1() {
  int intensity;
  if (Time_hrs < SUNRISE-1) {
    intensity = 0;
  }
  if (Time_hrs == SUNRISE-1) {
    if (Time_mins < 30) {
      intensity = Ramp(SUNRISE-1, 0 , 30, 0 , 30  );
    } else {
      intensity = Ramp(SUNRISE-1, 30, 30, 30, 0xFF);
    }
  }
  if (Time_hrs == SUNRISE) {
    intensity = 0xFF;
  }
  if (Time_hrs == SUNRISE+1) {
    if (Time_mins < 30) {
      intensity = Ramp(SUNRISE+1, 0 , 30, 0xFF, 30);
    } else {
      intensity = Ramp(SUNRISE+1, 30, 30, 30  , 0 );
    }
  }
  if (Time_hrs > SUNRISE+1) {
    intensity = 0;
  }
  
  analogWrite(6, 0xFF - intensity);
}

void OrangeSchedule2() {
  int intensity;
  if (Time_hrs < SUNSET-1) {
    intensity = 0;
  }
  if (Time_hrs == SUNSET-1) {
    if (Time_mins < 30) {
      intensity = Ramp(SUNSET-1, 0 , 30, 0 , 30  );
    } else {
      intensity = Ramp(SUNSET-1, 30, 30, 30, 0xFF);
    }
  }
  if (Time_hrs == SUNSET) {
    intensity = 0xFF;
  }
  if (Time_hrs == SUNSET+1) {
    if (Time_mins < 30) {
      intensity = Ramp(SUNSET+1, 0 , 30, 0xFF, 30);
    } else {
      intensity = Ramp(SUNSET+1, 30, 30, 30  , 0 );
    }
  }
  if (Time_hrs > SUNSET+1) {
    intensity = 0;
  }
  
  analogWrite(9, 0xFF - intensity);
}

void UpdateBrightness() {
  WhiteSchedule();
  BlueSchedule();
  OrangeSchedule1();
  OrangeSchedule2();
}

void OutputTime() {
  // print the time to the serial monitor:
  Serial.print(Time_hrs, DEC);
  Serial.print(":");
  Serial.print(Time_mins, DEC);
  Serial.print(":");
  Serial.println(Time_secs, DEC);
  
  // print the time to the LCD screen
  lcd.setCursor(0, 0);
  
  lcd.print("TIME ");
  if (Time_hrs < 10) {
    lcd.print("0");
  }
  lcd.print(Time_hrs);
  lcd.print(":");
  if (Time_mins < 10) {
    lcd.print("0");
  }
  lcd.print(Time_mins);
  lcd.print(":");
  if (Time_secs < 10) {
    lcd.print("0");
  }
  lcd.print(Time_secs);
}

void SetTime() {
  int Analog;
  int Normalized;
  int bounced;
  
  //Option to set the time using the hardware
  bouncer.update();
  if (bouncer.risingEdge()) {
    //input the hours
    lcd.clear();
    lcd.print("SET TIME");
    lcd.setCursor(0, 1);
    lcd.print("Input hours:");
    lcd.setCursor(0, 2);
    lcd.print("HOUR ");
    do {
      Analog = analogRead(A0);
      Normalized = Analog/43; //gives a value between 0 and 23
      lcd.setCursor(5, 2);
      if (Normalized < 10) {
        lcd.print("0");
      }
      lcd.print(Normalized);
      bouncer.update();
    } while (!bouncer.risingEdge());
    Time_hrs = Normalized;
    
    //input the minutes
    lcd.clear();
    lcd.print("SET TIME");
    lcd.setCursor(0, 1);
    lcd.print("Input minutes:");
    lcd.setCursor(0, 3);
    lcd.print("Hour = ");
    lcd.print(Time_hrs);
    lcd.setCursor(0, 2);
    lcd.print("MINUTE ");
    do {
      Analog = analogRead(A0);
      Normalized = Analog/17; //gives a value between 0 and 61
      if (Normalized > 59) {
        Normalized = 59;
      }
      lcd.setCursor(7, 2);
      if (Normalized < 10) {
        lcd.print("0");
      }
      lcd.print(Normalized);
      bouncer.update();
    } while (!bouncer.risingEdge());
    Time_mins = Normalized;
    Time_secs = 0;
    lcd.clear();     
    UpdateBrightness();
    EEPROM.write(0, Time_hrs);
    EEPROM.write(1, Time_mins);
    EEPROM.write(2, Time_secs);
    lWaitMillis = millis() + MILLIS_SEC;
  }
  
  //Option to set the time through the serial interface
  if (Serial.available() > 0) {
    inByte = Serial.read();
    //Serial.println(inByte, DEC);
    
    //set the time
    ValidTime = 0;
    while (ValidTime == 0) {
      Serial.println("Enter time in format AB:CD");
      Serial.println("Enter ABCD");
      while (Serial.available() <= 0) {
        delay(1);
      }
      inByte = Serial.read();
      Serial.println(inByte, DEC);
      Time_hrs = 10*(inByte-0x30);
      inByte = Serial.read();
      Serial.println(inByte, DEC);
      Time_hrs += inByte-0x30;
      inByte = Serial.read();
      Serial.println(inByte, DEC);
      Time_mins = 10*(inByte-0x30);
      inByte = Serial.read();
      Serial.println(inByte, DEC);
      Time_mins += inByte-0x30;
      Time_secs = 0;
      
      //make sure it's a valid time
      if ((Time_hrs >= 0) && (Time_hrs < 24) && (Time_mins >= 0) && (Time_mins < 60)) {
        ValidTime = 1;
        EEPROM.write(0, Time_hrs);
        EEPROM.write(1, Time_mins);
        EEPROM.write(2, Time_secs);
      } else {
        Serial.println("Invalid time!");
      }        
    }
    
    lWaitMillis = millis() + MILLIS_SEC;
    UpdateBrightness();
    
  }
}

void setup() {
  // initialize serial communications at 9600 bps:
  Serial.begin(9600);
  
  lWaitMillis = millis() + MILLIS_SEC;
  lcd.begin(20, 4);
  analogWrite(3, 0xFF);
  analogWrite(5, 0xFF);
  analogWrite(6, 0xFF);
  analogWrite(9, 0xFF);
  Time_hrs  = EEPROM.read(0);
  Time_mins = EEPROM.read(1);
  Time_secs = EEPROM.read(2);

}

void loop() {
  if ( (long)(millis() - lWaitMillis ) >= 0) {
    lWaitMillis += MILLIS_SEC;
    // The rest of this if loop will only execute once every second.
#ifndef FAST
    Time_secs++;
    EEPROM.write(2, Time_secs);
    if (Time_secs >= 60) {
      Time_secs = 0;
      EEPROM.write(2, Time_secs);
      Time_mins++;
      EEPROM.write(1, Time_mins);
      if (Time_mins >= 60) {
        Time_mins = 0;
        EEPROM.write(1, Time_mins);
        Time_hrs++;
        EEPROM.write(0, Time_hrs);
        if (Time_hrs >= 24) {
          Time_hrs = 0;
          EEPROM.write(0, Time_hrs);
        }
      }
      //every minute, update the brightess of each channel
      UpdateBrightness();
    }
#else
      Time_mins++;
      if (Time_mins >= 60) {
        Time_mins = 0;
        Time_hrs++;
        if (Time_hrs >= MOONSET + 1) {
          Time_hrs = 0;
        }
      }
      //every minute, update the brightess of each channel
      UpdateBrightness();
#endif
    
    OutputTime();

  } else {
    SetTime();
    delay(1);
  }
}
 
Back
Top Bottom