here are the things includedVortech mode displayed on main w/color of modeAll Measured ParametersVortech goto Nutrient transport for 30 min after feedVortech goto night when moonlights come onFull use of the PWM module - with my Seasons() function for a true sunphaseClouds, lightningMoonphase displayed on main - waning, waxing, quarter, full

Things I still need to code-SingleATO-Use of Floatvalve for flood control in overflow(im running 350gph through a 200gph overflow haha scary)-Custom Menu(Feed, Waterchange, Force Thunderstorm, Clear Overflow error, couple other things I havent thought of yet)-Sending force thunderstorm to pwm -couple other things I havent thought of yet

// This is just how we are going to reference the PWM expansion ports within the code.// You can change the labels if you would like, just as long as they are changed all throughout the code too.#define LEDPWM0 0#define LEDPWM1 1#define LEDPWM2 2#define LEDPWM3 3#define LEDPWM4 4#define LEDPWM5 5

// Initial values to all 6 channels at startup. They will always be 0.byte PWMChannel[]={ 0,0,0,0,0,0};//End of PWM Expansion Code Header//*********************************************************************************************************************************

//*********************************************************************************************************************************//Globals integerslong calcSec(long,long);long calcTime(long,long);short Ndays; //Returns the number of day in the year//*********************************************************************************************************************************

// Frequency in days based on the day of the month - number 2 means every 2 days, for example (day 2,4,6 etc) // For testing purposes, you can use 1 and cause the cloud to occur everyday#define Clouds_Every_X_Days 1

// Percentage chance of a cloud happening today // For testing purposes, you can use 100 and cause the cloud to have 100% chance of happening#define Cloud_Chance_per_Day 100

// Minimum number of minutes for cloud duration. Don't use max duration of less than 6#define Min_Cloud_Duration 6

// Maximum number of minutes for the cloud duration. Don't use max duration of more than 255#define Max_Cloud_Duration 20

// Minimum number of clouds that can happen per day#define Min_Clouds_per_Day 2

// Maximum number of clouds that can happen per day#define Max_Clouds_per_Day 5

// Only start the cloud effect after this setting // In this example, start could after 11:30am#define Start_Cloud_After NumMins(11,00)

// Always end the cloud effect before this setting // In this example, end could before 8:00pm#define End_Cloud_Before NumMins(17,00)

// Percentage chance of a lightning happen for every cloud // For testing purposes, you can use 100 and cause the lightning to have 100% chance of happening#define Lightning_Change_per_Cloud 100

// Channels used by the actinic LEDs on the PWM Expansion module // These channels will not be dimmed when the cloud effect is triggered // Number is a binary form. B001100 means channel 2 and 3 are used for actinics#define Actinic_Channels B001110

// Channels used by the daylight LEDs on the PWM Expansion module // These channels will be used for the spike when lightning effect is triggered // Number is a binary form. B000011 means channel 0 and 1 are used for daylights#define Daylight_Channels B000001

// Note: Make sure to choose correct values that will work within your PWMSLope settings. // For example, in our case, we could have a max of 5 clouds per day and they could last for 50 minutes. // Which could mean 250 minutes of clouds. We need to make sure the PWMSlope can accomodate 250 minutes of effects or unforseen // results could happen. // Also, make sure that you can fit double those minutes between Start_Cloud_After and End_Cloud_Before. // In our example, we have 510 minutes between Start_Cloud_After and End_Cloud_Before, so double the 250 minutes (or 500 minutes) can //fit in that 510 minutes window. // It's a tight fit, but it did.

//#define printdebug // Uncomment this for debug print on Serial Monitor window#define forcecloudcalculation // Uncomment this to force the cloud calculation to happen in the boot process.

#ifdef forcecloudcalculation if (cloudchance==255)#else if (hour()==0 && minute()==0 && second()==1 && cloudchance==255) #endif { //Pick a random number between 0 and 99 cloudchance=random(100); // if picked number is greater than Cloud_Chance_per_Day, we will not have clouds today if (cloudchance>Cloud_Chance_per_Day) cloudchance=0; // Check if today is day for clouds. if ((day()%Clouds_Every_X_Days)!=0) cloudchance=0; // If we have cloud today if (cloudchance) { // pick a random number for number of clouds between Min_Clouds_per_Day and Max_Clouds_per_Day numclouds=random(Min_Clouds_per_Day,Max_Clouds_per_Day); // pick the time that the first cloud will start // the range is calculated between Start_Cloud_After and the even distribuition of clouds on this day. cloudstart=random(Start_Cloud_After,Start_Cloud_After+((End_Cloud_Before-Start_Cloud_After)/(numclouds*2)));

// pick a random number for the cloud duration of first cloud. cloudduration=random(Min_Cloud_Duration,Max_Cloud_Duration); //Pick a random number between 0 and 99 lightningchance=random(100); // if picked number is greater than Lightning_Change_per_Cloud, we will not have lightning today if (lightningchance>Lightning_Change_per_Cloud) lightningchance=0; } } // Now that we have all the parameters for the cloud, let's create the effect

if (cloudchance) { //is it time for cloud yet? if (NumMins(hour(),minute())>=cloudstart && NumMins(hour(),minute())<(cloudstart+cloudduration)) { // let's go through all channels to pick which ones will be dimmed for (int a=0;a<6;a++) { if (bitRead(Actinic_Channels,a)==0) { // this will slope down the channel from the current PWM to 0 within 3minutes. // then it will stay at 0 for the duration of the cycle // and finally slope up from 0 to PWM value within 3 minutes // it is basically an inversed slope ChannelValue[a]=ReversePWMSlope(cloudstart,cloudstart+cloudduration,ChannelValue[a],0,180); } } if (lightningchance && (NumMins(hour(),minute())==(cloudstart+(cloudduration/2))) && second()<5) { for (int b=0;b<6;b++) { if (bitRead(Daylight_Channels,b)==1) { if (random(100)<20) lightningstatus=1; else lightningstatus=0; if (lightningstatus) ChannelValue[b]=100; else ChannelValue[b]=0; //delay(10); } else { ChannelValue[b]=20; } } } }

if (NumMins(hour(),minute())>(cloudstart+cloudduration)) { cloudindex++; if (cloudindex < numclouds) { cloudstart=random(Start_Cloud_After+(((End_Cloud_Before-Start_Cloud_After)/(numclouds*2))*cloudindex*2),(Start_Cloud_After+(((End_Cloud_Before-Start_Cloud_After)/(numclouds*2))*cloudindex*2))+((End_Cloud_Before-Start_Cloud_After)/(numclouds*2))); // pick a random number for the cloud duration of first cloud. cloudduration=random(Min_Cloud_Duration,Max_Cloud_Duration); //Pick a random number between 0 and 99 lightningchance=random(100); // if picked number is greater than Lightning_Change_per_Cloud, we will not have lightning today if (lightningchance>Lightning_Change_per_Cloud) lightningchance=0; } } }}//End Cloud Function//*********************************************************************************************************************************

//rise and set times set by hour and minute. there are 4 seasons however there are 8 highs & lows in rise and set throughout the year //first spot is second half of winter starting jan 1st int risehour[8]= { 7,7,7,6,6,5,6,6 }; int riseminute[8]={ 00,30,00,30,00,30,00,30 }; int sethour[8] = { 17,18,18,19,19,19,19,18 }; int setminute[8] = { 30,00,30,00,00,30,00,00 };

//calculate new sunrise/set difference from array value //here we take the difference in day and get a difference in seconds per day. So if the time difference is 30 minutes from the last e //uation we divide that by the start day of season subtracted by the end day of season to get the number of days in the season //example: 30 minutes/(day 45 – day 0) = 30/45 = 0.66666 //0.66666 is the difference of minutes each day throughout the season for sunrise risediffperday = iDiffrise/(seasons[ssnpt]-seasons[ssnp]); totalrise = risediffperday*(Ndays - seasons[ssnp]); setdiffperday = iDiffset/(seasons[ssnpt]-seasons[ssnp]); totalset = setdiffperday*(Ndays - seasons[ssnp]);

long calcTime(long seconds1, long seconds2){ long timediff=abs(seconds1-seconds2); return timediff;}

void DayNumber(unsigned int y, unsigned int m, unsigned int d){ int days[]={ 0,31,59,90,120,151,181,212,243,273,304,334 }; // Number of days at the beginning of the month in a not leap year. //Start to calculate the number of day if (m==1 || m==2){ Ndays = days[(m-1)]+d; //for any type of year, it calculate the number of days for January or february } // Now, try to calculate for the other months else if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0){ //those are the conditions to have a leap year Ndays = days[(m-1)]+d+1; // if leap year, calculate in the same way but increasing one day } else { //if not a leap year, calculate in the normal way, such as January or February Ndays = days[(m-1)]+d; }}

I realized I forgot some of the code when I posted here originally - Changes are

-Added ability to see pwm % for all channels -During Day PWM %'s are shown on screen -If Cloud, no pwm % is shown, Time of cloud and duration is shown, if lightning label of "cloud" changes to "storm" -Night time, Moon cycle & pwm % is shown-Still working on figuring out how to have more then one Vortech mode change in code & being able to define global variable to show current mode on main screen, changing modes Isn't the problem - its keeping the global defined-Added the ability for a user to Define a single Rise and Set hour in PWM expansion pde, code does the rest - may be adding the ability for a left to right delayed rise for people that have set up there LED fixture to rise on one side first

hmm I think of stuff daily to add to this so updates are always coming

// This is just how we are going to reference the PWM expansion ports within the code.// You can change the labels if you would like, just as long as they are changed all throughout the code too.#define LEDPWM0 0#define LEDPWM1 1#define LEDPWM2 2#define LEDPWM3 3#define LEDPWM4 4#define LEDPWM5 5

// Initial values to all 6 channels at startup. They will always be 0.byte PWMChannel[]={ 0,0,0,0,0,0};//End of PWM Expansion Code Header//*********************************************************************************************************************************

// Frequency in days based on the day of the month - number 2 means every 2 days, for example (day 2,4,6 etc) // For testing purposes, you can use 1 and cause the cloud to occur everyday#define Clouds_Every_X_Days 3

// Percentage chance of a cloud happening today // For testing purposes, you can use 100 and cause the cloud to have 100% chance of happening#define Cloud_Chance_per_Day 30

// Minimum number of minutes for cloud duration. Don't use max duration of less than 6#define Min_Cloud_Duration 6

// Maximum number of minutes for the cloud duration. Don't use max duration of more than 255#define Max_Cloud_Duration 30

// Minimum number of clouds that can happen per day#define Min_Clouds_per_Day 2

// Maximum number of clouds that can happen per day#define Max_Clouds_per_Day 5

// Only start the cloud effect after this setting // In this example, start could after 11:30am#define Start_Cloud_After NumMins(11,00)

// Always end the cloud effect before this setting // In this example, end could before 8:00pm#define End_Cloud_Before NumMins(15,00)

// Percentage chance of a lightning happen for every cloud // For testing purposes, you can use 100 and cause the lightning to have 100% chance of happening#define Lightning_Change_per_Cloud 40

// Channels used by the actinic LEDs on the PWM Expansion module // These channels will not be dimmed when the cloud effect is triggered // Number is a binary form. B001100 means channel 2 and 3 are used for actinics#define Actinic_Channels B011101

// Channels used by the daylight LEDs on the PWM Expansion module // These channels will be used for the spike when lightning effect is triggered // Number is a binary form. B000011 means channel 0 and 1 are used for daylights#define Daylight_Channels B000010

// Note: Make sure to choose correct values that will work within your PWMSLope settings. // For example, in our case, we could have a max of 5 clouds per day and they could last for 50 minutes. // Which could mean 250 minutes of clouds. We need to make sure the PWMSlope can accomodate 250 minutes of effects or unforseen // results could happen. // Also, make sure that you can fit double those minutes between Start_Cloud_After and End_Cloud_Before. // In our example, we have 510 minutes between Start_Cloud_After and End_Cloud_Before, so double the 250 minutes (or 500 minutes) can //fit in that 510 minutes window. // It's a tight fit, but it did.

//#define printdebug // Uncomment this for debug print on Serial Monitor window#define forcecloudcalculation // Uncomment this to force the cloud calculation to happen in the boot process.

#ifdef forcecloudcalculation if (cloudchance==255)#else if (hour()==0 && minute()==0 && second()==1 && cloudchance==255) #endif { //Pick a random number between 0 and 99 cloudchance=random(100); // if picked number is greater than Cloud_Chance_per_Day, we will not have clouds today if (cloudchance>Cloud_Chance_per_Day) cloudchance=0; // Check if today is day for clouds. if ((day()%Clouds_Every_X_Days)!=0) cloudchance=0; // If we have cloud today if (cloudchance) { // pick a random number for number of clouds between Min_Clouds_per_Day and Max_Clouds_per_Day numclouds=random(Min_Clouds_per_Day,Max_Clouds_per_Day); // pick the time that the first cloud will start // the range is calculated between Start_Cloud_After and the even distribuition of clouds on this day. cloudstart=random(Start_Cloud_After,Start_Cloud_After+((End_Cloud_Before-Start_Cloud_After)/(numclouds*2)));

// pick a random number for the cloud duration of first cloud. cloudduration=random(Min_Cloud_Duration,Max_Cloud_Duration); //Pick a random number between 0 and 99 lightningchance=random(100); // if picked number is greater than Lightning_Change_per_Cloud, we will not have lightning today if (lightningchance>Lightning_Change_per_Cloud) lightningchance=0; } } // Now that we have all the parameters for the cloud, let's create the effect

if (cloudchance) { //is it time for cloud yet? if (NumMins(hour(),minute())>=cloudstart && NumMins(hour(),minute())<(cloudstart+cloudduration)) { // let's go through all channels to pick which ones will be dimmed for (int a=0;a<6;a++) { if (bitRead(Actinic_Channels,a)==0) { // this will slope down the channel from the current PWM to 0 within 3minutes. // then it will stay at 0 for the duration of the cycle // and finally slope up from 0 to PWM value within 3 minutes // it is basically an inversed slope ChannelValue[a]=ReversePWMSlope(cloudstart,cloudstart+cloudduration,ChannelValue[a],0,180); } } if (lightningchance && (NumMins(hour(),minute())==(cloudstart+(cloudduration/2))) && second()<5) { for (int b=0;b<6;b++) { if (bitRead(Daylight_Channels,b)==1) { if (random(100)<20) lightningstatus=1; else lightningstatus=0; if (lightningstatus) ChannelValue[b]=100; else ChannelValue[b]=0; //delay(10); } else { ChannelValue[b]=20; } } } }

if (NumMins(hour(),minute())>(cloudstart+cloudduration)) { cloudindex++; if (cloudindex < numclouds) { cloudstart=random(Start_Cloud_After+(((End_Cloud_Before-Start_Cloud_After)/(numclouds*2))*cloudindex*2),(Start_Cloud_After+(((End_Cloud_Before-Start_Cloud_After)/(numclouds*2))*cloudindex*2))+((End_Cloud_Before-Start_Cloud_After)/(numclouds*2))); // pick a random number for the cloud duration of first cloud. cloudduration=random(Min_Cloud_Duration,Max_Cloud_Duration); //Pick a random number between 0 and 99 lightningchance=random(100); // if picked number is greater than Lightning_Change_per_Cloud, we will not have lightning today if (lightningchance>Lightning_Change_per_Cloud) lightningchance=0; } } }}//End Cloud Function//*********************************************************************************************************************************

//rise and set times set by hour and minute. there are 4 seasons however there are 8 highs & lows in rise and set throughout the year //first spot is second half of winter starting jan 1st - DO NOT CHANGE int risehour[8]= {UserRiseHour+1,UserRiseHour+1,UserRiseHour+1,UserRiseHour,UserRiseHour,UserRiseHour-1,UserRiseHour,UserRiseHour};/*{ 7,7,7,6,6,5,6,6 };*/ int riseminute[8]={ 00,30,00,30,00,30,00,30 }; int sethour[8] = {UserSetHour-2,UserSetHour-1,UserSetHour-1,UserSetHour,UserSetHour,UserSetHour,UserSetHour,UserSetHour-1};/*{ 17,18,18,19,19,19,19,18 };*/ int setminute[8] = { 30,00,30,00,00,30,00,00 };

//These are the off set times, standard rtime and stime are for Royal Blues & Blues // DO NOT CHANGE the operators in these equations ie +- // The number is in seconds (1200) change this number to change the offset for each color wrtime = rtime + 1200;//w r/stime is for Whites - shorter time span then blues wstime = stime - 1200; vrtime = rtime - 1200;//v r/stime is for Violets - Longer time then blues vstime = stime + 1200;

//This is the PWM Slope for each channel, each channel pulls an array value from above(hour,minute) to use, how you set them is up to you. //Just always use a Rise hour in a Rise spot, always a set hour in a set spot ect ect ChannelValue[LEDPWM0]=PWMSlope(vSunrise[1],vSunrise[2],vSunset[1],vSunset[2],0,100,1,ChannelValue[LEDPWM0]); ChannelValue[LEDPWM1]=PWMSlope(whSunrise[1],whSunrise[2],whSunset[1],whSunset[2],0,100,1,ChannelValue[LEDPWM1]); ChannelValue[LEDPWM2]=PWMSlope(Sunrise[1],Sunrise[2],Sunset[1],Sunset[2],0,100,1,ChannelValue[LEDPWM2]); ChannelValue[LEDPWM3]=PWMSlope(Sunrise[1],Sunrise[2],whSunset[1],whSunset[2],0,100,1,ChannelValue[LEDPWM3]);

long calcTime(long seconds1, long seconds2){ long timediff=abs(seconds1-seconds2); return timediff;}

void DayNumber(unsigned int y, unsigned int m, unsigned int d){ int days[]={ 0,31,59,90,120,151,181,212,243,273,304,334 }; // Number of days at the beginning of the month in a not leap year. //Start to calculate the number of day if (m==1 || m==2){ Ndays = days[(m-1)]+d; //for any type of year, it calculate the number of days for January or february } // Now, try to calculate for the other months else if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0){ //those are the conditions to have a leap year Ndays = days[(m-1)]+d+1; // if leap year, calculate in the same way but increasing one day } else { //if not a leap year, calculate in the normal way, such as January or February Ndays = days[(m-1)]+d; }}

That is the "official" fully commented and documented features file. This file gets updated with every generate with RAGen. Most of the features (and descriptions) are inside RAGen, but some of the newer ones are not (RF, Salinity, etc).

Read through that file and if you still have problems, just post more questions.

These are defined in my features file - sorry for the confusion Ill post my features file tonightAlso - updated pde will come tonight when I get home, I've fix a couple errorness loops in the pde preventing things from. displaying properly