ATO Topoff Brute Chosen By Salinity?
-
- Posts: 289
- Joined: Wed May 16, 2012 9:52 pm
ATO Topoff Brute Chosen By Salinity?
I am working on some ideas for my RA+ setup and I am set up with two 44 gallon Brutes. One for Saltwater and the other for RO/DI water. Currently I am using the default dual float switch ATO method. My salt levels are slowly decreasing due to salt creep in various places. I have set up both of my Brutes with Empty/Full float switches going to my IO module and both brutes also have a MaxiJet 600 at the bottom that pumps water to my sump. For the RO/DI brute the pump is for ATO. For the Saltwater brute the pump is for Water Changes. Since essentially both brutes are set up identically I could use either for topoff. So I am thinking I want my RA+ to read salinity from my salinity probe just before an auto topoff event and if the salinity is below level x ppt then top off with Saltwater from the saltwater brute and if the salinity is above x ppt to topoff with RO/DI water from the RO/DI brute?
I am not familiar with arduino coding syntax but basically want to something like this
IF autotopoff low float switch is active
THEN read salinity probe value
IF Salinity probe value <30ppt
THEN check if SW brute is empty (IO port 2 is active)
IF SWbrute is empty set alarm flag swbruteempty = 1 and end function
IF SWbrute is not empty (IO port 2 not active)
THEN activate SWPump relay port (primary relay box port 7) UNTIL Autotopoff High float switch is active or timeout
IF Salinity probe value =>30ppt
THEN check if RODI brute is empty (IO port 4 is active)
IF RODIbrute is empty set alarm flag rodibruteempty = 1 and end function
IF RODIbrute is not empty (IO port 4 not active)
THEN activate RODIPump relay port (primary relay box port 2) UNTIL Autotopoff High float switch is active or timeout
Anyone wanna help me out with some code?
Nick
I am not familiar with arduino coding syntax but basically want to something like this
IF autotopoff low float switch is active
THEN read salinity probe value
IF Salinity probe value <30ppt
THEN check if SW brute is empty (IO port 2 is active)
IF SWbrute is empty set alarm flag swbruteempty = 1 and end function
IF SWbrute is not empty (IO port 2 not active)
THEN activate SWPump relay port (primary relay box port 7) UNTIL Autotopoff High float switch is active or timeout
IF Salinity probe value =>30ppt
THEN check if RODI brute is empty (IO port 4 is active)
IF RODIbrute is empty set alarm flag rodibruteempty = 1 and end function
IF RODIbrute is not empty (IO port 4 not active)
THEN activate RODIPump relay port (primary relay box port 2) UNTIL Autotopoff High float switch is active or timeout
Anyone wanna help me out with some code?
Nick
180G FOWLR
20GH QT#1
29G QT#2

20GH QT#1
29G QT#2
Re: ATO Topoff Brute Chosen By Salinity?
Try this:
Code: Select all
if (ReefAngel.LowATO.IsActive())
{
if (ReefAngel.Params.Salinity<300)
{
if (ReefAngel.IO.GetChannel(2))
swbruteempty = 1;
else
ReefAngel.StandardATO(Port7);
}
else
{
if (ReefAngel.IO.GetChannel(4))
rodibruteempty = 1;
else
ReefAngel.StandardATO(Port2);
}
}
Roberto.
-
- Posts: 289
- Joined: Wed May 16, 2012 9:52 pm
Re: ATO Topoff Brute Chosen By Salinity?
Thanks Roberto. I will have to play with this.
I assume this code will replace my line...
ReefAngel.StandardATO( Port2,40 );
and if it does will the dual ato switches and safety timeout still function?
and if the ATOHigh switch becomes active while topping off (from either pump) how will the controller know which pump port to switch off?
Nick
I assume this code will replace my line...
ReefAngel.StandardATO( Port2,40 );
and if it does will the dual ato switches and safety timeout still function?
and if the ATOHigh switch becomes active while topping off (from either pump) how will the controller know which pump port to switch off?
Nick
180G FOWLR
20GH QT#1
29G QT#2

20GH QT#1
29G QT#2
Re: ATO Topoff Brute Chosen By Salinity?
Now that I'm looking at the code, I don't think it will work.
Roberto.
-
- Posts: 289
- Joined: Wed May 16, 2012 9:52 pm
Re: ATO Topoff Brute Chosen By Salinity?
I have not tried this yet due to you saying you think it wont work. I'm not any good at the syntax yet but from what I see in the code you posted it seems logical and like it would work to me. What makes you think it will not?
Nick
Nick
180G FOWLR
20GH QT#1
29G QT#2

20GH QT#1
29G QT#2
Re: ATO Topoff Brute Chosen By Salinity?
We will need to change it.
It is all depending on the Low switch to be active.
When water makes it float, it would never stop the pumps.
Do you really need the flags?
Could it be a single flag?
It would simplify things.
It would be something like this:
It is all depending on the Low switch to be active.
When water makes it float, it would never stop the pumps.
Do you really need the flags?
Could it be a single flag?
It would simplify things.
It would be something like this:
Code: Select all
static byte ATOPort;
static byte IOPort;
if (ReefAngel.Params.Salinity<300)
{
ATOPort=Port7;
IOPort=2;
}
else
{
ATOPort=Port2;
IOPort=4;
}
if (ReefAngel.IO.GetChannel(IOPort))
bruteempty = 1;
else
ReefAngel.StandardATO(ATOPort);
Roberto.
-
- Posts: 289
- Joined: Wed May 16, 2012 9:52 pm
Re: ATO Topoff Brute Chosen By Salinity?
I would like to have a flag for each brute to tell me when it is empty and sound (prefer a chirp every x minutes) my buzzer to tell me I need to kick on my RODI. I can just look at the IO Module display screen from my android and see that the Empty IO switch is on/off at any time to know if either is empty however I would like to set a custom Variable and use it to send me an e-mail if a brute is empty.
Looking at the code you provided here I don't see a reason that I MUST set a flag during ATO cycle. It seems this flag could be raised during my normal loop cycle if a brute is empty.
So long as the controller does not kick on a pump in an empty brute I think I'm happy.
Thinking to the future my next project (when I get my IO Mod sorted out) is to do my water change coding in which I will also not want a pump to kick on in an empty brute.
Nick
Looking at the code you provided here I don't see a reason that I MUST set a flag during ATO cycle. It seems this flag could be raised during my normal loop cycle if a brute is empty.
So long as the controller does not kick on a pump in an empty brute I think I'm happy.
Thinking to the future my next project (when I get my IO Mod sorted out) is to do my water change coding in which I will also not want a pump to kick on in an empty brute.
Nick
180G FOWLR
20GH QT#1
29G QT#2

20GH QT#1
29G QT#2
Re: ATO Topoff Brute Chosen By Salinity?
You are correct. The flag could be raised in the loop 

Roberto.
-
- Posts: 289
- Joined: Wed May 16, 2012 9:52 pm
Re: ATO Topoff Brute Chosen By Salinity?
Revisiting this...
The more I think about this, the more I am thinking...
Why not just take my ATO port definition "ReefAngel.StandardATO( Port2,40 );"
in my code and change the "Port2" part to a variable then read my salinity value just before this line in my main loop and set that variable according to my salinity value... Duh... seems this would be the perfect solution and I would still keep the 40 second safety timeout. I was also thinking that I check my IO Mod ports for each Brute in my normal loop and if either "BruteEmpty" IO mod port is active just mask the port for that pump off and set an alert/E-mail to inform me.
Hmmm... time to get back into my code...
Nick
The more I think about this, the more I am thinking...
Why not just take my ATO port definition "ReefAngel.StandardATO( Port2,40 );"
in my code and change the "Port2" part to a variable then read my salinity value just before this line in my main loop and set that variable according to my salinity value... Duh... seems this would be the perfect solution and I would still keep the 40 second safety timeout. I was also thinking that I check my IO Mod ports for each Brute in my normal loop and if either "BruteEmpty" IO mod port is active just mask the port for that pump off and set an alert/E-mail to inform me.
Hmmm... time to get back into my code...
Nick
180G FOWLR
20GH QT#1
29G QT#2

20GH QT#1
29G QT#2
-
- Posts: 289
- Joined: Wed May 16, 2012 9:52 pm
Re: ATO Topoff Brute Chosen By Salinity?
lol... funny... takes this coding stuff a while to sink in at times but I guess that is exactly what your last piece of code above essentially does.00Warpig00 wrote:Revisiting this...
The more I think about this, the more I am thinking...
Why not just take my ATO port definition "ReefAngel.StandardATO( Port2,40 );"
in my code and change the "Port2" part to a variable then read my salinity value just before this line in my main loop and set that variable according to my salinity value... Duh... seems this would be the perfect solution and I would still keep the 40 second safety timeout. I was also thinking that I check my IO Mod ports for each Brute in my normal loop and if either "BruteEmpty" IO mod port is active just mask the port for that pump off and set an alert/E-mail to inform me.
Hmmm... time to get back into my code...
Nick

Nick
180G FOWLR
20GH QT#1
29G QT#2

20GH QT#1
29G QT#2
-
- Posts: 289
- Joined: Wed May 16, 2012 9:52 pm
Re: ATO Topoff Brute Chosen By Salinity?
Thinking about giving this code a shot... Any comments...
I have the parts I have added commented between...
//*****Begin ATO By Salinity Additions
//*****End ATO By Salinity Additions
remarks.
So far without the Alert/Email portion...
Open to feedback.
Nick
I have the parts I have added commented between...
//*****Begin ATO By Salinity Additions
//*****End ATO By Salinity Additions
remarks.
So far without the Alert/Email portion...
Open to feedback.

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 <PH.h>
#include <WaterLevel.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
//*****Begin WC Additions
// Ports associated with ATO Ports
// can be multiple ports
byte ATOPorts = 0;
// skimmer port
byte SkimmerPort = Port4;
// return port
byte ReturnPort = Port3;
// sump drain port
byte SumpDrainPort = Port8;
// SaltWater brute pump
byte SWBrutePort = Port7;
// Timer for countdowns
TimerClass tm;
//*****End WC Additions
//*****Begin ATO By Salinity Additions
byte ATOBrutePort = Port2;
//*****End ATO By Salinity Additions
////// 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
//*****WC ReefAngel.WaterChangePorts = Port3Bit | Port4Bit;
//*****WC 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
//*****Begin WC Additions
// ATOPorts = Port1 | Port2; // ports 1 & 2
//*****End WC Additions
ReefAngel.CustomVar[0]=0;
ReefAngel.CustomVar[1]=0;
ReefAngel.CustomVar[2]=0;
ReefAngel.CustomVar[3]=0;
ReefAngel.CustomVar[4]=0;
ReefAngel.CustomVar[5]=0;
ReefAngel.CustomVar[6]=0;
ReefAngel.CustomVar[7]=255;
////// Place additional initialization code above here
}
void loop()
{
ReefAngel.StandardFan( Port1,790,820 );
//*****ATO ReefAngel.StandardATO( Port2,40 );
ReefAngel.Relay.DelayedOn( Port4,1 );
// 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 );
ReefAngel.PWM.SetActinic(millis()%30000<100?buzzer:0);
ReefAngel.PWM.SetDaylight(millis()%30000<100?buzzer:0);
////// Place your custom code below here
ReefAngel.CustomVar[0]=InternalMemory.read(ATO_Exceed_Flag);
ReefAngel.CustomVar[1]=InternalMemory.read(Overheat_Exceed_Flag);
ReefAngel.CustomVar[2]=InternalMemory.read(10);
ReefAngel.CustomVar[3]=0;
ReefAngel.CustomVar[4]=0;
ReefAngel.CustomVar[5]=0;
ReefAngel.CustomVar[6]=0;
ReefAngel.CustomVar[7]=255;
if ( ReefAngel.CustomVar[0]== 1 )
{
ReefAngel.Relay.RelayMaskOff=~(Port4Bit);
}
//*****Begin WC Additions
// If memory location 10 equals 1
// then we start the automatic water change
// Otherwise we ignore and proceed
if (ReefAngel.DisplayedMenu==WATERCHANGE_MODE)
// if ( InternalMemory.read(10) == 1 )
{
AutoWaterChange();
}
//*****End WC Additions
//*****Begin ATO By Salinity Additions
if (ReefAngel.Params.Salinity<300)
{
ATOBrutePort=Port7;
}
else
{
ATOBrutePort=Port2;
}
ReefAngel.StandardATO(ATOBrutePort,40 );
if (iochannel2flag == 1)
{
ReefAngel.Relay.RelayMaskOff=~(Port7Bit);
}
if (iochannel4flag == 1)
{
ReefAngel.Relay.RelayMaskOff=~(Port2Bit);
}
//*****End ATO By Salinity Additions
////// Place your custom code above here
// This should always be the last line
ReefAngel.Portal( "00Warpig00" );
ReefAngel.ShowInterface();
}
//*****Begin WC Additions
void AutoWaterChange()
{
// auto water change mode
//display internal memory location 10 water change mode
// ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 50, " ");
// ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 50, "internal Memory 10");
// ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 60, ReefAngel.CustomVar[2] ); waitForTime(3);
// Display Starting Water Change"
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Starting Water Change"); waitForTime(3);
// Check Saltwater BRUTE for sufficient saltwater on IO Module Port2
if ( isSWBruteEmpty() )
{
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Not Enough Saltwater"); waitForTime(3);
//Abort Water Change if insufficient saltwater
// Handles the cleanup to return to the main screen
ReefAngel.ClearScreen(DefaultBGColor);
ReefAngel.DisplayedMenu = DEFAULT_MENU;
DrawCustomGraph();
return;
}
//Display Disabling ATO Pump
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Disabling ATO Pump"); waitForTime(3);
// turn off ATO pump port to prevent ATO from trying to fill a sump being drained intentionally
// ReefAngel.Relay.RelayMaskOff = ~ATOPorts;
ReefAngel.Relay.RelayMaskOff=~(Port2Bit);
//ReefAngel.Relay.Write();
//Display Stopping Skimmer
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Stopping Skimmer"); waitForTime(3);
// turn off the skimmer port
ReefAngel.Relay.Off(SkimmerPort);
ReefAngel.Relay.Write();
//Display Skimmer Draining
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Skimmer Draining"); waitForTime(3);
// wait for 1 minute
waitForTime(60);
//Display Skimmer Done Draining
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Skimmer Done Draining"); waitForTime(3);
//display Stopping Return Pump
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Stopping Return Pump"); waitForTime(3);
//Stop Return Pump
ReefAngel.Relay.Off(ReturnPort);
ReefAngel.Relay.Write();
//Display Draining To Sump
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Draining To Sump"); waitForTime(3);
//display Sump Filling
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Sump Filling"); waitForTime(3);
// wait for IO Mod Port 1 to be active
waitForIOChannel(1);
//display Sump Is Full
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Sump Is Full"); waitForTime(3);
//Display Sump Settling
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Sump Settling"); waitForTime(3);
// wait for sump to settle
waitForTime(30);
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Sump Settled"); waitForTime(3);
// display Draining Sump
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Start Draining Sump"); waitForTime(3);
//turn on sump drain pump
ReefAngel.Relay.On(SumpDrainPort);
ReefAngel.Relay.Write();
//display Sump Draining
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Sump Draining"); waitForTime(3);
// wait for sump empty port active, IO Mod Port 0
waitForIOChannel(0);
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Sump Is Empty"); waitForTime(3);
//display Stopping Sump Draining
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Stopping Sump Drain"); waitForTime(3);
// turn off sump drain
ReefAngel.Relay.Off(SumpDrainPort);
ReefAngel.Relay.Write();
//Display Sump Settling
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Sump Settling"); waitForTime(3);
// wait for sump to settle
waitForTime(30);
//display Sump Settled
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Sump Settled"); waitForTime(3);
//display Starting Saltwater Pump
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Start Saltwater Pump"); waitForTime(3);
//turn on Saltwater Pump
ReefAngel.Relay.On(SWBrutePort);
ReefAngel.Relay.Write();
//display Saltwater Pumping
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Saltwater Pumping"); waitForTime(3);
// wait for sump full float switch active, IO Mod Port 1
waitForIOChannel(1);
//display Stop Saltwater Pump
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Stop Saltwater Pump"); waitForTime(3);
// turn off sw brute pump
ReefAngel.Relay.Off(SWBrutePort);
ReefAngel.Relay.Write();
//diasplay Sump is Full
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Sump Is Full"); waitForTime(3);
//Display Sump Settling
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Sump Settling"); waitForTime(3);
// wait for sump to settle
waitForTime(30);
//display Sump Settled
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Sump Settled"); waitForTime(3);
//display Starting Return Pump
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Starting Return Pump"); waitForTime(3);
// turn on return pump
ReefAngel.Relay.On(ReturnPort);
ReefAngel.Relay.Write();
//display Return Pump Started
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Return Pump Started"); waitForTime(3);
//display Normalizing Waterlevel
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Normalizing Waterlevel"); waitForTime(3);
//waiting 2 minutes for waterlevel to normalize
waitForTime(120);
//display Starting Skimer
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Starting Skimmer"); waitForTime(3);
//turn on skimmer
ReefAngel.Relay.On(SkimmerPort);
ReefAngel.Relay.Write();
//display Normalizing Skimmer
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Normalizing Skimmer"); waitForTime(3);
//wait for 2 minutes for skimmer to normalize
waitForTime(120);
//display Skimmer Normalized
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Skimmer Normalized"); waitForTime(3);
//display Enabling ATO Pump
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Enabling ATO Pump"); waitForTime(3);
//Enable ATO pump
ReefAngel.Relay.RelayMaskOff = B11111111;
ReefAngel.Relay.Write();
//display Water Change Complete
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, " ");
ReefAngel.LCD.DrawText(ModeScreenColor, DefaultBGColor, 2, 30, "Water Change Complete"); waitForTime(3);
// Handles the cleanup to return to the main screen
ReefAngel.ClearScreen(DefaultBGColor);
ReefAngel.DisplayedMenu = DEFAULT_MENU;
DrawCustomGraph();
}
bool isSWBruteEmpty()
{
// check status of IO Mod Port 2
if ( ! ReefAngel.IO.GetChannel(2) )
return true;
return false;
}
void waitForTime(int seconds)
{
bool done = false;
tm.SetInterval(seconds);
tm.Start();
int t = tm.Trigger - now();
do
{
// check the wifi interface
pingSerial();
// wait for specified seconds
if ( (t >= 0) && ! tm.IsTriggered() )
{
// TODO finish countdown on screen
// show countdown on screen
//LCD.Clear(DefaultBGColor,60+(intlength(t)*5),100,100,108);
//LCD.DrawText(DefaultFGColor,DefaultBGColor,60,100,t);
wdt_reset();
delay(200);
}
else
{
done = true;
}
} while ( !done );
return;
}
void waitForIOChannel(byte channel)
{
// TODO complete this function
do
{
wdt_reset();
// display something on screen
// check the wifi interface
pingSerial();
delay(200);
// TODO check the IO channel logic
} while ( ReefAngel.IO.GetChannel(channel) );
}
//*****End WC Additions
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()
{
}
Nick
180G FOWLR
20GH QT#1
29G QT#2

20GH QT#1
29G QT#2
-
- Posts: 289
- Joined: Wed May 16, 2012 9:52 pm
Re: ATO Topoff Brute Chosen By Salinity?
Testing seems to be going well on this. It appears to function properly.
One more item off my list.
Nick

One more item off my list.

Nick
180G FOWLR
20GH QT#1
29G QT#2

20GH QT#1
29G QT#2
Re: ATO Topoff Brute Chosen By Salinity?
Awesome. Keep up the work.00Warpig00 wrote:Testing seems to be going well on this. It appears to function properly.![]()
One more item off my list.
Nick

ATO Topoff Brute Chosen By Salinity?
Just curious, after reading your pde for your auto water change and reading this on how/why you did the selective ATO...
Have you considered doing automatic continuous water changes? I've known of the concept for a while, but just read a really basic summary of how you would do it with a salinity probe, which is what led me back here...
Basically, without shutting off your equipment, you turn on a drain for x amount of time. You let your selective ATO refill your sump based on the salinity. Obviously, never taking out more than your system can handle, but since it's automated you can do it in as small or as many increments as you want.
I believe I recall reading that continuous WC is at least 90% as effective as a full one time swap, maybe even up to 98% but I don't recall the source.
Anyway, just wondering if you had considered it, or if that was the next step in the evolution...
If I had my rig in the basement near my mixing station, I'd be all over it!
Have you considered doing automatic continuous water changes? I've known of the concept for a while, but just read a really basic summary of how you would do it with a salinity probe, which is what led me back here...
Basically, without shutting off your equipment, you turn on a drain for x amount of time. You let your selective ATO refill your sump based on the salinity. Obviously, never taking out more than your system can handle, but since it's automated you can do it in as small or as many increments as you want.
I believe I recall reading that continuous WC is at least 90% as effective as a full one time swap, maybe even up to 98% but I don't recall the source.
Anyway, just wondering if you had considered it, or if that was the next step in the evolution...
If I had my rig in the basement near my mixing station, I'd be all over it!

-
- Posts: 289
- Joined: Wed May 16, 2012 9:52 pm
Re: ATO Topoff Brute Chosen By Salinity?
I may go to a daily water change routine eventually. In theory all I would need to do is move a couple float switches around in my sump and change some code to fire off the function on a scheduled basis. Right now I have two issues with non supervised water changes. I have not built up a trust level that everything will function properly EVERY TIME without failure. I also have a simple logistics issue. I do not have a drain that I can put permanent plumbing to that is near my tank. I currently need to unroll a 15 foot long hose and drape it across the room and put the end in the sink to do a water change. If I had an easy way to put some plumbing in to make that drain more permanent then those ideas would be much more attractive to me.
Nick
Nick
180G FOWLR
20GH QT#1
29G QT#2

20GH QT#1
29G QT#2