Help me develop my PDE

Do you have a question on how to do something.
Ask in here.
Post Reply
jcm2m9
Posts: 26
Joined: Fri Feb 10, 2012 4:11 pm

Help me develop my PDE

Post by jcm2m9 »

I have owned my ReefAngel now for around 6 months and have been lurking the forums and begging Robert to help me develop my PDE. I have decided to start a thread to get all my ideas completed.

My RA is on my 14g biocube with retrofitted leds from Modularled. I have my whites and blues on two separate drivers. My whites are on a meanwell that is dimmed through PWM. I am successfully controlling my leds with the controller and simulating clouds and T-storms.

The first thing I would like to add is the code for a single low ATO. I have ordered the ATO kit from AVAST marine with the RA connection. I know I need to add the following line of code, but do not understand all the functions.

ReefAngel.SingleATO(true, Port1, 60, 1);

Could someone tell me what all the options do?

In the future I would like to make a custom main and menu system, but I would like to get the small things working first.

Below is my current PDE.

Code: Select all

// Autogenerated file by RAGen (v1.1.0.126), (01/30/2012 21:35)
// RA_013012_2135.pde
//
// This version designed for v0.8.5 Beta 17 or later

/* The following features are enabled for this PDE File: 
#define MetalHalideSetup
#define DisplayLEDPWM
#define wifi
#define StandardLightSetup
#define WDT
#define PWMEXPANSION
*/

#include <ReefAngel_Features.h>
#include <ReefAngel_Colors.h>
#include <ReefAngel_CustomColors.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>

//----------------------------------------------------------------------------------------------------------------------------------------------------------
//Give labels to outlets for easier programming
//----------------------------------------------------------------------------------------------------------------------------------------------------------
 
#define Fan                 8
#define Sump                7
#define Heater              6
#define Vortech             5
#define Return              4
#define Skimmer             3
#define BlueLED             2
#define WhiteLED            1

byte DaylightPWMValue=0;

void DrawCustomMain()
{
        // the graph is drawn/updated when we exit the main menu &
	// when the parameters are saved
	ReefAngel.LCD.DrawDate(6, 112);
	pingSerial();
#if defined DisplayLEDPWM && ! defined RemoveAllLights
	ReefAngel.LCD.DrawMonitor(15, 60, ReefAngel.Params,
		ReefAngel.PWM.GetDaylightValue(), ReefAngel.PWM.GetActinicValue());
#else // defined DisplayLEDPWM && ! defined RemoveAllLights
	ReefAngel.LCD.DrawMonitor(15, 60, ReefAngel.Params);
#endif // defined DisplayLEDPWM && ! defined RemoveAllLights
	pingSerial();
	byte TempRelay = ReefAngel.Relay.RelayData;
	TempRelay &= ReefAngel.Relay.RelayMaskOff;
	TempRelay |= ReefAngel.Relay.RelayMaskOn;
	ReefAngel.LCD.DrawOutletBox(12, 93, TempRelay);
}

void DrawCustomGraph()
{
	ReefAngel.LCD.DrawGraph(5, 5);
}

void setup()
{
    ReefAngel.Init();  //Initialize controller

    ReefAngel.FeedingModePorts = B00010000;
    ReefAngel.WaterChangePorts = B00011100;
    ReefAngel.OverheatShutoffPorts = B00000011;
    ReefAngel.LightsOnPorts = B00000011;

    // Ports that are always on
    ReefAngel.Relay.On(Skimmer);
    ReefAngel.Relay.On(Return);
    ReefAngel.Relay.On(Vortech);
    ReefAngel.Relay.On(Fan);
}

void loop()
{
    // Specific functions
    ReefAngel.MHLights(WhiteLED);
    ReefAngel.StandardLights(BlueLED);
    ReefAngel.StandardHeater(Heater);
    ReefAngel.PWM.SetActinic(MoonPhase());
    DaylightPWMValue=PWMSlope(12,00,20,00,13,40,200,DaylightPWMValue);
    //ReefAngel.PWM.SetActinic(MoonPhase());
    //DaylightPWMValue=100;
    CheckCloud();
    ReefAngel.PWM.SetDaylight(DaylightPWMValue);
    ReefAngel.ShowInterface();
  }

//*********************************************************************************************************************************
  // 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 5

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

   // 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(00,00)

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

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

   // 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()<10)
        {
          if (random(100)<20) lightningstatus=1;
          else lightningstatus=0;
          if (lightningstatus)
          {
            DaylightPWMValue=100;
            }
          else
          {
            DaylightPWMValue=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;
  }
binder
Posts: 2865
Joined: Fri Mar 18, 2011 6:20 pm
Location: Illinois
Contact:

Re: Help me develop my PDE

Post by binder »

Here's what the options mean:

Code: Select all

ReefAngel.SingleATO(true, Port1, 60, 1);
true - Use the LOW ato switch / connection
Port1 - The port / relay that is toggled based on the status of the port
60 - The number of seconds for the timeout.  This is the maximum number of seconds that the relay will be on before triggering an alert.
1 - This is the hour interval.  This means that the ATO port is only able to run 1 time per hour.  This can prevent it from running too often if the water fluctuates a lot.  You can put a 0 in to disable the hour interval.
Hopefully this explains and helps.
jcm2m9
Posts: 26
Joined: Fri Feb 10, 2012 4:11 pm

Re: Help me develop my PDE

Post by jcm2m9 »

binder wrote:Here's what the options mean:

Code: Select all

ReefAngel.SingleATO(true, Port1, 60, 1);
true - Use the LOW ato switch / connection
Port1 - The port / relay that is toggled based on the status of the port
60 - The number of seconds for the timeout.  This is the maximum number of seconds that the relay will be on before triggering an alert.
1 - This is the hour interval.  This means that the ATO port is only able to run 1 time per hour.  This can prevent it from running too often if the water fluctuates a lot.  You can put a 0 in to disable the hour interval.
Hopefully this explains and helps.

Awesome, that is exactly what I was looking for. I searched the forum for an hour and never found that.
binder
Posts: 2865
Joined: Fri Mar 18, 2011 6:20 pm
Location: Illinois
Contact:

Re: Help me develop my PDE

Post by binder »

yeah that information isn't really on the forum. it's all in the library source code. it has been tough to get a good list of things since the code continually evolves and improves. good suggestions. glad it helped.
jcm2m9
Posts: 26
Joined: Fri Feb 10, 2012 4:11 pm

Re: Help me develop my PDE

Post by jcm2m9 »

I have worked a little on my PDE. I added the code for the ATO and found a mainscreen that like. I edited the layout and colors slightly.

When go to compile the code I get a compile error at:

#define Vortech 5


Here is the error:

Current_PDE_0226:42: error: 'vvoid' does not name a type
Current_PDE_0226:50: error: 'vvoid' does not name a type

Code: Select all

// Autogenerated file by RAGen (v1.1.0.126), (01/30/2012 21:35)
// RA_013012_2135.pde
//
// This version designed for v0.8.5 Beta 17 or later

/* The following features are enabled for this PDE File: 
#define MetalHalideSetup
#define DisplayLEDPWM
#define wifi
#define StandardLightSetup
#define WDT
#define PWMEXPANSION
*/

#include <ReefAngel_Features.h>
#include <ReefAngel_Colors.h>
#include <ReefAngel_CustomColors.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>

//----------------------------------------------------------------------------------------------------------------------------------------------------------
//Give labels to outlets for easier programming
//----------------------------------------------------------------------------------------------------------------------------------------------------------
 
#define ATO                 8
#define Sump                7
#define Heater              6
#define Vortech             5
#define Return              4
#define Skimmer             3
#define BlueLED             2
#define WhiteLED            1

byte DaylightPWMValue=0;

vvoid DrawCustomMain()
{
  ReefAngel.LCD.DrawText(COLOR_RED, COLOR_BLUE, 0, 0, "                       "); //Top Banner
  ReefAngel.LCD.DrawText(COLOR_RED, COLOR_BLUE, 0, 2, " BioCube 14 Nano Reef  "); //Top Banner
  ReefAngel.LCD.DrawDate(6, 123);
  pingSerial();
  
  // Display Temp Text
  ReefAngel.LCD.DrawText(0,255,12,12,"Temp");
  
  // Display the T1 temp value 10,22
  char text[7];
  ConvertNumToString(text, ReefAngel.Params.Temp1, 10);
  ReefAngel.LCD.Clear(255, 0, 22, 50, 36);
  ReefAngel.LCD.DrawLargeText(COLOR_RED, 255, 10, 22, text, Num8x16);
  pingSerial();
  
  // Display pH Text
  ReefAngel.LCD.DrawText(0,255,100,12,"pH");
  
  // Display pH Value
  ConvertNumToString(text, ReefAngel.Params.PH, 100);
  ReefAngel.LCD.Clear(255, 90, 22, 98, 36);
  ReefAngel.LCD.DrawLargeText(COLOR_RED, 255, 90, 22, text, Num8x16);
  pingSerial();
   
  // Display Actinic Percentage Text
  ReefAngel.LCD.DrawText(0,255,8,40,"Actinic %");
  
  // Display the Actinic PWM channel value at 90,40
  ReefAngel.LCD.DrawSingleMonitor(ReefAngel.PWM.GetActinicValue(),COLOR_RED, 90, 40, 1);
  
  // Display Daylight Percentage Text
  ReefAngel.LCD.DrawText(0,255,8,50,"Daylight %");
    
  // Display the Daylight PWM channel value at 90,50
  ReefAngel.LCD.DrawSingleMonitor(ReefAngel.PWM.GetDaylightValue(),COLOR_RED, 90, 50, 1);
  
  // Display T2 Temp Text
  ReefAngel.LCD.DrawText(0,255,8,60,"LED Temp");
  
  // Display the T2 temperature value at 90,60
  ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp2, COLOR_RED, 90, 60, 10);
  
  // Display T3 Temp Text
  ReefAngel.LCD.DrawText(0,255,8,70,"Ambient Temp");
  
  // Display the T3 temperature at 90,70
  ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp3, COLOR_RED, 90, 70, 10);
  
  // Display Vortech MP10ew Mode Text at 90, 80
  ReefAngel.LCD.DrawText(0,255,8,80,"ATO On?");
  
  // Display EcoSmart Mode Value
  ReefAngel.LCD.DrawText(COLOR_RED,255,90,80,"Yes");
  
  //#if defined DisplayLEDPWM && ! defined RemoveAllLights
    //ReefAngel.LCD.DrawMonitor(11, 60, ReefAngel.Params,
    //ReefAngel.PWM.GetDaylightValue(), ReefAngel.PWM.GetActinicValue());
  //#else // defined DisplayLEDPWM && ! defined RemoveAllLights
    //ReefAngel.LCD.DrawMonitor(11, 60, ReefAngel.Params);
  //#endif // defined DisplayLEDPWM && ! defined RemoveAllLights
  pingSerial();
  byte TempRelay = ReefAngel.Relay.RelayData;
  TempRelay &= ReefAngel.Relay.RelayMaskOff;
  TempRelay |= ReefAngel.Relay.RelayMaskOn;
  ReefAngel.LCD.DrawOutletBox(13, 97, TempRelay);
}

void DrawCustomGraph()
{
// ReefAngel.LCD.DrawGraph(5,7);
}

void setup()
{
    ReefAngel.Init();  //Initialize controller

    ReefAngel.FeedingModePorts = B00010000;
    ReefAngel.WaterChangePorts = B00011100;
    ReefAngel.OverheatShutoffPorts = B00000011;
    ReefAngel.LightsOnPorts = B00000011;

    // Ports that are always on
    ReefAngel.Relay.On(Skimmer);
    ReefAngel.Relay.On(Return);
    ReefAngel.Relay.On(Vortech);
    }

void loop()
{
    // Specific functions
    ReefAngel.MHLights(WhiteLED);
    ReefAngel.StandardLights(BlueLED);
    ReefAngel.StandardHeater(Heater);
    ReefAngel.PWM.SetActinic(MoonPhase());
    DaylightPWMValue=PWMSlope(12,00,20,00,13,20,200,DaylightPWMValue);
    //ReefAngel.PWM.SetActinic(MoonPhase());
    //DaylightPWMValue=100;
    CheckCloud();
    ReefAngel.PWM.SetDaylight(DaylightPWMValue);
    ReefAngel.SingleATO(true, ATO, 60, 1);
    ReefAngel.ShowInterface();
  }

//*********************************************************************************************************************************
  // 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 5

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

   // 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(00,00)

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

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

   // 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()<10)
        {
          if (random(100)<20) lightningstatus=1;
          else lightningstatus=0;
          if (lightningstatus)
          {
            DaylightPWMValue=100;
            }
          else
          {
            DaylightPWMValue=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;
  }
rimai
Posts: 12857
Joined: Fri Mar 18, 2011 6:47 pm

Re: Help me develop my PDE

Post by rimai »

change this:

Code: Select all

vvoid DrawCustomMain()
To this:

Code: Select all

void DrawCustomMain()
Roberto.
jcm2m9
Posts: 26
Joined: Fri Feb 10, 2012 4:11 pm

Re: Help me develop my PDE

Post by jcm2m9 »

WOW! I feel stupuid now. I can not believe that I missed that!

Next question.

In my custommain area I have this snipet of code:

Code: Select all

  // Display ATO Text at 90, 80
  ReefAngel.LCD.DrawText(0,255,8,80,"ATO On?");
  
  // Display ATO value
  ReefAngel.LCD.DrawText(COLOR_RED,255,90,80,"Yes");
What I would like this to do is tell me if the ATO pump is running. This would be done in the //Display ATO value line
rimai
Posts: 12857
Joined: Fri Mar 18, 2011 6:47 pm

Re: Help me develop my PDE

Post by rimai »

Try this:

Code: Select all

if (bitRead(ReefAngel.Relay.RelayData,7)
ReefAngel.LCD.DrawText(COLOR_RED,255,90,80,"Yes");
else
ReefAngel.LCD.DrawText(COLOR_RED,255,90,80,"No ");
Roberto.
jcm2m9
Posts: 26
Joined: Fri Feb 10, 2012 4:11 pm

Re: Help me develop my PDE

Post by jcm2m9 »

Ok, everything is working so far. I have a few other questions though.

On my custom main where is the code to show when clouds and lighting will happen? On my screen this and the date are covering eachother up.

Also, if I wanted to add a second float switch for high water lever, how would I do this? What code needs to be added?
rimai
Posts: 12857
Joined: Fri Mar 18, 2011 6:47 pm

Re: Help me develop my PDE

Post by rimai »

Can you post your latest code?
Roberto.
jcm2m9
Posts: 26
Joined: Fri Feb 10, 2012 4:11 pm

Re: Help me develop my PDE

Post by jcm2m9 »

I forgot to grab my latest code, but it should be all the same as the one I posted above except f or the snipets of code I asked you about.

Code: Select all

// Autogenerated file by RAGen (v1.1.0.126), (01/30/2012 21:35)
// RA_013012_2135.pde
//
// This version designed for v0.8.5 Beta 17 or later

/* The following features are enabled for this PDE File: 
#define MetalHalideSetup
#define DisplayLEDPWM
#define wifi
#define StandardLightSetup
#define WDT
#define PWMEXPANSION
*/

#include <ReefAngel_Features.h>
#include <ReefAngel_Colors.h>
#include <ReefAngel_CustomColors.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>

//----------------------------------------------------------------------------------------------------------------------------------------------------------
//Give labels to outlets for easier programming
//----------------------------------------------------------------------------------------------------------------------------------------------------------
 
#define ATO                 8
#define Sump                7
#define Heater              6
#define Vortech             5
#define Return              4
#define Skimmer             3
#define BlueLED             2
#define WhiteLED            1

byte DaylightPWMValue=0;

vvoid DrawCustomMain()
{
  ReefAngel.LCD.DrawText(COLOR_RED, COLOR_BLUE, 0, 0, "                       "); //Top Banner
  ReefAngel.LCD.DrawText(COLOR_RED, COLOR_BLUE, 0, 2, " BioCube 14 Nano Reef  "); //Top Banner
  ReefAngel.LCD.DrawDate(6, 123);
  pingSerial();
  
  // Display Temp Text
  ReefAngel.LCD.DrawText(0,255,12,12,"Temp");
  
  // Display the T1 temp value 10,22
  char text[7];
  ConvertNumToString(text, ReefAngel.Params.Temp1, 10);
  ReefAngel.LCD.Clear(255, 0, 22, 50, 36);
  ReefAngel.LCD.DrawLargeText(COLOR_RED, 255, 10, 22, text, Num8x16);
  pingSerial();
  
  // Display pH Text
  ReefAngel.LCD.DrawText(0,255,100,12,"pH");
  
  // Display pH Value
  ConvertNumToString(text, ReefAngel.Params.PH, 100);
  ReefAngel.LCD.Clear(255, 90, 22, 98, 36);
  ReefAngel.LCD.DrawLargeText(COLOR_RED, 255, 90, 22, text, Num8x16);
  pingSerial();
   
  // Display Actinic Percentage Text
  ReefAngel.LCD.DrawText(0,255,8,40,"Actinic %");
  
  // Display the Actinic PWM channel value at 90,40
  ReefAngel.LCD.DrawSingleMonitor(ReefAngel.PWM.GetActinicValue(),COLOR_RED, 90, 40, 1);
  
  // Display Daylight Percentage Text
  ReefAngel.LCD.DrawText(0,255,8,50,"Daylight %");
    
  // Display the Daylight PWM channel value at 90,50
  ReefAngel.LCD.DrawSingleMonitor(ReefAngel.PWM.GetDaylightValue(),COLOR_RED, 90, 50, 1);
  
  // Display T2 Temp Text
  ReefAngel.LCD.DrawText(0,255,8,60,"LED Temp");
  
  // Display the T2 temperature value at 90,60
  ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp2, COLOR_RED, 90, 60, 10);
  
  // Display T3 Temp Text
  ReefAngel.LCD.DrawText(0,255,8,70,"Ambient Temp");
  
  // Display the T3 temperature at 90,70
  ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp3, COLOR_RED, 90, 70, 10);
  
  // Display Vortech MP10ew Mode Text at 90, 80
  ReefAngel.LCD.DrawText(0,255,8,80,"ATO On?");
  
  // Display EcoSmart Mode Value
  ReefAngel.LCD.DrawText(COLOR_RED,255,90,80,"Yes");
  
  //#if defined DisplayLEDPWM && ! defined RemoveAllLights
    //ReefAngel.LCD.DrawMonitor(11, 60, ReefAngel.Params,
    //ReefAngel.PWM.GetDaylightValue(), ReefAngel.PWM.GetActinicValue());
  //#else // defined DisplayLEDPWM && ! defined RemoveAllLights
    //ReefAngel.LCD.DrawMonitor(11, 60, ReefAngel.Params);
  //#endif // defined DisplayLEDPWM && ! defined RemoveAllLights
  pingSerial();
  byte TempRelay = ReefAngel.Relay.RelayData;
  TempRelay &= ReefAngel.Relay.RelayMaskOff;
  TempRelay |= ReefAngel.Relay.RelayMaskOn;
  ReefAngel.LCD.DrawOutletBox(13, 97, TempRelay);
}

void DrawCustomGraph()
{
// ReefAngel.LCD.DrawGraph(5,7);
}

void setup()
{
    ReefAngel.Init();  //Initialize controller

    ReefAngel.FeedingModePorts = B00010000;
    ReefAngel.WaterChangePorts = B00011100;
    ReefAngel.OverheatShutoffPorts = B00000011;
    ReefAngel.LightsOnPorts = B00000011;

    // Ports that are always on
    ReefAngel.Relay.On(Skimmer);
    ReefAngel.Relay.On(Return);
    ReefAngel.Relay.On(Vortech);
    }

void loop()
{
    // Specific functions
    ReefAngel.MHLights(WhiteLED);
    ReefAngel.StandardLights(BlueLED);
    ReefAngel.StandardHeater(Heater);
    ReefAngel.PWM.SetActinic(MoonPhase());
    DaylightPWMValue=PWMSlope(12,00,20,00,13,20,200,DaylightPWMValue);
    //ReefAngel.PWM.SetActinic(MoonPhase());
    //DaylightPWMValue=100;
    CheckCloud();
    ReefAngel.PWM.SetDaylight(DaylightPWMValue);
    ReefAngel.SingleATO(true, ATO, 60, 1);
    ReefAngel.ShowInterface();
  }

//*********************************************************************************************************************************
  // 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 5

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

   // 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(00,00)

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

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

   // 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()<10)
        {
          if (random(100)<20) lightningstatus=1;
          else lightningstatus=0;
          if (lightningstatus)
          {
            DaylightPWMValue=100;
            }
          else
          {
            DaylightPWMValue=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;
  }
rimai
Posts: 12857
Joined: Fri Mar 18, 2011 6:47 pm

Re: Help me develop my PDE

Post by rimai »

Try this:

Code: Select all

// Autogenerated file by RAGen (v1.1.0.126), (01/30/2012 21:35)
// RA_013012_2135.pde
//
// This version designed for v0.8.5 Beta 17 or later

/* The following features are enabled for this PDE File: 
#define MetalHalideSetup
#define DisplayLEDPWM
#define wifi
#define StandardLightSetup
#define WDT
#define PWMEXPANSION
*/

#include <ReefAngel_Features.h>
#include <ReefAngel_Colors.h>
#include <ReefAngel_CustomColors.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>

//----------------------------------------------------------------------------------------------------------------------------------------------------------
//Give labels to outlets for easier programming
//----------------------------------------------------------------------------------------------------------------------------------------------------------
 
#define ATO                 8
#define Sump                7
#define Heater              6
#define Vortech             5
#define Return              4
#define Skimmer             3
#define BlueLED             2
#define WhiteLED            1

byte DaylightPWMValue=0;

void DrawCustomMain()
{
  ReefAngel.LCD.DrawText(COLOR_RED, COLOR_BLUE, 0, 0, "                       "); //Top Banner
  ReefAngel.LCD.DrawText(COLOR_RED, COLOR_BLUE, 0, 2, " BioCube 14 Nano Reef  "); //Top Banner
  ReefAngel.LCD.DrawDate(6, 123);
  pingSerial();
  
  // Display Temp Text
  ReefAngel.LCD.DrawText(0,255,12,12,"Temp");
  
  // Display the T1 temp value 10,22
  char text[7];
  ConvertNumToString(text, ReefAngel.Params.Temp1, 10);
  ReefAngel.LCD.Clear(255, 0, 22, 50, 36);
  ReefAngel.LCD.DrawLargeText(COLOR_RED, 255, 10, 22, text, Num8x16);
  pingSerial();
  
  // Display pH Text
  ReefAngel.LCD.DrawText(0,255,100,12,"pH");
  
  // Display pH Value
  ConvertNumToString(text, ReefAngel.Params.PH, 100);
  ReefAngel.LCD.Clear(255, 90, 22, 98, 36);
  ReefAngel.LCD.DrawLargeText(COLOR_RED, 255, 90, 22, text, Num8x16);
  pingSerial();
   
  // Display Actinic Percentage Text
  ReefAngel.LCD.DrawText(0,255,8,40,"Actinic %");
  
  // Display the Actinic PWM channel value at 90,40
  ReefAngel.LCD.DrawSingleMonitor(ReefAngel.PWM.GetActinicValue(),COLOR_RED, 90, 40, 1);
  
  // Display Daylight Percentage Text
  ReefAngel.LCD.DrawText(0,255,8,50,"Daylight %");
    
  // Display the Daylight PWM channel value at 90,50
  ReefAngel.LCD.DrawSingleMonitor(ReefAngel.PWM.GetDaylightValue(),COLOR_RED, 90, 50, 1);
  
  // Display T2 Temp Text
  ReefAngel.LCD.DrawText(0,255,8,60,"LED Temp");
  
  // Display the T2 temperature value at 90,60
  ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp2, COLOR_RED, 90, 60, 10);
  
  // Display T3 Temp Text
  ReefAngel.LCD.DrawText(0,255,8,70,"Ambient Temp");
  
  // Display the T3 temperature at 90,70
  ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp3, COLOR_RED, 90, 70, 10);
  
  // Display Vortech MP10ew Mode Text at 90, 80
  ReefAngel.LCD.DrawText(0,255,8,80,"ATO On?");
  
  // Display EcoSmart Mode Value
  ReefAngel.LCD.DrawText(COLOR_RED,255,90,80,"Yes");
  
  //#if defined DisplayLEDPWM && ! defined RemoveAllLights
    //ReefAngel.LCD.DrawMonitor(11, 60, ReefAngel.Params,
    //ReefAngel.PWM.GetDaylightValue(), ReefAngel.PWM.GetActinicValue());
  //#else // defined DisplayLEDPWM && ! defined RemoveAllLights
    //ReefAngel.LCD.DrawMonitor(11, 60, ReefAngel.Params);
  //#endif // defined DisplayLEDPWM && ! defined RemoveAllLights
  pingSerial();
  byte TempRelay = ReefAngel.Relay.RelayData;
  TempRelay &= ReefAngel.Relay.RelayMaskOff;
  TempRelay |= ReefAngel.Relay.RelayMaskOn;
  ReefAngel.LCD.DrawOutletBox(13, 97, TempRelay);
}

void DrawCustomGraph()
{
// ReefAngel.LCD.DrawGraph(5,7);
}

void setup()
{
    ReefAngel.Init();  //Initialize controller

    ReefAngel.FeedingModePorts = B00010000;
    ReefAngel.WaterChangePorts = B00011100;
    ReefAngel.OverheatShutoffPorts = B00000011;
    ReefAngel.LightsOnPorts = B00000011;

    // Ports that are always on
    ReefAngel.Relay.On(Skimmer);
    ReefAngel.Relay.On(Return);
    ReefAngel.Relay.On(Vortech);
    }

void loop()
{
    // Specific functions
    ReefAngel.MHLights(WhiteLED);
    ReefAngel.StandardLights(BlueLED);
    ReefAngel.StandardHeater(Heater);
    ReefAngel.PWM.SetActinic(MoonPhase());
    DaylightPWMValue=PWMSlope(12,00,20,00,13,20,200,DaylightPWMValue);
    //ReefAngel.PWM.SetActinic(MoonPhase());
    //DaylightPWMValue=100;
    CheckCloud();
    ReefAngel.PWM.SetDaylight(DaylightPWMValue);
    ReefAngel.SingleATO(true, ATO, 60, 1);
    ReefAngel.ShowInterface();
  }

//*********************************************************************************************************************************
  // 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 5

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

   // 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(00,00)

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

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

   // 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()<10)
        {
          if (random(100)<20) lightningstatus=1;
          else lightningstatus=0;
          if (lightningstatus)
          {
            DaylightPWMValue=100;
            }
          else
          {
            DaylightPWMValue=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,112,132,122);
      ReefAngel.LCD.DrawText(0,255,5,112,"C");
      ReefAngel.LCD.DrawText(0,255,11,112,"00:00");
      ReefAngel.LCD.DrawText(0,255,45,112,"L");
      ReefAngel.LCD.DrawText(0,255,51,112,"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,112,(cloudstart/60));
        if ((cloudstart%60)>=10) x=29; else x=35;
        ReefAngel.LCD.DrawText(0,255,x,112,(cloudstart%60));
      }
      ReefAngel.LCD.DrawText(0,255,90,112,cloudduration);
      if (lightningchance)
      {
        int x=0;
        if (((cloudstart+(cloudduration/2))/60)>=10) x=51; else x=57;
        ReefAngel.LCD.DrawText(0,255,x,112,((cloudstart+(cloudduration/2))/60));
        if (((cloudstart+(cloudduration/2))%60)>=10) x=69; else x=75;
        ReefAngel.LCD.DrawText(0,255,x,112,((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;
  }
C=Cloud in military time
L=Lightning in military time
3rd number is cloud duration
Roberto.
jcm2m9
Posts: 26
Joined: Fri Feb 10, 2012 4:11 pm

Re: Help me develop my PDE

Post by jcm2m9 »

What line in the code is telling it to display that information?
rimai
Posts: 12857
Joined: Fri Mar 18, 2011 6:47 pm

Re: Help me develop my PDE

Post by rimai »

Code: Select all

    if (LastNumMins!=NumMins(hour(),minute()))
    {
      LastNumMins=NumMins(hour(),minute());
      ReefAngel.LCD.Clear(255,0,112,132,122);
      ReefAngel.LCD.DrawText(0,255,5,112,"C");
      ReefAngel.LCD.DrawText(0,255,11,112,"00:00");
      ReefAngel.LCD.DrawText(0,255,45,112,"L");
      ReefAngel.LCD.DrawText(0,255,51,112,"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,112,(cloudstart/60));
        if ((cloudstart%60)>=10) x=29; else x=35;
        ReefAngel.LCD.DrawText(0,255,x,112,(cloudstart%60));
      }
      ReefAngel.LCD.DrawText(0,255,90,112,cloudduration);
      if (lightningchance)
      {
        int x=0;
        if (((cloudstart+(cloudduration/2))/60)>=10) x=51; else x=57;
        ReefAngel.LCD.DrawText(0,255,x,112,((cloudstart+(cloudduration/2))/60));
        if (((cloudstart+(cloudduration/2))%60)>=10) x=69; else x=75;
        ReefAngel.LCD.DrawText(0,255,x,112,((cloudstart+(cloudduration/2))%60));
      }
    }  
Roberto.
jcm2m9
Posts: 26
Joined: Fri Feb 10, 2012 4:11 pm

Re: Help me develop my PDE

Post by jcm2m9 »

Awesome, I have everything working!

The only issue I have been having is with changing the background color. I want to change it all to blue, but can not get the background behind the switch from white. Any ideas?
binder
Posts: 2865
Joined: Fri Mar 18, 2011 6:20 pm
Location: Illinois
Contact:

Re: Help me develop my PDE

Post by binder »

Behind what switch are you talking about?

When you use the LCD.DrawText(...) function, the first parameter is the foreground color (text) and the second parameter is the background color. In the previous code post that Roberto did, it's hard coded to use black text (0) and white background (255). I would change the 255 to be COLOR_BLUE or whatever color you want it to be to match the rest of your controller.

Then, you would also want to change the first parameter in the LCD.Clear(...) function from 255 to COLOR_BLUE (or whatever color you use).

If you have the custom colors enabled and change your default background and foreground values, then you can just change those values to DefaultBGColor and DefaultFGColor.
Hopefully that makes sense to you.
jcm2m9
Posts: 26
Joined: Fri Feb 10, 2012 4:11 pm

Re: Help me develop my PDE

Post by jcm2m9 »

binder wrote:Behind what switch are you talking about?

When you use the LCD.DrawText(...) function, the first parameter is the foreground color (text) and the second parameter is the background color. In the previous code post that Roberto did, it's hard coded to use black text (0) and white background (255). I would change the 255 to be COLOR_BLUE or whatever color you want it to be to match the rest of your controller.

Then, you would also want to change the first parameter in the LCD.Clear(...) function from 255 to COLOR_BLUE (or whatever color you use).

If you have the custom colors enabled and change your default background and foreground values, then you can just change those values to DefaultBGColor and DefaultFGColor.
Hopefully that makes sense to you.
I will take a look at this tonight

Also, I have been noticing that the internal memory seems to take precedence over the timeout of the ATO. is this the case? I have been adjusting the 60 in the following lien and it does not seem to change anything.

ReefAngel.SingleATO(true, Port1, 60, 1);
binder
Posts: 2865
Joined: Fri Mar 18, 2011 6:20 pm
Location: Illinois
Contact:

Re: Help me develop my PDE

Post by binder »

jcm2m9 wrote:Also, I have been noticing that the internal memory seems to take precedence over the timeout of the ATO. is this the case? I have been adjusting the 60 in the following lien and it does not seem to change anything.

ReefAngel.SingleATO(true, Port1, 60, 1);
The function you mention only uses the values that are given to it. The SingleATOLow() and SingleATOHigh() use the internal memory values.

When I look at your function you are showing, it tells me that you want to use the Low ato port and that it can run only 1 time in a given hour time frame for a maximum of 60 seconds per run. So if it activates at 8:30a, it can only run for a max of 60 seconds before the timeout kicks in. It's then not able to run again until 9:30a. The 60 just tells the maximum number of seconds that the port will be allowed to stay on before an error is triggered and the port gets shutoff.
jcm2m9
Posts: 26
Joined: Fri Feb 10, 2012 4:11 pm

Re: Help me develop my PDE

Post by jcm2m9 »

binder wrote:
jcm2m9 wrote:Also, I have been noticing that the internal memory seems to take precedence over the timeout of the ATO. is this the case? I have been adjusting the 60 in the following lien and it does not seem to change anything.

ReefAngel.SingleATO(true, Port1, 60, 1);
The function you mention only uses the values that are given to it. The SingleATOLow() and SingleATOHigh() use the internal memory values.

When I look at your function you are showing, it tells me that you want to use the Low ato port and that it can run only 1 time in a given hour time frame for a maximum of 60 seconds per run. So if it activates at 8:30a, it can only run for a max of 60 seconds before the timeout kicks in. It's then not able to run again until 9:30a. The 60 just tells the maximum number of seconds that the port will be allowed to stay on before an error is triggered and the port gets shutoff.

That is exactly what happens, but if I change the 60 to say 120 it still only runs for 60s and then timesout. It will only run longer if I change the internal memory.
jcm2m9
Posts: 26
Joined: Fri Feb 10, 2012 4:11 pm

Re: Help me develop my PDE

Post by jcm2m9 »

Ok, I am having problems with my ATO, or so I think. I am not 100% positive that it is shutting off.

I am using the Avast ATO and I am not positive that it is working correctly. Is there anyway for me to display on the controller what the last time the ATO pump ran and possible for how long it ran? It would make my troubleshooting much easier.

Here is my current PDE.

Code: Select all

// Autogenerated file by RAGen (v1.1.0.126), (01/30/2012 21:35)
// RA_013012_2135.pde
//
// This version designed for v0.8.5 Beta 17 or later

/* The following features are enabled for this PDE File: 
#define MetalHalideSetup
#define DisplayLEDPWM
#define wifi
#define StandardLightSetup
#define WDT
#define PWMEXPANSION
*/

#include <ReefAngel_Features.h>
#include <ReefAngel_Colors.h>
#include <ReefAngel_CustomColors.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>

//----------------------------------------------------------------------------------------------------------------------------------------------------------
//Give labels to outlets for easier programming
//----------------------------------------------------------------------------------------------------------------------------------------------------------
 
#define ATO                 8
#define Sump                7
#define Heater              6
#define Vortech             5
#define Return              4
#define Skimmer             3
#define BlueLED             2
#define WhiteLED            1

byte DaylightPWMValue=0;

void DrawCustomMain()
{
  ReefAngel.LCD.DrawText(COLOR_RED, COLOR_BLUE, 0, 0, "                       "); //Top Banner
  ReefAngel.LCD.DrawText(COLOR_RED, COLOR_BLUE, 0, 2, " BioCube 14 Nano Reef  "); //Top Banner
  ReefAngel.LCD.DrawDate(6, 123);
  pingSerial();
  
  // Display Temp Text
  ReefAngel.LCD.DrawText(0,255,12,12,"Temp");
  
  // Display the T1 temp value 10,22
  char text[7];
  ConvertNumToString(text, ReefAngel.Params.Temp1, 10);
  ReefAngel.LCD.Clear(255, 0, 22, 50, 36);
  ReefAngel.LCD.DrawLargeText(COLOR_RED, 255, 10, 22, text, Num8x16);
  pingSerial();
  
  // Display pH Text
  ReefAngel.LCD.DrawText(0,255,100,12,"pH");
  
  // Display pH Value
  ConvertNumToString(text, ReefAngel.Params.PH, 100);
  ReefAngel.LCD.Clear(255, 90, 22, 98, 36);
  ReefAngel.LCD.DrawLargeText(COLOR_RED, 255, 90, 22, text, Num8x16);
  pingSerial();
   
  // Display Actinic Percentage Text
  ReefAngel.LCD.DrawText(0,255,8,40,"Actinic %");
  
  // Display the Actinic PWM channel value at 90,40
  ReefAngel.LCD.DrawSingleMonitor(ReefAngel.PWM.GetActinicValue(),COLOR_RED, 90, 40, 1);
  
  // Display Daylight Percentage Text
  ReefAngel.LCD.DrawText(0,255,8,50,"Daylight %");
    
  // Display the Daylight PWM channel value at 90,50
  ReefAngel.LCD.DrawSingleMonitor(ReefAngel.PWM.GetDaylightValue(),COLOR_RED, 90, 50, 1);
  
  // Display T2 Temp Text
  ReefAngel.LCD.DrawText(0,255,8,60,"LED Temp");
  
  // Display the T2 temperature value at 90,60
  ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp2, COLOR_RED, 90, 60, 10);
  
  // Display T3 Temp Text
  ReefAngel.LCD.DrawText(0,255,8,70,"Ambient Temp");
  
  // Display the T3 temperature at 90,70
  ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp3, COLOR_RED, 90, 70, 10);
  
  // Display Vortech MP10ew Mode Text at 90, 80
  ReefAngel.LCD.DrawText(0,255,8,80,"ATO On?");
  
  // Display EcoSmart Mode Value
  if bitRead(ReefAngel.Relay.RelayData,7)
     ReefAngel.LCD.DrawText(COLOR_RED,255,90,80,"Yes");
  else
    ReefAngel.LCD.DrawText(COLOR_RED,255,90,80,"No ");
  
  //#if defined DisplayLEDPWM && ! defined RemoveAllLights
    //ReefAngel.LCD.DrawMonitor(11, 60, ReefAngel.Params,
    //ReefAngel.PWM.GetDaylightValue(), ReefAngel.PWM.GetActinicValue());
  //#else // defined DisplayLEDPWM && ! defined RemoveAllLights
    //ReefAngel.LCD.DrawMonitor(11, 60, ReefAngel.Params);
  //#endif // defined DisplayLEDPWM && ! defined RemoveAllLights
  pingSerial();
  byte TempRelay = ReefAngel.Relay.RelayData;
  TempRelay &= ReefAngel.Relay.RelayMaskOff;
  TempRelay |= ReefAngel.Relay.RelayMaskOn;
  ReefAngel.LCD.DrawOutletBox(13, 97, TempRelay);
}

void DrawCustomGraph()
{
// ReefAngel.LCD.DrawGraph(5,7);
}

void setup()
{
    ReefAngel.Init();  //Initialize controller

    ReefAngel.FeedingModePorts = B00010000;
    ReefAngel.WaterChangePorts = B10011100;
    ReefAngel.OverheatShutoffPorts = B00000011;
    ReefAngel.LightsOnPorts = B01000011;

    // Ports that are always on
    ReefAngel.Relay.On(Skimmer);
    ReefAngel.Relay.On(Return);
    ReefAngel.Relay.On(Vortech);
    }

void loop()
{
    // Specific functions
    ReefAngel.MHLights(WhiteLED);
    ReefAngel.MHLights(Sump);
    ReefAngel.StandardLights(BlueLED);
    ReefAngel.StandardHeater(Heater);
    ReefAngel.PWM.SetActinic(MoonPhase());
    DaylightPWMValue=PWMSlope(14,00,18,00,13,45,60,DaylightPWMValue);
    //ReefAngel.PWM.SetActinic(MoonPhase());
    //DaylightPWMValue=100;
    CheckCloud();
    ReefAngel.PWM.SetDaylight(DaylightPWMValue);
    //ReefAngel.SingleATO(true, ATO, 360, 1);
    ReefAngel.SingleATOLow(ATO);
    ReefAngel.ShowInterface();
  }

//*********************************************************************************************************************************
  // 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 5

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

   // 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(00,00)

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

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

   // 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()<10)
        {
          if (random(100)<20) lightningstatus=1;
          else lightningstatus=0;
          if (lightningstatus)
          {
            DaylightPWMValue=100;
            }
          else
          {
            DaylightPWMValue=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,112,"C");
      ReefAngel.LCD.DrawText(0,255,11,112,"00:00");
      ReefAngel.LCD.DrawText(0,255,45,112,"L");
      ReefAngel.LCD.DrawText(0,255,51,112,"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,112,(cloudstart/60));
        if ((cloudstart%60)>=10) x=29; else x=35;
        ReefAngel.LCD.DrawText(0,255,x,112,(cloudstart%60));
      }
      ReefAngel.LCD.DrawText(0,255,90,112,cloudduration);
      if (lightningchance)
      {
        int x=0;
        if (((cloudstart+(cloudduration/2))/60)>=10) x=51; else x=57;
        ReefAngel.LCD.DrawText(0,255,x,112,((cloudstart+(cloudduration/2))/60));
        if (((cloudstart+(cloudduration/2))%60)>=10) x=69; else x=75;
        ReefAngel.LCD.DrawText(0,255,x,112,((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;
  }
rimai
Posts: 12857
Joined: Fri Mar 18, 2011 6:47 pm

Re: Help me develop my PDE

Post by rimai »

Try this:

Code: Select all

// Autogenerated file by RAGen (v1.1.0.126), (01/30/2012 21:35)
// RA_013012_2135.pde
//
// This version designed for v0.8.5 Beta 17 or later

/* The following features are enabled for this PDE File: 
#define MetalHalideSetup
#define DisplayLEDPWM
#define wifi
#define StandardLightSetup
#define WDT
#define PWMEXPANSION
*/

#include <ReefAngel_Features.h>
#include <ReefAngel_Colors.h>
#include <ReefAngel_CustomColors.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>

//----------------------------------------------------------------------------------------------------------------------------------------------------------
//Give labels to outlets for easier programming
//----------------------------------------------------------------------------------------------------------------------------------------------------------
 
#define AutoTopOff          8
#define Sump                7
#define Heater              6
#define Vortech             5
#define Return              4
#define Skimmer             3
#define BlueLED             2
#define WhiteLED            1

byte DaylightPWMValue=0;
byte ATOrunning=0;
time_t lastATO=0;

void DrawCustomMain()
{
  ReefAngel.LCD.DrawText(COLOR_RED, COLOR_BLUE, 0, 0, "                       "); //Top Banner
  ReefAngel.LCD.DrawText(COLOR_RED, COLOR_BLUE, 0, 2, " BioCube 14 Nano Reef  "); //Top Banner
  ReefAngel.LCD.DrawDate(6, 123);
  pingSerial();
  
  // Display Temp Text
  ReefAngel.LCD.DrawText(0,255,12,12,"Temp");
  
  // Display the T1 temp value 10,22
  char text[7];
  ConvertNumToString(text, ReefAngel.Params.Temp1, 10);
  ReefAngel.LCD.Clear(255, 0, 22, 50, 36);
  ReefAngel.LCD.DrawLargeText(COLOR_RED, 255, 10, 22, text, Num8x16);
  pingSerial();
  
  // Display pH Text
  ReefAngel.LCD.DrawText(0,255,100,12,"pH");
  
  // Display pH Value
  ConvertNumToString(text, ReefAngel.Params.PH, 100);
  ReefAngel.LCD.Clear(255, 90, 22, 98, 36);
  ReefAngel.LCD.DrawLargeText(COLOR_RED, 255, 90, 22, text, Num8x16);
  pingSerial();
   
  // Display Actinic Percentage Text
  ReefAngel.LCD.DrawText(0,255,8,40,"Actinic %");
  
  // Display the Actinic PWM channel value at 90,40
  ReefAngel.LCD.DrawSingleMonitor(ReefAngel.PWM.GetActinicValue(),COLOR_RED, 90, 40, 1);
  
  // Display Daylight Percentage Text
  ReefAngel.LCD.DrawText(0,255,8,50,"Daylight %");
    
  // Display the Daylight PWM channel value at 90,50
  ReefAngel.LCD.DrawSingleMonitor(ReefAngel.PWM.GetDaylightValue(),COLOR_RED, 90, 50, 1);
  
  // Display T2 Temp Text
  ReefAngel.LCD.DrawText(0,255,8,60,"LED Temp");
  
  // Display the T2 temperature value at 90,60
  ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp2, COLOR_RED, 90, 60, 10);
  
  // Display T3 Temp Text
  ReefAngel.LCD.DrawText(0,255,8,70,"Ambient Temp");
  
  // Display the T3 temperature at 90,70
  ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp3, COLOR_RED, 90, 70, 10);
  
  // Display Vortech MP10ew Mode Text at 90, 80
  ReefAngel.LCD.DrawText(0,255,8,80,"ATO On?");
  
  // Display EcoSmart Mode Value
  if bitRead(ReefAngel.Relay.RelayData,7)
  {
     ReefAngel.LCD.DrawText(COLOR_RED,255,90,80,"Yes");
     if (!ATOrunning)
     {
       int x;
       ReefAngel.LCD.DrawText(COLOR_RED,255,10,89,"00:00");
       if (hour()<10) x=16; else x=10;
       ReefAngel.LCD.DrawText(COLOR_RED,255,x,89,hour());
       if (minute()<10) x=32; else x=28; 
       ReefAngel.LCD.DrawText(COLOR_RED,255,x,89,minute());
       ATOrunning=true;
       lastATO=now();
     }
  }
  else
  {
    ReefAngel.LCD.DrawText(COLOR_RED,255,90,80,"No ");
    ReefAngel.LCD.DrawText(COLOR_RED,255,90,89,"    ");
    if (ATOrunning) ReefAngel.LCD.DrawText(COLOR_RED,255,90,89,int(now()-lastATO));
    ATOrunning=false;
  }
  
  //#if defined DisplayLEDPWM && ! defined RemoveAllLights
    //ReefAngel.LCD.DrawMonitor(11, 60, ReefAngel.Params,
    //ReefAngel.PWM.GetDaylightValue(), ReefAngel.PWM.GetActinicValue());
  //#else // defined DisplayLEDPWM && ! defined RemoveAllLights
    //ReefAngel.LCD.DrawMonitor(11, 60, ReefAngel.Params);
  //#endif // defined DisplayLEDPWM && ! defined RemoveAllLights
  pingSerial();
  byte TempRelay = ReefAngel.Relay.RelayData;
  TempRelay &= ReefAngel.Relay.RelayMaskOff;
  TempRelay |= ReefAngel.Relay.RelayMaskOn;
  ReefAngel.LCD.DrawOutletBox(13, 97, TempRelay);
}

void DrawCustomGraph()
{
// ReefAngel.LCD.DrawGraph(5,7);
}

void setup()
{
    ReefAngel.Init();  //Initialize controller

    ReefAngel.FeedingModePorts = B00010000;
    ReefAngel.WaterChangePorts = B10011100;
    ReefAngel.OverheatShutoffPorts = B00000011;
    ReefAngel.LightsOnPorts = B01000011;

    // Ports that are always on
    ReefAngel.Relay.On(Skimmer);
    ReefAngel.Relay.On(Return);
    ReefAngel.Relay.On(Vortech);
    }

void loop()
{
    // Specific functions
    ReefAngel.MHLights(WhiteLED);
    ReefAngel.MHLights(Sump);
    ReefAngel.StandardLights(BlueLED);
    ReefAngel.StandardHeater(Heater);
    ReefAngel.PWM.SetActinic(MoonPhase());
    DaylightPWMValue=PWMSlope(14,00,18,00,13,45,60,DaylightPWMValue);
    //ReefAngel.PWM.SetActinic(MoonPhase());
    //DaylightPWMValue=100;
    CheckCloud();
    ReefAngel.PWM.SetDaylight(DaylightPWMValue);
    //ReefAngel.SingleATO(true, ATO, 360, 1);
    ReefAngel.SingleATOLow(AutoTopOff);
    ReefAngel.ShowInterface();
  }

//*********************************************************************************************************************************
  // 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 5

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

   // 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(00,00)

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

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

   // 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()<10)
        {
          if (random(100)<20) lightningstatus=1;
          else lightningstatus=0;
          if (lightningstatus)
          {
            DaylightPWMValue=100;
            }
          else
          {
            DaylightPWMValue=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,112,"C");
      ReefAngel.LCD.DrawText(0,255,11,112,"00:00");
      ReefAngel.LCD.DrawText(0,255,45,112,"L");
      ReefAngel.LCD.DrawText(0,255,51,112,"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,112,(cloudstart/60));
        if ((cloudstart%60)>=10) x=29; else x=35;
        ReefAngel.LCD.DrawText(0,255,x,112,(cloudstart%60));
      }
      ReefAngel.LCD.DrawText(0,255,90,112,cloudduration);
      if (lightningchance)
      {
        int x=0;
        if (((cloudstart+(cloudduration/2))/60)>=10) x=51; else x=57;
        ReefAngel.LCD.DrawText(0,255,x,112,((cloudstart+(cloudduration/2))/60));
        if (((cloudstart+(cloudduration/2))%60)>=10) x=69; else x=75;
        ReefAngel.LCD.DrawText(0,255,x,112,((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;
  }
Roberto.
jcm2m9
Posts: 26
Joined: Fri Feb 10, 2012 4:11 pm

Re: Help me develop my PDE

Post by jcm2m9 »

Quick question, if the controller hits the time out (IE exceeds the ato timelimit) will the ato run the next hour when it is supposed to turn on or does the ATO have to be "cleared"?
jcm2m9
Posts: 26
Joined: Fri Feb 10, 2012 4:11 pm

Re: Help me develop my PDE

Post by jcm2m9 »

K, dumb question. If I am using a single ATO to detect a low water scenario in my sump and to add water when this happens should I be using the Low or High ATO funtion?
binder
Posts: 2865
Joined: Fri Mar 18, 2011 6:20 pm
Location: Illinois
Contact:

Re: Help me develop my PDE

Post by binder »

jcm2m9 wrote:K, dumb question. If I am using a single ATO to detect a low water scenario in my sump and to add water when this happens should I be using the Low or High ATO funtion?
You can use either function. The function correlates with the ato switch you are using.
jcm2m9
Posts: 26
Joined: Fri Feb 10, 2012 4:11 pm

Re: Help me develop my PDE

Post by jcm2m9 »

jcm2m9 wrote:Quick question, if the controller hits the time out (IE exceeds the ato timelimit) will the ato run the next hour when it is supposed to turn on or does the ATO have to be "cleared"?

What's the answer to this question? I am just trying to get my ATO figured out. It does not seem to work properly
binder
Posts: 2865
Joined: Fri Mar 18, 2011 6:20 pm
Location: Illinois
Contact:

Re: Help me develop my PDE

Post by binder »

jcm2m9 wrote:
jcm2m9 wrote:Quick question, if the controller hits the time out (IE exceeds the ato timelimit) will the ato run the next hour when it is supposed to turn on or does the ATO have to be "cleared"?

What's the answer to this question? I am just trying to get my ATO figured out. It does not seem to work properly
No. If the timeout expires, the ATO port will shutoff and the LED will turn on. Next time it tries to run, it will NOT run. It will not run again until you clear the ato timeout.

If you haven't read the ATO guide, it may help you: http://forum.reefangel.com/viewtopic.php?f=7&t=240
jcm2m9
Posts: 26
Joined: Fri Feb 10, 2012 4:11 pm

Re: Help me develop my PDE

Post by jcm2m9 »

Here is my issue, the controller will not let my ato run long enough to trip my float switch. I have the timeout set for 250 with the hour portion being set at 0.

My aqualifter is about 3' from my tank so when it kicks on there is only a slow dribble.

Could I use this code instead?

Code: Select all

void loop(){  
    //ATO Sump too low
    if(ReefAngel.LowATO.IsActive()){
      //Water in sump too low, turn ATO on
      ReefAngel.Relay.On(AutoTopOff)
    }
   else{
        ReefAngel.Relay.Off(AutoTopOff)
    }
 }
binder
Posts: 2865
Joined: Fri Mar 18, 2011 6:20 pm
Location: Illinois
Contact:

Re: Help me develop my PDE

Post by binder »

Yes, you can use that. That should work just fine for you.
jcm2m9
Posts: 26
Joined: Fri Feb 10, 2012 4:11 pm

Re: Help me develop my PDE

Post by jcm2m9 »

Awesome, Thanks.

I am going to have a few questions about my custom main screen, but cant access my pde until I get home tonight.
Post Reply