My code is quite complex in the way it monitors various systems.
1) is there a way to store some of this data somewhere else?
2) when things are triggered like low temperatures, the chiller is turned off, how do I stop the chiller from triggering on and off if the temp varies by half a degree? The same goes for pH how do I stop the kalk from switching on and off because the pH is bouncing by point 1 pH?
-----CODE BELOW ------
#include <Salinity.h>
#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>
////// Place global variable code below here
//// Relay 1
#define CHILLER Port1 /// Hailea Chiller 1/2 HP
#define HEATER Port2 /// Backup heater
#define RETURN_PUMP Port3 /// Return Pump
#define CHILLER_PUMP Port4 /// Pump for chiller and UV
#define SKIMMER Port5 /// Protien Skimmer
#define REAR_PUMPS_1 Port6 /// Rear Pumps 1 & 2
#define REAR_PUMPS_2 Port7 /// Dosing Pump 1
#define DOSING_PUMP_1 Port8 /// Dosing Pump 1
//// Relay 2
#define FRONT_LIGHTS Box1_Port1 /// Front t5s (4 X 100W)
#define REAR_LIGHTS Box1_Port2 /// Rear t5s (4 X 100W)
#define MIDDLE_LIGHTS Box1_Port3 /// Rear t5s (2 X 100)
#define MOON_LIGHTS Box1_Port4 /// Moon Lights (LED)
#define SUMP_LIGHTS Box1_Port5 /// Sump Lights (LED)
#define SALINITY_POWER Box1_Port7 /// Power to Salinity Module
#define ORP_POWER Box1_Port8 /// Power to ORP Module
#define TANK_TEMPRATURE ReefAngel.Params.Temp[T1_PROBE] /// tank temprature
/// outlet styles & colors
#define OutletBorderColor COLOR_ROYALBLUE /// Relay Border
#define OutletOnBGColor COLOR_WHITE /// Relay On
#define OutletOnFGColor COLOR_ROYALBLUE /// Relay Text Color
#define OutletOffBGColor COLOR_ROYALBLUE /// Relay Off0x4F
#define OutletOffFGColor COLOR_WHITE /// Relay Text Color 0xFF
#define YES 1 //// YES
#define NO 0 //// NO
/// error count & logs
int errorCount = 0;
int lowATO = NO;
int highATO = NO;
int highATOAlert = NO;
int powerFailure = NO;
int powerFailureCount = 0;
int powerFailureCountStarted = NO;
int noPowerAlert = NO;
int lowROWater = NO;
int highTemp = NO;
int lowTemp = NO;
int lowTempAlert = NO;
int highTempAlert = NO;
int phOut = NO;
int phAlert = NO;
byte lastMinute = 0;
byte sureOn = 0;
void setup(){
ReefAngel.Init(); /// Initialize controller
ReefAngel.SetTemperatureUnit( Celsius ); /// set Temp to Celcius
/// Toggled Ports
ReefAngel.LightsOnPorts = FRONT_LIGHTS | REAR_LIGHTS;
ReefAngel.FeedingModePorts = RETURN_PUMP | REAR_PUMPS_1 | REAR_PUMPS_2 | CHILLER | CHILLER_PUMP | SKIMMER;
ReefAngel.WaterChangePorts = RETURN_PUMP | REAR_PUMPS_1 | REAR_PUMPS_2 | CHILLER | CHILLER_PUMP | SKIMMER | FRONT_LIGHTS;
ReefAngel.OverheatProbe = T1_PROBE;
ReefAngel.OverheatShutoffPorts = HEATER | FRONT_LIGHTS | REAR_LIGHTS | MIDDLE_LIGHTS;
/// Immediate Start ( delayed starts in loop )
ReefAngel.Relay.On(REAR_PUMPS_1);
ReefAngel.Relay.On(REAR_PUMPS_2);
if(powerFailure == NO){
ReefAngel.Relay.On(SUMP_LIGHTS);
ReefAngel.Relay.On(SALINITY_POWER);
ReefAngel.Relay.On(ORP_POWER);
}
}
void DrawCustomMain(){
char text[7];
byte x = 6;
byte y = 2;
byte t;
//ReefAngel.LCD.DrawDate(COLOR_WHITE,COLOR_BLACK,6, 2);
ReefAngel.LCD.DrawText(COLOR_WHITE,COLOR_ROYALBLUE,0,1," RED SEA MAX S 650 ");
ReefAngel.LCD.DrawText(COLOR_ROYALBLUE,COLOR_WHITE,4,13,"Tank: Sump:");
ConvertNumToString(text, ReefAngel.Params.Temp[T1_PROBE], 10);
ReefAngel.LCD.DrawText(COLOR_MIDNIGHTBLUE, COLOR_WHITE, 35, 13, text);
if(ReefAngel.Params.Temp[T1_PROBE]>=260 || ReefAngel.Params.Temp[T2_PROBE]>=260){
sureOn = now();
highTemp = YES;
}
else
highTemp = NO;
ConvertNumToString(text, ReefAngel.Params.Temp[T2_PROBE], 10);
ReefAngel.LCD.DrawText(COLOR_MIDNIGHTBLUE, COLOR_WHITE, 101, 13, text);
//ReefAngel.LCD.Clear(DefaultFGColor, 0, 23, 128, 23);
pingSerial();
if(highTemp==NO && (ReefAngel.Params.Temp[T1_PROBE] <230 || ReefAngel.Params.Temp[T2_PROBE]<230))
ReefAngel.Relay.On(HEATER);
/* remove if(ReefAngel.Params.Temp[T1_PROBE] <210 || ReefAngel.Params.Temp[T2_PROBE]<210)
lowTemp = YES;
else
lowTemp = NO;*/
/// top relay styles - bring to edge
ReefAngel.LCD.Clear(COLOR_ROYALBLUE, 0, 25, 25, 25);
ReefAngel.LCD.Clear(COLOR_ROYALBLUE, 0, 26, 12, 36);
ReefAngel.LCD.Clear(COLOR_ROYALBLUE, 0, 37, 25, 37);
ReefAngel.LCD.Clear(COLOR_ROYALBLUE, 114, 25, 130, 25);
ReefAngel.LCD.Clear(COLOR_ROYALBLUE, 117, 26, 130, 36);
ReefAngel.LCD.Clear(COLOR_ROYALBLUE, 114, 37, 130, 37);
/// relay 1 - 8
byte TempRelay = ReefAngel.Relay.RelayData;
TempRelay &= ReefAngel.Relay.RelayMaskOff;
TempRelay |= ReefAngel.Relay.RelayMaskOn;
ReefAngel.LCD.DrawOutletBox(12, 25, TempRelay);
/// bottom relay styles - bring to edge
ReefAngel.LCD.Clear(COLOR_ROYALBLUE, 0, 38, 12, 48);
ReefAngel.LCD.Clear(COLOR_ROYALBLUE, 0, 49, 12, 49);
ReefAngel.LCD.Clear(COLOR_ROYALBLUE, 117, 38, 130, 48);
ReefAngel.LCD.Clear(COLOR_ROYALBLUE, 114, 49, 130, 49);
/// relay 9 - 16
TempRelay = ReefAngel.Relay.RelayDataE[0];
TempRelay &= ReefAngel.Relay.RelayMaskOffE[0];
TempRelay |= ReefAngel.Relay.RelayMaskOnE[0];
ReefAngel.LCD.DrawOutletBox(12, 37, TempRelay);
pingSerial();
/// set high low
//ReefAngel.LCD.Clear(COLOR_GREEN, 0, 60, 25, 85);
ReefAngel.LCD.DrawLargeText(COLOR_ROYALBLUE,COLOR_WHITE,20,64,"LOW", Font8x16);
ReefAngel.LCD.DrawLargeText(COLOR_ROYALBLUE,COLOR_WHITE,85,64,"HIGH", Font8x16);
/// seperator before water level & pH
ReefAngel.LCD.Clear(COLOR_ROYALBLUE, 0, 76, 130, 77);
ReefAngel.LCD.DrawText(COLOR_ROYALBLUE,COLOR_WHITE,10,80,"pH:");
ConvertNumToString(text, ReefAngel.Params.PH, 100);
ReefAngel.LCD.DrawLargeText(COLOR_BLACK, COLOR_WHITE, 31, 80, text, Num8x16);
pingSerial();
ReefAngel.LCD.DrawText(COLOR_ROYALBLUE,COLOR_WHITE,70,80,"ATO:");
ConvertNumToString(text, ReefAngel.WaterLevel.GetLevel() , 1);
strcat(text,"% ");
ReefAngel.LCD.DrawLargeText(COLOR_BLACK,COLOR_WHITE,95,80, text);
pingSerial();
ReefAngel.LCD.Clear(COLOR_ROYALBLUE, 0, 90, 130, 91);
ReefAngel.LCD.DrawText(COLOR_ROYALBLUE,COLOR_WHITE,6,96,"Sal:");
ConvertNumToString(text, ReefAngel.Params.Salinity, 10);
ReefAngel.LCD.DrawLargeText(COLOR_BLACK,COLOR_WHITE,31,96, text);
pingSerial();
ReefAngel.LCD.DrawText(COLOR_ROYALBLUE,COLOR_WHITE,70,96,"ORP:");
ConvertNumToString(text, ReefAngel.Params.ORP, 1);
ReefAngel.LCD.DrawLargeText(COLOR_BLACK,COLOR_WHITE,95,96, text);
pingSerial();
//ReefAngel.LCD.Clear(COLOR_ROYALBLUE, 0, 107, 128, 122);
if(hour()>=18 && hour()<22){
ReefAngel.LCD.Clear(COLOR_DEEPSKYBLUE,0, 107, 130, 121);
ReefAngel.LCD.DrawLargeText(COLOR_WHITE,COLOR_DEEPSKYBLUE,0,110, " Moon Mode ");
}
else if(hour()>=23 || (hour()>=0 && hour()<8)){
ReefAngel.LCD.Clear(COLOR_BLACK,0, 107, 130, 121);
ReefAngel.LCD.DrawLargeText(COLOR_WHITE,COLOR_BLACK,0,110, " Night Mode ");
}
else if(hour()>=8 && hour()<18){
ReefAngel.LCD.Clear(COLOR_YELLOW,0, 107, 130, 121);
ReefAngel.LCD.DrawLargeText(COLOR_BLACK,COLOR_YELLOW,0,110, " Day Mode ");
}
ReefAngel.LCD.DrawDate(6, 123);
}
void DrawCustomGraph(){
}
void loop(){
/// lighting if no errors
if(powerFailure == NO && highTemp==NO){
// remove ReefAngel.DosingPumpRepeat(DOSING_PUMP_1,0,1,15);
if(now() - sureOn >= 600 || sureOn ==0){ /// if the lights have been off for 10 mins
ReefAngel.StandardLights(MIDDLE_LIGHTS,8,30,19,30);
ReefAngel.StandardLights(REAR_LIGHTS,9,00,19,30);
ReefAngel.StandardLights(FRONT_LIGHTS,10,00,18,30);
ReefAngel.StandardLights(MOON_LIGHTS,19,00,23,00);
sureOn = 0;
}
}
if(highATO + lowATO + powerFailure <1){
/// Default LEDS to 0 - useed for error reporting and system status
ReefAngel.PWM.SetDaylight(0);
ReefAngel.PWM.SetActinic(0);
/// Delayed Starts
/// 1 Minute
ReefAngel.Relay.DelayedOn (SKIMMER,1);
ReefAngel.Relay.DelayedOn (RETURN_PUMP,1);
ReefAngel.Relay.DelayedOn(CHILLER_PUMP,1);
/// 2 Minute
ReefAngel.Relay.DelayedOn(CHILLER,2);
}
/// Check for errors
/// Check Sump Levels
if (!ReefAngel.LowATO.IsActive() || !ReefAngel.HighATO.IsActive()){
if(!ReefAngel.LowATO.IsActive()){
lowATO = YES;
ReefAngel.LCD.FillCircle(72,67,6,COLOR_RED);
}
else{
lowATO = NO;
ReefAngel.LCD.FillCircle(72,67,6,COLOR_GREEN);
}
if(!ReefAngel.HighATO.IsActive()){
highATO = YES;
ReefAngel.LCD.FillCircle(55,67,6,COLOR_RED);
}
else{
highATO = NO;
ReefAngel.LCD.FillCircle(55,67,6,COLOR_GREEN);
}
}
else{
lowATO = NO;
highATO = NO;
ReefAngel.LCD.FillCircle(55,67,6,COLOR_GREEN);
ReefAngel.LCD.FillCircle(72,67,6,COLOR_GREEN);
}
pingSerial();
if (!ReefAngel.Relay.IsRelayPresent(EXP1_RELAY)){
powerFailure = YES;
}
else{
powerFailure = NO;
}
if(ReefAngel.WaterLevel.GetLevel()<20)
lowROWater = YES;
else
lowROWater = NO;
pingSerial();
checkForErrors();
//// End Code
ReefAngel.Portal( "******" ,"******");
ReefAngel.ShowInterface();
}
void checkForErrors(){
errorCount = 0;
/// see if any errors have been logged
/// first check sump levels
if(lowATO+highATO>0){
if(lowATO==YES){
//char text2[7];
//ConvertNumToString(text2, lastMinute,1);
ReefAngel.LCD.DrawLargeText(COLOR_WHITE,COLOR_RED,0,50," LOW SUMP LEVEL ", Font8x16);//
errorCount++;
//ReefAngel.PWM.SetDaylight(ErrorPulse(0, 100, 120, false));
//checkLastMin(lastMinute, 1);
}
if(highATO==YES){
errorCount++;
ReefAngel.LCD.DrawLargeText(COLOR_WHITE,COLOR_RED,0,50," HIGH SUMP LEVEL ", Font8x16);
ReefAngel.PWM.SetDaylight(ErrorPulse(0, 60, 5, false));
}
ReefAngel.PWM.SetActinic(ErrorPulse(0, 100, 5, false));
pingSerial();
}
else if(lowROWater == YES){
errorCount++;
//ReefAngel.PWM.SetDaylight(ErrorPulse(0, 100, 120, false));
ReefAngel.PWM.SetActinic(100);
}
/// check tempreature levels
if(highTemp==YES){
errorCount++;
ReefAngel.LCD.DrawLargeText(COLOR_WHITE,COLOR_RED,0,50," HIGH TEMPRATURE ", Font8x16);
ReefAngel.PWM.SetDaylight(ErrorPulse(0, 60, 5, false));
ReefAngel.Relay.Off(FRONT_LIGHTS);
ReefAngel.Relay.Off(REAR_LIGHTS);
ReefAngel.Relay.Off(MIDDLE_LIGHTS);
if(highTempAlert==NO){
WifiSendAlert(2);
highTempAlert = YES;
}
pingSerial();
}
if(lowTemp==YES){
errorCount++;
ReefAngel.LCD.DrawLargeText(COLOR_WHITE,COLOR_RED,0,50," LOW TEMPRATURE ", Font8x16);
ReefAngel.PWM.SetDaylight(ErrorPulse(0, 60, 5, false));
ReefAngel.Relay.Off(CHILLER);
ReefAngel.Relay.On(HEATER);
ReefAngel.Relay.On(FRONT_LIGHTS);
ReefAngel.Relay.On(REAR_LIGHTS);
ReefAngel.Relay.On(MIDDLE_LIGHTS);
if(lowTempAlert==NO)
WifiSendAlert(3);
lowTempAlert = YES;
}
if(lowTemp==NO && highTemp==NO){
lowTempAlert = NO;
highTempAlert = NO;
}
/* remove if(ReefAngel.Params.PH > 830 || ReefAngel.Params.PH < 795){
ReefAngel.LCD.DrawLargeText(COLOR_WHITE,COLOR_RED,0,50," CHECK pH ", Font8x16);
ReefAngel.PWM.SetDaylight(ErrorPulse(0, 60, 5, false));
if(phAlert==NO){
if(ReefAngel.Params.PH > 830)
WifiSendAlert(5);
else
WifiSendAlert(6);
phAlert = YES;
}
errorCount++;
}
else
phAlert = NO; remove */
/// check for power failure
if(powerFailure==YES){
errorCount++;
if(powerFailureCountStarted==NO){
powerFailureCountStarted = YES;
}
powerFailureCount = powerFailureCount + 1;
/// if no power what to do
/// immediately kill
ReefAngel.Relay.Off(SUMP_LIGHTS);
ReefAngel.Relay.Off(SALINITY_POWER);
ReefAngel.Relay.Off(ORP_POWER);
ReefAngel.Relay.Off(FRONT_LIGHTS);
ReefAngel.Relay.Off(REAR_LIGHTS);
ReefAngel.Relay.Off(MIDDLE_LIGHTS);
if(powerFailureCount > 1800){
ReefAngel.Relay.Off (SKIMMER); /// kill skimmer after 3 minutes
ReefAngel.Relay.Off (SUMP_LIGHTS); /// kill sump lights after 3 minutes
}
if(powerFailureCount > 3000) {
if(TANK_TEMPRATURE <26.6){
ReefAngel.Relay.Off (CHILLER); /// kill chiller after 5 minutes
ReefAngel.Relay.Off (CHILLER_PUMP); /// kill chiller pump after 5 minutes
ReefAngel.Relay.Off (RETURN_PUMP); /// kill return pump after 5 minutes
}
else{
ReefAngel.Relay.On (CHILLER); /// kill chiller after 5 minutes
ReefAngel.Relay.On (CHILLER_PUMP); /// kill chiller pump after 5 minutes
ReefAngel.Relay.On (RETURN_PUMP); /// kill return pump after 5 minutes
}
ReefAngel.Relay.Off(REAR_PUMPS_2); /// kill rear pumps
}
/*f(powerFailureCount > 3000 && TANK_TEMPRATURE >26.6){ //// if ten minutes pass or water gets too warm.
ReefAngel.Relay.On (CHILLER); /// turn back on
ReefAngel.Relay.On (CHILLER_PUMP); /// turn back on
}*/
ReefAngel.PWM.SetDaylight(ErrorPulse(10, 60, 1, false));
ReefAngel.PWM.SetActinic(ErrorPulse(0, 100, 1, false));
/// No power countdown
char text[40] = " NO POWER: ";
char text2[7];
ConvertNumToString(text2, powerFailureCount,10);
strcat(text, text2);
strcat(text, " ");
ReefAngel.LCD.DrawLargeText(COLOR_WHITE,COLOR_RED,0,50,text, Font8x16);
//ReefAngel.LCD.DrawLargeText(COLOR_WHITE,COLOR_RED,0,50," POWER OUTAFGE ", Font8x16);
}
else if(errorCount==0){
powerFailureCountStarted = NO;
ReefAngel.LCD.DrawLargeText(COLOR_WHITE,COLOR_GREEN,0,50," STATUS OK ", Font8x16);
ReefAngel.PWM.SetActinic(0);
ReefAngel.PWM.SetDaylight(0);
}
}
byte ErrorPulse(byte MinPulse, byte MaxPulse, int PulseDuration, boolean PulseSync)
{
byte tspeed=0;
MinPulse=constrain(MinPulse,0,100);
MaxPulse=constrain(MaxPulse,0,100);
tspeed=(now()%(PulseDuration*2)<PulseDuration?MinPulse:MaxPulse);
if (PulseSync)
return tspeed;
else
return (tspeed==MinPulse)?MaxPulse:MinPulse;
}
byte checkLastMin(byte lastMinute, byte minutesToWait){
if(lastMinute == 0)
lastMinute = minute() ;
if(minute()-lastMinute == minutesToWait){
ReefAngel.PWM.SetDaylight(ErrorPulse(0, 60, 2, false));
if(lastMinute != minute())
lastMinute = minute() ;
}
}
void WifiSendAlert(byte id)
{
Serial.print("GET /status/wifialert.asp?e=log@procrm.com.au&id=******&msg=Test%20without%20key");
//Serial.print("GET http//crm1.com.au/reeftest.php");
Serial.print(id,DEC);
Serial.println("\n\n");
}
Delayed Restart
- lnevo
- Posts: 5422
- Joined: Fri Jul 20, 2012 9:42 am
Re: Delayed Restart
There is a byte array (ReefAngel.CustomVars[8]) that you can store some statuses in. The trick is that at least one must contain a non-0 value for the feature to be enabled on the portal.
Also instead of the way you are turning on/off the chiller is whats causing it to cycle. Don't use the delayedon and then on / off. Keep your code but just use it for the alert and status. The best way is to do ReefAngel.StandardFan(port,low,high) the chiller will turn on when it reaches the high temp and off when it reaches the low temp. Its basically the opposite of StandardHeater
Same thing for your ph based device. But there are two functions depending on behavior. PHControl and CO2Control. PHControl turns on when low ph is reached CO2Control turns off when low ph is reached. But both give you a range to operate and so shouldn't cycle on/off constantly because of .1 variance.
Also instead of the way you are turning on/off the chiller is whats causing it to cycle. Don't use the delayedon and then on / off. Keep your code but just use it for the alert and status. The best way is to do ReefAngel.StandardFan(port,low,high) the chiller will turn on when it reaches the high temp and off when it reaches the low temp. Its basically the opposite of StandardHeater
Same thing for your ph based device. But there are two functions depending on behavior. PHControl and CO2Control. PHControl turns on when low ph is reached CO2Control turns off when low ph is reached. But both give you a range to operate and so shouldn't cycle on/off constantly because of .1 variance.