This is working PREFECT NOW! Thanks Roberto.
Here is my total current running config with this working for anyone that has been following along that the code might be useful for.
What it does...
My Dual ATO is set to have a very small window where neither of my two top off float switches are active. When the low switch becomes active (low water state) the MaxiJet 600 pump in my RO/DI topoff Brute starts pumping water into my sump. Because my window (the activation levels between my two ATO float switches) is very small (less than a 1/2 inch of water) my topoff pump will activate and pump more frequently for a short period of time at each activation. I have set a fairly aggressive ATO timeout of 40 seconds. During normal conditions when the ATO low switch becomes active and the pump activates it takes less than 30 seconds to pump in the required water to activate the ATO High Float switch (ATO cycle to full optimum level) this should normally NOT exceed the 40 seconds I have allotted before the ATO pump shuts off and sets the ATO timeout flag. If it DOES in fact time out and sets the timeout flag this tells me that my ATO high topoff float switch probably malfunctioned and that my sump has more water in it at this point than the "optimum" level. This could cause my skimmer to overflow so I decided if the timeout activated it might be wise to turn off my skimmer to prevent it from overflowing. I used the custom variables to make the fact that an ATO timeout has occurred visible on the portal. I also configured the portal to email me and let me know this has occurred. At this point manual intervention is required to clear the ATO timeout from the Android app and also lets me wait a while for some evaporation to occur before I use the android app to remove the mask and set my skimmer back to auto/on mode. Now while I am not home I will be notified that my ATO timed out and there will be NO MORE topoff function until I intervene. This will let me take the appropriate steps to clear the ATO timeout flag and prevent my sump's return section from evaporating and not getting topped off and running dry in the event the timeout occurs while I am away. Since it takes almost 48 hours for enough water to evap from my sump before my pump pumps dry this gives me plenty of warning that I need to do something.
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,40 );
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()
{
}