Yes.. it is called from the loop. In fact every once in a while I get a shutdown for some reason. So the rest of the code works.
I use similar code in others parts, with no luck either. I posted the shutdown function just to ilustrate.
But I know... nothing better than the real code, so.. here it is. I am not a professional programmer, so dont be very judgmental..
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 <Humidity.h>
#include <DCPump.h>
#include <WiFiAlert.h>
#include <ReefAngel.h>
void startTimeRunningRetPump();
void checkMaxSewer();
void checkMinWaterSump();
void checkMaxWaterSump();
void checkMaxReservoir();
void emergencyShutDown(char *message);
void WChange();
void DrawCustomMain();
void feedingMode();
void waterFallControl();
void setFlowPump();
void DrawRelays();
void DrawMainScreen();
void dailyRebootReefAngel();
void checkCleaningMode();
void phControl();
void tempControl();
void cleanningPump();
void lightsControl();
//######################################## CUSTOM MENU ###########################################
#include <avr/pgmspace.h>
prog_char menu0_label[] PROGMEM = "Feeding Mode";
prog_char menu1_label[] PROGMEM = "Auto Feed";
prog_char menu2_label[] PROGMEM = "Water Change";
prog_char menu3_label[] PROGMEM = "Water Level Calib.";
prog_char menu4_label[] PROGMEM = "PH Calibration";
prog_char menu5_label[] PROGMEM = "Shut Down";
prog_char menu6_label[] PROGMEM = "Cleaning Mode";
prog_char menu7_label[] PROGMEM = "Manual Lights on/off";
prog_char menu8_label[] PROGMEM = "Reboot ReefAngel";
PROGMEM const char *menu_items[] = {
menu0_label, menu1_label, menu2_label,
menu3_label, menu4_label, menu5_label,
menu6_label, menu7_label, menu8_label//, menu8_label
};
//#################################################################################################
//######################################## CUSTOM MODES ###########################################
//auto feed option on feed mode
boolean AUTOFEED=true;
//if true, disable max sump water level check to be able to clean the aquarium
//using the sump.
boolean CLEANING_MODE=false;
#define MAX_TIME_CLEANING_MODE 3600 //1 hour to clean aquarium. After that, regular checking is on.
//Water Change Status
int WC_STATUS=0;
//perform regular level checks after some time after return pump is on
boolean RETPUMP_ON_TIME=false;
//#################################################################################################
//#################################### REEF ANGEL SCREEN LOG ######################################
//log message
boolean DISPLAYLOG=false;
char *LOGMESSAGE;
//#################################################################################################
//#################################### RELAY PORTS ################################################
//Rename ports
#define LIGHTS Port1
#define WOUT Port2
#define COOLER_SUMP Port3
#define CO2 Port4
#define WIN Port5
#define WCHANGE Port6
#define NOT_USED_01 Port7
#define DOSER_02 Port8
#define HEATER_SUMP Box1_Port1
#define FEEDER Box1_Port2
#define DOSER_01 Box1_Port3
#define UV Box1_Port4
#define HEATER_RESERVOIR Box1_Port5
#define COOLER_RESERVOIR Box1_Port6
#define O2 Box1_Port7
#define CLEANER_PUMP Box1_Port8
//#################################################################################################
//#################################### CUSTON VARS ################################################
#define RETPUMP_ON_TIME_C_VAR 0
#define LAST_AWC 1
#define EMERNCY_SHUTDOWN 2
#define LAST_AUTO_FEED 3
//#################################################################################################
//#################################### TEMP PROBES ################################################
//Define Temp Probes
#define SUMP_TEMP_PROBE T1_PROBE
#define RESERVOIR_TEMP_PROBE T2_PROBE
#define REFUGIUM_TEMP_PROBE T3_PROBE
//#################################################################################################
//#################################### WATER LEVEL ################################################
//Define WaterLevel Channels
#define WL_SEWER 1
#define WL_REFUGIUM 2
#define WL_RESERVOIR 3
#define WL_SUMP 4
//#################################################################################################
//######################## WATER CHANGE PARAMETERS AND WATER LEVEL CONTROL ########################
//Define times (hour) to Auto Water Change (AWC)
#define WCHANGE_T1 9
#define WCHANGE_T2 16
#define WCHANGE_T3 22
//Min e Max parameters to Auto Water Change (AWC)
#define MIN_SEWER 10 //max sewer level to be able to begin AWC
#define MAX_SEWER 30 //sump max level before emergency sistem shutdow
#define MIN_RESERVOIR_START_WC 80 //min reservoir to be able to begin AWC
#define MAX_RESERVOIR 84 //max reservoir to fill after AWC
#define MIN_RESERVOIR_DURING_CHANGE 15 //min reservoir at change, to avoid pump demage
#define MAX_SUMP 60 //ideal sump level after AWC
#define MIN_WATER_SUMP 40 //minimun Sump Level, preventing pump damage
#define PROXY_MAX_SUMP 1.20 //Value to avoid emercy shotdown on every tyne little level variation.
#define PROXY_MAX_RESERVOIR 1.06 //Value to avoid emercy shotdown on every tyne little level variation.
//AWC max time
#define AWC_MAX_TIME_COMPLETE_CHANGE 1200; //20 minutes
#define AWC_MAX_TIME_RESERVOIR_FILL 300; //5 minutes
//AWC Max Temp Dif
#define AWC_MAX_TEMP_DIF 10 //or 1 C
#define RETURN_PUMP_SECONDS_ON 180 //Running pump time, in seconds, before checking min sump level
#define TIME_TO_EMERGENCY_SHUTDOWN 10 //time to shutdown system. Used to avoid water level miss-reading.
#define WCHANGE_DOSER_SECOND 6 //awc dosing time
//#################################################################################################
//######################################## LIGHTS ################################################
//Time On/Off Lights
#define LIGHTS_ON_H 19
#define LIGHTS_OFF_H 23
//#################################################################################################
//######################################## FEEDING ################################################
//Time do auto-feed
#define FEEDING_H_T1 19
#define FEEDING_M_T1 30
#define FEEDING_H_T2 20
#define FEEDING_M_T2 30
//Number of feeding times done in 15 minutes
#define FEEDING_TIMES 5
#define SECONDS_FEEDER_ON 10 //seconds feeder to complete 1 full rotation
//#################################################################################################
//######################################## REBOOTING #############################################
//Time to reboot reefangel
#define REBOOT_HOUR 0
#define REBOOT_MINUTE 0
//#################################################################################################
//######################################## PH CONTROL #############################################
//Define Max and Min PH
#define TARGET_PH 635
#define PH_SUPERIOR_BOUND 639
#define PH_INFERIOR_BOUND 630
#define MAX_PH_TO_ALERT 645
#define MIN_PH_TO_ALERT 625
#define TIME_TO_PH_CHECK 1200 //20 minutes to check low ph and to add bicarbonate
#define DOSER_INCREASE_TIME 10
//#################################################################################################
//###################################### TEMP CONTROL #############################################
//Target tenperature, in celcius
#define TARGET_TEMP 285
#define MIN_TEMP 280
#define MAX_TEMP 290
#define MAX_TEMP_TO_ALERT 300
#define MIN_TEMP_TO_ALERT 270
//#################################################################################################
//###################################### WP40 CONTROL #############################################
#define WP40_FLOW_RATE 30
#define WP40_VARIATION 5
//#################################################################################################
//################################### WATER FLOW CONTROL ##########################################
//Consts to regulate the water flow
#define INI_FLOW 100
#define SWITCH_ON_SECONDS 3
#define STEP_DOWN_VALUE 10
#define SWITCH_DOWN_SECONDS 2
#define TOTAL_STEP_DOWN_VALUE 1
#define RESET_TIME_SECONDS 3600
#define CLENER_PUMP_CICLE_MINUTES 1
#define CLENER_PUMP_DURATION_SECONDS 15
#define SWITCH_ON_CLEANER_SECONDS 5
//#################################################################################################
//################################### CLEANNING PUMP CONTROL ######################################
#define CLEANNING_PUMP_ON_TIME 60 //1 minute on
#define CLEANNING_PUMP_OFF_TIME 600 //10 minutes off
//#################################################################################################
void setup()
{
// This must be the first line
ReefAngel.Init(); //Initialize controller
ReefAngel.InitMenu(pgm_read_word(&(menu_items[0])),SIZE(menu_items)); //inicialize Menu
ReefAngel.SetTemperatureUnit(Celsius); // set to Celsius Temperature
ReefAngel.AddMultiChannelWaterLevelExpansion(); // Water Level Expansion Module
ReefAngel.FeedingModePorts = 0; //control it manually
ReefAngel.WaterChangePorts = 0; //control it manually
ReefAngel.OverheatShutoffPorts = 0; //control it manually
ReefAngel.LightsOnPorts = 0; //control it manually
//relays allways on
ReefAngel.Relay.On(UV);
//dns
ReefAngel.DDNS("home");
//relays allways off
ReefAngel.Relay.Off(LIGHTS);
ReefAngel.Relay.Off(WOUT);
ReefAngel.Relay.Off(COOLER_SUMP);
ReefAngel.Relay.Off(CO2);
ReefAngel.Relay.Off(WIN);
ReefAngel.Relay.Off(WCHANGE);
ReefAngel.Relay.Off(NOT_USED_01);
ReefAngel.Relay.Off(DOSER_02);
ReefAngel.Relay.Off(HEATER_SUMP);
ReefAngel.Relay.Off(FEEDER);
ReefAngel.Relay.Off(DOSER_01);
ReefAngel.Relay.Off(HEATER_RESERVOIR);
ReefAngel.Relay.Off(COOLER_RESERVOIR);
ReefAngel.Relay.Off(O2);
ReefAngel.Relay.Off(CLEANER_PUMP);
}
void loop()
{
//ReefAngel Portal
ReefAngel.Portal("rrodriguess","xxxxxxxxxxxxxxx";
//Lights Control
lightsControl();
//#################### MAIN PUMPS ####################
//Set runnning return pump time
startTimeRunningRetPump();
//Set flow pump WP40
setFlowPump();
//control water fall to sump
waterFallControl();
//CleanningPump
cleanningPump();
//#################### WATER CHANGE ####################
//Auto Water Change (AWC) function
WChange();
//#################### MODES ####################
//feeding mode
feedingMode();
//Cleaning Mode contro
checkCleaningMode();
//#################### CONTROLS ####################
//Ph control using CO2 (solenoid) and dosing 02
phControl();
//Sump and Reservoir Temp Control using heaters and fan
tempControl();
//#################### CHECKS ####################
//prevent pump damage on low eater level
checkMinWaterSump();
//prevent sump overflow
checkMaxWaterSump();
//prevent sewer overflow
checkMaxSewer();
//prevent Reservoir overflow
checkMaxReservoir();
//#################### REBOOT ####################
//reboot Reefangel midnigh to prevent address variable corrution
dailyRebootReefAngel();
////// Place your custom code above here
// This should always be the last line
ReefAngel.ShowInterface();
}
void lightsControl(){
if(hour()>=LIGHTS_ON_H && hour() <= LIGHTS_OFF_H) ReefAngel.Relay.Set(LIGHTS, true);
else ReefAngel.Relay.Set(LIGHTS, false);
}
void tempControl(){
//temp control - heater
if(ReefAngel.Params.Temp[SUMP_TEMP_PROBE] >= TARGET_TEMP) ReefAngel.Relay.Set(HEATER_SUMP, false);
if(ReefAngel.Params.Temp[SUMP_TEMP_PROBE] <= MIN_TEMP) ReefAngel.Relay.Set(HEATER_SUMP, true && RETPUMP_ON_TIME);
if(ReefAngel.Params.Temp[RESERVOIR_TEMP_PROBE] >= TARGET_TEMP) ReefAngel.Relay.Set(HEATER_RESERVOIR, false);
if(ReefAngel.Params.Temp[RESERVOIR_TEMP_PROBE] <= MIN_TEMP) ReefAngel.Relay.Set(HEATER_RESERVOIR, true);
//temp control - fan
if(ReefAngel.Params.Temp[SUMP_TEMP_PROBE] <= TARGET_TEMP) ReefAngel.Relay.Set(COOLER_SUMP, false);
if(ReefAngel.Params.Temp[SUMP_TEMP_PROBE] >= MAX_TEMP) ReefAngel.Relay.Set(COOLER_SUMP, true && RETPUMP_ON_TIME);
if(ReefAngel.Params.Temp[RESERVOIR_TEMP_PROBE] <= TARGET_TEMP) ReefAngel.Relay.Set(COOLER_RESERVOIR, false);
if(ReefAngel.Params.Temp[RESERVOIR_TEMP_PROBE] >= MAX_TEMP) ReefAngel.Relay.Set(COOLER_RESERVOIR, true);
}
void phControl(){
static boolean doseIt=false;
static long timeToCheck=now()+TIME_TO_PH_CHECK;
static long runningTime=0;
static boolean check=true;
if(RETPUMP_ON_TIME==false || CLEANING_MODE || WC_STATUS>0 || ReefAngel.DisplayedMenu==FEEDING_MODE){
ReefAngel.Relay.Set(CO2, false);
ReefAngel.Relay.Set(O2, false);
ReefAngel.Relay.Set(DOSER_02, false);
return;
}
if(doseIt==false && ReefAngel.Params.PH < PH_INFERIOR_BOUND) doseIt = true;//set dose if PH < PH INFERIOR BOUND
if(doseIt==true && ReefAngel.Params.PH >= TARGET_PH) doseIt = false; //set back dose only if PH >= TARGET_PH
if(now()>timeToCheck){ //set next time to check;
timeToCheck=now()+TIME_TO_PH_CHECK;
check=true;
}
if(doseIt && check){
runningTime = now() + DOSER_INCREASE_TIME;
check=false;
}
ReefAngel.Relay.Set(DOSER_02, runningTime >= now() && doseIt);
//PH Control - increase PH
ReefAngel.PHControl(O2,PH_INFERIOR_BOUND,TARGET_PH);
//PH Control - decrease PH
if(ReefAngel.Relay.Status(UV) && RETPUMP_ON_TIME){
ReefAngel.CO2Control(CO2,TARGET_PH,PH_SUPERIOR_BOUND );
}
else {
ReefAngel.Relay.Set(CO2, false);
}
}
void checkCleaningMode(){
static long startTime=0;
if(WC_STATUS>0 || ReefAngel.DisplayedMenu==FEEDING_MODE) CLEANING_MODE=false;
if(CLEANING_MODE){
if(startTime==0){
startTime=now();
}
if((now()-startTime) > MAX_TIME_CLEANING_MODE){
CLEANING_MODE = false;
}
}
else{
startTime=0;
}
}
void setFlowPump(){
//set wp40 flow
if(ReefAngel.Relay.Status(LIGHTS) && ReefAngel.DisplayedMenu!=FEEDING_MODE && RETPUMP_ON_TIME && CLEANING_MODE==false){
ReefAngel.PWM.SetActinic( ReefCrestMode(WP40_FLOW_RATE,WP40_VARIATION,false) );
}
else {
ReefAngel.PWM.SetActinic(0);
}
}
void cleanningPump(){
if(RETPUMP_ON_TIME){
ReefAngel.DosingPumpRepeat( CLEANER_PUMP,0,10,120); //run every 10 minutes for 120 seconds
}
else {
ReefAngel.Relay.Set(CLEANER_PUMP,false);
}
}
void dailyRebootReefAngel(){
//reboot reefangel only if its not feeding time and not AWC
if(hour()==REBOOT_HOUR && minute()==REBOOT_MINUTE && second()==0 && ReefAngel.DisplayedMenu!=FEEDING_MODE && WC_STATUS==0) while(true);
}
void waterFallControl(){
static long countSeconds=0;
static boolean lastStatus = ReefAngel.HighATO.IsActive();
static long startTime=now();
static long OperatingPWM=INI_FLOW;
static long maxPWM=INI_FLOW;
static long upCount=SWITCH_ON_SECONDS;
static boolean stepDown=false;
if(ReefAngel.DisplayedMenu==FEEDING_MODE || CLEANING_MODE==true){
ReefAngel.PWM.SetDaylight(0);
return;
}
ReefAngel.PWM.SetDaylight(OperatingPWM);
if(ReefAngel.HighATO.IsActive() != lastStatus){ //last status changed
lastStatus=ReefAngel.HighATO.IsActive();
upCount=SWITCH_ON_SECONDS;
startTime=now();
}
countSeconds = now()-startTime;
//emergency shutdown
if(lastStatus==true && countSeconds >=70) emergencyShutDown("ATO On 70");
//step down STEP_DOWN_VALUE every SWITCH_ON_SECONDS
if(lastStatus==true && countSeconds > upCount){
OperatingPWM = OperatingPWM - STEP_DOWN_VALUE;
upCount = upCount + SWITCH_ON_SECONDS;
stepDown=true;
}
//step up to maxPWM; Regulate maxPWM - TOTAL_STEP_DOWN_VALUE every stepdown sequence
if(lastStatus==false && countSeconds > SWITCH_DOWN_SECONDS) {
if(stepDown){
stepDown=false;
maxPWM=maxPWM-TOTAL_STEP_DOWN_VALUE;
}
OperatingPWM = maxPWM;
}
//reset maxPWN with INI_FLOW every RESET_TIME_SECONDS
if(lastStatus==false && countSeconds >= RESET_TIME_SECONDS){
startTime=now();
maxPWM = INI_FLOW;
}
}
void startTimeRunningRetPump(){
//set global var true after return pump is running for a certain period of time.
static boolean timerOn=false;
static long finalTime=0;
if(ReefAngel.PWM.GetDaylightValue() >= 30 && !timerOn) {
finalTime = now()+RETURN_PUMP_SECONDS_ON;
timerOn=true;
}
if(now()>=finalTime && ReefAngel.PWM.GetDaylightValue() >= 30) {
RETPUMP_ON_TIME=true;
ReefAngel.CustomVar[EMERNCY_SHUTDOWN]=false; //system is online
}
if(ReefAngel.PWM.GetDaylightValue() < 30){
RETPUMP_ON_TIME=false;
timerOn=false;
}
ReefAngel.CustomVar[RETPUMP_ON_TIME_C_VAR]=RETPUMP_ON_TIME;
}
void checkMaxReservoir()
{
static long startTime=0;
if(ReefAngel.WaterLevel.GetLevel(WL_RESERVOIR) > (MAX_RESERVOIR*PROXY_MAX_RESERVOIR)){
if(startTime==0){
startTime=now();
}
if(now()-startTime > TIME_TO_EMERGENCY_SHUTDOWN){
emergencyShutDown("Res > Max");
}
}
else {
startTime =0;
}
}
void checkMaxSewer()
{
static long startTime=0;
if(ReefAngel.WaterLevel.GetLevel(WL_SEWER) > MAX_SEWER){
if(startTime==0){
startTime=now();
}
if(now()-startTime > TIME_TO_EMERGENCY_SHUTDOWN){
emergencyShutDown("Sewer > Max");
}
}
else {
startTime =0;
}
}
void checkMinWaterSump()
{
static long startTime=0;
if(ReefAngel.WaterLevel.GetLevel(WL_SUMP) <=MIN_WATER_SUMP){
if(startTime==0){
startTime=now();
}
if(now()-startTime > TIME_TO_EMERGENCY_SHUTDOWN){
emergencyShutDown("Sump < Min");
}
}
else {
startTime =0;
}
}
void checkMaxWaterSump()
{
static boolean isOn=false;
static long startTime=0;
if(RETPUMP_ON_TIME && WC_STATUS==0 && ReefAngel.DisplayedMenu!=FEEDING_MODE && !CLEANING_MODE){
if(isOn){
ReefAngel.Relay.Set(WOUT, ReefAngel.WaterLevel.GetLevel(WL_SUMP) > MAX_SUMP);
isOn = ReefAngel.WaterLevel.GetLevel(WL_SUMP) > MAX_SUMP;
}
else {
if(ReefAngel.WaterLevel.GetLevel(WL_SUMP) > MAX_SUMP*PROXY_MAX_SUMP){
if(startTime==0){
startTime=now();
}
}
else {
startTime=0;
}
if(ReefAngel.WaterLevel.GetLevel(WL_SUMP) > MAX_SUMP*PROXY_MAX_SUMP && now()-startTime > TIME_TO_EMERGENCY_SHUTDOWN){
isOn = true;
startTime=0;
}
}
}
else {
startTime=0;
}
}
void emergencyShutDown(char *message){
static WiFiAlert t;
t.SetDelay(0);
t.Send(message);
WC_STATUS=0; //cancel any AWC
DISPLAYLOG=true;
LOGMESSAGE = message;
ReefAngel.PWM.SetDaylight(0); //turn off return pump
ReefAngel.PWM.SetActinic(0); //turn off WP40
ReefAngel.Relay.AllOff();
ReefAngel.CustomVar[EMERNCY_SHUTDOWN]=true;
}
void WChange()
{
static boolean timerOn=false;
static long finalTime=0;
static boolean forceIt=false;
static boolean extraRun=false;
static long wcDosingTimer=0;
static WiFiAlert t;
t.SetDelay(0);
if(WC_STATUS==0 && RETPUMP_ON_TIME && (ReefAngel.DisplayedMenu==WATERCHANGE_MODE || ((hour()==WCHANGE_T1 || hour()==WCHANGE_T2 || hour()==WCHANGE_T3) && minute()==0))){
WC_STATUS=1;
if((hour()==WCHANGE_T1 || hour()==WCHANGE_T2 || hour()==WCHANGE_T3) && minute()==0) forceIt=false;
else forceIt=true;
}
else
if(WC_STATUS==0 && RETPUMP_ON_TIME==false && ReefAngel.DisplayedMenu==WATERCHANGE_MODE){
ReefAngel.DisplayedMenu = RETURN_MAIN_MODE;
}
if(WC_STATUS==0) return;
if(timerOn && now() > finalTime){
WC_STATUS = 8;
emergencyShutDown("AWC Time Exc");
}
switch (WC_STATUS){
case 1:
ReefAngel.WaterChangeModeStart();
ReefAngel.DisplayedMenu = WATERCHANGE_MODE;
if(ReefAngel.WaterLevel.GetLevel(WL_RESERVOIR)<MIN_RESERVOIR_START_WC){
t.Send("Filling reservoir.");
WC_STATUS=5;
timerOn=true;
extraRun=forceIt; //set extraRun only if forceIt=true; Otherwise just fill the reservoir.
if(extraRun){
finalTime = now() + AWC_MAX_TIME_COMPLETE_CHANGE + AWC_MAX_TIME_RESERVOIR_FILL;
}
else {
finalTime = now() + AWC_MAX_TIME_RESERVOIR_FILL;
}
return;
}
else {
t.Send("AWC Started");
timerOn=true;
finalTime = now()+AWC_MAX_TIME_COMPLETE_CHANGE;
if(forceIt) WC_STATUS=3;
else WC_STATUS=2;
return;
}
break;
case 2:
//check min sewer
if(ReefAngel.WaterLevel.GetLevel(WL_SEWER)>MIN_SEWER){
emergencyShutDown("AWC Canceled: Sewer > Min Sewer");
WC_STATUS = 8;
return;
}
//check temperature difference
if(abs(ReefAngel.Params.Temp[RESERVOIR_TEMP_PROBE] - ReefAngel.Params.Temp[SUMP_TEMP_PROBE]) > AWC_MAX_TEMP_DIF){
t.Send("AWC not realized due to Temperature difference");
WC_STATUS = 8;
return;
}
//check return pump minimun running time
if(!RETPUMP_ON_TIME){
t.Send("AWC Canceled: Return Pump Not Running min time");
WC_STATUS = 8;
return;
}
WC_STATUS=3;
break;
case 3:
//AWC: reservoir to sump
if(ReefAngel.WaterLevel.GetLevel(WL_RESERVOIR)>(MIN_RESERVOIR_DURING_CHANGE)){
ReefAngel.Relay.On(WCHANGE);
}
else{
ReefAngel.Relay.Off(WCHANGE);
WC_STATUS = 4;
}
break;
case 4:
//AWC: sump to sewer
if(ReefAngel.WaterLevel.GetLevel(WL_SUMP)>(MAX_SUMP)){
ReefAngel.Relay.On(WOUT);
}
else{
ReefAngel.Relay.Off(WOUT);
WC_STATUS = 5;
}
break;
case 5:
//get doser ready
wcDosingTimer= now() + WCHANGE_DOSER_SECOND;
WC_STATUS = 6;
break;
case 6:
//dosing
if (now()<wcDosingTimer) {
ReefAngel.Relay.On(DOSER_01);
}
else {
ReefAngel.Relay.Off(DOSER_01);
wcDosingTimer=0;
WC_STATUS = 7;
}
break;
case 7:
//fill reservoir for the next water change
if(ReefAngel.WaterLevel.GetLevel(WL_RESERVOIR)<MAX_RESERVOIR){
ReefAngel.Relay.On(WIN);
}
else{
ReefAngel.Relay.Off(WIN);
t.Send("AWC Ended");
ReefAngel.CustomVar[LAST_AWC]=hour();
WC_STATUS = 8;
}
break;
case 8:
timerOn=false;
finalTime=0;
WC_STATUS=0;
if(extraRun){
extraRun=false;
WC_STATUS=3;
}
else{
forceIt=false;
ReefAngel.DisplayedMenu = RETURN_MAIN_MODE;
}
break;
} //switch
}
void feedingMode(){
static long feeding=0;
static int nrFeedings=0;
static long timeToRun=0;
static long timeOffFeeder=0;
static WiFiAlert t;
t.SetDelay(0);
if(WC_STATUS==0 && CLEANING_MODE==false && (ReefAngel.DisplayedMenu==FEEDING_MODE || ((hour()==FEEDING_H_T1 && minute()==FEEDING_M_T1) || (hour()==FEEDING_H_T2 && minute()==FEEDING_M_T2)))){
if(ReefAngel.DisplayedMenu!=FEEDING_MODE) ReefAngel.FeedingModeStart();
t.Send("Feed Mode Started");
if(AUTOFEED){
timeToRun = 900/(FEEDING_TIMES+1);
if(feeding==0){
feeding = now()+timeToRun;
}
if(feeding > 0 && now()>=feeding && nrFeedings < FEEDING_TIMES){
timeOffFeeder = now() + SECONDS_FEEDER_ON;
nrFeedings++;
ReefAngel.CustomVar[LAST_AUTO_FEED]=hour();
feeding = 0;
}
ReefAngel.Relay.Set(FEEDER, timeOffFeeder >= now());
}
}
else {
AUTOFEED=true;
feeding=0;
nrFeedings=0;
timeToRun=0;
}
}
void DrawCustomMain()
{
static byte screenCount=0;
static boolean screenHome=true;
if(ReefAngel.Joystick.IsLeft() || ReefAngel.Joystick.IsRight()){
ReefAngel.ClearScreen(DefaultBGColor);
screenHome=!screenHome;
}
if(screenHome) DrawMainScreen();
if(!screenHome) DrawRelays();
}
void DrawMainScreen(){
char text[80];
char str[80];
pingSerial();
//Initial Title
if(DISPLAYLOG){
ReefAngel.LCD.DrawText(COLOR_MEDIUMSEAGREEN, COLOR_WHITE, 40, 4, " ");
ReefAngel.LCD.DrawLargeText(COLOR_DARKTURQUOISE, COLOR_WHITE, 6, 4 , LOGMESSAGE);
}
else {
ReefAngel.LCD.DrawLargeText(COLOR_DARKTURQUOISE, COLOR_WHITE, 40, 4 , "RafaLu");
}
//Division Line
ReefAngel.LCD.Clear(COLOR_MAROON, 1, 13, 132, 13);
//Main Temperature
ReefAngel.LCD.DrawText(COLOR_GOLDENROD, COLOR_WHITE, 6, 15, "SumpTemp:");
ConvertNumToString(text, ReefAngel.Params.Temp[SUMP_TEMP_PROBE], 10);
ReefAngel.LCD.DrawText(COLOR_GOLDENROD, DefaultBGColor, 63, 15, text);
pingSerial();
//PH
ReefAngel.LCD.DrawText(COLOR_MEDIUMSEAGREEN, COLOR_WHITE, 6, 25, "SumpPH:");
ConvertNumToString(text, ReefAngel.Params.PH, 100);
ReefAngel.LCD.DrawText(PHColor, DefaultBGColor, 63, 25, text);
pingSerial();
//Res Temperature
ReefAngel.LCD.DrawText(COLOR_GOLDENROD, COLOR_WHITE, 6, 35, "ResTemp:");
ConvertNumToString(text, ReefAngel.Params.Temp[RESERVOIR_TEMP_PROBE], 10);
ReefAngel.LCD.DrawText(COLOR_GOLDENROD, DefaultBGColor, 63, 35, text);
pingSerial();
//Ref Temperature
ReefAngel.LCD.DrawText(COLOR_GOLDENROD, COLOR_WHITE, 6, 45, "RefTemp:");
ConvertNumToString(text, ReefAngel.Params.Temp[REFUGIUM_TEMP_PROBE], 10);
ReefAngel.LCD.DrawText(COLOR_GOLDENROD, DefaultBGColor, 63, 45, text);
pingSerial();
//Division Line
ReefAngel.LCD.Clear(COLOR_MAROON, 1, 55, 132, 55);
ReefAngel.LCD.DrawText(COLOR_MEDIUMSEAGREEN, COLOR_WHITE, 6, 57, "FlowSwitch:");
strcpy(text,"Off");
if(ReefAngel.HighATO.IsActive()){
strcpy(text,"On");
}
ReefAngel.LCD.DrawText(PHColor, DefaultBGColor, 72, 57, " ");
ReefAngel.LCD.DrawText(PHColor, DefaultBGColor, 72, 57, text);
pingSerial();
//Return Pump
ReefAngel.LCD.DrawText(COLOR_MEDIUMSEAGREEN, COLOR_WHITE, 6, 67, " ");
ConvertNumToString(text, ReefAngel.PWM.GetDaylightValue(), 1);
strcpy (str,"Return Pump At: ");
strcat (str,text);
strcat (str,"%");
ReefAngel.LCD.DrawText(COLOR_MEDIUMSEAGREEN, COLOR_WHITE, 6, 67, str);
//Division Line
ReefAngel.LCD.Clear(COLOR_MAROON, 1, 77, 132, 77);
//WATER LEVEL 01
ReefAngel.LCD.DrawText(COLOR_MEDIUMSEAGREEN, COLOR_WHITE, 6, 89, " ");
ConvertNumToString(text, ReefAngel.WaterLevel.GetLevel(WL_SEWER), 1);
strcpy (str,"SEWER:");
strcat (str,text);
strcat (str,"%");
ReefAngel.LCD.DrawText(COLOR_MEDIUMSEAGREEN, COLOR_WHITE, 6, 89, str);
//WATER LEVEL 02
ReefAngel.LCD.DrawText(COLOR_MEDIUMSEAGREEN, COLOR_WHITE, 74, 89," ");
ConvertNumToString(text, ReefAngel.WaterLevel.GetLevel(WL_REFUGIUM), 1);
strcpy (str,"REF: ");
strcat (str,text);
strcat (str,"%");
ReefAngel.LCD.DrawText(COLOR_MEDIUMSEAGREEN, COLOR_WHITE, 74, 89,str);
//WATER LEVEL 03
ReefAngel.LCD.DrawText(COLOR_MEDIUMSEAGREEN, COLOR_WHITE, 6, 101, " ");
ConvertNumToString(text, ReefAngel.WaterLevel.GetLevel(WL_RESERVOIR), 1);
strcpy (str,"RES: ");
strcat (str,text);
strcat (str,"%");
ReefAngel.LCD.DrawText(COLOR_MEDIUMSEAGREEN, COLOR_WHITE, 6, 101, str);
//WATER LEVEL 04
ReefAngel.LCD.DrawText(COLOR_MEDIUMSEAGREEN, COLOR_WHITE, 74, 101," ");
ConvertNumToString(text, ReefAngel.WaterLevel.GetLevel(WL_SUMP), 1);
strcpy (str,"SUMP:");
strcat (str,text);
strcat (str,"%");
ReefAngel.LCD.DrawText(COLOR_MEDIUMSEAGREEN, COLOR_WHITE, 74, 101,str);
//Date and Time
ReefAngel.LCD.DrawDate(6,120);
pingSerial();
}
void DrawRelays(){
//Initial Title
if(DISPLAYLOG){
ReefAngel.LCD.DrawLargeText(COLOR_DARKTURQUOISE, COLOR_WHITE, 6, 4 , LOGMESSAGE);
}
else {
ReefAngel.LCD.DrawLargeText(COLOR_DARKTURQUOISE, COLOR_WHITE, 40, 4 , "RafaLu");
}
//Division Line
ReefAngel.LCD.Clear(COLOR_MAROON, 1, 13, 132, 13);
//Relays
//B01 R01
ReefAngel.LCD.DrawText(COLOR_MEDIUMSEAGREEN,DefaultBGColor,80,20,"Lights");
//B01 R02
ReefAngel.LCD.DrawText(COLOR_MEDIUMSEAGREEN,DefaultBGColor,6,20,"WOut");
//B01 R03
ReefAngel.LCD.DrawText(COLOR_MEDIUMSEAGREEN,DefaultBGColor,80,30,"Sump Fan");
//B01 R04
ReefAngel.LCD.DrawText(COLOR_MEDIUMSEAGREEN,DefaultBGColor,6,30,"CO2");
//B01 R05
ReefAngel.LCD.DrawText(COLOR_MEDIUMSEAGREEN,DefaultBGColor,80,40,"WIn");
//B01 R06
ReefAngel.LCD.DrawText(COLOR_MEDIUMSEAGREEN,DefaultBGColor,6,40,"WChange");
//B01 R07
ReefAngel.LCD.DrawText(COLOR_MEDIUMSEAGREEN,DefaultBGColor,80,50,"Not Used");
//B01 R08
ReefAngel.LCD.DrawText(COLOR_MEDIUMSEAGREEN,DefaultBGColor,6,50,"Not Used");
//B02 R01
ReefAngel.LCD.DrawText(COLOR_MEDIUMSEAGREEN,DefaultBGColor,80,70,"Sump Heat");
//B02 R02
ReefAngel.LCD.DrawText(COLOR_MEDIUMSEAGREEN,DefaultBGColor,6,70,"Feeder");
//B02 R03
ReefAngel.LCD.DrawText(COLOR_MEDIUMSEAGREEN,DefaultBGColor,80,80,"Doser 01");
//B02 R04
ReefAngel.LCD.DrawText(COLOR_MEDIUMSEAGREEN,DefaultBGColor,6,80,"UV");
//B02 R05
ReefAngel.LCD.DrawText(COLOR_MEDIUMSEAGREEN,DefaultBGColor,80,90,"Res Heat");
//B02 R06
ReefAngel.LCD.DrawText(COLOR_MEDIUMSEAGREEN,DefaultBGColor,6,90,"Res Fan");
//B02 R07
ReefAngel.LCD.DrawText(COLOR_MEDIUMSEAGREEN,DefaultBGColor,80,100,"O2");
//B02 R08
ReefAngel.LCD.DrawText(COLOR_MEDIUMSEAGREEN,DefaultBGColor,6,100,"Clnr Pump");
byte TempRelay = ReefAngel.Relay.RelayData;
TempRelay &= ReefAngel.Relay.RelayMaskOff;
TempRelay |= ReefAngel.Relay.RelayMaskOn;
ReefAngel.LCD.DrawCircleOutletBox(60, 23, TempRelay, true);
byte TempRelay2 = ReefAngel.Relay.RelayDataE[0];
TempRelay &= ReefAngel.Relay.RelayMaskOffE[0];
TempRelay |= ReefAngel.Relay.RelayMaskOnE[0];
ReefAngel.LCD.DrawCircleOutletBox(60, 73, TempRelay2, true);
}
void DrawCustomGraph()
{
}
void MenuEntry1()
{
AUTOFEED=false;
ReefAngel.FeedingModeStart();
}
void MenuEntry2()
{
AUTOFEED=true;
ReefAngel.FeedingModeStart();
}
void MenuEntry3()
{
ReefAngel.WaterChangeModeStart();
}
void MenuEntry4()
{
ReefAngel.SetupCalibrateWaterLevel();
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry5()
{
ReefAngel.SetupCalibratePH();
}
void MenuEntry6()
{
// Clear the screen
ReefAngel.ClearScreen(DefaultBGColor);
// Display some text on the screen
ReefAngel.LCD.DrawText(DefaultFGColor, DefaultBGColor, 5, 10, "Turn Everything Off");
// Turn off the ports
emergencyShutDown("Manual ShutDown");
ReefAngel.Relay.Write();
}
void MenuEntry7()
{
CLEANING_MODE = !CLEANING_MODE;
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry8()
{
if(ReefAngel.Relay.Status(LIGHTS)==false){
ReefAngel.Relay.RelayMaskOn = ReefAngel.LightsOnPorts;
#ifdef RelayExp
for ( byte i = 0; i < MAX_RELAY_EXPANSION_MODULES; i++ )
{
ReefAngel.Relay.RelayMaskOnE[i] = ReefAngel.LightsOnPortsE[i];
}
#endif // RelayExp
ReefAngel.Relay.Write();
}
else {
ReefAngel.Relay.RelayMaskOn = 0;
#ifdef RelayExp
for ( byte i = 0; i < MAX_RELAY_EXPANSION_MODULES; i++ )
{
ReefAngel.Relay.RelayMaskOnE[i] = 0;
}
#endif // RelayExp
ReefAngel.Relay.Write();
}
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry9()
{
while(true);
}