A Few more Questions

Related to the development libraries, released by Curt Binder
cain
Posts: 83
Joined: Tue Aug 02, 2011 10:59 am

Re: A Few more Questions

Post by cain »

features file, i got this from the library folder.
ReefAngel_Features.h
(1 KiB) Downloaded 457 times
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: A Few more Questions

Post by rimai »

Use this instead:

Code: Select all

#ifndef __REEFANGEL_FEATURES_H__
#define __REEFANGEL_FEATURES_H__


#define DisplayLEDPWM
#define wifi
#define SIMPLE_MENU


#endif  // __REEFANGEL_FEATURES_H__
Roberto.
cain
Posts: 83
Joined: Tue Aug 02, 2011 10:59 am

Re: A Few more Questions

Post by cain »

rimai wrote:Use this instead:

Code: Select all

#ifndef __REEFANGEL_FEATURES_H__
#define __REEFANGEL_FEATURES_H__


#define DisplayLEDPWM
#define wifi
#define SIMPLE_MENU


#endif  // __REEFANGEL_FEATURES_H__
i put this in the library and save it.

however, still getting "sketch too big" when i went to verify.
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: A Few more Questions

Post by rimai »

Make sure to replace everything in the ReefAngel_Feature.h file with that.
Roberto.
cain
Posts: 83
Joined: Tue Aug 02, 2011 10:59 am

Re: A Few more Questions

Post by cain »

OK, verified it and no more errors.
lemme try it for a day or 2, see how it works.
TY.
cain
Posts: 83
Joined: Tue Aug 02, 2011 10:59 am

Re: A Few more Questions

Post by cain »

i have this on my controller display
C00:00 L00:00 19
what does this mean?
TY.
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: A Few more Questions

Post by rimai »

it means you won't have clouds or lightning today.
Every midnight, the RA will check whether you have cloud or not.
And for every cloud you have, there's a chance of lightning.
You can change all the parameters on the defines within your code.
Roberto.
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: A Few more Questions

Post by rimai »

rimai wrote:You could, but it would be sharing one of the channels.
What time do you want the moonlight on?
Roberto.
cain
Posts: 83
Joined: Tue Aug 02, 2011 10:59 am

Re: A Few more Questions

Post by cain »

rimai wrote:
rimai wrote:You could, but it would be sharing one of the channels.
What time do you want the moonlight on?
simulate lunar cycle?
i dont know what time, can you give an advise?
my lights are from 12pm-930pm.
cain
Posts: 83
Joined: Tue Aug 02, 2011 10:59 am

Re: A Few more Questions

Post by cain »

rimai wrote:it means you won't have clouds or lightning today.
Every midnight, the RA will check whether you have cloud or not.
And for every cloud you have, there's a chance of lightning.
You can change all the parameters on the defines within your code.
BTW, i've already tested this for 2 days, everything is working perfectly. although i didnt see any lihgtning yet since i put my chance of lightning at 30%.
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: A Few more Questions

Post by rimai »

I want to see a video of the lightining on your tank :)
Choose the time frame for moonlights. For your reference, I turn mine on at 9pm and off at 9am, but some people do opposite of lighting cycle.
Don't forget we are sharing the channel, so the moonlights will actually be on whenever you have your actinics on too.
Roberto.
cain
Posts: 83
Joined: Tue Aug 02, 2011 10:59 am

Re: A Few more Questions

Post by cain »

when lightning is in forecast, i'll get a video.

if we are sharing with the actinic, wouldnt the actinic turn on if the moonlights are on?
we can simulate the lunar cycle intensity right?
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: A Few more Questions

Post by rimai »

It will not turn your LEDs on, because we are going to kill the relay that powers the drivers and change the PWM output to moon phase intensity.
Roberto.
cain
Posts: 83
Joined: Tue Aug 02, 2011 10:59 am

Re: A Few more Questions

Post by cain »

rimai wrote:It will not turn your LEDs on, because we are going to kill the relay that powers the drivers and change the PWM output to moon phase intensity.
ok. got it. relay is already on/off, it turns on at 11:58am and turns off at 9:32pm. so no problem there.
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: A Few more Questions

Post by rimai »

Try this:

Code: Select all

// Autogenerated file by RAGen (v1.0.4.92), (09/01/2011 21:51)
// RA_090111_2151.pde
//
// This version designed for v0.8.5 Beta 12 or later

/* The following features are enabled for this PDE File: 
#define DisplayImages
#define WavemakerSetup
#define DateTimeSetup
#define VersionMenu
#define ATOSetup
#define MetalHalideSetup
#define DirectTempSensor
#define DisplayLEDPWM
#define SingleATOSetup
#define StandardLightSetup
*/


#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>

byte ActinicPWMValue=0;
byte DaylightPWMValue=0;

void setup()
{
randomSeed(analogRead(0));

ReefAngel.Init(); //Initialize controller
  ReefAngel.PHMin=526;// 526=PH7.0
  ReefAngel.PHMax=813;// 813=PH10.0
  ReefAngel.FeedingModePorts = B10000000;
  ReefAngel.OverheatShutoffPorts = B01000000;

  // Ports that are always on
  ReefAngel.Relay.On(Port8);
  ReefAngel.Timer[1].SetInterval(random(10,150));
  ReefAngel.Timer[1].Start();
  ReefAngel.Relay.On(Port4);
}

void loop()
{
  ReefAngel.ShowInterface();

  // Specific functions
  ReefAngel.StandardATO(Port1);
  ReefAngel.StandardLights(Port2);
  ReefAngel.MHLights(Port3);
  if ( ReefAngel.Timer[1].IsTriggered() )
{

  ReefAngel.Timer[1].SetInterval(random(10,150));
  ReefAngel.Timer[1].Start();
  ReefAngel.Relay.Toggle(Port4);
  ReefAngel.Relay.Toggle(Port5);

}

  ReefAngel.StandardFan(Port6);
  ReefAngel.StandardHeater(Port7);

  // Have PWM on from 12p to 9:30p, with gradual 150 minute ramp up and 180 down for actinic, and 120 minute ramp up and down for daylight starting at given times
  // From 12pm to 1pm, actinic will slowly ramp up from 10% to 100%, and from 12:30p to 2p, daylight will slowly ramp up from 10% to 50%
  // From 8:30p to 9:30p, actinic will slowly ramp down from 100% to 10%, and from 7p to 8:30p daylight will slowly ramp down from 50% to 10%
  
 if (hour()<16)
  {
  	if  (hour()<12)
  		ActinicPWMValue=Moonphase();
  	else
    	ActinicPWMValue=PWMSlope(12,0,21,30,10,100,150,ReefAngel.PWM.GetActinicValue());
  }
  else
  {
  	if  (hour()<21)
    	ActinicPWMValue=PWMSlope(12,0,21,30,10,100,180,ReefAngel.PWM.GetActinicValue());
  	else if (hour()=21 && minute()<=30)
    {
    	ActinicPWMValue=PWMSlope(12,0,21,30,10,100,180,ReefAngel.PWM.GetActinicValue());
    }
    else
    	ActinicPWMValue=Moonphase();
    	
  } 
  DaylightPWMValue=PWMSlope(12,30,20,30,10,50,120,ReefAngel.PWM.GetDaylightValue());
  CheckCloud();
  ReefAngel.PWM.SetActinic(ActinicPWMValue);
  ReefAngel.PWM.SetDaylight(DaylightPWMValue);
}

//*********************************************************************************************************************************
// Random Cloud/Thunderstorm effects function
void CheckCloud()
{

  // ------------------------------------------------------------
  // Change the values below to customize your cloud/storm effect

  // 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 8

  // 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 1

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

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

  // Always end the cloud effect before this setting
  // In this example, end could before 6:00pm
#define End_Cloud_Before NumMins(18,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 10

  // 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 resul 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. 


  // Change the values above to customize your cloud/storm effect
  // ------------------------------------------------------------
  // Do not change anything below here

  static byte cloudchance=255;
  static byte cloudduration=0;
  static int cloudstart=0;
  static byte numclouds=0;
  static byte lightningchance=0;
  static byte cloudindex=0;
  static byte lightningstatus=0;
  static int LastNumMins=0;
  // Every day at midnight, we check for chance of cloud happening today
  if (hour()==0 && minute()==0 && second()==0) cloudchance=255;

#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))
    {
      DaylightPWMValue=ReversePWMSlope(cloudstart,cloudstart+cloudduration,DaylightPWMValue,0,180);
      if (lightningchance && (NumMins(hour(),minute())==(cloudstart+(cloudduration/2))) && second()<5) 
      {
        if (random(100)<20) lightningstatus=1; 
        else lightningstatus=0;
        if (lightningstatus)
        {
          DaylightPWMValue=100; 
          ActinicPWMValue=100;
        }
        else 
        {
          DaylightPWMValue=0;
          ActinicPWMValue=0;
        }
        delay(1);
      }
    }
    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;
      }
    }
  }
  
  if (LastNumMins!=NumMins(hour(),minute()))
  {
    LastNumMins=NumMins(hour(),minute());
    ReefAngel.LCD.Clear(255,0,120,132,132);
    ReefAngel.LCD.DrawText(0,255,5,120,"C");
    ReefAngel.LCD.DrawText(0,255,11,120,"00:00");
    ReefAngel.LCD.DrawText(0,255,45,120,"L");
    ReefAngel.LCD.DrawText(0,255,51,120,"00:00");
    if (cloudchance && (NumMins(hour(),minute())<cloudstart))
    {
      int x=0;
      if ((cloudstart/60)>=10) x=11; else x=17;
      ReefAngel.LCD.DrawText(0,255,x,120,(cloudstart/60));
      if ((cloudstart%60)>=10) x=29; else x=35;
      ReefAngel.LCD.DrawText(0,255,x,120,(cloudstart%60));
    }
    ReefAngel.LCD.DrawText(0,255,90,120,cloudduration);
    if (lightningchance) 
    {
      int x=0;
      if (((cloudstart+(cloudduration/2))/60)>=10) x=51; else x=57;
      ReefAngel.LCD.DrawText(0,255,x,120,((cloudstart+(cloudduration/2))/60));
      if (((cloudstart+(cloudduration/2))%60)>=10) x=69; else x=75;
      ReefAngel.LCD.DrawText(0,255,x,120,((cloudstart+(cloudduration/2))%60));
    }
  }   
}

byte ReversePWMSlope(long cstart,long cend,byte PWMStart,byte PWMEnd, byte clength)
{
  long n=elapsedSecsToday(now());
  cstart*=60;
  cend*=60;
  if (n<cstart) return PWMStart;
  if (n>=cstart && n<=(cstart+clength)) return map(n,cstart,cstart+clength,PWMStart,PWMEnd);
  if (n>(cstart+clength) && n<(cend-clength)) return PWMEnd;
  if (n>=(cend-clength) && n<=cend) return map(n,cend-clength,cend,PWMEnd,PWMStart);
  if (n>cend) return PWMStart;
}
    
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;
}    
Roberto.
cain
Posts: 83
Joined: Tue Aug 02, 2011 10:59 am

Re: A Few more Questions

Post by cain »

ok, thanks. will need to go to homedepot tomorrow to splice this thing. :)
i'll splice it together with my actinic led's right? but how come in the code it says lowATOPin?
i'm not using my ATO molex.


Roberto, this varies in intensity like the moon right?
TY.
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: A Few more Questions

Post by rimai »

The lowATOPin is commented out. It's reminescent of previous code.
Yes, it will vary according to moon phase and you should splice with the Actinic channel.
Roberto.
cain
Posts: 83
Joined: Tue Aug 02, 2011 10:59 am

Re: A Few more Questions

Post by cain »

ok, done splicing today, when i verified the code it says "moonphase was not declared in this scope".

if (hour()<16)
{
if (hour()<12)
ActinicPWMValue=Moonphase();
else
ActinicPWMValue=PWMSlope(12,0,21,30,10,100,150,ReefAngel.PWM.GetActinicValue());
}
else
{
if (hour()<21)
ActinicPWMValue=PWMSlope(12,0,21,30,10,100,180,ReefAngel.PWM.GetActinicValue());
else if (hour()=21 && minute()<=30)
{
DaylightPWMValue=PWMSlope(12,30,20,30,10,50,120,ReefAngel.PWM.GetDaylightValue());
}
else
ActinicPWMValue=Moonphase();
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: A Few more Questions

Post by rimai »

Sorry typo... :(
Change it to MoonPhase
Roberto.
cain
Posts: 83
Joined: Tue Aug 02, 2011 10:59 am

Re: A Few more Questions

Post by cain »

another error,
ivalue required as left operand of assignment



else
{
if (hour()<21)
ActinicPWMValue=PWMSlope(12,0,21,30,10,100,180,ReefAngel.PWM.GetActinicValue());
else if (hour()=21 && minute()<=30)
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: A Few more Questions

Post by rimai »

:(
I had my RA hooked up and performing 2.5 hr long simulation yesterday when I was coding this for you and couldn't compile to verify errors.
Anyway, try this now:

Code: Select all

// Autogenerated file by RAGen (v1.0.4.92), (09/01/2011 21:51)
// RA_090111_2151.pde
//
// This version designed for v0.8.5 Beta 12 or later

/* The following features are enabled for this PDE File: 
#define DisplayImages
#define WavemakerSetup
#define DateTimeSetup
#define VersionMenu
#define ATOSetup
#define MetalHalideSetup
#define DirectTempSensor
#define DisplayLEDPWM
#define SingleATOSetup
#define StandardLightSetup
*/


#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>

byte ActinicPWMValue=0;
byte DaylightPWMValue=0;

void setup()
{
randomSeed(analogRead(0));

ReefAngel.Init(); //Initialize controller
  ReefAngel.PHMin=526;// 526=PH7.0
  ReefAngel.PHMax=813;// 813=PH10.0
  ReefAngel.FeedingModePorts = B10000000;
  ReefAngel.OverheatShutoffPorts = B01000000;

  // Ports that are always on
  ReefAngel.Relay.On(Port8);
  ReefAngel.Timer[1].SetInterval(random(10,150));
  ReefAngel.Timer[1].Start();
  ReefAngel.Relay.On(Port4);
}

void loop()
{
  ReefAngel.ShowInterface();

  // Specific functions
  ReefAngel.StandardATO(Port1);
  ReefAngel.StandardLights(Port2);
  ReefAngel.MHLights(Port3);
  if ( ReefAngel.Timer[1].IsTriggered() )
{

  ReefAngel.Timer[1].SetInterval(random(10,150));
  ReefAngel.Timer[1].Start();
  ReefAngel.Relay.Toggle(Port4);
  ReefAngel.Relay.Toggle(Port5);

}

  ReefAngel.StandardFan(Port6);
  ReefAngel.StandardHeater(Port7);

  // Have PWM on from 12p to 9:30p, with gradual 150 minute ramp up and 180 down for actinic, and 120 minute ramp up and down for daylight starting at given times
  // From 12pm to 1pm, actinic will slowly ramp up from 10% to 100%, and from 12:30p to 2p, daylight will slowly ramp up from 10% to 50%
  // From 8:30p to 9:30p, actinic will slowly ramp down from 100% to 10%, and from 7p to 8:30p daylight will slowly ramp down from 50% to 10%
  
if (hour()<16)
  {
     if  (hour()<12)
        ActinicPWMValue=MoonPhase();
     else
       ActinicPWMValue=PWMSlope(12,0,21,30,10,100,150,ReefAngel.PWM.GetActinicValue());
  }
  else
  {
     if  (hour()<21)
       ActinicPWMValue=PWMSlope(12,0,21,30,10,100,180,ReefAngel.PWM.GetActinicValue());
     else if (hour()==21 && minute()<=30)
    {
       ActinicPWMValue=PWMSlope(12,0,21,30,10,100,180,ReefAngel.PWM.GetActinicValue());
    }
    else
       ActinicPWMValue=MoonPhase();
       
  } 
  DaylightPWMValue=PWMSlope(12,30,20,30,10,50,120,ReefAngel.PWM.GetDaylightValue());
  CheckCloud();
  ReefAngel.PWM.SetActinic(ActinicPWMValue);
  ReefAngel.PWM.SetDaylight(DaylightPWMValue);
}

//*********************************************************************************************************************************
// Random Cloud/Thunderstorm effects function
void CheckCloud()
{

  // ------------------------------------------------------------
  // Change the values below to customize your cloud/storm effect

  // 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 8

  // 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 1

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

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

  // Always end the cloud effect before this setting
  // In this example, end could before 6:00pm
#define End_Cloud_Before NumMins(18,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 10

  // 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 resul 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. 


  // Change the values above to customize your cloud/storm effect
  // ------------------------------------------------------------
  // Do not change anything below here

  static byte cloudchance=255;
  static byte cloudduration=0;
  static int cloudstart=0;
  static byte numclouds=0;
  static byte lightningchance=0;
  static byte cloudindex=0;
  static byte lightningstatus=0;
  static int LastNumMins=0;
  // Every day at midnight, we check for chance of cloud happening today
  if (hour()==0 && minute()==0 && second()==0) cloudchance=255;

#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))
    {
      DaylightPWMValue=ReversePWMSlope(cloudstart,cloudstart+cloudduration,DaylightPWMValue,0,180);
      if (lightningchance && (NumMins(hour(),minute())==(cloudstart+(cloudduration/2))) && second()<5) 
      {
        if (random(100)<20) lightningstatus=1; 
        else lightningstatus=0;
        if (lightningstatus)
        {
          DaylightPWMValue=100; 
          ActinicPWMValue=100;
        }
        else 
        {
          DaylightPWMValue=0;
          ActinicPWMValue=0;
        }
        delay(1);
      }
    }
    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;
      }
    }
  }
  
  if (LastNumMins!=NumMins(hour(),minute()))
  {
    LastNumMins=NumMins(hour(),minute());
    ReefAngel.LCD.Clear(255,0,120,132,132);
    ReefAngel.LCD.DrawText(0,255,5,120,"C");
    ReefAngel.LCD.DrawText(0,255,11,120,"00:00");
    ReefAngel.LCD.DrawText(0,255,45,120,"L");
    ReefAngel.LCD.DrawText(0,255,51,120,"00:00");
    if (cloudchance && (NumMins(hour(),minute())<cloudstart))
    {
      int x=0;
      if ((cloudstart/60)>=10) x=11; else x=17;
      ReefAngel.LCD.DrawText(0,255,x,120,(cloudstart/60));
      if ((cloudstart%60)>=10) x=29; else x=35;
      ReefAngel.LCD.DrawText(0,255,x,120,(cloudstart%60));
    }
    ReefAngel.LCD.DrawText(0,255,90,120,cloudduration);
    if (lightningchance) 
    {
      int x=0;
      if (((cloudstart+(cloudduration/2))/60)>=10) x=51; else x=57;
      ReefAngel.LCD.DrawText(0,255,x,120,((cloudstart+(cloudduration/2))/60));
      if (((cloudstart+(cloudduration/2))%60)>=10) x=69; else x=75;
      ReefAngel.LCD.DrawText(0,255,x,120,((cloudstart+(cloudduration/2))%60));
    }
  }   
}

byte ReversePWMSlope(long cstart,long cend,byte PWMStart,byte PWMEnd, byte clength)
{
  long n=elapsedSecsToday(now());
  cstart*=60;
  cend*=60;
  if (n<cstart) return PWMStart;
  if (n>=cstart && n<=(cstart+clength)) return map(n,cstart,cstart+clength,PWMStart,PWMEnd);
  if (n>(cstart+clength) && n<(cend-clength)) return PWMEnd;
  if (n>=(cend-clength) && n<=cend) return map(n,cend-clength,cend,PWMEnd,PWMStart);
  if (n>cend) return PWMStart;
}
    
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;
}    
Roberto.
cain
Posts: 83
Joined: Tue Aug 02, 2011 10:59 am

Re: A Few more Questions

Post by cain »

thanks Roberto!
cain
Posts: 83
Joined: Tue Aug 02, 2011 10:59 am

Re: A Few more Questions

Post by cain »

it's working, nice, real cool.
do you think i need another moonlight for a 3ft tank?
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: A Few more Questions

Post by rimai »

I have a 3ft tank and I use 2.
But I can see it with just one in the center, with just some lack of coverage at the extremities.
Roberto.
aranax
Posts: 120
Joined: Thu Jun 02, 2011 11:54 pm

Re: A Few more Questions

Post by aranax »

Hey Robert et al,
Can you please help me with my MoonPhase code? I have the Meanwell P drivers so I need them to start at 15 but I want them at 0 for a period of time.

I'd like to have:

from 12:30PM to 6:00PM - PWMChannel[LEDPWM3]=PWMSlope(12,30,22,00,15,60,240,PWMChannel[LEDPWM3])

from 6:00PM to 4:00AM (next day) -
PWMChannel[LEDPWM3]=MoonPhase()

from 4:00AM to 12:30PM -
PWMChannel[LEDPWM3]=0;

Thanks.

-J
Image
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: A Few more Questions

Post by rimai »

Try this:

Code: Select all

  if (now()>ScheduleTime(12,30,0) && now()<=ScheduleTime(18,0,0))
     PWMChannel[LEDPWM3]=PWMSlope(12,30,22,00,15,60,240,PWMChannel[LEDPWM3])
  else if (now()>ScheduleTime(18,0,0) || now()<=ScheduleTime(4,0,0))
    PWMChannel[LEDPWM3]=MoonPhase();
  else
    PWMChannel[LEDPWM3]=0;
Roberto.
aranax
Posts: 120
Joined: Thu Jun 02, 2011 11:54 pm

Re: A Few more Questions

Post by aranax »

Thanks Robert. So far, so good.

-J
Image
Post Reply