/*

originally written by Christian, cptbjorn@gmail.com

modified by Cesar,  caddnima@gmail.com,  
https://sites.google.com/site/caddnima/
Version 1.00, 2012-03-13


*/


#define DS1307_I2C_ADDRESS 0x68   // address used for clock
#include "Wire.h"                 // library used
#include <LiquidCrystal.h>        // library used


/* ******************************************************************************************************************** */
/* *                                                                                                                  * */
/* *                                 R E L A Y   P A R T                                                              * */
/* *                                 S I M P L E   O N   A N D   O F F   F E A T U R E                                * */
/* *                                                                                                                  * */
/* ******************************************************************************************************************** */


const int relayPin1 =  2;         // arduino pin (non pwm) used for relay 1
const int relayPin2 =  8;         // arduino pin (non pwm) used for relay 2

int relayState1 = LOW;             
int relayState2 = LOW; 

long previousMillis1 = 0;        
long previousMillis2 = 0;

long interval1 = 30000;           // how many milliseconds to turn it on and off for RELAY1
long interval2 = 50000;           // how many milliseconds to turn it on and off for RELAY2



/* ******************************************************************************************************************** */
/* *                                                                                                                  * */
/* *                                 L E D   D I M M I N G   P A R T                                                  * */
/* *                                 F A D E S   I N   A N D   O U T                                                  * */
/* *                                                                                                                  * */
/* ******************************************************************************************************************** */



/* ********************************************************************************* */
/* *                          * */
/* *     Note: time for ramp down is the same as time for ramp up.                 * */
/* *                          * */
/* ********************************************************************************* */
int ontime = 10 ;                 // what time do you want the blue to start to ramp up?
int blueramptime = 60 ;           // how many minutes do you want the blue to ramp up?
int whiteramptime = 180 ;         // after the blue, how many minutes do you want the white to ramp up?
int photoperiod = 240 ;           // after the white, how many minutes do you want it to stay at max intensity?
int blue = 3;                     // which arduino pwm pin are you using for the blue?
int white = 11;                   // which arduino pwm pin are you using for the white?




int bluemin = 0 ;          
int whitemin = 0 ; 



/* ********************************************************************************* */
/* *                                                                               * */
/* *     the line below is needed if you are using meanwell ELN60-48D, for analog  * */
/* *     these are the values in 10% increments                                    * */
/* *     [11] is not the arduino pin but the number of steps used from 0 to 255    * */
/* *                                                                               * */
/* ********************************************************************************* */
int bluepercent[11] = { 0, 1, 2, 5, 8 ,12, 18, 27, 44, 80, 255 };   
int whitepercent[11] = { 0, 1, 2, 5, 8 ,12, 18, 27, 44, 80, 255 };   




/* ********************************************************************************* */
/* *                                                                               * */
/* *     the line below is needed if you are using meanwell ELN60-48P, for pwm     * */
/* *     these are the values in 10% increments                                    * */
/* *     [11] is not the arduino pin but the number of steps used from 0 to 255    * */
/* *     just remove // sign below for the blue and white                          * */
/* *     and add // sign above for the blue and white                              * */
/* *                                                                               * */
/* ********************************************************************************* */
//int bluepercent[11] = { 0, 26, 52, 78, 103, 128, 154, 180, 205, 230, 255 };   
//int whitepercent[11] = { 0, 26, 52, 78, 103, 128, 154, 180, 205, 230, 255 };   



// int pwm_one = 10;              // extra pwm pin for future use (spare)
// int pwm_one = 9;               // extra pwm pin for future use (spare)




/* ********************************************************************************* */
/* *                                                                               * */
/* *     originally arduino pins 8, 9, 4, 5, 6, 7 are used,                        * */
/* *     I have to use different arduino non pwm pins, so I can reserved the pwm   * */
/* *     pins for other use.                                                       * */
/* *                                                                               * */
/* ********************************************************************************* */
LiquidCrystal lcd(12, 13, 4, 5, 6, 7);   
                                         



/* ******************************************************************************************************************** */
/* *                                                                                                                  * */
/* *                                 R T C   C L O C K   D S 1 3 0 7                                                  * */
/* *                                                                                                                  * */
/* ******************************************************************************************************************** */
byte decToBcd(byte val)           // Convert normal decimal numbers to binary coded decimal
{
  return ( (val/10*16) + (val%10) );
}


byte bcdToDec(byte val)           // Convert binary coded decimal to normal decimal numbers
{
  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));      // If you want 12 hour am/pm you need to set
                                  // bit 6 (also need to change readDateDs1307)
  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)
{
  // 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());
}



/* ******************************************************************************************************************** */
/* *                                                                                                                  * */
/* *                                 D E F I N E  :  O N E S E C O N D                                                * */
/* *                                                                                                                  * */
/* ******************************************************************************************************************** */

void onesecond() //function that runs once per second while program is running
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  lcd.setCursor(0, 0);
  if(hour>0)
  {
    if(hour<=12)
    {
      lcd.print(hour, DEC);
    }
    else
    {
      lcd.print(hour-12, DEC);
    }
  }
  else
  {
    lcd.print("12");
  }
  lcd.print(":");
  if (minute < 10) {
    lcd.print("0");
  }
  lcd.print(minute, DEC);
  lcd.print(":");
  if (second < 10) {
    lcd.print("0");
  }
  lcd.print(second, DEC);
  if(hour<12)
  {
    lcd.print("am");
  }
  else
  {
    lcd.print("pm");
  }
  lcd.print(" ");
  delay(1000);
}





/* ******************************************************************************************************************** */
/* *                                                                                                                  * */
/* *                                 D E F I N E  :  R E L A Y 1                                                      * */
/* *                                                                                                                  * */
/* ******************************************************************************************************************** */

void relay1()                        //FUNCTION TO TURN ON AND OFF RELAY 1.
{ 
  unsigned long currentMillis = millis();

  if(currentMillis - previousMillis1 > interval1) 
  { 
    previousMillis1 = currentMillis;   
    if (relayState1 == LOW)
      relayState1 = HIGH;
    else
      relayState1 = LOW;
    digitalWrite(relayPin1, relayState1);
  }
}





/* ******************************************************************************************************************** */
/* *                                                                                                                  * */
/* *                                 D E F I N E  :  R E L A Y 2                                                      * */
/* *                                                                                                                  * */
/* ******************************************************************************************************************** */

void relay2()
{
  unsigned long currentMillis2 = millis();

  if(currentMillis2 - previousMillis2 > interval2) 
  {
    previousMillis2 = currentMillis2;   
    if (relayState2 == LOW)
      relayState2 = HIGH;
    else
      relayState2 = LOW;
    digitalWrite(relayPin2, relayState2);
  }
}




/* ******************************************************************************************************************** */
/* *                                                                                                                  * */
/* *                                 S E T U P                                                                        * */
/* *                                                                                                                  * */
/* ******************************************************************************************************************** */

void setup() {
  pinMode(relayPin1, OUTPUT);     // set the digital pin as output:
  pinMode(relayPin2, OUTPUT);     // set the digital pin as output:
  


/* ******************************************************************************************************************** */
/* *                                                                                                                  * */
/* *                                 S E T U P - D I S P L A Y                                                        * */
/* *                                                                                                                  * */
/* ******************************************************************************************************************** */

  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  Wire.begin();
  second = 56;
  minute = 57;
  hour = 23;
  dayOfWeek = 6;                    // Sunday is 0
  dayOfMonth = 26;
  month = 2;
  year = 11;


/* ********************************************************************************* */
/* *                                                                               * */
/* *     this is where you set your time...                                        * */
/* *     1) change the second, minute, hour, etc above                             * */
/* *     2) remove // below                                                        * */
/* *     3) and load this sketch to your arduino                                   * */
/* *     4) after loading the sketch, put the // back again                        * */
/* *     5) and load this sketch again to your arduino, and save                   * */
/* *                                                                               * */
/* ********************************************************************************* */
  //setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);


  analogWrite(blue, bluemin);
  analogWrite(white, whitemin);
  lcd.begin(16, 2); // set up the LCD's number of rows and columns: 
  //  lcd.print("12:00 80.6");    // Print a message to the LCD.
  //  lcd.print(char(223));
  lcd.setCursor(0, 1);
  lcd.print("blue:");
  lcd.print(33*bluemin/85);
  lcd.setCursor(8, 1);
  lcd.print("white:");
  lcd.print(33*whitemin/85);  
}




/* ******************************************************************************************************************** */
/* *                                                                                                                  * */
/* *                                 L O O P                                                                          * */
/* *                                                                                                                  * */
/* ******************************************************************************************************************** */




void loop()
{
  onesecond();
  relay2();
  relay1();




/* ******************************************************************************************************************** */
/* *                                                                                                                  * */
/* *                                 L O O P - D I M   F U N C T I O N                                                * */
/* *                                                                                                                  * */
/* ******************************************************************************************************************** */

  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  int daybyminute = ((hour * 60) + minute); //converts time of day to a single value in minutes
      

  int bluerampup;
     if (daybyminute >= (ontime*60)) 
       bluerampup = (((ontime*60) + blueramptime) - daybyminute);
     else
       bluerampup = blueramptime;
       
  int whiterampup;
    if (daybyminute >= (ontime*60 + blueramptime)) 
       whiterampup = (((ontime*60) + blueramptime + whiteramptime) - daybyminute);
     else
       whiterampup = whiteramptime;

  int whiterampdown;
    if (((ontime * 60) + photoperiod + blueramptime + whiteramptime) <= daybyminute)
      whiterampdown = (((ontime*60) + photoperiod + blueramptime + 2*whiteramptime) - daybyminute);
    else
      whiterampdown = whiteramptime;
      
  int bluerampdown;
    if (((ontime * 60) + photoperiod + blueramptime + 2*whiteramptime) <= daybyminute)
      bluerampdown = (((ontime*60) + photoperiod + 2*blueramptime + 2*whiteramptime) - daybyminute);
    else
      bluerampdown = blueramptime;





/* ******************************************************************************************************************** */
/* *                                                                                                                  * */
/* *                                 L O O P - F A D E  I N                                                           * */
/* *                                                                                                                  * */
/* ******************************************************************************************************************** */

 if (daybyminute >= (ontime*60))
  { 
    if (daybyminute <= ((ontime*60) + blueramptime + (whiteramptime))) //if time is in range of fade in, start fading in + (whiteramptime/10*9)
    {
      // fade blue LEDs in from min to max.
      for (int i = 1; i <= 10; i++) // setting ib value for 10% increment. Start with 0% 
      { 
        analogWrite(blue, bluepercent[i]); 
        lcd.setCursor(5, 1);
        lcd.print(i);
        lcd.print(" "); 
      
        int countdown = ((bluerampup*60)/10); // calculates seconds to next step
        while (countdown>0)
          {
          onesecond(); // updates clock once per second
          countdown--;
          relay2();
          relay1();
        }
      }      

      // fade white LEDs in from min to max.
      for (int i = 1; i <= 10; i++) // setting i value for 10% increment. Start with 0%
      { 
        analogWrite(white, whitepercent[i]); 
        lcd.setCursor(14, 1);
        lcd.print(i);
        lcd.print(" "); 

        int countdown = ((whiterampup*60)/10); // calculates seconds to next step
        while (countdown>0)
        {
          onesecond(); // updates clock once per second
          countdown--;
          relay2();
          relay1();
        }
      } 
    }
  }

  
/* ******************************************************************************************************************** */
/* *                                                                                                                  * */
/* *                                 L O O P - M A X  V A L U E                                                       * */
/* *                                                                                                                  * */
/* ******************************************************************************************************************** */

 if (daybyminute >= ((ontime * 60) + blueramptime + whiteramptime)) 
  { 
    if ( daybyminute < ((ontime * 60) + blueramptime + whiteramptime + photoperiod)) // if time is in range of photoperiod, turn lights on to maximum fade value
    {
      analogWrite(blue, 255);
        lcd.setCursor(5, 1);
        lcd.print(10);
        lcd.print(" ");
      analogWrite(white, 255); 
        lcd.setCursor(14, 1);
        lcd.print(10);
        lcd.print(" "); 
      
    } 
  }


/* ******************************************************************************************************************** */
/* *                                                                                                                  * */
/* *                                 L O O P - F A D E  O U T                                                         * */
/* *                                                                                                                  * */
/* ******************************************************************************************************************** */

  if (((ontime * 60) + photoperiod + blueramptime + whiteramptime) <= daybyminute)
  { 
    if (((ontime * 60) + photoperiod + 2*whiteramptime + 2*blueramptime) >= daybyminute)
    {
      // fade white LEDs out from max to min in increments of 1 point:
      for (int i = 10; i >= 0; i--) // setting i value for 10% increment. Start with 10%
      { 
        analogWrite(blue, 255);
        lcd.setCursor(5, 1);
        lcd.print(10);
        lcd.print(" "); 
        
        analogWrite(white, whitepercent[i]); 
        lcd.setCursor(14, 1);
        lcd.print(i);
        lcd.print(" ");  

        int countdown = ((whiterampdown*60)/10); // calculates seconds to next step
        while (countdown>0)
        {
          onesecond(); // updates clock once per second
          countdown--;
          relay2();
          relay1();
        }

      } 

      // fade blue LEDs out from max to min in increments of 1 point:
      for (int i = 10; i >= 0; i--) // setting i value for 10% increment. Start with 10%
      { 
        analogWrite(blue, bluepercent[i]);
        lcd.setCursor(5, 1);
        lcd.print(i);
        lcd.print(" "); 

        int countdown = ((bluerampdown*60)/10); // calculates seconds to next step
        while (countdown>0)
        {
          onesecond(); // updates clock once per second
          countdown--;
          relay2();
          relay1();
        }
      }
    }
  }


}  // END LOOP