Natural Reef Aquarium Lighting Controller

WOW this is really amazing. I was trying to do something similar with my last tank which was sadly wiped out by hurricane sandy. My code was nowhere near this complex! Thank you so much for this i will be incorporating some of these functions in my next controller! Which i will share with everyone when the time comes. I think it would be wise to make this into a library at some point.

Hi numlock10, I would like to know how you can set the date in the code?? Thank you

I don't see where the time and date are set in the code. He must use a different sketch to do that.

In my code i had included a rtc lib called "RTClib.h" and the date was set in void setup with

RTC.adjust(DateTime(__DATE__, __TIME__));

which somehow grabs the correct date and time from the PC when the code is compiled, so its important to compile and upload right away without waiting too long.

You could easily make a sketch with that lib and the one line there in void setup, compile and upload just to set the RTC time and date and then upload whatever code instead of that. The RTC would keep its time and date as long as it still has power from the battery. HTH!
 
Hi numlock10, I would like to know how you can set the date in the code?? Thank you

I do this at this way....

SetTime:
PHP:
#include "Wire.h"

#define DS1307_ADDRESS 0x68

void setup(){
  Wire.begin();
    
  Serial.begin(9600);
  
  byte second =      0; //0-59     change the values to the actual time
  byte minute =      44; //0-59    and date
  byte hour =        10; //0-23
  byte weekDay =     1; //1-7
  byte monthDay =    22; //1-31
  byte month =       9; //1-12
  byte year  =       14; //0-99

  Wire.beginTransmission(DS1307_ADDRESS);
    
  Wire.write(0x00); //Point to register 0
  
  Wire.write(decToBcd(second));
  Wire.write(decToBcd(minute));
  Wire.write(decToBcd(hour));
  Wire.write(decToBcd(weekDay));
  Wire.write(decToBcd(monthDay));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(year));

  Wire.endTransmission();
  
}

void loop(){
}

byte decToBcd(byte val){
//convert dezimal in BCD 
  return ( (val/10*16) + (val%10) );
}

ReadTime:
PHP:
#include "Wire.h"
#define DS1307_ADDRESS 0x68

void setup(){
  Wire.begin();
  Serial.begin(9600);
}

void loop(){
  
  Wire.beginTransmission(DS1307_ADDRESS);  //Set pointer to register 0
  Wire.write(0x00);
  Wire.endTransmission();
  
  Wire.requestFrom(DS1307_ADDRESS, 7);    //request timeZeit abfragen

  int second = bcdToDec(Wire.read());
  int minute = bcdToDec(Wire.read());
  int hour = bcdToDec(Wire.read());
  int weekDay = bcdToDec(Wire.read());
  int monthDay = bcdToDec(Wire.read());
  int month = bcdToDec(Wire.read());
  int year = bcdToDec(Wire.read());

  //print date in format dd.mm.yy - hh:mm:ss
  Serial.print(monthDay);
  Serial.print(".");
  Serial.print(month);
  Serial.print(".");
  Serial.print(year);
  Serial.print(" - ");
  Serial.print(hour);
  Serial.print(":");
  Serial.print(minute);
  Serial.print(":");
  Serial.println(second);
  delay(1000);
}

byte bcdToDec(byte val)  {
//convert BCD in dezimal
  return ( (val/16*10) + (val%16) );
}

You can read now the actual date and time with the SerialMonitor....

After you do that, reload the code you want.
I think is the simpliest way without touch the code.

Regards Hekto
 
Hi Jason,

i test the code for few days now. The lighting works very fine. :)
Actual, I would like to embed 2 aux-channels, but it doesn't work.
But te real status of relays is always HIGH but it does not switch to LOW state...

PHP:
// Auxilery Pins   

byte auxPins[] = { 50, 51 };   
byte auxChannels = 2;   

int auxStart[] = { 20, 50 };   
int auxStop[] = { 80, 100 };

PHP:
// Main Aux Pin Cycle  

int AuxUpdate (byte _pin, int _mins, int _start, int _stop)   
{   
  byte auxVal;   
  if (_mins < _start || _mins > _stop)   
  {   
    auxVal = LOW;   
  }   
  if (_mins >= _start && _mins <= _stop)   
  {   
    auxVal = HIGH;   
  }   
 digitalWrite(_pin, auxVal);   
 return auxVal;   
}

PHP:
void update_aux(){   
  Serial.print(minCounter);   
  Serial.println();   
  for (int i = 0; i < auxChannels; i++)   
  {   
    byte value = AuxUpdate(auxPins[i], minCounter, auxStart[i], auxStop[i]);   
    Serial.print("Pin ");   
    Serial.print(auxPins[i]);   
    Serial.print(" Value ");   
    Serial.print(value);   
    Serial.println();   
  }


regards Thomas
 
Hi Jason!
I've been running your code for almost a year now and everything works just great!
Now, I've been trying to create some cloud and lightning effects in the sketch, but It's not working at all.

You did a sketch a couple of years back (http://www.reefcentral.com/forums/showpost.php?p=17542851&postcount=206) and I tried to use that into this sketch. But, to be honest, I realy don't know what I'm doing:spin2:

Right now, the sketch I'm working on looks like this:
Code:
// Natural Reef Aquarium Lighting V2.5.6
// 30/11/2013
// Developed by J. Harp (nUm - RTAW Forums, Numlock10 - Reef Central Forums)
// Formulas based off of information from NOAA website for sunrise / sunset times.
// Includes Lunar Simulation.
// Compiled in Arduino 1.5.2
//
// Testing;
// Moon Correction (was inverted)
// Will not calculate string values if Channel count is 0 to save on processor time
// Float Map for moonlight with corrected formula
//
// Future Development:
// Weather Simulation
//
// Please feel free to use this and modify as you see fit, if you have any comments or suggestions please let me know via messages on the forums listed above.
//

#include <math.h>
#include <Wire.h>
#define DS1307_I2C_ADDRESS 0x68

// RTC variables
byte second, rtcMins, oldMins, rtcHrs, oldHrs, dayOfWeek, dayOfMonth, month, year, psecond;

// LED variables (Change to match your needs) 
byte bluePins[] = { 6 };      // PWM pins for blues 
byte whitePins[] = { 10, 11 };    // PWM pins for whites 
byte uvPins[] = { 5, 9 };         // PWM pins for UVs 
byte moonPins[] = { 3 };         // PWM pins for moonlights
byte lightningPins [] = {5, 6, 9, 10, 11};   //PWM pins for lighning

byte blueChannels = 1;    // how many PWMs for blues (count from above) 
byte whiteChannels = 2;    // how many PWMs for whites (count from above) 
byte uvChannels = 2;    // how many PWMs for uv (count from above) 
byte moonChannels = 1;    // how many PWMs from moon (count from above)
byte lightningChannels = 5; //how many PWMs from lightning

byte BluePWMHigh[] = { 200 };        // High value for Blue PWM each vale is for each string - if your values are noraml this is 255, if your values are inverted this is 0 
byte BluePWMLow[] = { 0 };            // Low value for Blue PWM - if your values are noraml this is 0, if your values are inverted this is 255 
float BlueFull[] = { 25 };          // Value in degrees (sun angle) that each Blue string will be at max output (Larger = more sunlight) 
byte WhitePWMHigh[] = { 150, 150 };        // High value for White PWM - if your values are noraml this is 255, if your values are inverted this is 0 
byte WhitePWMLow[] = { 0, 0 };            // Low value for White PWM - if your values are noraml this is 0, if your values are inverted this is 255 
float WhiteFull[] = { 37.5, 37.5 };      // Value in degrees (sun angle) that each White string will be at max output (Larger = more sunlight) 
byte UVPWMHigh[] = { 200, 200 };             // High value for UV PWM - if your values are noraml this is 255, if your values are inverted this is 0 
byte UVPWMLow[] = { 0, 0 };               // Low value for UV PWM - if your values are noraml this is 0, if your values are inverted this is 255 
float UVFull[] = { 30, 30 };              // Value in degrees (sun angle) that each UV string will be at max output (Larger = more sunlight) 
byte MoonPWMHigh[] = { 40 };             // High value for Moon PWM - if your values are noraml this is 255, if your values are inverted this is 0 
byte MoonPWMLow[] = { 0 };               // Low value for Moon PWM - if your values are noraml this is 0, if your values are inverted this is 255
byte LightningPWMHigh[] = {255}
byte LightningPWMLow[] = {50}

// Set for the location of the world you want to replicate. 

float latitude = -17.730211;   // + to N  Defualt - (-19.770621) Heart Reef, Great Barrier Reef, QLD, Australia  
float longitude = 177.127218;  // + to E  Defualt - (149.238532) 
int TimeZone = 12;             // + to E  Defulat - (10)

// Sunlight Variables

int delayTime = -150;     // start time delay in minutes,  - will push the day back, + will bring the day forward

float floatMap(float x, float in_min, float in_max, int out_min, int out_max)
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

int SunLight(byte _ledPin, byte _ledHigh, byte _ledLow, float _fullSun, byte _year, byte _month, byte _day, byte _hour, byte _min, byte _sec)
{
    float a = floor((14.0 - _month) / 12.0);
    float y = _year + 4800.0 - a;
    float m = _month + (12.0 * a) - 3.0;
    float AH;
    int result;

        float JC = (((_day + floor(((153.0 * m) + 2.0) / 5.0) + (365.0 * y) + floor(y / 4.0) - floor(y / 100.0) + floor(y / 400.0) - 32045.0) + ((_hour / 24.0) + (_min / 1444.0) + (_sec / 86400.0))) - 2451556.08) / 36525.0;

    float GMLS = fmod(280.46646 + JC*(36000.76983 + JC * 0.0003032), 360.0);

    float GMAS = 357.52911 + JC * (35999.05029 - 0.0001537 * JC);

    float EEO = 0.016708634 - JC * (0.000042037 + 0.0000001267 * JC);

    float SEoC = sin((GMAS * M_PI) / 180.0)*(1.914602 - JC * (0.004817 + 0.000014 * JC)) + sin(((2.0 * GMAS) * M_PI) / 180.0) * (0.019993 - 0.000101 * JC) + sin(((3.0 * JC) * M_PI) / 180.0) * 0.000289;

    float STL = GMLS + SEoC;

    float STA = GMAS + SEoC;

    float SRV = (1.000001018 * (1.0 - EEO * EEO)) / (1.0 + EEO * cos((STA * M_PI) / 180.0));

    float SAL = STL - 0.00569 - 0.00478 * sin(((125.04 - 1934.136 * JC) * M_PI) / 180.0);

    float MOE = 23.0 + (26.0 + ((21.448 - JC * (46.815 + JC * (0.00059 - JC * 0.001813)))) / 60.0) / 60.0;

    float OC = MOE + 0.00256 * cos(((215.04 - 1934.136 * JC) * M_PI) / 180.0);

    float SD = (asin(sin((OC * M_PI) / 180.0) * sin((SAL * M_PI) / 180.0))) * (180.0 / M_PI);

    float vy = tan(((OC / 2.0) * M_PI) / 180.0) * tan(((OC / 2.0) * M_PI) / 180.0);

    float EQoT = (4.0 * (vy * (sin(2.0 * ((GMLS * M_PI) / 180.0)) - 2.0 * EEO * sin((GMAS * M_PI) / 180.0) + 4.0 * EEO * vy * sin((GMAS * M_PI) / 180.0) * cos(2.0 * ((GMLS * M_PI) / 180.0)) - 0.5 * vy * vy * sin(4.0 * ((GMLS * M_PI) / 180.0)) - 1.25 * EEO * EEO * sin(2 * ((GMAS * M_PI) / 180))))) * (180 / M_PI);

    float HAS = acos(cos((90.833 * M_PI) / 180.0) / (cos((latitude * M_PI) / 180.0) * cos((SD * M_PI) / 180.0)) - tan((latitude * M_PI) / 180.0) * tan((SD * M_PI) / 180.0)) * (180.0 / M_PI);

    float SN = (720.0 - 4.0 * longitude - EQoT + TimeZone * 60.0);

    float SR = SN - HAS * 4.0;

    float SS = SN + HAS * 4.0;

    float STD = 8.0 * HAS;

    float TST = fmod((((_hour)+(_min / 60.0) + (_sec / 3600.0)) / 24.0) * 1440.0 + EQoT + 4.0 * longitude - 60.0 * TimeZone, 1440.0) + delayTime;

    if (TST / 4 < 0.0)
    {
        AH = ((TST / 4.0) + 180.0);
    }
    else
    {
        AH = ((TST / 4.0) - 180.0);
    }

    float SZA = (acos(sin((latitude * M_PI) / 180.0) * sin((SD * M_PI) / 180.0) + cos((latitude * M_PI) / 180.0) * cos((SD * M_PI) / 180.0) * cos((AH * M_PI) / 180.0))) * (180.0 / M_PI);

    float SEA = 90.0 - SZA;

    if (SEA <= 0.0)
    {
        result = _ledLow;
    }

    if (SEA > 0.0 && SEA < _fullSun)
    {
        result = map(SEA, 0, _fullSun, _ledLow, _ledHigh);
    }

    if (SEA >= _fullSun)
    {
        result = _ledHigh;
    }

    analogWrite(_ledPin, result);
    return result;

}

int MoonLight(byte _ledPin, byte _ledHigh, byte _ledLow, byte _year, byte _month, byte _day, byte _hour, byte _min, byte _sec)
{
    int result;

    float a = floor((14.0 - _month) / 12.0);
    float y = _year + 4800.0 - a;
    float m = _month + (12.0 * a) - 3.0;
    
        float mJDN = ((_day  + ((153.0 * m + 2.0) / 5.0) + (365.0 * y) + (y / 4.0) - ( y / 100.0) + (y / 400.0) - 32045.0) + 730483.71);

        float mJDR = (_hour / 24.0) + (_min / 1444.0) + (_sec / 86400.0);

        float mJD = mJDN + mJDR;
        
    float moon = fmod((mJD - 2456318.69458333), 29.530589);

    if (moon <= 14.7652945)
    {
        result = floatMap(moon, 0.0, 14.7652945, _ledHigh, _ledLow);
    }

    if (moon >= 14.7652946)
    {
        result = floatMap(moon, 14.7652946, 29.530589, _ledLow, _ledHigh);
    }
    analogWrite(_ledPin, result);
    return result;
}

int Lightning(byte _ledPin, byte _ledHigh, byte _ledLow, byte _year, byte _month, byte _day, byte _hour, byte _min, byte _sec)


/***** 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));
}

// 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.write(0);
    Wire.endTransmission();

    Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

    *second = bcdToDec(Wire.read() & 0x7f);
    *minute = bcdToDec(Wire.read());
    *hour = bcdToDec(Wire.read() & 0x3f);
    *dayOfWeek = bcdToDec(Wire.read());
    *dayOfMonth = bcdToDec(Wire.read());
    *month = bcdToDec(Wire.read());
    *year = bcdToDec(Wire.read());
}

void setup() {
    delay(500);
    Serial.begin(57600);
    Wire.begin();
}

void loop() {
    getDateDs1307(&second, &rtcMins, &rtcHrs, &dayOfWeek, &dayOfMonth, &month, &year);
    if (psecond != second){
        psecond = second;
        Serial.print(rtcHrs);
        Serial.print(":");
        Serial.print(rtcMins);
        Serial.print(":");
        Serial.print(second);
        Serial.print(" ");
        Serial.print(dayOfMonth);
        Serial.print("/");
        Serial.print(month);
        Serial.print("/");
        Serial.println(year);
        update_leds();
    }
}

void update_leds(){
    int i;
    byte value;
    if (blueChannels > 0){
        Serial.println("Blue LED's");
        for (i = 0; i < blueChannels; i++)
        {
            value = SunLight(bluePins[i], BluePWMHigh[i], BluePWMLow[i], BlueFull[i], year, month, dayOfMonth, rtcHrs, rtcMins, second);
            Serial.print(map(value, BluePWMLow[i], BluePWMHigh[i], 0, 100));
            Serial.print("% ");
        }
        Serial.println();
    }
    if (whiteChannels > 0){
        Serial.println("White LED's");
        for (i = 0; i < whiteChannels; i++)
        {
            value = SunLight(whitePins[i], WhitePWMHigh[i], WhitePWMLow[i], WhiteFull[i], year, month, dayOfMonth, rtcHrs, rtcMins, second);
            Serial.print(map(value, WhitePWMLow[i], WhitePWMHigh[i], 0, 100));
            Serial.print("% ");
        }
        Serial.println();
    }
    if (uvChannels > 0){
        Serial.println("UV LED's");
        for (i = 0; i < uvChannels; i++)
        {
            value = SunLight(uvPins[i], UVPWMHigh[i], UVPWMLow[i], UVFull[i], year, month, dayOfMonth, rtcHrs, rtcMins, second);
            Serial.print(map(value, UVPWMLow[i], UVPWMHigh[i], 0, 100));
            Serial.print("% ");
        }
        Serial.println();
    }

    if (moonChannels > 0){
        Serial.println("Moon Value");
        for (i = 0; i < moonChannels; i++)
        {
            value = MoonLight(moonPins[i], MoonPWMHigh[i], MoonPWMLow[i], year, month, dayOfMonth, rtcHrs, rtcMins, second);
            Serial.print(map(value, MoonPWMLow[i], MoonPWMHigh[i], 0, 100));
            Serial.print("% ");
        }
        Serial.println();
    }
    
    if (lightningChannels > 0){
        Serial.println("Lightning Value");
        for (i = 0; i < lightningChannels; i++)
        {
            value = Lightning(lightningPins[i], LightningPWMHigh[i], LightningPWMLow[i], year, month, dayOfMonth, rtcHrs, rtcMins, second);
            Serial.print(map(value, LightningPWMLow[i], LightningPWMHigh[i], 0, 100));
            Serial.print("% ");
        }
        Serial.println();
    }
}

//Patrik
 
Hi All

Firstly, Numlock10, thanks for the code, after weeks of trying various bits of code and writing my own(well trying to) I found yours.

I'm using 'Natural Reef Aquarium Lighting V2.7.3 ' and I've got it working and added temperature display and I'm currently trying to add a menu so that I can change Latitude/Longitude, Timezone, PWM, sun angle values and temperature alarms- not too much of an issue.

The main issue I'm having is that I would like to display the Sunrise and Sunset times and also calculate the same for the following day but I'm unable to get it to return the times (in minutes) so that I can display it and use it for the calculations.

Any thoughts/ideas/suggestions would be helpful?
 
Natural Reef Aquarium Lighting V2.5.4

Natural Reef Aquarium Lighting V2.5.4

Good day Jason,
I have used your sketch which includes lunar and lcd. I have ommitted the UV.
The serial monitor shows the correct info but the lcd does not show the correct light intencity %.
Please see attached code perhaps I missed something out.
I am using a UNO and lcd robot keypad shield.

// Natural Reef Aquarium Lighting V2.5.4
// 23/11/2013
// Developed by J. Harp (nUm - RTAW Forums, Numlock10 - Reef Central Forums)
// Formulas based off of information from NOAA website for sunrise / sunset times.
// Includes Lunar Simulation.
// Compiled in Arduino 1.5.2
//
// Testing;
// Moon Correction (was inverted)
// Will not calculate string values if Channel count is 0 to save on processor time
// Float Map for moonlight
//
// Future Development:
// Weather Simulation
//
// Please feel free to use this and modify as you see fit, if you have any comments or suggestions please let me know via messages on the forums listed above.
//
#include <LiquidCrystal.h>
#include <math.h>
#include <Wire.h>
#define DS1307_I2C_ADDRESS 0x68

//Declare lcd
LiquidCrystal lcd (8,9,4,5,6,7);

// RTC variables
byte second, rtcMins, oldMins, rtcHrs, oldHrs, dayOfWeek, dayOfMonth, month, year, psecond;

// LED variables (Change to match your needs)
byte bluePins[] = { 3 }; // PWM pins for blues
byte whitePins[] = {10 }; // PWM pins for whites
byte moonPins[] = {11 }; // PWM pins for moonlights

byte blueChannels = 1; // how many PWMs for blues (count from above)
byte whiteChannels = 1; // how many PWMs for whites (count from above)
byte moonChannels = 1; // how many PWMs from moon (count from above)

byte BluePWMHigh[] = { 255 }; // High value for Blue PWM each vale is for each string - if your values are noraml this is 255, if your values are inverted this is 0
byte BluePWMLow[] = { 0 }; // Low value for Blue PWM - if your values are noraml this is 0, if your values are inverted this is 255
float BlueFull[] = { 25 }; // Value in degrees (sun angle) that each Blue string will be at max output (Larger = more sunlight)
byte WhitePWMHigh[] = { 255, 255 }; // High value for White PWM - if your values are noraml this is 255, if your values are inverted this is 0
byte WhitePWMLow[] = { 0, 0 }; // Low value for White PWM - if your values are noraml this is 0, if your values are inverted this is 255
float WhiteFull[] = { 37.5, 37.5 }; // Value in degrees (sun angle) that each White string will be at max output (Larger = more sunlight)
byte MoonPWMHigh[] = { 10 }; // High value for Moon PWM - if your values are noraml this is 255, if your values are inverted this is 0
byte MoonPWMLow[] = { 0 }; // Low value for Moon PWM - if your values are noraml this is 0, if your values are inverted this is 255

// Set for the location of the world you want to replicate.

float latitude = -21.534847; // + to S Defualt - (-21.534847) Heart Reef, Great Barrier Reef, QLD, Australia
float longitude = 174.287109; // + to E Defualt - (174.287109)
int TimeZone = 12; // + to E Defulat - (12)



// Sunlight Variables

int delayTime = -150; // start time delay in minutes, - will push the day back, + will bring the day forward

float floatMap(float x, float in_min, float in_max, int out_min, int out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

int SunLight(byte _ledPin, byte _ledHigh, byte _ledLow, float _fullSun, byte _year, byte _month, byte _day, byte _hour, byte _min, byte _sec)
{
float a = floor((14.0 - _month) / 12.0);
float y = _year + 4800.0 - a;
float m = _month + (12.0 * a) - 3.0;
float AH;
int result;

float JC = (((_day + floor(((153.0 * m) + 2.0) / 5.0) + (365.0 * y) + floor(y / 4.0) - floor(y / 100.0) + floor(y / 400.0) - 32045.0) + ((_hour / 24.0) + (_min / 1444.0) + (_sec / 86400.0))) - 2451556.08) / 36525.0;

float GMLS = fmod(280.46646 + JC*(36000.76983 + JC * 0.0003032), 360.0);

float GMAS = 357.52911 + JC * (35999.05029 - 0.0001537 * JC);

float EEO = 0.016708634 - JC * (0.000042037 + 0.0000001267 * JC);

float SEoC = sin((GMAS * M_PI) / 180.0)*(1.914602 - JC * (0.004817 + 0.000014 * JC)) + sin(((2.0 * GMAS) * M_PI) / 180.0) * (0.019993 - 0.000101 * JC) + sin(((3.0 * JC) * M_PI) / 180.0) * 0.000289;

float STL = GMLS + SEoC;

float STA = GMAS + SEoC;

float SRV = (1.000001018 * (1.0 - EEO * EEO)) / (1.0 + EEO * cos((STA * M_PI) / 180.0));

float SAL = STL - 0.00569 - 0.00478 * sin(((125.04 - 1934.136 * JC) * M_PI) / 180.0);

float MOE = 23.0 + (26.0 + ((21.448 - JC * (46.815 + JC * (0.00059 - JC * 0.001813)))) / 60.0) / 60.0;

float OC = MOE + 0.00256 * cos(((215.04 - 1934.136 * JC) * M_PI) / 180.0);

float SD = (asin(sin((OC * M_PI) / 180.0) * sin((SAL * M_PI) / 180.0))) * (180.0 / M_PI);

float vy = tan(((OC / 2.0) * M_PI) / 180.0) * tan(((OC / 2.0) * M_PI) / 180.0);

float EQoT = (4.0 * (vy * (sin(2.0 * ((GMLS * M_PI) / 180.0)) - 2.0 * EEO * sin((GMAS * M_PI) / 180.0) + 4.0 * EEO * vy * sin((GMAS * M_PI) / 180.0) * cos(2.0 * ((GMLS * M_PI) / 180.0)) - 0.5 * vy * vy * sin(4.0 * ((GMLS * M_PI) / 180.0)) - 1.25 * EEO * EEO * sin(2 * ((GMAS * M_PI) / 180))))) * (180 / M_PI);

float HAS = acos(cos((90.833 * M_PI) / 180.0) / (cos((latitude * M_PI) / 180.0) * cos((SD * M_PI) / 180.0)) - tan((latitude * M_PI) / 180.0) * tan((SD * M_PI) / 180.0)) * (180.0 / M_PI);

float SN = (720.0 - 4.0 * longitude - EQoT + TimeZone * 60.0);

float SR = SN - HAS * 4.0;

float SS = SN + HAS * 4.0;

float STD = 8.0 * HAS;

float TST = fmod((((_hour)+(_min / 60.0) + (_sec / 3600.0)) / 24.0) * 1440.0 + EQoT + 4.0 * longitude - 60.0 * TimeZone, 1440.0) + delayTime;

if (TST / 4 < 0.0)
{
AH = ((TST / 4.0) + 180.0);
}
else
{
AH = ((TST / 4.0) - 180.0);
}

float SZA = (acos(sin((latitude * M_PI) / 180.0) * sin((SD * M_PI) / 180.0) + cos((latitude * M_PI) / 180.0) * cos((SD * M_PI) / 180.0) * cos((AH * M_PI) / 180.0))) * (180.0 / M_PI);

float SEA = 90.0 - SZA;

if (SEA <= 0.0)
{
result = _ledLow;
}

if (SEA > 0.0 && SEA < _fullSun)
{
result = map(SEA, 0, _fullSun, _ledLow, _ledHigh);
}

if (SEA >= _fullSun)
{
result = _ledHigh;
}

analogWrite(_ledPin, result);
return result;

}

int MoonLight(byte _ledPin, byte _ledHigh, byte _ledLow, byte _year, byte _month, byte _day, byte _hour, byte _min, byte _sec)
{
int result;
float a = floor((14.0 - _month) / 12.0);
float y = _year + 4800.0 - a;
float m = _month + (12.0 * a) - 3.0;

float JC = (((_day + floor(((153.0 * m) + 2.0) / 5.0) + (365.0 * y) + floor(y / 4.0) - floor(y / 100.0) + floor(y / 400.0) - 32045.0) + ((_hour / 24.0) + (_min / 1444.0) + (_sec / 86400.0))) - 2451556.08) / 36525.0;

float moon = fmod((2456318.69458333 - JC), 29.530589);

if (moon <= 14.7652945)
{
result = floatMap(moon, 0.0, 14.7652945, _ledHigh, _ledLow);
}

if (moon >= 14.7652946)
{
result = floatMap(moon, 14.7652946, 29.530589, _ledLow, _ledHigh);
}
analogWrite(_ledPin, result);
return result;
}


/***** 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));
}

// 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.write(0);
Wire.endTransmission();

Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

*second = bcdToDec(Wire.read() & 0x7f);
*minute = bcdToDec(Wire.read());
*hour = bcdToDec(Wire.read() & 0x3f);
*dayOfWeek = bcdToDec(Wire.read());
*dayOfMonth = bcdToDec(Wire.read());
*month = bcdToDec(Wire.read());
*year = bcdToDec(Wire.read());
}

void setup() {
delay(500);
Serial.begin(57600);
Wire.begin();
}

void loop() {
getDateDs1307(&second, &rtcMins, &rtcHrs, &dayOfWeek, &dayOfMonth, &month, &year);
if (psecond != second){
psecond = second;
Serial.print(rtcHrs);
Serial.print(":");
Serial.print(rtcMins);
Serial.print(":");
Serial.print(second);
Serial.print(" ");
Serial.print(dayOfMonth);
Serial.print("/");
Serial.print(month);
Serial.print("/");
Serial.println(year);
update_leds();

lcd.begin (16,2);
lcd.setCursor (0,0);
lcd.print(rtcHrs);
lcd.print(":");
lcd.print(rtcMins);


lcd.setCursor (8,0);
lcd.print(dayOfMonth);
lcd.print("/");
lcd.print(month);
lcd.print("/");
lcd.println(year);


}
}

void update_leds(void){
int i;
byte value;
if (blueChannels > 0){
Serial.println("Blue LED's");
for (i = 0; i < blueChannels; i++)
{
value = SunLight(bluePins, BluePWMHigh, BluePWMLow, BlueFull, year, month, dayOfMonth, rtcHrs, rtcMins, second);
Serial.print(map(value, BluePWMLow, BluePWMHigh, 0, 100));
Serial.print("% ");
}
Serial.println();
}
if (whiteChannels > 0){
Serial.println("White LED's");
for (i = 0; i < whiteChannels; i++)
{
value = SunLight(whitePins, WhitePWMHigh, WhitePWMLow, WhiteFull, year, month, dayOfMonth, rtcHrs, rtcMins, second);
Serial.print(map(value, WhitePWMLow, WhitePWMHigh, 0, 100));
Serial.print("% ");
}
Serial.println();
}
if (uvChannels > 0){
Serial.println("UV LED's");
for (i = 0; i < uvChannels; i++)
{
value = SunLight(uvPins, UVPWMHigh, UVPWMLow, UVFull, year, month, dayOfMonth, rtcHrs, rtcMins, second);
Serial.print(map(value, UVPWMLow, UVPWMHigh, 0, 100));
Serial.print("% ");
}
Serial.println();
}
if (moonChannels > 0){
Serial.println("Moon Value");
for (i = 0; i < moonChannels; i++)
{
value = MoonLight(moonPins, MoonPWMHigh, MoonPWMLow, year, month, dayOfMonth, rtcHrs, rtcMins, second);
Serial.print(map(value, MoonPWMLow, MoonPWMHigh, 0, 100));
Serial.print("% ");
}
Serial.println();




lcd.setCursor(0,1);
lcd.print ("Blue Leds");
lcd.setCursor (11,1);
lcd.print(map(value, BluePWMLow, BluePWMHigh, 0, 100));
lcd.print("% ");
delay(5000);

lcd.setCursor(0,1);
lcd.print ("White Leds");
lcd.setCursor (11,1);
lcd.print(map(value, WhitePWMLow, WhitePWMHigh, 0, 100));
lcd.print("% ");
delay(5000);

lcd.setCursor(0,1);
lcd.print ("Other Leds");
lcd.setCursor (11,1);
lcd.print(map(value, UVPWMLow, UVPWMHigh, 0, 100));
lcd.print("% ");
delay(5000);

lcd.setCursor(0,1);
lcd.print ("Moonlights");
lcd.setCursor (11,1);
lcd.print (map(value, MoonPWMLow, MoonPWMHigh, 0, 100));
lcd.print("% ");
delay(5000);

}}
 
Back
Top