Moonphase on custom main
Posted: Sat Dec 31, 2011 7:31 am
Would it be possible to show what phase the moon(moonlights) is in on the main screen?
Community discussion about Reef Angel Controllers and reefing related subjects
https://forum.reefangel.com/
Code: Select all
ReefAngel.LCD.DrawText(0,255,70,82,"Moon%");
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.PWM.GetActinicValue(),COLOR_CORNFLOWERBLUE, 105, 109, 1); Code: Select all
byte MoonPhase()
{
int m,d,y;
int yy,mm;
long K1,K2,K3,J,V;
byte PWMvalue;
m = month();
d = day();
y = year();
yy = y-((12-m)/10);
mm = m+9;
if (mm>=12) mm -= 12;
K1 = 365.25*(yy+4712);
K2 = 30.6*mm+.5;
K3 = int(int((yy/100)+49)*.75)-38;
J = K1+K2+d+59-K3;
V = (J-2451550.1)/0.29530588853;
V -= int(V/100)*100;
V = abs(V-50);
PWMvalue = 4*abs(50-V); // 5.12=100% 4=~80%
//pinMode(lowATOPin,OUTPUT);
return (PWMvalue*100)/255;
}
Code: Select all
if (ReefAngel.PWM.GetActinicValue() ==0) ReefAngel.LCD.DrawText(0,255,12,12,"No Moon");
if else(ReefAngel.PWM.GetActinicValue() >=1 && ReefAngel.PWM.GetActinicValue() < 20) ReefAngel.LCD.DrawText(0,255,12,12,"New Moon");
if else(ReefAngel.PWM.GetActinicValue() >=20 && ReefAngel.PWM.GetActinicValue() < 35) ReefAngel.LCD.DrawText(0,255,12,12,"Cresent Moon");
if else(ReefAngel.PWM.GetActinicValue() >=35 && ReefAngel.PWM.GetActinicValue() < 45) ReefAngel.LCD.DrawText(0,255,12,12,"Half Moon");
if else(ReefAngel.PWM.GetActinicValue() >=45 && ReefAngel.PWM.GetActinicValue() < 60) ReefAngel.LCD.DrawText(0,255,12,12,"Gibbous Moon");
if else(ReefAngel.PWM.GetActinicValue() >=60 && ReefAngel.PWM.GetActinicValue() < 80) ReefAngel.LCD.DrawText(0,255,12,12,"Full Moon");
That's the hard part. I was having Dave create a custom main screen generator app, but that has kind of stalled out now. Maybe we can get him to get it working better (or maybe I should just work on it too).dpitalo wrote: I've got to learn how to place things on the custom main. I'll give it a shot in a few.
Hahah...yep, I'm all too familiar with that loop.Deckoz2302 wrote:Its pretty simple, just trial and error getting things perfectly placed ect ect. A generator would be nice, even if it wasn't a generator a program that you could preview what the code you wrote produces would be cool - right now its load > oops > fix position > load > hope its right > oops > fix > load > ok! haha
Code: Select all
#define SIMPLE_MENU
#define DisplayLEDPWM
#include <ReefAngel_Features.h>
#include <ReefAngel_Globals.h>
#include <ReefAngel_Wifi.h>
#include <Wire.h>
#include <OneWire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <ReefAngel_EEPROM.h>
#include <ReefAngel_NokiaLCD.h>
#include <ReefAngel_ATO.h>
#include <ReefAngel_Joystick.h>
#include <ReefAngel_LED.h>
#include <ReefAngel_TempSensor.h>
#include <ReefAngel_Relay.h>
#include <ReefAngel_PWM.h>
#include <ReefAngel_Timer.h>
#include <ReefAngel_Memory.h>
#include <ReefAngel.h>
#define AutoTopOff 1
#define Daylight 2
#define Relay3 3
#define Heater 4
#define Skimmer 5
#define MetalHalide 6
#define SeaSwirl 7
#define Return 8
#include <avr/pgmspace.h>
//Create the menu entries
prog_char menu1_label[] PROGMEM= "Chow Time";
prog_char menu2_label[] PROGMEM= "h2o Change";
prog_char menu3_label[] PROGMEM= "Force Halide On";
prog_char menu4_label[] PROGMEM= "ph Calibration";
prog_char menu5_label[] PROGMEM= "Set Date Time";
//Group menu entries together
PROGMEM const char *menu_items[] = {
menu1_label, menu2_label, menu3_label,
menu4_label, menu5_label
};
void MenuEntry1()
{
ReefAngel.FeedingModeStart();
}
void MenuEntry2()
{
ReefAngel.WaterChangeModeStart();
}
void MenuEntry3()
{
ReefAngel.Relay.On(MetalHalide);
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry4()
{
ReefAngel.SetupCalibratePH();
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry5()
{
ReefAngel.SetupDateTime();
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void DrawCustomMain()
{
byte x = 6;
byte y = 2;
byte t;
ReefAngel.LCD.DrawLargeText(COLOR_BLACK, COLOR_WHITE, 6, 3, "Dave's 40g Reef");
ReefAngel.LCD.DrawDate(6, 120);
ReefAngel.LCD.Clear(COLOR_BLACK, 1, 14, 131, 14);
//pingSerial();
x = 12;
y += MENU_START_ROW+1;
ReefAngel.LCD.DrawText(COLOR_BLUE, COLOR_WHITE, x, y+6, "Temp: ph");
char text[7];
ConvertNumToString(text, ReefAngel.Params.PH, 100);
ReefAngel.LCD.Clear(DefaultBGColor, x+16, y+65, x+65, y+16);
ReefAngel.LCD.DrawLargeText(PHColor, DefaultBGColor, x+75, y+18, text);
//pingSerial();
ConvertNumToString(text, ReefAngel.Params.Temp1, 10);
y += MENU_START_ROW*2;
x = 10;
ReefAngel.LCD.Clear(DefaultBGColor,x,y,x+(16*4),y+16);
//pingSerial();
ReefAngel.LCD.DrawHugeNumbers(T1TempColor, DefaultBGColor, x, y, text);
//pingSerial();
//Start Moon Phase Display
x += (16*4) + 8;
y += MENU_START_ROW+3;
ReefAngel.LCD.DrawText(COLOR_BLACK, COLOR_WHITE, 12, 55, "Moon Phase:");
if (ReefAngel.PWM.GetActinicValue() ==0) ReefAngel.LCD.DrawText(20,255,81,55,"Off");
else if(ReefAngel.PWM.GetActinicValue() >=1 && ReefAngel.PWM.GetActinicValue() < 20) ReefAngel.LCD.DrawText(20,255,81,55,"New");
else if(ReefAngel.PWM.GetActinicValue() >=20 && ReefAngel.PWM.GetActinicValue() < 35) ReefAngel.LCD.DrawText(20,255,81,55,"Cresent");
else if(ReefAngel.PWM.GetActinicValue() >=35 && ReefAngel.PWM.GetActinicValue() < 45) ReefAngel.LCD.DrawText(20,255,81,55,"Half");
else if(ReefAngel.PWM.GetActinicValue() >=45 && ReefAngel.PWM.GetActinicValue() < 60) ReefAngel.LCD.DrawText(20,255,81,55,"Gibbous");
else if(ReefAngel.PWM.GetActinicValue() >=60 && ReefAngel.PWM.GetActinicValue() < 80) ReefAngel.LCD.DrawText(20,255,81,55,"Full");
//End Display Moon Phase Display
byte TempRelay = ReefAngel.Relay.RelayData;
TempRelay &= ReefAngel.Relay.RelayMaskOff;
TempRelay |= ReefAngel.Relay.RelayMaskOn;
ReefAngel.LCD.DrawOutletBox(12, 102, TempRelay);
}
void DrawCustomGraph()
{
}
void setup()
{
ReefAngel.Init(); //Initialize controller
ReefAngel.InitMenu(pgm_read_word(&(menu_items[0])),SIZE(menu_items));
ReefAngel.Relay.On(Return); //Turn Return on at startup
ReefAngel.Relay.On(Skimmer); //Turn Skimmer on at startup
ReefAngel.Relay.On(SeaSwirl); //Turn SeaSwirl on at startup
}
void loop()
{
ReefAngel.StandardATO(AutoTopOff,10); //Setup AutoTopOff as Auto Top-Off function with 10s timeout
ReefAngel.MHLights(MetalHalide,10,0,22,30,15); //Daylight schedule 10:00am - 10:30pm with 15min cool down
ReefAngel.StandardHeater(Heater,788,792); // Setup Heater to turn on at 78.8F and off at 79.2F
if (hour()>=22 || hour()<=9)
{
ReefAngel.PWM.SetActinic(MoonPhase());
}
else
{
ReefAngel.PWM.SetActinic(0);
}
ReefAngel.ShowInterface(); //Draw the Standard Interface
}
Code: Select all
byte DayAge;
byte ThisPhase;
int JulianDate(int,int,int);
double MoonAge(int,int,int);
byte MoonState();Code: Select all
ReefAngel.LCD.DrawText(0,255,8,97,"Moon");
DayAge = MoonAge(day(), month(), year());
MoonState(DayAge);
char* ThisPhaseLabel[]={"New","Waxing Crescent","First Quarter","Waxing Gibbous","Full","Waning Gibbous","Last Quarter","Waning Crescent"};
ReefAngel.LCD.DrawText(COLOR_CORNFLOWERBLUE,255,35,97,ThisPhaseLabel[ThisPhase]);Code: Select all
int JulianDate(int d, int m, int y)
{
int mm, yy;
int k1, k2, k3;
int j;
yy = y - (int)((12 - m) / 10);
mm = m + 9;
if (mm >= 12)
{
mm = mm - 12;
}
k1 = (int)(365.25 * (yy + 4712));
k2 = (int)(30.6001 * mm + 0.5);
k3 = (int)((int)((yy / 100) + 49) * 0.75) - 38;
// 'j' for dates in Julian calendar:
j = k1 + k2 + d + 59;
if (j > 2299160)
{
// For Gregorian calendar:
j = j - k3; // 'j' is the Julian date at 12h UT (Universal Time)
}
return j;
}
double MoonAge(int d, int m, int y)
{
int j = JulianDate(d, m, y);
//Calculate the approximate phase of the moon
int ip = (j + 4.867) / 29.53059;
ip = ip - abs(ip);
//After several trials I've seen to add the following lines,
//which gave the result was not bad
if(ip < 0.5)
int ag = ip * 29.53059 + 29.53059 / 2;
else
int ag = ip * 29.53059 - 29.53059 / 2;
// Moon's age in days
byte ag = abs(ag) + 1;
return ag;
}
byte MoonState(byte D)
{
switch(D){
case 1:
0, 29;
ThisPhase = 0;
case 2:
1, 2, 3, 4, 5, 6;
ThisPhase = 1;
case 3:
7;
ThisPhase = 2;
case 4:
8, 9, 10, 11, 12, 13;
ThisPhase = 3;
case 5:
14;
ThisPhase = 4;
case 6:
15, 16, 17, 18, 19, 20, 21;
ThisPhase = 5;
case 7:
22;
ThisPhase = 6;
case 8:
23, 24, 25, 26, 27, 28;
ThisPhase = 7;
default:
return 0;
}
}Code: Select all
char* ThisPhaseLabel[]={"New","Waxing Crescent","First Quarter","Waxing Gibbous","Full","Waning Gibbous","Last Quarter","Waning Crescent"};
Code: Select all
ReefAngel.LCD.DrawText(COLOR_CORNFLOWERBLUE,255,35,97,ThisPhaseLabel[ThisPhase]);
Deckoz2302 wrote:Ok I rewrote it to get waning/waxing/first/last
add above setup()add to custom main()Code: Select all
byte DayAge; byte ThisPhase; int JulianDate(int,int,int); double MoonAge(int,int,int); byte MoonState();
add this after loopCode: Select all
ReefAngel.LCD.DrawText(0,255,8,97,"Moon"); DayAge = MoonAge(day(), month(), year()); MoonState(DayAge); if (ThisPhase == 0) ReefAngel.LCD.DrawText(COLOR_CORNFLOWERBLUE,255,35,97,"New"); else if (ThisPhase == 1) ReefAngel.LCD.DrawText(COLOR_CORNFLOWERBLUE,255,35,97,"Waxing Crescent"); else if (ThisPhase == 2) ReefAngel.LCD.DrawText(COLOR_CORNFLOWERBLUE,255,35,97,"First Quarter"); else if (ThisPhase == 3) ReefAngel.LCD.DrawText(COLOR_CORNFLOWERBLUE,255,35,97,"Waxing Gibbous"); else if (ThisPhase == 4) ReefAngel.LCD.DrawText(COLOR_CORNFLOWERBLUE,255,35,97,"Full"); else if (ThisPhase == 5) ReefAngel.LCD.DrawText(COLOR_CORNFLOWERBLUE,255,35,97,"Waning Gibbous"); else if (ThisPhase == 6) ReefAngel.LCD.DrawText(COLOR_CORNFLOWERBLUE,255,35,97,"Last Quarter"); else if (ThisPhase == 7) ReefAngel.LCD.DrawText(COLOR_CORNFLOWERBLUE,255,35,97,"Waning Crescent");
Code: Select all
int JulianDate(int d, int m, int y) { int mm, yy; int k1, k2, k3; int j; yy = y - (int)((12 - m) / 10); mm = m + 9; if (mm >= 12) { mm = mm - 12; } k1 = (int)(365.25 * (yy + 4712)); k2 = (int)(30.6001 * mm + 0.5); k3 = (int)((int)((yy / 100) + 49) * 0.75) - 38; // 'j' for dates in Julian calendar: j = k1 + k2 + d + 59; if (j > 2299160) { // For Gregorian calendar: j = j - k3; // 'j' is the Julian date at 12h UT (Universal Time) } return j; } double MoonAge(int d, int m, int y) { int j = JulianDate(d, m, y); //Calculate the approximate phase of the moon int ip = (j + 4.867) / 29.53059; ip = ip - abs(ip); //After several trials I've seen to add the following lines, //which gave the result was not bad if(ip < 0.5) int ag = ip * 29.53059 + 29.53059 / 2; else int ag = ip * 29.53059 - 29.53059 / 2; // Moon's age in days byte ag = abs(ag) + 1; return ag; } byte MoonState(byte D) { switch(D){ case 1: 0, 29; ThisPhase = 0; case 2: 1, 2, 3, 4, 5, 6; ThisPhase = 1; case 3: 7; ThisPhase = 2; case 4: 8, 9, 10, 11, 12, 13; ThisPhase = 3; case 5: 14; ThisPhase = 4; case 6: 15, 16, 17, 18, 19, 20, 21; ThisPhase = 5; case 7: 22; ThisPhase = 6; case 8: 23, 24, 25, 26, 27, 28; ThisPhase = 7; default: return 0; } }
Code: Select all
byte MoonState(byte D)
{
switch(D){
case 1:
0, 29;
ThisPhase = 0;
case 2:
1, 2, 3, 4, 5, 6;
ThisPhase = 1;
case 3:
7;
ThisPhase = 2;
case 4:
8, 9, 10, 11, 12, 13;
ThisPhase = 3;
case 5:
14;
ThisPhase = 4;
case 6:
15, 16, 17, 18, 19, 20, 21;
ThisPhase = 5;
case 7:
22;
ThisPhase = 6;
case 8:
23, 24, 25, 26, 27, 28;
ThisPhase = 7;
default:
return 0;
}
}
Code: Select all
// above setup()
void MoonState(byte D);
// after loop()
void MoonState(byte D)
{
switch(D){
default:
case 1:
//0, 29;
ThisPhase = 0;
break;
case 2:
//1, 2, 3, 4, 5, 6;
ThisPhase = 1;
break;
case 3:
//7;
ThisPhase = 2;
break;
case 4:
//8, 9, 10, 11, 12, 13;
ThisPhase = 3;
break;
case 5:
//14;
ThisPhase = 4;
break;
case 6:
//15, 16, 17, 18, 19, 20, 21;
ThisPhase = 5;
break;
case 7:
//22;
ThisPhase = 6;
break;
case 8:
//23, 24, 25, 26, 27, 28;
ThisPhase = 7;
break;
}
}
Code: Select all
// above setup()
void MoonState(byte D);
// after loop()
void MoonState(byte D)
{
switch(D){
default:
case 1:
if(D == 0 || D ==29);
ThisPhase = 0;
break;
case 2:
if(D >=1 && D <=6);
ThisPhase = 1;
break;
case 3:
if(D ==7);
ThisPhase = 2;
break;
case 4:
if( D >= 8 && D <=13);
ThisPhase = 3;
break;
case 5:
if (D ==14);
ThisPhase = 4;
break;
case 6:
if( D >= 15 && D<=21);
ThisPhase = 5;
break;
case 7:
if(D == 22)
ThisPhase = 6;
break;
case 8:
if( D>=23 && D <=28);
ThisPhase = 7;
break;
}
}Code: Select all
void MoonState(byte D)
{
switch(D){
default:
case 1:
if(D == 0 || D ==29); // could be true if D is 0 or 29, but D would most likely be 1 in this case
ThisPhase = 0;
break;
case 2:
if(D >=1 && D <=6); // always true since D is 2, empty statement gets called with ;
ThisPhase = 1;
break;
case 3:
if(D ==7); // never true, D is 3
ThisPhase = 2;
break;
case 4:
if( D >= 8 && D <=13); // never true, D is 4 and not in range
ThisPhase = 3;
break;
case 5:
if (D ==14); // never true, D is 5
ThisPhase = 4;
break;
case 6:
if( D >= 15 && D<=21); // never evaluate true, since D is 6
ThisPhase = 5;
break;
case 7:
// This statement will never be true and ThisPhase will never get set to 6 because D will never be 22
if(D == 22)
ThisPhase = 6;
break;
case 8:
if( D>=23 && D <=28); // This line will always evaluate false since 8 is outside the range
ThisPhase = 7;
break;
}
}
Code: Select all
// Moon Global Variables - Thanks Deckoz2302!
byte DayAge;
byte ThisPhase;
int JulianDate(int,int,int);
double MoonAge(int,int,int);
byte MoonState();
char* ThisPhaseLabel[]={
"New","Waxing Crescent","First Quarter","Waxing Gibbous","Full","Waning Gibbous","Last Quarter","Waning Crescent" };
void Moonstate(byte D);Code: Select all
// Display the % Moonlight
ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 64, 23,"MN:");
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.PWM.GetActinicValue(), COLOR_BLACK, 82, 23, 1);
ReefAngel.LCD.DrawText(DPColor,DefaultBGColor, 100, 23,"%");
//moonphase
ReefAngel.LCD.DrawText(T2TempColor,DefaultBGColor,64,43,"MP:");
ReefAngel.LCD.DrawSingleMonitor(MoonPhase(), COLOR_BLACK, 92, 43, 1);
// Display Moon Phase & State
DayAge = MoonAge(day(), month(), year());
MoonState(DayAge);
ReefAngel.LCD.DrawLargeText(COLOR_CORNFLOWERBLUE,255,5,93,ThisPhaseLabel[ThisPhase]);
Code: Select all
// Moon Calculators - Thanks Deckoz2302!
int JulianDate(int d, int m, int y)
{
int mm, yy;
int k1, k2, k3;
int j;
yy = y - (int)((12 - m) / 10);
mm = m + 9;
if (mm >= 12)
{
mm = mm - 12;
}
k1 = (int)(365.25 * (yy + 4712));
k2 = (int)(30.6001 * mm + 0.5);
k3 = (int)((int)((yy / 100) + 49) * 0.75) - 38;
// 'j' for dates in Julian calendar:
j = k1 + k2 + d + 59;
if (j > 2299160)
{
// For Gregorian calendar:
j = j - k3; // 'j' is the Julian date at 12h UT (Universal Time)
}
return j;
}
double MoonAge(int d, int m, int y)
{
int j = JulianDate(d, m, y);
//Calculate the approximate phase of the moon
int ip = (j + 4.867) / 29.53059;
ip = ip - abs(ip);
//After several trials I've seen to add the following lines,
//which gave the result was not bad
if(ip < 0.5)
int ag = ip * 29.53059 + 29.53059 / 2;
else
int ag = ip * 29.53059 - 29.53059 / 2;
// Moon's age in days
byte ag = abs(ag) + 1;
return ag;
}
void MoonState(byte D)
{
switch(D){
default:
case 1:
//0, 29;
ThisPhase = 0;
break;
case 2:
//1, 2, 3, 4, 5, 6;
ThisPhase = 1;
break;
case 3:
//7;
ThisPhase = 2;
break;
case 4:
//8, 9, 10, 11, 12, 13;
ThisPhase = 3;
break;
case 5:
//14;
ThisPhase = 4;
break;
case 6:
//15, 16, 17, 18, 19, 20, 21;
ThisPhase = 5;
break;
case 7:
//22;
ThisPhase = 6;
break;
case 8:
//23, 24, 25, 26, 27, 28;
ThisPhase = 7;
break;
}
}Code: Select all
// Globals Needed for MoonPhase from Deckoz2302
byte ThisPhase;
int MoonState(int,int,int);
char* ThisPhaseLabel[]={" New Moon","Waxing Crescent Moon"," First Quarter Moon","Waxing Gibbous Moon"," Full Moon",
"Waning Gibbous Moon"," Last Quarter Moon","Waning Crescent Moon"};Code: Select all
// Display Moon Phase during night and Sky Type During Day
if (ReefAngel.PWM.GetChannelValue(0) > 0) //If Moonlights are active
{
ThisPhase = MoonState(day(), month(), year());
ReefAngel.LCD.DrawText(COLOR_CORNFLOWERBLUE,255,6,94,ThisPhaseLabel[ThisPhase]);
}
else
ReefAngel.LCD.DrawText(COLOR_CORNFLOWERBLUE,255,6,94," Clear Skies");Code: Select all
// Moon Phase Calculator - courtesy of www.voidware.com/moon_phase.com
int MoonState(int d, int m, int y)
{
/*
Calculates the moon phase (0-7), accurate to 1 segment.
0 = New Moon
1 = Waxing Crescent Moon
2 = First Quarter Moon
3 = Waxing Gibbous Moon
4 = Full Moon
5 = Waning Gibbous Moon
6 = Last Quarter Moon
7 = Waning Crescent Moon
*/
int c, e, fd;
double jd;
int b;
if (m < 3)
{
y--;
m += 12;
}
++m;
c = 365.25 * y;
e = 30.6 * m;
jd = c + e + d - 694041.09; // jd is total days elapsed
jd /= 29.53; // divide by the moon cycle (29.53 days)
fd = jd; // int(jd) -> fd, take integer part of jd
jd -= fd; // subtract integer part to leave fractional part of original jd
b = jd * 8 + .5; // scale fraction from 0-8 and round by adding 0.5
b = b & 7; // 0 and 8 are the same so turn 8 into 0
return b;
}Code: Select all
char* MoonPhaseLabel()
{
int m,d,y;
int yy,mm;
long K1,K2,K3,J;
double V;
byte PWMvalue;
m = month();
d = day();
y = year();
yy = y-((12-m)/10);
mm = m+9;
if (mm>=12) mm -= 12;
K1 = 365.25*(yy+4712);
K2 = 30.6*mm+.5;
K3 = int(int((yy/100)+49)*.75)-38;
J = K1+K2+d+59-K3;
V = (J-2451550.1)/29.530588853;
V -= floor(V);
if (V<0) V++;
if (V<0.0625) return "New Moon";
else if (V<0.1875) return "Waxing Crescent";
else if (V<0.3125) return "First Quarter";
else if (V<0.4375) return "Waxing Gibbous";
else if (V<0.5625) return "Fuul Moon";
else if (V<0.6875) return "Waning Gibbous";
else if (V<0.8125) return "Last Quarter";
else if (V<0.9375) return "Waning Crescent";
else return "New Moon";
}
Code: Select all
ReefAngel.LCD.DrawText(0,255,10,10,MoonPhaseLabel());