Maybe I just need another new screen (I got this one as a replacement for a broken one early this year), but before I order another, I'd really appreciate it if an expert could check my code for possible software reasons this is happening.
The board is an RA+ and I'm using the 2e3f279 libraries.
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 <ReefAngel.h>
#include <RA_Colors.h>
#include <RA_CustomColors.h>
#include <RA_CustomLabels.h>
#include <RA_CustomSettings.h>
#include <PH.h>
#include <avr/pgmspace.h>
//Ports assignment:
//First relay box is for the reef system.
//Port1 - Metal Halide Daylights.
#define lights Port1
//Port2 - AWC drain pump.
#define AWCdrain Port2
//Port3 - AWC fill pump.
#define AWCfill Port3
//Port4 - Carbon-dosing pump.
#define carbon Port4
//Port5 - Clockwise circulation pumps.
#define clockCirc Port5
//Port6 - Counterclockwise circulation pumps.
#define countCirc Port6
//Port7 - ATO pump.
#define ATOPump Port7
//Port8 - Empty.
#define lastPort Port8
/*After a circulation pump leaked current into the tank, triggering the 10 amp breaker in the relay box to shut off
all power the tank and cause the deaths of most Acros, a peppermint shrimp, and a yellow tang, I decided to move some
devices to a separate circuit that isn't controlled by the RA. These devices include:
1) Return pump
2) Skimmer pump
3) Chiller
4) Chiller feed pump
5) Cabinet fans
These devices will be on 24/7 and the RA will have no control over them.*/
//Change these values as needed. They are the threshold values for the low and high temperatures, respectively.
int lowTempWarning = 250; //low temp warning below 25.0C.
int highTempWarning = 275; //high temp warning above 27.5C.
static time_t overheatTimer; //Used to automatically reset the overheat flag.
int overheatTimeOut = 1800; //Used to automatically reset the overheat flag after 30 mins of temps below highTempWarning.
boolean overheatCheck = false;
//These vairable are used to control the ATO system.
static time_t ATOTimer;
int ATOTimeOut = 100;
boolean ATOdisabled = false;
static time_t ATOdisabledTimer;
//The following variables control when automatic water changes occur.
int AWCHour = 12;
int AWCMinute = 0;
char AWCChar[] = "AWC Scheduled: 1200"; //This string will be printed to the display until an AWC is attempted each day.
//These variables will be used to keep track of the progress of an AWC.
int AWCCheck = 0;
boolean AWCFail = false;
boolean drained = false;
//This variable will trigger an AWC().
boolean AWC = false;
//This variable will be set to true if a water change has been done since the last midnight and will be set to false at midnight.
boolean AWCToday = false;
//This vairable will store the current time for comparisons on when to initialize an AWC.
time_t AWCt;
//This variable will be a backup timer for AWC.
static time_t AWCTimer;
//These variables will control how long the AWC pumps should be on (in seconds) in case of float switch failure.
int AWCDrainSecs = 150;
int AWCFillSecs = 150;
//This function will check to make sure the water level in the sump is at the high float before initiating an AWC.
int AWCATOCheck()
{
/*if (!ReefAngel.Relay.Status(returnPump)) //If the return pump is not on, don't run an AWC and return 0 (false).
return 0; //Returning zero here is the only way for AWCCheck to equal 0 while AWC equals true. This will cause the AWC process to pause until the return pump is on again.*/
if (!ReefAngel.HighATO.IsActive()) //If the water level is not at the maximum normal level, run the ATO.
{
ATOTimer = now();
ReefAngel.Relay.On(ATOPump); //Fill the return section to the high float with RODI.
AWCToday = true;
return 2;
}
else
{
AWCToday = true;
return 1;
}
}
//Custom Menu Code
const unsigned char menu1_label[] PROGMEM = "Feed for 5 Mins";
const unsigned char menu2_label[] PROGMEM = "Start AWC";
const unsigned char menu3_label[] PROGMEM = "Clear Alerts & Vars";
//const unsigned char menu4_label[] PROGMEM = "pH Calibration";
const unsigned char menu4_label[] PROGMEM = "Disable ATO for 4h";
const unsigned char menu5_label[] PROGMEM = "Set Date & Time";
const unsigned char menu6_label[] PROGMEM = "Toggle Port8";
const unsigned char menu7_label[] PROGMEM = "Version";
PROGMEM const char * const menu_items[] = {
menu1_label, menu2_label, menu3_label, menu4_label, menu5_label, menu6_label, menu7_label
};
void MenuEntry1()
{
ReefAngel.FeedingModeStart();
}
void MenuEntry2()
{
AWCToday = false;
AWC = true;
ReefAngel.DisplayMenuEntry("AWC Starting");
}
void MenuEntry3()
{
//Clear portal variables.
//ReefAngel.CustomVar[Var_AWCCountTotal] = 0;
//ReefAngel.CustomVar[Var_AWCCountToday] = 0;
//ReefAngel.CustomVar[Var_AWCDrainFail] = 0;
//ReefAngel.CustomVar[Var_AWCFillFail] = 0;
//ReefAngel.CustomVar[Var_AWCATOFail] = 0;
//Clear overheat status:
ReefAngel.OverheatClear();
//Clear AWC control variables:
AWC = false;
AWCToday = false;
AWCFail = false;
AWCCheck = 0;
//Clear ATO timeout:
ReefAngel.ATOClear();
ReefAngel.DisplayMenuEntry("ATO, AWC, & Overheat Vars Reset");
}
void MenuEntry4()
{
//ReefAngel.StartSetupCalibrateChoicePH();
//ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
ATOdisabled = true;
ATOdisabledTimer = now();
ReefAngel.DisplayMenuEntry("ATO disabled for 4 hours");
}
void MenuEntry5()
{
ReefAngel.SetupDateTime();
//ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry6()
{
//ReefAngel.WaterChangeModeStart();
//ReefAngel.DisplayMenuEntry("Return & skimmer pumps off");
ReefAngel.Relay.Toggle(lastPort);
}
void MenuEntry7()
{
ReefAngel.DisplayVersion();
}
void DrawCustomMain()
{
// the graph is drawn/updated when we exit the main menu & when the parameters are saved
ReefAngel.LCD.DrawDate(6, 120);
pingSerial();
//T2 probe is main temp sensor, while T1 probe is cabinet temp sensor.
byte mainTempColor;
//To make changes for each temp sensor, change the value of tempColor to be the appropriate color
if ( ReefAngel.Params.Temp[T2_PROBE] < lowTempWarning ) { mainTempColor = COLOR_CYAN; }
else if ( ReefAngel.Params.Temp[T2_PROBE] > highTempWarning ) { mainTempColor = COLOR_RED; }
else { mainTempColor = COLOR_SEAGREEN; }
//Display the T2 Main System temperature
int T2y = 66; //Y-position of T2 probe reading.
ReefAngel.LCD.DrawText(mainTempColor, DefaultBGColor, 5, T2y, "Tank Temp: ");
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp[T2_PROBE], mainTempColor, 65, T2y, 10);
//Display the T1 Room temperature
int T1y = 75; //Y-position of T1 probe reading.
ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 5, T1y, "Cabinet Temp: ");
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp[T1_PROBE], COLOR_BLACK, 85, T1y, 10);
/*byte pHColor;
//Depending upon the pH, change the value of pHColor to be the appropriate color
if ( ReefAngel.Params.PH < 790 ) { pHColor = COLOR_YELLOW; }
else if ( ReefAngel.Params.PH > 810 ) { pHColor = COLOR_MAGENTA; }
else { pHColor = COLOR_SEAGREEN; }
//Display the pH starting at 88, 74
ReefAngel.LCD.DrawText(pHColor, DefaultBGColor, 5, 80, "pH: ");
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.PH, pHColor, 30, 80, 100);*/
//Display whether the ATO/AWC high float switch is active (purple highlight, float away from wires) or inactive (green highlight, float close to wires):
byte floatColor; //Text color for ATO reading.
int ATOy = 84; //Y-position for ATO reading.
ReefAngel.LCD.Clear(DefaultBGColor, 0,ATOy, 128,ATOy+7); //Default font size is 5 pixels wide by 8 pixels high.
if (ReefAngel.HighATO.IsActive() && !ReefAngel.isATOTimeOut())
{
floatColor = COLOR_MEDIUMORCHID;
ReefAngel.LCD.DrawText(COLOR_WHITE, floatColor, 5, ATOy, "High Float");
}
else if (!ReefAngel.HighATO.IsActive() && !ReefAngel.isATOTimeOut())
{
floatColor = COLOR_SEAGREEN;
ReefAngel.LCD.DrawText(COLOR_WHITE, floatColor, 5, ATOy, "High Float");
}
else {ReefAngel.LCD.DrawText(COLOR_WHITE, COLOR_RED, 5, ATOy, "ATO Fail");}
//Display whether the AWC low float switch is active (purple highlight, float away from wires) or inactive (green highlight, float close to wires):
if (ReefAngel.LowATO.IsActive())
{
floatColor = COLOR_MEDIUMORCHID;
ReefAngel.LCD.DrawText(COLOR_WHITE, floatColor, 70, ATOy, "Low Float");
}
else
{
floatColor = COLOR_SEAGREEN;
ReefAngel.LCD.DrawText(COLOR_WHITE, floatColor, 70, ATOy, "Low Float");
}
//Display whether an AWC has occurred today, or when today's AWC is scheduled,
//or that an AWC is in progress, or that an AWC failure has occurred:
//byte AWCColor; //Text color for AWC info.
int AWCy = 95; //Y-position for AWC info.
ReefAngel.LCD.Clear(DefaultBGColor, 0,AWCy, 128,AWCy+7); //Default font size is 5 pixels wide by 8 pixels high.
if (AWCFail)
{
ReefAngel.LCD.DrawText(COLOR_WHITE, COLOR_RED, 2, AWCy, "AWC Failure");
}
else
{
if (AWC)
{
ReefAngel.LCD.DrawText(COLOR_BLACK, COLOR_YELLOW, 2, AWCy, "AWC In Progress");
}
else if (AWCToday)
{
ReefAngel.LCD.DrawText(COLOR_GREEN, COLOR_WHITE, 2, AWCy, "AWC Completed Today");
}
else {ReefAngel.LCD.DrawText(COLOR_BLUE, COLOR_WHITE, 2, AWCy, AWCChar);}
}
//Display relay box 1 ports with status at 12,105
byte TempRelay = ReefAngel.Relay.RelayData;
TempRelay &= ReefAngel.Relay.RelayMaskOff;
TempRelay |= ReefAngel.Relay.RelayMaskOn;
ReefAngel.LCD.DrawOutletBox(12, 105, TempRelay);
}
void DrawCustomGraph()
{
//Print "Pringle Lab Reef" at the top of the screen
ReefAngel.LCD.DrawText(DefaultFGColor, DefaultBGColor, 18, 2, "Pringle Lab Reef");
ReefAngel.LCD.DrawGraph(5,13);
}
////// Place global variable code above here
void setup()
{
InternalMemory.LCDID_write(1);
ReefAngel.Init();
ReefAngel.SetTemperatureUnit(Celsius); //Set to celsius Temperature units.
for (int a=0;a<SIZE(menu_items);a++)
{
ReefAngel.InitMenu(pgm_read_word(&(menu_items[a])),a);
}
ReefAngel.UseFlexiblePhCalibration();
ReefAngel.FeedingModePorts = Port5Bit | Port6Bit; // Turn off Ports 5 & 6 (circulation pumps) when Feeding Mode is activated.
//ReefAngel.WaterChangePorts = Port8Bit; // Turn off port 8 (return & skimmer pumps) when Water Change Mode is activated
ReefAngel.OverheatShutoffPorts = Port1Bit; // Turn off lights if overheat condition.
ReefAngel.OverheatProbe = T2_PROBE; // Use T2 probe (tank temperature) for overheat functions.
InternalMemory.OverheatTemp_write(highTempWarning); // Set the overheat temperature to the highTempWarning value.
//Initialize portal variables.
//ReefAngel.CustomVar[Var_AWCCountTotal] = 0;
//ReefAngel.CustomVar[Var_AWCCountToday] = 0;
//ReefAngel.CustomVar[Var_AWCFillFail] = 0;
//ReefAngel.CustomVar[Var_AWCDrainFail] = 0;
//ReefAngel.CustomVar[Var_AWCATOFail] = 0;
//startupTimer = now();
}
void loop()
{
//Start an AWC once per day at AWCHour:AWCMinute if an AWC hasn't happened since midnight and there hasn't been an ATO timeout.
AWCt = now();
if (!AWCFail && (hour(AWCt) == AWCHour) && (minute(AWCt) == AWCMinute) && !AWCToday && !AWC && !ReefAngel.isATOTimeOut())
{
AWC = true; //Sets the AWC control variable to true.
}
//Reset the automatic water change variable and AWC and dosing counts every day at midnight. Also add the day's AWC count to the total AWC count.
if (hour(AWCt) == 0 && minute(AWCt) == 0 && AWCToday)
{
AWCToday = false;
//ReefAngel.CustomVar[Var_AWCCountTotal] += ReefAngel.CustomVar[Var_AWCCountToday];
//ReefAngel.CustomVar[Var_AWCCountToday] = 0;
}
//Start the chain of AWC functions.
if (AWC && !AWCToday && AWCCheck == 0)
{
AWCCheck = AWCATOCheck(); //If AWCATOCheck returns non-zero, it will also set AWCToday to true.
}
if (AWCCheck == 2) // Fill return section of sump with ATO pump to the high mark:
{
if (!ReefAngel.HighATO.IsActive())
{
ReefAngel.Relay.Off(ATOPump);
AWCCheck = 1;
}
if ((now() - ATOTimer) >= ATOTimeOut)
{
ReefAngel.Relay.Off(ATOPump);
bitSet(ReefAngel.AlertFlags,ATOTimeOutFlag); //Trigger ATO timeout flag.
AWCFail = true;
//ReefAngel.CustomVar[Var_AWCATOFail] = 1;
AWCCheck = 0;
AWC = false;
}
}
if (AWCCheck == 1 && !ReefAngel.Relay.Status(AWCdrain) && !drained) // Drain the return section of sump to the low mark:
{
AWCTimer = now();
ReefAngel.Relay.On(AWCdrain);
}
if (ReefAngel.Relay.Status(AWCdrain))
{
if (ReefAngel.LowATO.IsActive())
{
ReefAngel.Relay.Off(AWCdrain);
drained = true;
}
if (now()-AWCTimer >= AWCDrainSecs)
{
ReefAngel.Relay.Off(AWCdrain);
AWCFail = true;
//ReefAngel.CustomVar[Var_AWCDrainFail] = 1;
AWCCheck = 0;
AWC = false;
ReefAngel.ATOClear();
}
}
if (drained)
{
if (!ReefAngel.Relay.Status(AWCfill)) // Fill the return section of the sump to the high mark with fresh ASW.
{
AWCTimer = now();
ReefAngel.Relay.On(AWCfill);
}
if (ReefAngel.Relay.Status(AWCfill))
{
if (!ReefAngel.HighATO.IsActive())
{
ReefAngel.Relay.Off(AWCfill);
drained = false;
AWC = false;
AWCCheck = 0;
ReefAngel.ATOClear();
//ReefAngel.CustomVar[Var_AWCCountToday] += 1;
}
if (now()-AWCTimer >= AWCFillSecs)
{
ReefAngel.Relay.Off(AWCfill);
drained = false;
AWCFail = true;
//ReefAngel.CustomVar[Var_AWCFillFail] = 1;
AWCCheck = 0;
AWC = false;
ReefAngel.ATOClear();
}
}
}
//Light Control:
ReefAngel.StandardLights(lights, 8,00, 18,00); //Lights on at 8 am and off at 6 pm.
//Temp control is handled by the chiller:
/*Turn off chiller if the temp gets too low.
if (ReefAngel.Params.Temp[T2_PROBE] <= lowTempWarning && ReefAngel.Relay.Status(chiller))
{
ReefAngel.Relay.Off(chiller);
} else if (!ReefAngel.Relay.Status(chiller) && ReefAngel.Params.Temp[T2_PROBE] >= (lowTempWarning + highTempWarning)/2) {
ReefAngel.Relay.On(chiller); //Turn chiller back on if the temp rises to the mean of lowTempWarning & highTempWarning.
}*/
//Overheat staus will be cleared if the temperature drops below highTempWarning and stays there for at least 30 minutes:
if (bitRead(ReefAngel.AlertFlags, OverheatFlag) && !overheatCheck && ReefAngel.Params.Temp[T2_PROBE] < highTempWarning)
{
overheatCheck = true;
overheatTimer = now();
}
if (overheatCheck && bitRead(ReefAngel.AlertFlags, OverheatFlag))
{
if (ReefAngel.Params.Temp[T2_PROBE] >= highTempWarning)
{
overheatCheck = false; //Reset the overheatCheck flag if the temp rises to or above highTempWarning.
} else if (now()-overheatTimer >= overheatTimeOut)
{
ReefAngel.OverheatClear(); //Clear overheat status and overheatCheck flag if the temp stays below highTempWarning for at least 30 mins.
overheatCheck = false;
}
}
//Wavemaker control
ReefAngel.WavemakerRandom(clockCirc, 30, 300); // Turn clockwise circulation pumps on/off random cycles that lasts from 30 to 300 secs.
ReefAngel.Relay.Set(countCirc, !ReefAngel.Relay.Status(clockCirc)); // Turn counterclockwise circulation pumps on/off on opposite cycle from clockwise circulation pumps.
//ATO
if (!AWC && !ATOdisabled) {
ReefAngel.SingleATO(false, ATOPump, ATOTimeOut, 1); // Use single high float switch (false = high) for reef ATO with 100 second timeout. Runs at most once per hour.
} else {ReefAngel.Relay.Off(ATOPump);}
if (ATOdisabled && (now()-ATOdisabledTimer >= (4*60*60))) {ATOdisabled = false;} // If ATO is manually disabled, re-enable it after 4 hours.
//Carbon dosing
ReefAngel.DosingPumpRepeat(carbon, 60, 720, 10); //Turn on carbon dosing pump for 10 seconds every 12 hours (at 1am & 1pm).
ReefAngel.ShowInterface();
}
I really appreciate any help/advice you can offer me.
Thanks,
Gabe