Jump to content
Innovative Marine Aquariums

A lunar phase function for the Arduino


NightAtTheOpera

Recommended Posts

NightAtTheOpera

Someone may have already posted something like this but just in case...

 

This is a function you can use in your Arduino sketches for calculating the current lunar phase. The function, GetPhase, takes three parameters: the year, the month and the day. Note that the year must be 4 digits. The function returns a float type containing the percentage of illumination (0 for new, .25 for crescent, .5 for quarter, .75 for gibbous and 1 for full). You can then set your lunar light PWM pin to 255 multiplied by the returned percentage to simulate current moon phase lunar lighting. In future I'd like to beef up this function to reflect percentages between phases instead of always returning 0, .25, .50, .75 or 1.

 

In order to use this function you will need a realtime clock module such as the DS1307 so that you can obtain the current date.

 

Following are the functions GetPhase and MyNormalize (which is called by GetPhase)

 

float GetPhase(int nYear, int nMonth, int nDay) // calculate the current phase of the moon

{

float phase;

double AG, IP;

long YY, MM, K1, K2, K3, JD;

YY = nYear - floor((12 - nMonth) / 10);

MM = nMonth + 9;

if (MM >= 12)

{

MM = MM - 12;

}

K1 = floor(365.25 * (YY + 4712));

K2 = floor(30.6 * MM + 0.5);

K3 = floor(floor((YY / 100) + 49) * 0.75) - 38;

JD = K1 + K2 + nDay + 59;

if (JD > 2299160)

{

JD = JD - K3;

}

IP = MyNormalize((JD - 2451550.1) / 29.530588853);

AG = IP*29.53;

phase = 0;

if ((AG < 1.84566) && (phase == 0))

{

phase = 0; //new; 0% illuminated

}

if ((AG < 5.53699) && (phase == 0))

{

phase = .25; //Waxing crescent; 25% illuminated

}

if ((AG < 9.922831) && (phase == 0))

{

phase = .50; //First quarter; 50% illuminated

}

if ((AG < 12.91963) && (phase == 0))

{

phase = .75; //Waxing gibbous; 75% illuminated

}

if ((AG < 16.61096) && (phase == 0))

{

phase = 1; //Full; 100% illuminated

}

if ((AG < 20.30228) && (phase == 0))

{

phase = .75; //Waning gibbous; 75% illuminated

}

if ((AG < 23.99361) && (phase == 0))

{

phase = .50; //Last quarter; 50% illuminated

}

if ((AG < 27.68493) && (phase == 0))

{

phase = .25; //Waning crescent; 25% illuminated

}

if (phase == 0)

{

phase = 0; //default to new; 0% illuminated

}

return phase;

}

 

double MyNormalize(double v)

{

v = v - floor(v);

if (v < 0)

v = v + 1;

return v;

}

Link to comment
NightAtTheOpera
My head just exploded....... :huh:

 

-Prof

 

Sorry 'bout that :blush: I've seen posts where people were asking how to use the Arduino for phased lunar lighting so I thought I'd post this function. I guess it only makes sense to programmers and people who use Arduinos or other microcontrollers.

Link to comment
Sorry 'bout that :blush: I've seen posts where people were asking how to use the Arduino for phased lunar lighting so I thought I'd post this function. I guess it only makes sense to programmers and people who use Arduinos or other microcontrollers.

 

Don't apologize for me being dumb. I just don't understand anything that can't be hit with a hammer......... :P Computers and I don't get along.

 

-Prof

Link to comment
Sorry 'bout that :blush: I've seen posts where people were asking how to use the Arduino for phased lunar lighting so I thought I'd post this function. I guess it only makes sense to programmers and people who use Arduinos or other microcontrollers.

 

Excellent work, now I'm pretty dumb myself when it comes to this..... But I'm not dumb enough not to ask if you could you be so kind to give us a how to and what we need to do this? Ya know hold our hands? Pictures, parts, etc? It'd be greatly appreciated... I assume this could be done very similarly for bringing up the sun slowly and setting it? Blues ramp up then bout halfway thru the whites start coming on?

Link to comment
NightAtTheOpera
Excellent work, now I'm pretty dumb myself when it comes to this..... But I'm not dumb enough not to ask if you could you be so kind to give us a how to and what we need to do this? Ya know hold our hands? Pictures, parts, etc? It'd be greatly appreciated... I assume this could be done very similarly for bringing up the sun slowly and setting it? Blues ramp up then bout halfway thru the whites start coming on?

 

You absolutely can use the Arduino to control your lighting, from simulated sunup and sundown to phased lunar lighting to random cloud coverage and full blown storm clouds.

 

WHAT YOU'LL NEED

 

First and foremost, dimmable LED lighting. I don't think this will work with anything else. There are dimmable T5's but I know nothing about them (even less than I do LED lighting).

 

An Arduino Duemilanove. I got mine at sparkfun.com, part #DEV-00666. They have good prices and fast shipping.

A DS1307 real time clock module. I got this at sparkfun as well, part #BOB-00099.

A wall wart with 2.1mm center positive barrel plug to power the Arduino. I had a 9v, 600ma laying around and that works well; any 9V from 100 to 600ma is fine. Sparkfun and other companies like Adafruit sell wall warts for the Arduino if you don't have the right one on hand. Note that you won't need this wall wart while the Arduino is connected to your computer; it will be powered by the USB cable. You will only need it once the Arduino is ready to run independantly from the computer.

A standard A - B USB cable to connect the Arduino to your computer. You need this for uploading the sketches (programs) to the Arduino and if you don't have one laying around they have them at, you guessed it, Sparkfun.

22 AWG solid hookup wire to connect the RTC module to the Arduino. Don't use stranded wire for this.

USB VCP (Virtual COM Port) driver for the Arduino. The driver you'll need depends on your operating system. You can download the driver from the following site: http://www.ftdichip.com/Drivers/VCP.htm

The Arduino development environment. This has to be installed on your computer so you can compile sketches and upload them. You can download it from the following: http://www.arduino.cc/en/Main/Software

 

Ok, once you have all this stuff come back and let me know. I'll step you through connecting the RTC module, hooking up the Arduino and writing a sketch to run your LEDs.

Link to comment
You absolutely can use the Arduino to control your lighting, from simulated sunup and sundown to phased lunar lighting to random cloud coverage and full blown storm clouds.

 

WHAT YOU'LL NEED

 

First and foremost, dimmable LED lighting. I don't think this will work with anything else. There are dimmable T5's but I know nothing about them (even less than I do LED lighting).

 

An Arduino Duemilanove. I got mine at sparkfun.com, part #DEV-00666. They have good prices and fast shipping.

A DS1307 real time clock module. I got this at sparkfun as well, part #BOB-00099.

A wall wart with 2.1mm center positive barrel plug to power the Arduino. I had a 9v, 600ma laying around and that works well; any 9V from 100 to 600ma is fine. Sparkfun and other companies like Adafruit sell wall warts for the Arduino if you don't have the right one on hand. Note that you won't need this wall wart while the Arduino is connected to your computer; it will be powered by the USB cable. You will only need it once the Arduino is ready to run independantly from the computer.

A standard A - B USB cable to connect the Arduino to your computer. You need this for uploading the sketches (programs) to the Arduino and if you don't have one laying around they have them at, you guessed it, Sparkfun.

22 AWG solid hookup wire to connect the RTC module to the Arduino. Don't use stranded wire for this.

USB VCP (Virtual COM Port) driver for the Arduino. The driver you'll need depends on your operating system. You can download the driver from the following site: http://www.ftdichip.com/Drivers/VCP.htm

The Arduino development environment. This has to be installed on your computer so you can compile sketches and upload them. You can download it from the following: http://www.arduino.cc/en/Main/Software

 

Ok, once you have all this stuff come back and let me know. I'll step you through connecting the RTC module, hooking up the Arduino and writing a sketch to run your LEDs.

 

 

Fair enough man... Getting ready to build my LED setup so I'm w/ ya on that. I downloaded all the stuff on my mac. I was kind of surprised they had it for it as well. I actually opened up VMware getting ready to do it all in XP. I'm going to order the stuff form sparkfun shortly. I tried copying and pasting your sketch in to the arduino app it didnt seem to take when i clicked verify. Of course I'm sure its not that simple. Thanx for all the info. Tho I'm not sure about all the soldering again which is where pics would help greatly... Thanx again! I'd love to get that sunrise/sunset/cloud/storm/lunar phase thing going... Would be ideal.

Link to comment

Nice writeup Night....

 

I got an arduino like a year ago with the intentions of doing this, however I think I forgot about it..

 

I have slightly different equipment though. I have a duemilanove, and I got an LCD and RTC that I'm attempting to hook up through the I2C bus. I'm not a programmer or an electrical engineer though, so this sort of stuff takes me some serious time to figure out! Hahaha... This has me all excited to "fire it up" again... I think it's safe to say you can probably expect a PM from me soon :)

 

This is the back of my LCD screen. I've gotten it to display a scrolling text program, but I haven't figured out how to piggyback I/O devices yet...

DSC00517.jpg

Link to comment
NightAtTheOpera
Fair enough man... Getting ready to build my LED setup so I'm w/ ya on that. I downloaded all the stuff on my mac. I was kind of surprised they had it for it as well. I actually opened up VMware getting ready to do it all in XP. I'm going to order the stuff form sparkfun shortly. I tried copying and pasting your sketch in to the arduino app it didnt seem to take when i clicked verify. Of course I'm sure its not that simple. Thanx for all the info. Tho I'm not sure about all the soldering again which is where pics would help greatly... Thanx again! I'd love to get that sunrise/sunset/cloud/storm/lunar phase thing going... Would be ideal.

 

I had to chuckle at "fair enough man" since I'm a woman! I know, not alot of ladies on the reefing sites...I don't know why. Anywho, the reason that the code didn't compile (verify) properly is because this is not a complete sketch. They are just functions that you put into the sketch. Arduino sketches require a SETUP procedure and a LOOP procedure in order to compile properly. If you open some of the example sketches in your Arduino software (File -> Examples) you will see that each one contains a SETUP and LOOP procedure. The SETUP procedure runs only once when the Arduino is powered up or reset; the LOOP procedure, like the name indicates, runs over and over again. This allows us to program for events to happen at certain times. For example, the LOOP will call a function which gets the time from the clock. Depending on what time it is it can turn the lights on or off. If it's time to turn on the lights it can get the date from the clock and call the GetPhase function to get the lunar cycle so the lights can be set to the proper illumination. Depending on the complexity of the code the lights don't have to just turn on or off; they can be slowly ramped up or down to the proper illumination level, simulating moonrise, moonset, sunrise and sunset.

 

I haven't been able to post any pictures because believe it or not I don't own a digital camera. I hope to get one soon. The soldering isn't a big deal. There are only four wires that need to be soldered to the clock; the other ends go into headers that come attached to the Arduino. You might want to get a header to solder into the clock instead of soldering the wires; that's what I did. I just got a strip of headers when I ordered from Sparkfun and used wire clippers to cut to the size I needed. I also ordered the Arduino protoshield but that's not a requirement. I needed to do ALOT of soldering to get that put together. I should add that this was the first time I had ever soldered anything in my life so if I can do it without messing it up anyone can!

 

I assume this would work w/ the meanwell D drivers?

 

Yes, I'm pretty sure it will work with the dimmable meanwell drivers. On the buckpuck the CTRL and REF wires, which usually go to a potentiometer, are wired to the Arduino through a transistor and a resistor. Might be the same with meanwells but I'm not sure. Evil was VERY helpful on helping me figure out the buckpuck schematic so you might want to check with him re: meanwells.

Link to comment
NightAtTheOpera
Nice writeup Night....

 

I got an arduino like a year ago with the intentions of doing this, however I think I forgot about it..

 

I have slightly different equipment though. I have a duemilanove, and I got an LCD and RTC that I'm attempting to hook up through the I2C bus. I'm not a programmer or an electrical engineer though, so this sort of stuff takes me some serious time to figure out! Hahaha... This has me all excited to "fire it up" again... I think it's safe to say you can probably expect a PM from me soon :)

 

This is the back of my LCD screen. I've gotten it to display a scrolling text program, but I haven't figured out how to piggyback I/O devices yet...

DSC00517.jpg

 

I am a programmer but I know next to nothing about putting electronic components together. I got lots of help from Evil and others on this site, as well as info from all around the net (NASA has some great videos on how to solder electronic components...gotta love the Internet!)

 

The RTC is pretty easy to connect: SCL to analog pin 5, SDA to analog pin 4, GND to GND and 5V to 5V. The Arduino Duemilanove has built in pull up resistors so you don't need to include any in your wiring.

 

I ordered an LCD screen but I haven't gotten it connected yet. So far I use the serial monitor in the Arduino environment to make changes i.e. set the current date and time, set the time for moonrise and moonset, set the time for sunrise and sunset, etc. Eventually I want to be able to do this through an LCD that has programable input buttons. That's a ways off, though.

Link to comment

I'd do it today,

but those clocks don't work out here in Hawaii.

How do I keep time without using an atomic clock?

I've looked but no luck.

I'm looking for an external board with a coin cell batter so fi the power goes it it keeps the time,

then I set it's time, date and year then it gives it's info to arduino.

That would be great then I can use my arduino that's gathering dust.

Link to comment

Thanks for posting the sketch! I bought my arduino a few weeks ago and started playing with it. Now I'm just waiting for the RTC, display and some relays to really get down to business. A lunar cycle was one function I definitely wanted so now I at least have the code for that.

Link to comment
NightAtTheOpera
I'd do it today,

but those clocks don't work out here in Hawaii.

How do I keep time without using an atomic clock?

I've looked but no luck.

I'm looking for an external board with a coin cell batter so fi the power goes it it keeps the time,

then I set it's time, date and year then it gives it's info to arduino.

That would be great then I can use my arduino that's gathering dust.

 

The RTC module I mentioned is exactly what you need. It is a DS1307 soldered to a circuit board that has a battery for keeping time; it doesn't use any external power source. Once the date/time is set it will continue to update wether or not it's connected to the Arduino.

 

I'm not sure what you mean when you say that those clocks don't work in Hawaii. Doesn't Hawaii use a 24 hour clock like the rest of the world?

 

Thanks for posting the sketch! I bought my arduino a few weeks ago and started playing with it. Now I'm just waiting for the RTC, display and some relays to really get down to business. A lunar cycle was one function I definitely wanted so now I at least have the code for that.

 

Hi lotekfish:

 

You're welcome. Remember, this isn't a full sketch. They are just functions you can put in your sketch and then call to get the lunar phase.

Link to comment
  • 11 months later...
  • 4 months later...

Night,

 

Am new to all this myself and learning slowly but surely.Right now I currently have Katchupoy's sketch and was wondering if I could still incorporate the Lunar Phase code into theirs if there is already a ramp up/down code?

 

/*originally written by Christian, cptbjorn@gmail.com*/#include "Wire.h" #define DS1307_I2C_ADDRESS 0x68 //set rtc#include <LiquidCrystal.h> // initialize the library with the numbers of the interface pins/*|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||  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 ledPin1 =  2;		  // pin number for relay 1const int ledPin2 =  8;		  // pin number for relay 2int ledState1 = LOW;			 int ledState2 = LOW; long previousMillis1 = 0;		long previousMillis2 = 0;long interval1 = 30000;		  // interval at which to blink (milliseconds) for RELAY1long interval2 = 50000;		 // interval at which to blink (milliseconds) 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  |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||*/int blueramptime = 60;	// time for blue LEDs to dim on and off in minutesint whiteramptime = 180;  // time for white LEDs to dim on and off in minutesint bluemin = 0;		  // minimmum dimming value of blue LEDs, range of 0-255int bluemax = 255;		// maximum dimming value of blue LEDs, range of 0-255int whitemin = 0;		 // minimum dimming value of white LEDs, range of 0-255int whitemax = 255;	   // maximum dimming value of white LEDs, range of 0-255int photoperiod = 240;	// amount of time array is on at full power in minutesint ontime = 10;		  // time of day (hour, 24h clock) to begin photoperiod fade inint blue = 3;			  // blue LEDs connected to digital pin 3 (pwm)int white = 11;			// white LEDs connected to digital pin 11 (pwm)int bluepercent[11] = { 0, 1, 2, 5, 8 ,12, 18, 27, 44, 80, 255 };   // this line is needed if you are using meanwell ELN60-48Dint whitepercent[11] = { 0, 1, 2, 5, 8 ,12, 18, 27, 44, 80, 255 };   // these are the values in 10% increments//int bluepercent[11] = { 0, 26, 52, 78, 103, 128, 154, 180, 205, 230, 255 };   // this line is needed if you are using meanwell ELN60-48P//int whitepercent[11] = { 0, 26, 52, 78, 103, 128, 154, 180, 205, 230, 255 };   // these are the values in 10% increments// int pwm_one = 10;	   // extra pwm pin for future use// int pwm_one = 9;		// extra pwm pin for future useLiquidCrystal lcd(12, 13, 4, 5, 6, 7);   // typically 8, 9, 4, 5, 6, 7										 // have to change to free up more pwm pins/*|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||  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 numbersvoid setDateDs1307(byte second, // 0-59byte minute, // 0-59byte hour, // 1-23byte dayOfWeek, // 1-7byte dayOfMonth, // 1-28/29/30/31byte month, // 1-12byte 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 ds1307void 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 (ledState1 == LOW)	  ledState1 = HIGH;	else	  ledState1 = LOW;	digitalWrite(ledPin1, ledState1);  }}/*|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||  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 (ledState2 == LOW)	  ledState2 = HIGH;	else	  ledState2 = LOW;	digitalWrite(ledPin2, ledState2);  }}/*|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||  S E T U P  |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||*/void setup() {  pinMode(ledPin1, OUTPUT);	// set the digital pin as output:  pinMode(ledPin2, 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();  // 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.  second = 56;  minute = 57;  hour = 23;  dayOfWeek = 6;  // Sunday is 0  dayOfMonth = 26;  month = 2;  year = 11;  //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/10*9))) //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 + whiteramptime + 2*blueramptime + (blueramptime/10*9)) >= 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

Link to comment
  • 4 years later...

hello, i am very happy to found this, thanks a lot!

 

so i created a terrarium control system for dwarf chameleons with RGB leds and humidity and oled display and so on. If somebody interested in it, i am glad to share the source code and some HW list.

 

one issue i have with this getPhase func: today this function 0.25 phase...:( and i see that is 54% today.

my RTC displays 2016-03-01 (we write date in reversed order in hungary, so its march. 1. 2016 :))

 

i use the 'official' library for ds1302RTC (i know already this is a worst version of RTCs bcause it is not as accurate than the ds1307)

 

i had reef aquarium before but not in the moment.

my future plan is to create another version of this controlling system for nano aquarium too..cant live without reef, haha

 

Someone may have already posted something like this but just in case...

This is a function you can use in your Arduino sketches for calculating the current lunar phase. The function, GetPhase, takes three parameters: the year, the month and the day. Note that the year must be 4 digits. The function returns a float type containing the percentage of illumination (0 for new, .25 for crescent, .5 for quarter, .75 for gibbous and 1 for full). You can then set your lunar light PWM pin to 255 multiplied by the returned percentage to simulate current moon phase lunar lighting. In future I'd like to beef up this function to reflect percentages between phases instead of always returning 0, .25, .50, .75 or 1.

In order to use this function you will need a realtime clock module such as the DS1307 so that you can obtain the current date.

Following are the functions GetPhase and MyNormalize (which is called by GetPhase)

float GetPhase(int nYear, int nMonth, int nDay) // calculate the current phase of the moon
{
float phase;
double AG, IP;
long YY, MM, K1, K2, K3, JD;
YY = nYear - floor((12 - nMonth) / 10);
MM = nMonth + 9;
if (MM >= 12)
{
MM = MM - 12;
}
K1 = floor(365.25 * (YY + 4712));
K2 = floor(30.6 * MM + 0.5);
K3 = floor(floor((YY / 100) + 49) * 0.75) - 38;
JD = K1 + K2 + nDay + 59;
if (JD > 2299160)
{
JD = JD - K3;
}
IP = MyNormalize((JD - 2451550.1) / 29.530588853);
AG = IP*29.53;
phase = 0;
if ((AG < 1.84566) && (phase == 0))
{
phase = 0; //new; 0% illuminated
}
if ((AG < 5.53699) && (phase == 0))
{
phase = .25; //Waxing crescent; 25% illuminated
}
if ((AG < 9.922831) && (phase == 0))
{
phase = .50; //First quarter; 50% illuminated
}
if ((AG < 12.91963) && (phase == 0))
{
phase = .75; //Waxing gibbous; 75% illuminated
}
if ((AG < 16.61096) && (phase == 0))
{
phase = 1; //Full; 100% illuminated
}
if ((AG < 20.30228) && (phase == 0))
{
phase = .75; //Waning gibbous; 75% illuminated
}
if ((AG < 23.99361) && (phase == 0))
{
phase = .50; //Last quarter; 50% illuminated
}
if ((AG < 27.68493) && (phase == 0))
{
phase = .25; //Waning crescent; 25% illuminated
}
if (phase == 0)
{
phase = 0; //default to new; 0% illuminated
}
return phase;
}

double MyNormalize(double v)
{
v = v - floor(v);
if (v < 0)
v = v + 1;
return v;
}

Link to comment

Archived

This topic is now archived and is closed to further replies.

  • Recommended Discussions

×
×
  • Create New...