Page 1 of 2

question on dual ATO topoff switch positioning.

Posted: Thu Aug 16, 2012 10:09 pm
by 00Warpig00
I installed my dual ATO topoff floats tonight and I think I correctly calibrated my switches to me desired water level. I used two DVM's and hooked one DVM to each switch. Does it matter that there is about a 3mm span that neither switch is activated? If I understand correctly when my "wires out the top" or low level switch closes (low water condition) the pump outlet turns on. It continues to pump even if that switch opens until either the "wires out the bottom" or High level switch closes (Hi water condition) or the timeout occurs (whichever happens first). If I am understanding correctly this means the water level that changes between these two switches toggling will just change how much and how often my topoff pump runs. Is this correct? Any suggestions on the best way to set this up. Currently my water level only changes by about 3mm before one of the two switches closes. Should this "window" be larger or smaller?

Nick

Re: question on dual ATO topoff switch positioning.

Posted: Thu Aug 16, 2012 10:46 pm
by rimai
I think you are good.

Re: question on dual ATO topoff switch positioning.

Posted: Thu Aug 30, 2012 7:04 pm
by 00Warpig00
does the ATO timeout expire? or does it require a manual clearing from the joystick on the controller? If it does not time out say after 24 a hour period and MUST be reset from the controller joystick what do I do when It times out while I am away for 4 days to prevent my sump from running dry?

I have my timeout set rather aggressively at 30 seconds. It does not take long for my maxijet 600 to fill my topoff. My atoLow and atoHigh switches have a very small window where neither switch is active. For the first time in a several days it appears to have timed out and set the atoflag. My sump was only 1/2 inch above my optimum fill line which can be enough to overflow my skimmer. Not a big deal but I am supposed to leave town for four days and now I'm scared to death to leave because if it malfunctions and doesn't stop pumping there will be a flood (I doubt this will happen as proven by the timeout flag) however what does seem WILL happen if it times out while I am out of town is that my return pump will start to pump dry while I am gone.

What to do?

Re: question on dual ATO topoff switch positioning.

Posted: Thu Aug 30, 2012 7:34 pm
by binder
if you use the android app, you can clear the ato timeout from it. i don't know of a way to tell if the timeout has been set though other than the led light.
just my input.

Re: question on dual ATO topoff switch positioning.

Posted: Thu Aug 30, 2012 9:15 pm
by rimai
This is what I use:

Code: Select all

  ReefAngel.CustomVar[0]=InternalMemory.read(ATO_Single_Exceed_Flag);
  ReefAngel.CustomVar[7]=255;
Then on the Portal, I set a trigger to send me email alert for when C1=1
To clear, you can use browser or Android app.

question on dual ATO topoff switch positioning.

Posted: Thu Aug 30, 2012 9:19 pm
by lnevo
Question... Why the need for C[7]? I noticed this in the other example for sending alerts...

Re: question on dual ATO topoff switch positioning.

Posted: Thu Aug 30, 2012 9:25 pm
by rimai
Hehehe :)
Trick to keep the custom variables in the portal alive.
The thing is that the Portal doesn't store 0s to save in database space.
It also doesn't show anything that has 0 assuming the feature is not being used.
So, if you have all custom variables being zero, it won't show in the portal. By using c[7] with any value other than 0, will force the Portal to show up the custom variables :)
It is not needed if you have other variables being used that are non-zero.

Re: question on dual ATO topoff switch positioning.

Posted: Fri Aug 31, 2012 9:39 am
by lnevo
rimai wrote:Hehehe :)
Trick to keep the custom variables in the portal alive.
The thing is that the Portal doesn't store 0s to save in database space.
It also doesn't show anything that has 0 assuming the feature is not being used.
So, if you have all custom variables being zero, it won't show in the portal. By using c[7] with any value other than 0, will force the Portal to show up the custom variables :)
It is not needed if you have other variables being used that are non-zero.
Ugly hack :) How much space is it to store 8 0's for each user in the database? unless you're keeping history...

How about this...instead of storing an extra variable... doing something like this:

ReefAngel.CustomVar[0]=InternalMemory.read(ATO_Single_Exceed_Flag)+1;

and then setting the email trigger to send at 2 instead of 1 :) Would that work?

Re: question on dual ATO topoff switch positioning.

Posted: Fri Aug 31, 2012 10:17 am
by rimai
That works too :)
Yeah, I keep history of everything that is sent and non-zero, which means for every single controller, I store data every 5 minutes. For my controller for example, it sends about 70 parameters every 5 minutes, but I only need to store about 30 at night and about 50 during the day.
So, it can get pretty large if I start including 0s too.

Re: question on dual ATO topoff switch positioning.

Posted: Fri Aug 31, 2012 11:21 am
by lnevo
Sorry to the OPs for hijacking the thread.. but since it's all related...

I only need to use the CustomVar if I want the float switch status to be remembered if triggered...

i.e. float switch triggers, kills return pump, causing the float to unactivate return pump back on.... loop...

If I just want to monitor ATO reservoir and not turn anything on/off can I just have the trigger for ATOLOW?

If I want to monitor the sump and if the level drops below the minimum and I want to turn off the return pump and skimmer, then I need to use the customvar? and trigger the alert on the customvar?

I think I've got it, but I've been very confused on this topic, you should add some code examples to the ATO tutorial :)

Re: question on dual ATO topoff switch positioning.

Posted: Fri Aug 31, 2012 11:31 am
by rimai
no, you don't need customvar at all.
ATOLOW is already part of the data that is sent to the server.
You would use customvar only for stuff that is not sent to the portal.
For example, flow meter values, light intensity values, ATO timeout flags, moonlight % or anything that you may want to see in the portal and have alert triggers for it.
Look at my portal custom var section:
portal.jpg
portal.jpg (33.58 KiB) Viewed 6850 times
I have the ATO timeout and moon cycle %.

Re: question on dual ATO topoff switch positioning.

Posted: Fri Aug 31, 2012 11:58 am
by lnevo
Sorry, I'm struggling here...

So for ATO reservoir monitoring using LowATO, I don't need any code... (since no actions taken..only portal trigger)... ATOLOW=1 send mail...

For monitoring level in sump (if ATO fails and/or drain problem)...

Code: Select all

// in setup
ReefAngel.CustomVar[0]=1;

// in loop
if ReefAngel.HighATO.IsActive() ReefAngel.CustomVar[0]=2; // Enable variable for trigger

ReefAngel.Relay.Set(Port1, ReefAngel.CusotmVar[0]-1); // Shutdown return pump if variable gets bumped up.
Then alert would be triggered and monitored if C0=2.

Btw, that Water level module output looks sweet... :)

Re: question on dual ATO topoff switch positioning.

Posted: Fri Aug 31, 2012 12:02 pm
by lnevo
And also, my point in the last post was that if ReefAngel.HighATO.IsActive becomes false, there's no code to reset it... would need to be manually unset in the portal so that when return pump shuts down, it doesn't get to go back on when the water fills the sump back up...just making sure i have the process right :)

Re: question on dual ATO topoff switch positioning.

Posted: Fri Aug 31, 2012 12:03 pm
by rimai
No, you can just set the portal to send alerts on ATOLOW and ATOHIGH

question on dual ATO topoff switch positioning.

Posted: Fri Aug 31, 2012 12:07 pm
by lnevo
What about keeping the pump off part?

Re: question on dual ATO topoff switch positioning.

Posted: Fri Aug 31, 2012 12:17 pm
by rimai
That has nothing to do with what email alerts you want to get.
You can code it with Set() like you did, but use the ato high as boolean variable.

question on dual ATO topoff switch positioning.

Posted: Fri Aug 31, 2012 12:38 pm
by lnevo
Fine, but the problem with the boolean is that once the return pump shuts off the water level will rise back up...and then the boolean flips back...i guess this is the confusing part...or can i use the exceed flags?

Re: question on dual ATO topoff switch positioning.

Posted: Fri Aug 31, 2012 12:50 pm
by rimai
Ahh... now I got it...
Yes, your original code would work for turning off and sending email, but not to turn back on.
You need to use mask off, so you can easily remove the mask remotely.

Code: Select all

// in setup
ReefAngel.CustomVar[0]=1;

// in loop
if ReefAngel.HighATO.IsActive()
{
  ReefAngel.CustomVar[0]=2; // Enable variable for trigger
  ReefAngel.Relay.RelayMaskOff=~Port1Bit;
}

question on dual ATO topoff switch positioning.

Posted: Fri Aug 31, 2012 1:00 pm
by lnevo
rimai wrote:Ahh... now I got it...
Yes, your original code would work for turning off and sending email, but not to turn back on.
You need to use mask off, so you can easily remove the mask remotely.

Code: Select all

// in setup
ReefAngel.CustomVar[0]=1;

// in loop
if ReefAngel.HighATO.IsActive()
{
  ReefAngel.CustomVar[0]=2; // Enable variable for trigger
  ReefAngel.Relay.RelayMaskOff=~Port1Bit;
}
Ok, I think I'm getting it too... I guess I don't really understand the masks...is that what gets used when you override the auto from your phone and stuff!

And I still need the customvar because ATOHIGH may revert before the info is sent to the portal...right?

Re: question on dual ATO topoff switch positioning.

Posted: Fri Aug 31, 2012 1:12 pm
by rimai
Yes, correct for everything :)

question on dual ATO topoff switch positioning.

Posted: Fri Aug 31, 2012 1:17 pm
by lnevo
Awesome...so what's the story on that water level sensor? :) any timeframe?

Re: question on dual ATO topoff switch positioning.

Posted: Fri Aug 31, 2012 1:47 pm
by rimai
Yes :)
In about 2 weeks they should be popping up :twisted:

Re: question on dual ATO topoff switch positioning.

Posted: Fri Aug 31, 2012 11:01 pm
by 00Warpig00
no problem on hijacking the thread. It is all related and quite an education for me to boot.

So let me see if I am following the concepts here...

If I add to my setup code...

Code: Select all

ReefAngel.CustomVar[7]=255
This will force the "Custom Fields" section to appear and remain in my portal which will normally read
with Values C1=0 C2=0 C3=0 C4=0 C5=0 C6=0 C7=255.

If I add the following code to my loop...

Code: Select all

ReefAngel.CustomVar[0]=InternalMemory.read(ATO_Single_Exceed_Flag);
during each loop this will make the c1 field read 1 if the ATO timeout has triggered.

shouldnt this be "ReefAngel.CustomVar[1]" to change the C1 value from 0 to 1? or am I missing something.
Just seems if "ReefAngel.CustomVar[7]" correlates to C7 that "ReefAngel.CustomVar[1]" would correlate to C1... no?

If during a loop the C1 does = 1 I can set the portal to e-mail me to tell me this. I can also just log into the portal
to check this myself. I like the e-mail idea.

so as I mentioned if the ATO timeout occurs my sump will be overfilled to some extent, minimally due
to my aggressive timeout setting that I am considdering adding an additional 10 seconds to, however I'm hesitant because I think this will just overfill my sump past my "normal max" line for an additional 10 seconds. It is my belief that my float switch is the cause of the timeout and NOT just that not enough water has pumped in. I believe this because (1) my sump was overfilled on the last/only trigger I have seen so far (2) I already have one float switch that is very flaky, why not two? 10 more seconds of water to the sump is no big deal except that it is probably enough to cause my skimmer to overflow. If I wanted to turn off my skimmer in the case of an ATO Timeout would I add this code to my loop? (assuming my skimmer is plugged into port4)

Code: Select all

if ReefAngel.CustomVar[0]=1
{
  ReefAngel.Relay.RelayMaskOff= Port4Bit;
}
then if i receive an e-mail or look at the portal and see that C1=1 and not 0 I will know I have had an ATO timeout and I should see that my skimmer relay port on my primary relay box has been masked off on the portal. I can then use the android app to reset the flag changing c1 from 1 back to 0 and then can use the android app or the portal to turn my skimmer back on and put it back into auto mode and wait for the next ATO timeout.

Nick

Re: question on dual ATO topoff switch positioning.

Posted: Sat Sep 01, 2012 9:33 am
by rimai
Yeah, computers start count at 0 and we humans start counting at 1 :(
So the array is from CustomVar[0] to CustomVar[7].
In the Portal, you will have C0 to C7.
Sorry if I made a mistake previously, but if you use CustomVar[0], use C0 to trigger the email.
But your logic of thinking is good :)
Apologies for the confusion.

Re: question on dual ATO topoff switch positioning.

Posted: Sat Sep 01, 2012 10:58 am
by 00Warpig00
Just wanted to be sure I was getting it. when I looked at your custom variables section snapshot on the previous page you have the ATO box labeled so I wasn't sure. I just need to be sure what I am going to code in is going to work.

Re: question on dual ATO topoff switch positioning.

Posted: Sat Sep 01, 2012 11:20 am
by 00Warpig00
So below is what I propose my new code to be. I have made the additions to the "insert your additional code here" sections. If it would be better to insert it in other places or rearrange slightly please advise. Then Off to the Portal to set up C0 variable and e-mail

:)

Nick

Code: Select all

#include <ReefAngel_Features.h>
#include <Globals.h>
#include <RA_Wifi.h>
#include <Wire.h>
#include <OneWire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <InternalEEPROM.h>
#include <RA_NokiaLCD.h>
#include <RA_ATO.h>
#include <RA_Joystick.h>
#include <LED.h>
#include <RA_TempSensor.h>
#include <Relay.h>
#include <RA_PWM.h>
#include <Timer.h>
#include <Memory.h>
#include <InternalEEPROM.h>
#include <RA_Colors.h>
#include <RA_CustomColors.h>
#include <Salinity.h>
#include <RF.h>
#include <IO.h>
#include <ORP.h>
#include <AI.h>
#include <ReefAngel.h>

// Initialize Buzzer variables
byte buzzer=0;
byte overheatflag=0;
byte atoflag=0;
byte iochannel0flag=0;
byte iochannel1flag=0;
byte iochannel2flag=0;
byte iochannel3flag=0;
byte iochannel4flag=0;
byte iochannel5flag=0;

////// Place global variable code below here


////// Place global variable code above here


void setup()
{
    // This must be the first line
    ReefAngel.Init();  //Initialize controller
    // Ports toggled in Feeding Mode
    ReefAngel.FeedingModePorts = 0;
    ReefAngel.FeedingModePortsE[0] = 0;
    // Ports toggled in Water Change Mode
    ReefAngel.WaterChangePorts = Port3Bit | Port4Bit;
    ReefAngel.WaterChangePortsE[0] = 0;
    // Ports toggled when Lights On / Off menu entry selected
    ReefAngel.LightsOnPorts = 0;
    ReefAngel.LightsOnPortsE[0] = Port1Bit | Port2Bit;
    // Ports turned off when Overheat temperature exceeded
    ReefAngel.OverheatShutoffPorts = Port4Bit | Port5Bit | Port6Bit;
    ReefAngel.OverheatShutoffPortsE[0] = 0;
    // Use T1 probe as temperature and overheat functions
    ReefAngel.TempProbe = T1_PROBE;
    ReefAngel.OverheatProbe = T1_PROBE;
    // Set the Overheat temperature setting
    InternalMemory.OverheatTemp_write( 850 );


    // Ports that are always on
    ReefAngel.Relay.On( Port3 );
    ReefAngel.Relay.On( Box1_Port5 );
    ReefAngel.Relay.On( Box1_Port6 );
    ReefAngel.Relay.On( Box1_Port7 );

    ////// Place additional initialization code below here
 
    ReefAngel.CustomVar[7]=255;

    ////// Place additional initialization code above here
}

void loop()
{
    ReefAngel.StandardFan( Port1,790,820 );
    ReefAngel.StandardATO( Port2,30 );
    ReefAngel.Relay.DelayedOn( Port4,5 );
    ReefAngel.WavemakerRandom( Port5,30,100 );
    ReefAngel.StandardHeater( Port6,750,760 );
    ReefAngel.StandardLights( Box1_Port1,13,0,23,0 );
    ReefAngel.StandardLights( Box1_Port2,13,0,23,0 );
    ReefAngel.StandardHeater( Box1_Port3,750,760 );
    ReefAngel.StandardHeater( Box1_Port4,750,760 );
    ReefAngel.PWM.SetChannel( 0, PWMParabola(14,0,23,59,1,100,1) );
    ReefAngel.PWM.SetChannel( 1, PWMParabola(14,0,23,59,1,100,1) );
    ReefAngel.PWM.SetChannel( 3, PWMSlope(2,0,7,30,0,50,0,0) );
    ReefAngel.PWM.SetChannel( 4, PWMSlope(0,0,14,0,0,50,0,0) );
    overheatflag = InternalMemory.read( Overheat_Exceed_Flag );
    atoflag = InternalMemory.read( ATO_Exceed_Flag );
    iochannel0flag = ReefAngel.IO.GetChannel( 0 );
    iochannel1flag = ReefAngel.IO.GetChannel( 1 );
    iochannel2flag = ReefAngel.IO.GetChannel( 2 );
    iochannel3flag = ReefAngel.IO.GetChannel( 3 );
    iochannel4flag = ReefAngel.IO.GetChannel( 4 );
    iochannel5flag = ReefAngel.IO.GetChannel( 5 );
    buzzer = overheatflag + atoflag + iochannel0flag + iochannel1flag + iochannel2flag + iochannel3flag + iochannel4flag + iochannel5flag;
    if ( buzzer >= 1 ) buzzer = 100;
    ReefAngel.PWM.SetDaylight( buzzer );
    ReefAngel.PWM.SetActinic( buzzer );

    ////// Place your custom code below here
 
    ReefAngel.CustomVar[0]=InternalMemory.read(ATO_Single_Exceed_Flag);
    if ( ReefAngel.CustomVar[0]= 1 )
      {
        ReefAngel.Relay.RelayMaskOff= Port4Bit;
      }

    ////// Place your custom code above here

    // This should always be the last line
    ReefAngel.Portal( "00Warpig00" );
    ReefAngel.ShowInterface();
}

void DrawCustomMain()
{
    int x,y;
    char text[10];
    // Dimming Expansion
    x = 15;
    y = 2;
    for ( int a=0;a<6;a++ )
    {
      if ( a>2 ) x = 75;
      if ( a==3 ) y = 2;
      ReefAngel.LCD.DrawText( COLOR_DARKGOLDENROD,DefaultBGColor,x,y,"Ch :" );
      ReefAngel.LCD.DrawText( COLOR_DARKGOLDENROD,DefaultBGColor,x+12,y,a );
      ReefAngel.LCD.DrawText( COLOR_DARKGOLDENROD,DefaultBGColor,x+24,y,ReefAngel.PWM.GetChannelValue(a) );
      y += 10;
    }
    pingSerial();

    // I/O Expansion
    byte bkcolor;
    x = 14;
    y = 34;
    for ( int a=0;a<6;a++ )
    {
      ReefAngel.LCD.DrawCircleOutline( x+(a*20),y,4,COLOR_MEDIUMORCHID );
      if ( ReefAngel.IO.GetChannel(a) ) bkcolor=COLOR_WHITE; else bkcolor=COLOR_GRAY;
      ReefAngel.LCD.FillCircle( x+(a*20),y,2,bkcolor );
    }
    pingSerial();

    // Parameters
#if defined DisplayLEDPWM && ! defined RemoveAllLights
    ReefAngel.LCD.DrawMonitor( 15, 44, ReefAngel.Params,
    ReefAngel.PWM.GetDaylightValue(), ReefAngel.PWM.GetActinicValue() );
#else // defined DisplayLEDPWM && ! defined RemoveAllLights
    ReefAngel.LCD.DrawMonitor( 15, 44, ReefAngel.Params );
#endif // defined DisplayLEDPWM && ! defined RemoveAllLights
    pingSerial();

    // Salinity
    ReefAngel.LCD.DrawText( COLOR_DARKKHAKI,DefaultBGColor,15,76, "SAL:" );
    ReefAngel.LCD.DrawText( COLOR_DARKKHAKI,DefaultBGColor,39,76, ReefAngel.Params.Salinity );
    pingSerial();

    // Main Relay Box
    byte TempRelay = ReefAngel.Relay.RelayData;
    TempRelay &= ReefAngel.Relay.RelayMaskOff;
    TempRelay |= ReefAngel.Relay.RelayMaskOn;
    ReefAngel.LCD.DrawOutletBox( 12, 90, TempRelay );
    pingSerial();

    // Relay Expansion
    TempRelay = ReefAngel.Relay.RelayDataE[0];
    TempRelay &= ReefAngel.Relay.RelayMaskOffE[0];
    TempRelay |= ReefAngel.Relay.RelayMaskOnE[0];
    ReefAngel.LCD.DrawOutletBox( 12, 104, TempRelay );
    pingSerial();

    // Date and Time
    ReefAngel.LCD.DrawDate( 6, 122 );
    pingSerial();
}

void DrawCustomGraph()
{
}
except my Syntax is wrong on the

ReefAngel.CustomVar[7]=255

so I made it

ReefAngel.CustomVar[7]=255;

now I'm past that but I have a syntax problem here too

if ReefAngel.CustomVar[0]=1

compiler says "expected `(' before 'ReefAngel'

think I got it.

I changed that line to

if ( ReefAngel.CustomVar[0]= 1 )

based on the buzzer IF/THEN code a few lines above. compiled ok

Re: question on dual ATO topoff switch positioning.

Posted: Sat Sep 01, 2012 12:06 pm
by 00Warpig00
Uploaded my code. made sure skimmer was plugged into my port4. booted up controller and waited 5 minutes for my skimmer's delayed start. After skimmer turned on I took a bout a gallon of water out of my return section to force an ATO cycle and a timeout. C0 is reading 1 on portal, red light is on on controller but skimmer is still on. I have something not quite right yet. In fact it appears as if this code has masked all of my relay ports off except port 4 (my skimmer) which is the only one left on. Now I am really Confused... I rebooted the controller the red LED is off but the C0 is still flagged at 1. I am missing something... are these CustomVar non volatile? It's all I can think of that would cause c0 to = 1 straight away after a reboot without the red LED being on.


Nick

Re: question on dual ATO topoff switch positioning.

Posted: Sat Sep 01, 2012 12:43 pm
by rimai
This needs

Code: Select all

if ( ReefAngel.CustomVar[0]= 1 )
Needs to be changed to this:

Code: Select all

if ( ReefAngel.CustomVar[0]== 1 )
The first one you are assigning it instead of comparing it.

Re: question on dual ATO topoff switch positioning.

Posted: Sat Sep 01, 2012 12:51 pm
by 00Warpig00
ahh so in that if statement I am assigning it to 1 no matter what it is. Kinda makes sense that it would always be 1 at that point. Trying the == now

Re: question on dual ATO topoff switch positioning.

Posted: Sat Sep 01, 2012 1:34 pm
by 00Warpig00
something is still not quite right...

forced another ato timeout. Red LED on controller is on. Portal says C0=0 and skimmer is still on. Portal still shows relay port 4 for my skimmer to be "auto" android app says on but not masked (no green dot).

here is my code. I have to be missing something... wait it might be my bogus sump empty float switch
iochannel0flag = ReefAngel.IO.GetChannel( 0 );
is probably setting the LED the switch has been stuck in the active position for weeks even though the switch is fully submerged with the wires out the top (IE it should NOT be active) Gonna rem it out and try again. I had it rem'd out in my previous running config before today's experiments.

Not thinking the IO channel was the culprit. I used the clear ato command from the android app and the LED turned off. why is my c0 variable not updating?

I may be on to it... I found this line where the RA+ manipulates the buzzer etc.

atoflag = InternalMemory.read( ATO_Exceed_Flag );

and the code I was running was

ReefAngel.CustomVar[0]=InternalMemory.read(ATO_Single_Exceed_Flag);

since I am using dual ATO not single maybe I am looking at the wrong flag

it should probably be...

ReefAngel.CustomVar[0]=InternalMemory.read(ATO_Exceed_Flag);

Also this line of code in my if statement

ReefAngel.Relay.RelayMaskOff=Port4Bit;

is still masking Off all my relays EXCEPT 4 which is staying on auto. I guess I need to try to figure out how these functions work. Obviously not how I think they work. lol ;)


Nick

Code: Select all

#include <ReefAngel_Features.h>
#include <Globals.h>
#include <RA_Wifi.h>
#include <Wire.h>
#include <OneWire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <InternalEEPROM.h>
#include <RA_NokiaLCD.h>
#include <RA_ATO.h>
#include <RA_Joystick.h>
#include <LED.h>
#include <RA_TempSensor.h>
#include <Relay.h>
#include <RA_PWM.h>
#include <Timer.h>
#include <Memory.h>
#include <InternalEEPROM.h>
#include <RA_Colors.h>
#include <RA_CustomColors.h>
#include <Salinity.h>
#include <RF.h>
#include <IO.h>
#include <ORP.h>
#include <AI.h>
#include <ReefAngel.h>

// Initialize Buzzer variables
byte buzzer=0;
byte overheatflag=0;
byte atoflag=0;
byte iochannel0flag=0;
byte iochannel1flag=0;
byte iochannel2flag=0;
byte iochannel3flag=0;
byte iochannel4flag=0;
byte iochannel5flag=0;

////// Place global variable code below here


////// Place global variable code above here


void setup()
{
    // This must be the first line
    ReefAngel.Init();  //Initialize controller
    // Ports toggled in Feeding Mode
    ReefAngel.FeedingModePorts = 0;
    ReefAngel.FeedingModePortsE[0] = 0;
    // Ports toggled in Water Change Mode
    ReefAngel.WaterChangePorts = Port3Bit | Port4Bit;
    ReefAngel.WaterChangePortsE[0] = 0;
    // Ports toggled when Lights On / Off menu entry selected
    ReefAngel.LightsOnPorts = 0;
    ReefAngel.LightsOnPortsE[0] = Port1Bit | Port2Bit;
    // Ports turned off when Overheat temperature exceeded
    ReefAngel.OverheatShutoffPorts = Port4Bit | Port5Bit | Port6Bit;
    ReefAngel.OverheatShutoffPortsE[0] = 0;
    // Use T1 probe as temperature and overheat functions
    ReefAngel.TempProbe = T1_PROBE;
    ReefAngel.OverheatProbe = T1_PROBE;
    // Set the Overheat temperature setting
    InternalMemory.OverheatTemp_write( 850 );


    // Ports that are always on
    ReefAngel.Relay.On( Port3 );
    ReefAngel.Relay.On( Box1_Port5 );
    ReefAngel.Relay.On( Box1_Port6 );
    ReefAngel.Relay.On( Box1_Port7 );

    ////// Place additional initialization code below here
    ReefAngel.CustomVar[0]=0;
    ReefAngel.CustomVar[7]=255;   

    ////// Place additional initialization code above here
}

void loop()
{
    ReefAngel.StandardFan( Port1,790,820 );
    ReefAngel.StandardATO( Port2,30 );
    ReefAngel.Relay.DelayedOn( Port4,5 );
    ReefAngel.WavemakerRandom( Port5,30,100 );
    ReefAngel.StandardHeater( Port6,750,760 );
    ReefAngel.StandardLights( Box1_Port1,13,0,23,0 );
    ReefAngel.StandardLights( Box1_Port2,13,0,23,0 );
    ReefAngel.StandardHeater( Box1_Port3,750,760 );
    ReefAngel.StandardHeater( Box1_Port4,750,760 );
    ReefAngel.PWM.SetChannel( 0, PWMParabola(14,0,23,59,1,100,1) );
    ReefAngel.PWM.SetChannel( 1, PWMParabola(14,0,23,59,1,100,1) );
    ReefAngel.PWM.SetChannel( 3, PWMSlope(2,0,7,30,0,50,0,0) );
    ReefAngel.PWM.SetChannel( 4, PWMSlope(0,0,14,0,0,50,0,0) );
    overheatflag = InternalMemory.read( Overheat_Exceed_Flag );
    atoflag = InternalMemory.read( ATO_Exceed_Flag );
 //   iochannel0flag = ReefAngel.IO.GetChannel( 0 );
    iochannel1flag = ReefAngel.IO.GetChannel( 1 );
    iochannel2flag = ReefAngel.IO.GetChannel( 2 );
    iochannel3flag = ReefAngel.IO.GetChannel( 3 );
    iochannel4flag = ReefAngel.IO.GetChannel( 4 );
    iochannel5flag = ReefAngel.IO.GetChannel( 5 );
    buzzer = overheatflag + atoflag + iochannel0flag + iochannel1flag + iochannel2flag + iochannel3flag + iochannel4flag + iochannel5flag;
    if ( buzzer >= 1 ) buzzer = 100;
    ReefAngel.PWM.SetDaylight( buzzer );
    ReefAngel.PWM.SetActinic( buzzer );

    ////// Place your custom code below here
 
    ReefAngel.CustomVar[0]=InternalMemory.read(ATO_Exceed_Flag);
    if ( ReefAngel.CustomVar[0]== 1 )
      {
        ReefAngel.Relay.RelayMaskOff=Port4Bit;
      }

    ////// Place your custom code above here

    // This should always be the last line
    ReefAngel.Portal( "00Warpig00" );
    ReefAngel.ShowInterface();
}

void DrawCustomMain()
{
    int x,y;
    char text[10];
    // Dimming Expansion
    x = 15;
    y = 2;
    for ( int a=0;a<6;a++ )
    {
      if ( a>2 ) x = 75;
      if ( a==3 ) y = 2;
      ReefAngel.LCD.DrawText( COLOR_DARKGOLDENROD,DefaultBGColor,x,y,"Ch :" );
      ReefAngel.LCD.DrawText( COLOR_DARKGOLDENROD,DefaultBGColor,x+12,y,a );
      ReefAngel.LCD.DrawText( COLOR_DARKGOLDENROD,DefaultBGColor,x+24,y,ReefAngel.PWM.GetChannelValue(a) );
      y += 10;
    }
    pingSerial();

    // I/O Expansion
    byte bkcolor;
    x = 14;
    y = 34;
    for ( int a=0;a<6;a++ )
    {
      ReefAngel.LCD.DrawCircleOutline( x+(a*20),y,4,COLOR_MEDIUMORCHID );
      if ( ReefAngel.IO.GetChannel(a) ) bkcolor=COLOR_WHITE; else bkcolor=COLOR_GRAY;
      ReefAngel.LCD.FillCircle( x+(a*20),y,2,bkcolor );
    }
    pingSerial();

    // Parameters
#if defined DisplayLEDPWM && ! defined RemoveAllLights
    ReefAngel.LCD.DrawMonitor( 15, 44, ReefAngel.Params,
    ReefAngel.PWM.GetDaylightValue(), ReefAngel.PWM.GetActinicValue() );
#else // defined DisplayLEDPWM && ! defined RemoveAllLights
    ReefAngel.LCD.DrawMonitor( 15, 44, ReefAngel.Params );
#endif // defined DisplayLEDPWM && ! defined RemoveAllLights
    pingSerial();

    // Salinity
    ReefAngel.LCD.DrawText( COLOR_DARKKHAKI,DefaultBGColor,15,76, "SAL:" );
    ReefAngel.LCD.DrawText( COLOR_DARKKHAKI,DefaultBGColor,39,76, ReefAngel.Params.Salinity );
    pingSerial();

    // Main Relay Box
    byte TempRelay = ReefAngel.Relay.RelayData;
    TempRelay &= ReefAngel.Relay.RelayMaskOff;
    TempRelay |= ReefAngel.Relay.RelayMaskOn;
    ReefAngel.LCD.DrawOutletBox( 12, 90, TempRelay );
    pingSerial();

    // Relay Expansion
    TempRelay = ReefAngel.Relay.RelayDataE[0];
    TempRelay &= ReefAngel.Relay.RelayMaskOffE[0];
    TempRelay |= ReefAngel.Relay.RelayMaskOnE[0];
    ReefAngel.LCD.DrawOutletBox( 12, 104, TempRelay );
    pingSerial();

    // Date and Time
    ReefAngel.LCD.DrawDate( 6, 122 );
    pingSerial();
}

void DrawCustomGraph()
{
}