Re: Got my controller,
Posted: Sat Sep 08, 2012 4:05 pm
Ok. I created a ticket.
https://github.com/reefangel/Libraries/issues/46
https://github.com/reefangel/Libraries/issues/46
Community discussion about Reef Angel Controllers and reefing related subjects
https://forum.reefangel.com/
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>
#include <SunLocation.h>
////// Place global variable code below here
#define CUSTOM_MENU
#define CUSTOM_MENU_ENTRIES 8
#define NUMBERS_8x16
// Custom Menu Code
#include <avr/pgmspace.h>
prog_char menu1_label[] PROGMEM = "Feeding";
prog_char menu2_label[] PROGMEM = "Water Change";
prog_char menu3_label[] PROGMEM = "Vortech Mode";
prog_char menu4_label[] PROGMEM = "Refugium Light";
prog_char menu5_label[] PROGMEM = "ATO Clear";
prog_char menu6_label[] PROGMEM = "PH Calibration";
prog_char menu7_label[] PROGMEM = "Date / Time";
prog_char menu8_label[] PROGMEM = "Version";
// Group the menu entries together
PROGMEM const char *menu_items[] = {
menu1_label, menu2_label, menu3_label,
menu4_label, menu5_label, menu6_label,
menu7_label, menu8_label
};
// Vortech Defaults
byte vtMode=Random2;
byte vtSpeed=45;
byte vtDuration=5;
byte vtNTMSpeed=65;
byte vtNTMDuration=5;
byte vtNightSpeed=10;
byte vtNightDuration=20;
byte vtPrevMode;
byte vtPrevSpeed;
byte vtPrevDuration;
boolean isNight=false;
boolean isFeeding=false;
boolean vtOverride=false;
SunLocation sl;
byte SunriseHour, SunriseMin, SunsetHour, SunsetMin;
//Define Relay Ports
#define Return 1
#define Skimmer 2
#define WhiteLEDs 3
#define BlueLEDs 4
#define UPS 5
#define Heater 6
#define Refugium 7
#define Vortech 8
////// Place global variable code above here
// Setup on controller startup/reset
void setup()
{
// This must be the first line
ReefAngel.Init(); //Initialize controller
// Initialize Menu
ReefAngel.InitMenu(pgm_read_word(&(menu_items[0])),SIZE(menu_items));
// Ports toggled in Feeding Mode
ReefAngel.FeedingModePorts = Port1Bit | Port2Bit;
// Ports toggled in Water Change Mode
ReefAngel.WaterChangePorts = Port1Bit | Port2Bit | Port6Bit;
// Ports toggled when Lights On / Off menu entry selected
ReefAngel.LightsOnPorts = Port4Bit | Port7Bit ;
// Ports turned off when Overheat temperature exceeded
ReefAngel.OverheatShutoffPorts = Port6Bit;
// Use T1 probe as temperature and overheat functions
ReefAngel.TempProbe = T1_PROBE;
ReefAngel.OverheatProbe = T1_PROBE;
// Set the Overheat temperature setting
InternalMemory.OverheatTemp_write( 820 );
// Ports that are always on
ReefAngel.Relay.On( Return );
ReefAngel.Relay.On( Vortech );
ReefAngel.Relay.On( UPS );
////// Place additional initialization code below here
// Setup SunLocation class
sl.Init(-18.285833, 147.699722);
sl.SetOffset(-9,472,-9,506);
// Save previous used vortech mode.
vtPrevMode=InternalMemory.RFMode_read();
vtPrevSpeed=InternalMemory.RFSpeed_read();
vtPrevDuration=InternalMemory.RFDuration_read();
////// Place additional initialization code above here
}
void loop()
{
ReefAngel.Relay.DelayedOn( Skimmer, 20 );
ReefAngel.StandardHeater( Heater,778,782 );
////// Place your custom code below here
sl.CheckAndUpdate();
SunriseHour=sl.GetRiseHour(); SunriseMin=sl.GetRiseMinute();
SunsetHour=sl.GetSetHour(); SunsetMin=sl.GetSetMinute();
// Send the SunLocation info to the portal
ReefAngel.CustomVar[0]=SunriseHour; ReefAngel.CustomVar[1]=SunriseMin;
ReefAngel.CustomVar[2]=SunsetHour; ReefAngel.CustomVar[3]=SunsetMin;
// Turn the lights on
ReefAngel.StandardLights( WhiteLEDs,SunriseHour+1,SunriseMin,SunsetHour-3, SunsetMin );
ReefAngel.StandardLights( BlueLEDs,SunriseHour,SunriseMin,SunsetHour,SunsetMin );
// Let's make the time one number so we can figure out it's night or day...
int currTime = hour()*100+minute();
int riseTime=SunriseHour*100+SunriseMin;
int setTime=SunsetHour*100+SunsetMin;
if ( (currTime <= riseTime) || (currTime >= setTime) ) isNight=true; else isNight=false;
if (isNight)
{
ReefAngel.PWM.SetDaylight( MoonPhase() );
ReefAngel.PWM.SetActinic( MoonPhase() );
ReefAngel.Relay.On( Refugium );
if (vtOverride==false && isFeeding==false) {
setRFmode(Night,vtNightSpeed,vtNightDuration);
}
} else {
// It's Daytime!
ReefAngel.PWM.SetDaylight( 0 );
ReefAngel.PWM.SetActinic( 0 );
ReefAngel.Relay.Off( Refugium );
if (vtOverride==false && vtMode==Night) {
setRFmode(vtPrevMode,vtPrevSpeed,vtPrevDuration);
}
}
if (ReefAngel.DisplayedMenu==FEEDING_MODE) isFeeding=true;
if (ReefAngel.DisplayedMenu==WATERCHANGE_MODE) ReefAngel.Relay.On( Refugium );
if (ReefAngel.DisplayedMenu==DEFAULT_MENU && isFeeding )
{
isFeeding=false;
setRFmode(Smart_NTM,vtNTMSpeed,vtNTMDuration);
}
if (vtOverride && ReefAngel.Timer[1].IsTriggered())
{
vtOverride=false;
setRFmode(vtPrevMode,vtPrevSpeed,vtPrevDuration);
} else {
setRFmode(); // Update if set externally
}
////// Place your custom code above here
// This should always be the last line
ReefAngel.Portal( "lnevo" );
ReefAngel.ShowInterface();
}
// Vortech Helper functions
void setRFmode(int mode, int speed, int duration) {
// Check if mode has changed
if (mode!=vtMode) {
vtPrevMode=vtMode;
vtMode=mode;
if (mode!=InternalMemory.RFMode_read()) {
InternalMemory.RFMode_write(mode);
}
// Temp fix for coming out of night mode
if (vtPrevMode==Night) {
ReefAngel.RF.UseMemory=false;
ReefAngel.RF.SetMode(Feeding_Stop,0,0);
ReefAngel.RF.UseMemory=true;
}
if ( (isNight && vtMode != Night) || vtMode==Smart_NTM) {
setRFtimer(30);
}
}
// Check if speed has changed
if (speed!=vtSpeed) {
vtPrevSpeed=vtSpeed;
vtSpeed=speed;
if (speed!=InternalMemory.RFSpeed_read()) {
InternalMemory.RFSpeed_write(speed);
}
}
// Check if duration has changed
if (duration!=vtDuration) {
vtPrevDuration=vtDuration;
vtDuration=duration;
if (speed!=InternalMemory.RFSpeed_read()) {
InternalMemory.RFSpeed_write(speed);
}
}
}
void setRFmode() {
setRFmode(InternalMemory.RFMode_read(), InternalMemory.RFSpeed_read(), InternalMemory.RFDuration_read());
}
void setRFtimer(int minutes) {
ReefAngel.Timer[1].SetInterval(minutes*60);
ReefAngel.Timer[1].Start();
vtOverride=true;
}
// Menu Code
void MenuEntry1()
{
ReefAngel.FeedingModeStart();
}
void MenuEntry2()
{
ReefAngel.WaterChangeModeStart();
}
void MenuEntry3()
{
byte mode, speed,duration;
mode=vtMode;
mode++;
if (mode > 9 ) {
mode=0;
speed=50; duration=0; // Constant
} else if (mode == 1) {
speed=40; duration=0; // Lagoon
} else if (mode == 2) {
speed=45; duration=0; // Reef Crest
} else if (mode == 3) {
speed=50; duration=10; // Short Pulse
} else if (mode == 4) {
speed=50; duration=20; // Long Pulse
} else if (mode == 6) {
speed=45; duration=10; // Smart_TSM
} else if (mode == 5) {
speed=vtNTMSpeed; duration=vtNTMDuration; // Smart_NTM
} else if (mode == 7) {
speed=vtNightSpeed; duration=vtNightDuration; // Night
mode=9;
}
setRFmode(mode,speed,duration);
ReefAngel.DisplayedMenu = RETURN_MAIN_MODE;
}
void MenuEntry4()
{
ReefAngel.Relay.Toggle ( Refugium );
ReefAngel.DisplayedMenu = RETURN_MAIN_MODE;
}
void MenuEntry5()
{
ReefAngel.ATOClear();
ReefAngel.DisplayMenuEntry("Clear ATO Timeout");
}
void MenuEntry6()
{
ReefAngel.SetupCalibratePH();
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry7()
{
ReefAngel.SetupDateTime();
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry8()
{
ReefAngel.DisplayVersion();
}
// Custom Main Screen
void DrawCustomMain()
{
char buf[16];
byte x = 5;
byte y = 2;
byte t;
if (isFeeding) { ReefAngel.ClearScreen(DefaultBGColor); return; }
// Main Header
ReefAngel.LCD.DrawText(DefaultFGColor, DefaultBGColor, 35, y,"Lee's Reef");
ReefAngel.LCD.Clear(COLOR_BLACK, 1, y+9, 128, y+9);
// Param Header
y+=18;
ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,x+5,y,"Temp:");
ReefAngel.LCD.DrawText(PHColor,DefaultBGColor,x+60, y, "PH:");
// Temp and PH
y+=8;
ConvertNumToString(buf, ReefAngel.Params.Temp[T1_PROBE], 10);
ReefAngel.LCD.DrawLargeText(T1TempColor, DefaultBGColor, x+5, y, buf, Num8x16);
ConvertNumToString(buf, ReefAngel.Params.PH, 100);
ReefAngel.LCD.DrawLargeText(PHColor, DefaultBGColor, x+60, y, buf, Num8x16);
pingSerial();
/// Display Sunrise / Sunset (to be calculated later...)
y+=20; t=x;
sprintf(buf, "%02d:%02d", SunriseHour, SunriseMin);
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,t,y,"Rise:"); t+=31;
ReefAngel.LCD.DrawText(COLOR_RED,DefaultBGColor,t,y,buf);
sprintf(buf, "%02d:%02d", SunsetHour, SunsetMin); t+=36;
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,t,y,"Set:"); t+=25;
ReefAngel.LCD.DrawText(COLOR_RED,DefaultBGColor,t,y,buf);
// MoonPhase
y+=10;
ReefAngel.LCD.DrawText(0,255,x,y,"Moon:");
ReefAngel.LCD.Clear(DefaultBGColor,x+32,y,x+(128-x),y+8);
ReefAngel.LCD.DrawText(COLOR_MAGENTA,255,x+32,y,MoonPhaseLabel());
pingSerial();
// MoonLight %
y+=10;
t = intlength(ReefAngel.PWM.GetDaylightValue()) + 1; t *= 5;
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,x,y,"MoonLights:");
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.PWM.GetDaylightValue(), DPColor, x+68, y, 1);
ReefAngel.LCD.DrawText(DPColor, DefaultBGColor, x+68+t, y, "%");
pingSerial();
// Vortech Mode
y+=10; t=x;
ReefAngel.LCD.DrawText(0,255,x,y,"RF:"); t+=20;
ReefAngel.LCD.Clear(DefaultBGColor,t,y,x+(128-x),y+8);
if (vtMode == 0) ReefAngel.LCD.DrawLargeText(COLOR_GREEN,255,t,y,"Constant");
else if(vtMode == 1) ReefAngel.LCD.DrawLargeText(COLOR_GOLD,255,t,y,"Lagoon");
else if (vtMode == 2) ReefAngel.LCD.DrawLargeText(COLOR_GOLD,255,t,y,"Reef Crest");
else if (vtMode == 3) ReefAngel.LCD.DrawLargeText(COLOR_RED,255,t,y,"Short Pulse");
else if (vtMode == 4) ReefAngel.LCD.DrawLargeText(COLOR_RED,255,t,y,"Long Pulse");
else if (vtMode == 5) ReefAngel.LCD.DrawLargeText(COLOR_MAGENTA,255,t,y,"Smart NTM");
else if (vtMode == 6) ReefAngel.LCD.DrawLargeText(COLOR_MAGENTA,255,t,y,"Tidal Swell");
else if (vtMode == 9) ReefAngel.LCD.DrawLargeText(COLOR_WHITE,0,t,y,"Night");
y+=10; t=x;
ReefAngel.LCD.DrawText(0,255,x,y,"RF Speed:"); t+=60;
ReefAngel.LCD.Clear(DefaultBGColor,t,y,x+(128-x),y+8);
ReefAngel.LCD.DrawText(COLOR_BLUE, DefaultBGColor,t,y,InternalMemory.RFSpeed_read()); t+=15;
ReefAngel.LCD.DrawText(COLOR_BLUE, DefaultBGColor,t,y,"/"); t+=10;
ReefAngel.LCD.DrawText(COLOR_BLUE, DefaultBGColor,t,y,InternalMemory.RFDuration_read());
pingSerial();
// Relays
byte TempRelay = ReefAngel.Relay.RelayData;
TempRelay &= ReefAngel.Relay.RelayMaskOff;
TempRelay |= ReefAngel.Relay.RelayMaskOn;
ReefAngel.LCD.DrawOutletBox(12, 103, TempRelay);
pingSerial();
// Date+Time
ReefAngel.LCD.DrawDate(6, 122);
pingSerial();
}
void DrawCustomGraph()
{
}
Can you help me replicate this issue?lnevo wrote:Also, sometimes when going into feeding mode, the LCD does not clear completely even though i added a flag to return and clearscreen in my CustomMain.
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>
#include <SunLocation.h>
////// Place global variable code below here
#define CUSTOM_MENU
#define CUSTOM_MENU_ENTRIES 8
#define NUMBERS_8x16
// Custom Menu Code
#include <avr/pgmspace.h>
prog_char menu1_label[] PROGMEM = "Feeding";
prog_char menu2_label[] PROGMEM = "Water Change";
prog_char menu3_label[] PROGMEM = "Vortech Mode";
prog_char menu4_label[] PROGMEM = "Refugium Light";
prog_char menu5_label[] PROGMEM = "ATO Clear";
prog_char menu6_label[] PROGMEM = "PH Calibration";
prog_char menu7_label[] PROGMEM = "Date / Time";
prog_char menu8_label[] PROGMEM = "Version";
// Group the menu entries together
PROGMEM const char *menu_items[] = {
menu1_label, menu2_label, menu3_label,
menu4_label, menu5_label, menu6_label,
menu7_label, menu8_label
};
// Vortech Defaults
byte vtPrevMode=0;
byte vtPrevSpeed=0;
byte vtPrevDuration=0;
byte vtMode=Random2;
byte vtSpeed=45;
byte vtDuration=5;
byte vtNTMSpeed=55;
byte vtNTMDuration=5;
byte vtNightSpeed=10;
byte vtNightDuration=20;
boolean isNight=false;
boolean isFeeding=false;
boolean vtOverride=false;
boolean activatedHighATO=true;
SunLocation sl;
//Define Relay Ports
#define Return 1
#define Skimmer 2
#define WhiteLEDs 3
#define BlueLEDs 4
#define UPS 5
#define Heater 6
#define Refugium 7
#define Vortech 8
////// Place global variable code above here
// Setup on controller startup/reset
void setup()
{
// This must be the first line
ReefAngel.Init(); //Initialize controller
// Initialize Menu
ReefAngel.InitMenu(pgm_read_word(&(menu_items[0])),SIZE(menu_items));
// Ports toggled in Feeding Mode
ReefAngel.FeedingModePorts = Port1Bit | Port2Bit;
// Ports toggled in Water Change Mode
ReefAngel.WaterChangePorts = Port1Bit | Port2Bit | Port6Bit;
// Ports toggled when Lights On / Off menu entry selected
ReefAngel.LightsOnPorts = Port4Bit | Port7Bit ;
// Ports turned off when Overheat temperature exceeded
ReefAngel.OverheatShutoffPorts = Port6Bit;
// Use T1 probe as temperature and overheat functions
ReefAngel.TempProbe = T1_PROBE;
ReefAngel.OverheatProbe = T1_PROBE;
// Set the Overheat temperature setting
InternalMemory.OverheatTemp_write( 820 );
// Ports that are always on
ReefAngel.Relay.On( Return );
ReefAngel.Relay.On( Vortech );
ReefAngel.Relay.On( UPS );
////// Place additional initialization code below here
// Setup SunLocation class
sl.Init(-18.285833, 147.699722); // GBR
sl.SetOffset(-9,472,-9,506); // 9 hour difference
// Save previous used vortech mode.
vtPrevMode=InternalMemory.RFMode_read();
vtPrevSpeed=InternalMemory.RFSpeed_read();
vtPrevDuration=InternalMemory.RFDuration_read();
////// Place additional initialization code above here
}
void loop()
{
ReefAngel.Relay.DelayedOn( Skimmer, 5 );
ReefAngel.StandardHeater( Heater );
////// Place your custom code below here
sl.CheckAndUpdate();
// Turn on the lights
ReefAngel.StandardLights( WhiteLEDs );
ReefAngel.ActinicLights( BlueLEDs );
// Let's make the time one number so we can figure out it's night or day...
int currTime=NumMins(hour(),minute());
int riseTime=NumMins(sl.GetRiseHour(),sl.GetRiseMinute());
int setTime=NumMins(sl.GetSetHour(),sl.GetSetMinute());
if ( (currTime <= riseTime) || (currTime >= setTime) ) isNight=true; else isNight=false;
if (isNight)
{
ReefAngel.PWM.SetDaylight( MoonPhase() );
ReefAngel.PWM.SetActinic( MoonPhase() );
ReefAngel.Relay.On( Refugium );
if (vtOverride==false && isFeeding==false) {
setRFmode(Night,vtNightSpeed,vtNightDuration);
}
// Trigger night mode again to extend built-in timer
if ( ((hour() == 6) && (minute() == 00) && (second() == 00) ) ) {
setRFmode(vtPrevMode,vtPrevSpeed,vtPrevDuration);
}
} else {
// It's Daytime!
ReefAngel.PWM.SetDaylight( 0 );
ReefAngel.PWM.SetActinic( 0 );
ReefAngel.Relay.Off( Refugium );
if (vtOverride==false && vtMode==Night) {
setRFmode(vtPrevMode,vtPrevSpeed,vtPrevDuration);
ReefAngel.Timer[1].ForceTrigger();
}
}
if (ReefAngel.DisplayedMenu==FEEDING_MODE) isFeeding=true;
if (ReefAngel.DisplayedMenu==WATERCHANGE_MODE) ReefAngel.Relay.On( Refugium );
if (ReefAngel.DisplayedMenu==FEEDING_MODE || ReefAngel.DisplayedMenu==WATERCHANGE_MODE) activatedHighATO=true;
if (ReefAngel.DisplayedMenu==DEFAULT_MENU && isFeeding )
{
isFeeding=false;
setRFmode(Smart_NTM,vtNTMSpeed,vtNTMDuration);
}
else if (vtOverride && ReefAngel.Timer[1].IsTriggered())
{
vtOverride=false;
setRFmode(vtPrevMode,vtPrevSpeed,vtPrevDuration);
}
else
{
setRFmode(); // Update if set externally
}
if ( ((hour() == 15) && (minute() == 00) && (second() == 00) ) ) {
setRFmode(Smart_NTM,vtNTMSpeed,vtNTMDuration);
}
if (ReefAngel.LowATO.IsActive()) {
bitClear(ReefAngel.Relay.RelayMaskOff,Return-1);
bitClear(ReefAngel.Relay.RelayMaskOff,Skimmer-1);
}
if (ReefAngel.HighATO.IsActive()) {
if (!activatedHighATO) {
activatedHighATO=true;
ReefAngel.CustomVar[0]=2;
bitClear(ReefAngel.Relay.RelayMaskOff,Return-1);
bitClear(ReefAngel.Relay.RelayMaskOff,Skimmer-1);
}
} else {
ReefAngel.CustomVar[0]=1;
activatedHighATO=false;
}
// Turn off Skimmer if Return pump is shutoff.
if (bitRead(ReefAngel.Relay.RelayMaskOff,Return-1)==0) {
bitClear(ReefAngel.Relay.RelayMaskOff,Skimmer-1);
}
////// Place your custom code above here
// This should always be the last line
ReefAngel.Portal( "lnevo" );
ReefAngel.ShowInterface();
}
// Vortech Helper functions
void setRFmode(int mode, int speed, int duration) {
// Check if mode has changed
if (mode!=vtMode) {
vtPrevMode=vtMode;
vtMode=mode;
if (mode!=InternalMemory.RFMode_read()) {
InternalMemory.RFMode_write(mode);
}
// Temp fix for coming out of night mode
if (vtPrevMode==Night) {
ReefAngel.RF.UseMemory=false;
ReefAngel.RF.SetMode(Feeding_Stop,0,0);
ReefAngel.RF.UseMemory=true;
}
if ( (isNight && vtMode != Night) || vtMode==Smart_NTM) {
setRFtimer(30);
}
}
// Check if speed has changed
if (speed!=vtSpeed) {
vtPrevSpeed=vtSpeed;
vtSpeed=speed;
if (speed!=InternalMemory.RFSpeed_read()) {
InternalMemory.RFSpeed_write(speed);
}
}
// Check if duration has changed
if (duration!=vtDuration) {
vtPrevDuration=vtDuration;
vtDuration=duration;
if (speed!=InternalMemory.RFSpeed_read()) {
InternalMemory.RFSpeed_write(speed);
}
}
}
void setRFmode() {
setRFmode(InternalMemory.RFMode_read(), InternalMemory.RFSpeed_read(), InternalMemory.RFDuration_read());
}
void setRFtimer(int minutes) {
ReefAngel.Timer[1].SetInterval(minutes*60);
ReefAngel.Timer[1].Start();
vtOverride=true;
}
// Menu Code
void MenuEntry1()
{
ReefAngel.FeedingModeStart();
}
void MenuEntry2()
{
ReefAngel.WaterChangeModeStart();
}
void MenuEntry3()
{
byte mode,speed,duration,prev_mode,prev_speed,prev_dur;
mode=vtMode;
mode++;
if (mode > 9 ) {
mode=0;
speed=50; duration=0; // Constant
} else if (mode == 1) {
speed=40; duration=0; // Lagoon
} else if (mode == 2) {
speed=45; duration=0; // Reef Crest
} else if (mode == 3) {
speed=50; duration=10; // Short Pulse
} else if (mode == 4) {
speed=50; duration=20; // Long Pulse
} else if (mode == 6) {
speed=45; duration=10; // Smart_TSM
} else if (mode == 5) {
speed=vtNTMSpeed; duration=vtNTMDuration; // Smart_NTM
} else if (mode == 7) {
speed=vtNightSpeed; duration=vtNightDuration; // Night
mode=9;
}
prev_mode=vtPrevMode; prev_speed=vtPrevSpeed; prev_dur=vtPrevDuration;
setRFmode(mode,speed,duration);
if (!isNight) {
vtPrevMode=prev_mode; vtPrevSpeed=prev_speed; vtPrevDuration=prev_dur;
}
ReefAngel.DisplayedMenu = RETURN_MAIN_MODE;
}
void MenuEntry4()
{
if (isNight) {
if (bitRead(ReefAngel.Relay.RelayMaskOff,Refugium-1)==1) {
bitClear(ReefAngel.Relay.RelayMaskOff,Refugium-1);
} else {
bitSet(ReefAngel.Relay.RelayMaskOff,Refugium-1);
}
} else {
if (bitRead(ReefAngel.Relay.RelayMaskOn,Refugium-1)==1) {
bitClear(ReefAngel.Relay.RelayMaskOn,Refugium-1);
} else {
bitSet(ReefAngel.Relay.RelayMaskOn,Refugium-1);
}
}
ReefAngel.DisplayedMenu = RETURN_MAIN_MODE;
}
void MenuEntry5()
{
ReefAngel.ATOClear();
ReefAngel.DisplayMenuEntry("Clear ATO Timeout");
}
void MenuEntry6()
{
ReefAngel.SetupCalibratePH();
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry7()
{
ReefAngel.SetupDateTime();
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry8()
{
ReefAngel.DisplayVersion();
}
// Custom Main Screen
void DrawCustomMain()
{
char buf[16];
byte x = 5;
byte y = 2;
byte t;
if (isFeeding) { ReefAngel.ClearScreen(DefaultBGColor); return; }
// Main Header
ReefAngel.LCD.DrawText(DefaultFGColor, DefaultBGColor, 35, y,"Lee's Reef");
ReefAngel.LCD.Clear(COLOR_BLACK, 1, y+9, 128, y+9);
// Param Header
y+=18;
ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,x+5,y,"Temp:");
ReefAngel.LCD.DrawText(PHColor,DefaultBGColor,x+60, y, "PH:");
// Temp and PH
y+=8;
ConvertNumToString(buf, ReefAngel.Params.Temp[T1_PROBE], 10);
ReefAngel.LCD.DrawLargeText(T1TempColor, DefaultBGColor, x+5, y, buf, Num8x16);
ConvertNumToString(buf, ReefAngel.Params.PH, 100);
ReefAngel.LCD.DrawLargeText(PHColor, DefaultBGColor, x+60, y, buf, Num8x16);
pingSerial();
/// Display Sunrise / Sunset (to be calculated later...)
y+=20; t=x;
sprintf(buf, "%02d:%02d", sl.GetRiseHour(), sl.GetRiseMinute());
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,t,y,"Rise:"); t+=31;
ReefAngel.LCD.DrawText(COLOR_RED,DefaultBGColor,t,y,buf);
sprintf(buf, "%02d:%02d", sl.GetSetHour(), sl.GetSetMinute()); t+=36;
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,t,y,"Set:"); t+=25;
ReefAngel.LCD.DrawText(COLOR_RED,DefaultBGColor,t,y,buf);
// MoonPhase
y+=10;
ReefAngel.LCD.DrawText(0,255,x,y,"Moon:");
ReefAngel.LCD.Clear(DefaultBGColor,x+32,y,x+(128-x),y+8);
ReefAngel.LCD.DrawText(COLOR_MAGENTA,255,x+32,y,MoonPhaseLabel());
pingSerial();
// MoonLight %
y+=10;
t = intlength(ReefAngel.PWM.GetDaylightValue()) + 1; t *= 5;
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,x,y,"MoonLights:");
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.PWM.GetDaylightValue(), DPColor, x+68, y, 1);
ReefAngel.LCD.DrawText(DPColor, DefaultBGColor, x+68+t, y, "%");
pingSerial();
// Vortech Mode
y+=10; t=x;
ReefAngel.LCD.DrawText(0,255,x,y,"RF:"); t+=20;
ReefAngel.LCD.Clear(DefaultBGColor,t,y,x+(128-x),y+8);
if (vtMode == 0) ReefAngel.LCD.DrawLargeText(COLOR_GREEN,255,t,y,"Constant");
else if(vtMode == 1) ReefAngel.LCD.DrawLargeText(COLOR_GOLD,255,t,y,"Lagoon");
else if (vtMode == 2) ReefAngel.LCD.DrawLargeText(COLOR_GOLD,255,t,y,"Reef Crest");
else if (vtMode == 3) ReefAngel.LCD.DrawLargeText(COLOR_RED,255,t,y,"Short Pulse");
else if (vtMode == 4) ReefAngel.LCD.DrawLargeText(COLOR_RED,255,t,y,"Long Pulse");
else if (vtMode == 5) ReefAngel.LCD.DrawLargeText(COLOR_MAGENTA,255,t,y,"Smart NTM");
else if (vtMode == 6) ReefAngel.LCD.DrawLargeText(COLOR_MAGENTA,255,t,y,"Tidal Swell");
else if (vtMode == 9) ReefAngel.LCD.DrawLargeText(COLOR_WHITE,0,t,y,"Night");
y+=10; t=x;
ReefAngel.LCD.DrawText(0,255,x,y,"RF Speed:"); t+=60;
ReefAngel.LCD.Clear(DefaultBGColor,t,y,x+(128-x),y+8);
ReefAngel.LCD.DrawText(COLOR_BLUE, DefaultBGColor,t,y,InternalMemory.RFSpeed_read()); t+=15;
ReefAngel.LCD.DrawText(COLOR_BLUE, DefaultBGColor,t,y,"/"); t+=10;
ReefAngel.LCD.DrawText(COLOR_BLUE, DefaultBGColor,t,y,InternalMemory.RFDuration_read());
pingSerial();
// Relays
byte TempRelay = ReefAngel.Relay.RelayData;
TempRelay &= ReefAngel.Relay.RelayMaskOff;
TempRelay |= ReefAngel.Relay.RelayMaskOn;
ReefAngel.LCD.DrawOutletBox(12, 103, TempRelay);
pingSerial();
// Date+Time
ReefAngel.LCD.DrawDate(6, 122);
pingSerial();
}
void DrawCustomGraph()
{
}
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>
#include <SunLocation.h>
#include <WaterLevel.h>
////// Place global variable code below here
#define CUSTOM_MENU
#define CUSTOM_MENU_ENTRIES 8
#define NUMBERS_8x16
// Custom Menu Code
#include <avr/pgmspace.h>
prog_char menu1_label[] PROGMEM = "Feeding";
prog_char menu2_label[] PROGMEM = "Water Change";
prog_char menu3_label[] PROGMEM = "Vortech Mode";
prog_char menu4_label[] PROGMEM = "Refugium Light";
prog_char menu5_label[] PROGMEM = "Clear Overrides";
prog_char menu6_label[] PROGMEM = "PH Calibration";
prog_char menu7_label[] PROGMEM = "WLS Calibration";
prog_char menu8_label[] PROGMEM = "Date / Time";
prog_char menu9_label[] PROGMEM = "Version";
// Group the menu entries together
PROGMEM const char *menu_items[] = {
menu1_label, menu2_label, menu3_label,
menu4_label, menu5_label, menu6_label,
menu7_label, menu8_label, menu9_label
};
// Vortech Defaults
byte vtPrevMode=0;
byte vtPrevSpeed=0;
byte vtPrevDuration=0;
byte vtMode=Random2;
byte vtSpeed=45;
byte vtDuration=5;
byte vtNTMSpeed=65;
byte vtNTMDuration=5;
byte vtNightSpeed=20;
byte vtNightDuration=10;
boolean isNight=false;
boolean isFeeding=false;
boolean feedDelay=false;
boolean vtOverride=false;
boolean floatHigh=true;
boolean powerOutage=true;
int riseOffset=472;
int setOffset=506;
byte acclTime=0;
SunLocation sl;
//Define Custom Memory Location
#define Mem_B_RefillATO 100
#define Mem_B_Vacation 101
#define Mem_B_AcclTime 102
//Define Relay Ports
#define Return 1
#define Skimmer 2
#define WhiteLEDs 3
#define BlueLEDs 4
#define Extension 5
#define Heater 6
#define Refugium 7
#define Reactor 8
#define Unused1 Box1_Port1
#define Unused2 Box1_Port2
#define Vortech1 Box1_Port3
#define Vortech2 Box1_Port4
#define VortechUPS Box1_Port5
#define Unused3 Box1_Port6
#define DPump1 Box1_Port7
#define DPump2 Box1_Port8
////// Place global variable code above here
// Setup on controller startup/reset
void setup()
{
// This must be the first line
ReefAngel.Init(); //Initialize controller
// Initialize Menu
ReefAngel.InitMenu(pgm_read_word(&(menu_items[0])),SIZE(menu_items));
// Ports toggled in Feeding Mode
ReefAngel.FeedingModePorts = Port1Bit | Port2Bit;
// Ports toggled in Water Change Mode
ReefAngel.WaterChangePorts = Port1Bit | Port2Bit | Port6Bit;
// Ports toggled when Lights On / Off menu entry selected
ReefAngel.LightsOnPorts = Port4Bit | Port7Bit ;
// Ports turned off when Overheat temperature exceeded
ReefAngel.OverheatShutoffPorts = Port6Bit;
// Use T1 probe as temperature and overheat functions
ReefAngel.TempProbe = T1_PROBE;
ReefAngel.OverheatProbe = T1_PROBE;
// Set the Overheat temperature setting
InternalMemory.OverheatTemp_write( 820 );
// Ports that are always on
ReefAngel.Relay.On( Return );
ReefAngel.Relay.On( Vortech1 );
ReefAngel.Relay.On( Vortech2 );
ReefAngel.Relay.On( VortechUPS );
ReefAngel.Relay.Off( Extension );
ReefAngel.Relay.Off( Unused1 );
ReefAngel.Relay.Off( Unused2 );
ReefAngel.Relay.Off( Unused3 );
////// Place additional initialization code below here
// Setup SunLocation class
sl.Init(-18.285833, 147.699722); // GBR
// Save previous used vortech mode.
vtPrevMode=InternalMemory.RFMode_read();
vtPrevSpeed=InternalMemory.RFSpeed_read();
vtPrevDuration=InternalMemory.RFDuration_read();
ReefAngel.CustomVar[7]=255;
////// Place additional initialization code above here
}
void loop()
{
ReefAngel.StandardHeater( Heater );
ReefAngel.DosingPumpRepeat1( DPump1 );
ReefAngel.DosingPumpRepeat2( DPump2 );
ReefAngel.StandardLights( WhiteLEDs );
ReefAngel.ActinicLights( BlueLEDs );
if (powerOutage && ReefAngel.Relay.IsRelayPresent(EXP1_RELAY))
{
powerOutage=false;
LastStart=now();
ReefAngel.CustomVar[1]=0;
}
ReefAngel.Relay.DelayedOn( Skimmer, 5 );
ReefAngel.Relay.DelayedOn( Reactor, 10 );
if (InternalMemory.read( Mem_B_Vacation )==1) {
ReefAngel.WaterLevelATO( Extension,30,61,63 );
ReefAngel.CustomVar[3]=1;
} else {
ReefAngel.CustomVar[3]=0;
ReefAngel.Relay.Off( Extension );
}
if (InternalMemory.read( Mem_B_RefillATO )==1) {
if (ReefAngel.WaterLevel.GetLevel()<=100) {
ReefAngel.Relay.On( Extension );
ReefAngel.CustomVar[2]=1;
} else {
ReefAngel.Relay.Off( Extension );
InternalMemory.write( Mem_B_RefillATO, 0);
ReefAngel.CustomVar[2]=0;
}
}
acclTime=InternalMemory.read( Mem_B_AcclTime );
if (acclTime > 0) {
ReefAngel.CustomVar[4]=acclTime;
if ( (hour()==0) && (minute()==0) && (second()==0)) {
acclTime--;
InternalMemory.write( Mem_B_AcclTime, acclTime );
}
}
////// Place your custom code below here
sl.SetOffset(-9,riseOffset+(acclTime*240),-9,setOffset+(acclTime*120)); // 9 hour difference
sl.CheckAndUpdate();
// Let's make the time one number so we can figure out it's night or day...
int currTime=NumMins(hour(),minute());
int riseTime=NumMins(sl.GetRiseHour(),sl.GetRiseMinute());
int setTime=NumMins(sl.GetSetHour(),sl.GetSetMinute());
if ( (currTime <= riseTime) || (currTime >= setTime) ) isNight=true; else isNight=false;
if (isNight)
{
if ((hour()>=3) && (hour()<=5)) {
ReefAngel.PWM.SetDaylight( 0 );
ReefAngel.PWM.SetActinic( 0 );
} else {
ReefAngel.PWM.SetDaylight( MoonPhase() );
ReefAngel.PWM.SetActinic( MoonPhase() );
}
if (vtOverride==false && isFeeding==false) {
setRFmode(Night,vtNightSpeed,vtNightDuration);
}
ReefAngel.Relay.On( Refugium );
} else {
// It's Daytime!
ReefAngel.PWM.SetDaylight( 0 );
ReefAngel.PWM.SetActinic( 0 );
ReefAngel.Relay.Off( Refugium );
if (vtOverride==false && vtMode==Night) {
setRFmode(vtPrevMode,vtPrevSpeed,vtPrevDuration);
ReefAngel.Timer[1].ForceTrigger();
}
}
if (ReefAngel.DisplayedMenu==FEEDING_MODE) isFeeding=true;
if (ReefAngel.DisplayedMenu==WATERCHANGE_MODE) ReefAngel.Relay.On( Refugium );
if (ReefAngel.DisplayedMenu==FEEDING_MODE || ReefAngel.DisplayedMenu==WATERCHANGE_MODE) floatHigh=true;
if (ReefAngel.DisplayedMenu==DEFAULT_MENU && isFeeding )
{
isFeeding=false;
feedDelay=true;
setRFtimer(30); // Stay in FeedMode for a while longer.
}
else if (vtOverride && ReefAngel.Timer[1].IsTriggered())
{
vtOverride=false;
if(feedDelay) {
feedDelay=false;
setRFmode(Smart_NTM,vtNTMSpeed,vtNTMDuration);
} else {
setRFmode(vtPrevMode,vtPrevSpeed,vtPrevDuration);
}
}
else
{
setRFmode(); // Update if set externally
}
if ( ((hour() == 15) && (minute() == 00) && (second() == 00) ) ) {
setRFmode(Smart_NTM,vtNTMSpeed,vtNTMDuration);
}
if (ReefAngel.LowATO.IsActive()) {
bitClear(ReefAngel.Relay.RelayMaskOff,Return-1);
bitClear(ReefAngel.Relay.RelayMaskOff,Skimmer-1);
}
if (ReefAngel.HighATO.IsActive()) {
if (!floatHigh) {
floatHigh=true;
ReefAngel.CustomVar[0]=1;
bitClear(ReefAngel.Relay.RelayMaskOff,Return-1);
bitClear(ReefAngel.Relay.RelayMaskOff,Skimmer-1);
}
} else {
ReefAngel.CustomVar[0]=0;
floatHigh=false;
}
// Turn off Skimmer if Return pump is shutoff.
if (bitRead(ReefAngel.Relay.RelayMaskOff,Return-1)==0) {
bitClear(ReefAngel.Relay.RelayMaskOff,Skimmer-1);
}
// Power Outage - Only Return Pump
if (!ReefAngel.Relay.IsRelayPresent(EXP1_RELAY)) // Exp1 Relay NOT present
{
powerOutage=true;
ReefAngel.Relay.Off (Skimmer);
ReefAngel.Relay.Off (WhiteLEDs);
ReefAngel.Relay.Off (BlueLEDs);
ReefAngel.Relay.Off (Extension);
ReefAngel.Relay.Off (Heater);
ReefAngel.Relay.Off (Refugium);
ReefAngel.Relay.Off (Reactor);
ReefAngel.CustomVar[1]=1;
}
////// Place your custom code above here
// This should always be the last line
ReefAngel.Portal( "lnevo" );
ReefAngel.ShowInterface();
}
// Vortech Helper functions
void setRFmode(int mode, int speed, int duration) {
// Check if mode has changed
if (mode!=vtMode) {
vtPrevMode=vtMode;
vtMode=mode;
if (mode!=InternalMemory.RFMode_read()) {
InternalMemory.RFMode_write(mode);
}
// Temp fix for coming out of night mode
if (vtPrevMode==Night) {
ReefAngel.RF.UseMemory=false;
ReefAngel.RF.SetMode(Feeding_Stop,0,0);
ReefAngel.RF.UseMemory=true;
}
if ( (isNight && vtMode != Night) || vtMode==Smart_NTM) {
setRFtimer(60);
}
}
// Check if speed has changed
if (speed!=vtSpeed) {
vtPrevSpeed=vtSpeed;
vtSpeed=speed;
if (speed!=InternalMemory.RFSpeed_read()) {
InternalMemory.RFSpeed_write(speed);
}
}
// Check if duration has changed
if (duration!=vtDuration) {
vtPrevDuration=vtDuration;
vtDuration=duration;
if (speed!=InternalMemory.RFSpeed_read()) {
InternalMemory.RFSpeed_write(speed);
}
}
}
void setRFmode() {
setRFmode(InternalMemory.RFMode_read(), InternalMemory.RFSpeed_read(), InternalMemory.RFDuration_read());
}
void setRFtimer(int minutes) {
ReefAngel.Timer[1].SetInterval(minutes*60);
ReefAngel.Timer[1].Start();
vtOverride=true;
}
// Menu Code
void MenuEntry1()
{
ReefAngel.FeedingModeStart();
}
void MenuEntry2()
{
ReefAngel.WaterChangeModeStart();
}
void MenuEntry3()
{
byte mode,speed,duration,prev_mode,prev_speed,prev_dur;
mode=vtMode;
mode++;
prev_mode=vtPrevMode; prev_speed=vtPrevSpeed; prev_dur=vtPrevDuration;
if (mode > 9 ) {
mode=0;
speed=50; duration=0; // Constant
} else if (mode == 1) {
speed=40; duration=0; // Lagoon
} else if (mode == 2) {
speed=45; duration=0; // Reef Crest
} else if (mode == 3) {
speed=55; duration=10; // Short Pulse
} else if (mode == 4) {
speed=55; duration=20; // Long Pulse
} else if (mode == 6) {
speed=50; duration=10; // Smart_TSM
} else if (mode == 5) {
speed=vtNTMSpeed; duration=vtNTMDuration; // Smart_NTM
} else if (mode == 7) {
speed=vtNightSpeed; duration=vtNightDuration; // Night
mode=9;
}
prev_mode=vtPrevMode; prev_speed=vtPrevSpeed; prev_dur=vtPrevDuration;
setRFmode(mode,speed,duration);
if (!isNight) {
vtPrevMode=prev_mode; vtPrevSpeed=prev_speed; vtPrevDuration=prev_dur;
}
ReefAngel.DisplayedMenu = RETURN_MAIN_MODE;
}
void MenuEntry4()
{
if (isNight) {
if (bitRead(ReefAngel.Relay.RelayMaskOff,Refugium-1)==1) {
bitClear(ReefAngel.Relay.RelayMaskOff,Refugium-1);
} else {
bitSet(ReefAngel.Relay.RelayMaskOff,Refugium-1);
}
} else {
if (bitRead(ReefAngel.Relay.RelayMaskOn,Refugium-1)==1) {
bitClear(ReefAngel.Relay.RelayMaskOn,Refugium-1);
} else {
bitSet(ReefAngel.Relay.RelayMaskOn,Refugium-1);
}
}
ReefAngel.DisplayedMenu = RETURN_MAIN_MODE;
}
void MenuEntry5()
{
ReefAngel.ATOClear();
ReefAngel.DisplayMenuEntry("Clear ATO Timeout");
ReefAngel.OverheatClear();
ReefAngel.DisplayMenuEntry("Clear Overheat");
}
void MenuEntry6()
{
ReefAngel.SetupCalibratePH();
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry7()
{
ReefAngel.SetupCalibrateWaterLevel();
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry8()
{
ReefAngel.SetupDateTime();
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry9()
{
ReefAngel.DisplayVersion();
}
// Custom Main Screen
void DrawCustomMain()
{
char buf[16];
byte x = 5;
byte y = 2;
byte t;
// if (isFeeding) { ReefAngel.ClearScreen(DefaultBGColor); return; }
// Main Header
// ReefAngel.LCD.DrawText(DefaultFGColor, DefaultBGColor, 35, y,"Lee's Reef");
// Date+Time
ReefAngel.LCD.DrawDate(x+1, y);
ReefAngel.LCD.Clear(COLOR_BLACK, 1, y+9, 128, y+9);
// Param Header
y+=12;
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,x+5,y,"Temp:");
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,x+80, y, "PH:");
// Temp and PH
y+=2;
ConvertNumToString(buf, ReefAngel.Params.Temp[T2_PROBE], 10);
ReefAngel.LCD.DrawText(T2TempColor, DefaultBGColor, x+45, y, buf);
y+=6;
ConvertNumToString(buf, ReefAngel.Params.Temp[T1_PROBE], 10);
ReefAngel.LCD.DrawLargeText(T1TempColor, DefaultBGColor, x+5, y, buf, Num8x16);
ConvertNumToString(buf, ReefAngel.Params.PH, 100);
ReefAngel.LCD.DrawLargeText(PHColor, DefaultBGColor, x+80, y, buf, Num8x16);
y+=5;
ConvertNumToString(buf, ReefAngel.Params.Temp[T3_PROBE], 10);
ReefAngel.LCD.DrawText(T3TempColor, DefaultBGColor, x+45, y, buf);
pingSerial();
/// Display Sunrise / Sunset (to be calculated later...)
y+=15; t=x;
sprintf(buf, "%02d:%02d", sl.GetRiseHour(), sl.GetRiseMinute());
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,t,y,"Rise:"); t+=31;
ReefAngel.LCD.DrawText(COLOR_RED,DefaultBGColor,t,y,buf);
sprintf(buf, "%02d:%02d", sl.GetSetHour(), sl.GetSetMinute()); t+=36;
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,t,y,"Set:"); t+=25;
ReefAngel.LCD.DrawText(COLOR_RED,DefaultBGColor,t,y,buf);
pingSerial();
// MoonPhase
y+=10;
ReefAngel.LCD.DrawText(0,255,x,y,"Moon:");
ReefAngel.LCD.Clear(DefaultBGColor,x+32,y,x+(128-x),y+8);
ReefAngel.LCD.DrawText(COLOR_MAGENTA,255,x+32,y,MoonPhaseLabel());
pingSerial();
// MoonLight %
y+=10;
t = intlength(ReefAngel.PWM.GetDaylightValue()) + 1; t *= 5;
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,x,y,"MoonLights:");
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.PWM.GetDaylightValue(), DPColor, x+68, y, 1);
ReefAngel.LCD.DrawText(DPColor, DefaultBGColor, x+68+t, y, "%");
pingSerial();
// Display Water level
y+=10; t=x;
ConvertNumToString(buf, ReefAngel.WaterLevel.GetLevel(), 1);
strcat(buf," ");
ReefAngel.LCD.DrawText(DefaultFGColor,DefaultBGColor,x,y,"AT0 Level:"); t+=60;
ReefAngel.LCD.DrawText(DefaultFGColor,DefaultBGColor,t,y,buf);
// Vortech Mode
y+=10; t=x;
ReefAngel.LCD.DrawText(0,255,x,y,"RF:"); t+=20;
ReefAngel.LCD.Clear(DefaultBGColor,t,y,x+(128-x),y+8);
if (vtMode == 0) ReefAngel.LCD.DrawLargeText(COLOR_GREEN,255,t,y,"Constant");
else if(vtMode == 1) ReefAngel.LCD.DrawLargeText(COLOR_GOLD,255,t,y,"Lagoon");
else if (vtMode == 2) ReefAngel.LCD.DrawLargeText(COLOR_GOLD,255,t,y,"Reef Crest");
else if (vtMode == 3) ReefAngel.LCD.DrawLargeText(COLOR_RED,255,t,y,"Short Pulse");
else if (vtMode == 4) ReefAngel.LCD.DrawLargeText(COLOR_RED,255,t,y,"Long Pulse");
else if (vtMode == 5) ReefAngel.LCD.DrawLargeText(COLOR_MAGENTA,255,t,y,"Smart NTM");
else if (vtMode == 6) ReefAngel.LCD.DrawLargeText(COLOR_MAGENTA,255,t,y,"Tidal Swell");
else if (vtMode == 9) ReefAngel.LCD.DrawLargeText(COLOR_WHITE,0,t,y,"Night");
y+=10; t=x;
ReefAngel.LCD.DrawText(0,255,x,y,"RF Speed:"); t+=60;
ReefAngel.LCD.Clear(DefaultBGColor,t,y,x+(128-x),y+8);
ReefAngel.LCD.DrawText(COLOR_BLUE, DefaultBGColor,t,y,InternalMemory.RFSpeed_read()); t+=15;
ReefAngel.LCD.DrawText(COLOR_BLUE, DefaultBGColor,t,y,"/"); t+=10;
ReefAngel.LCD.DrawText(COLOR_BLUE, DefaultBGColor,t,y,InternalMemory.RFDuration_read());
pingSerial();
y+=15;
// Relays
byte TempRelay = ReefAngel.Relay.RelayData;
TempRelay &= ReefAngel.Relay.RelayMaskOff;
TempRelay |= ReefAngel.Relay.RelayMaskOn;
ReefAngel.LCD.DrawOutletBox(12, y, TempRelay);
pingSerial();
y+=12;
TempRelay = ReefAngel.Relay.RelayDataE[0];
TempRelay &= ReefAngel.Relay.RelayMaskOffE[0];
TempRelay |= ReefAngel.Relay.RelayMaskOnE[0];
ReefAngel.LCD.DrawOutletBox(12, y, TempRelay);
pingSerial();
}
void DrawCustomGraph()
{
}
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 <RA_Colors.h>
#include <RA_CustomColors.h>
//#include <Salinity.h>
//#include <IO.h>
//#include <ORP.h>
//#include <AI.h>
#include <RF.h>
#include <ReefAngel.h>
#include <SunLocation.h>
#include <WaterLevel.h>
////// Place global variable code below here
#define CUSTOM_MENU
#define CUSTOM_MENU_ENTRIES 8
#define NUMBERS_8x16
// Custom Menu Code
#include <avr/pgmspace.h>
prog_char menu1_label[] PROGMEM = "Feeding";
prog_char menu2_label[] PROGMEM = "Water Change";
prog_char menu3_label[] PROGMEM = "Vortech Mode";
prog_char menu4_label[] PROGMEM = "Refugium Light";
prog_char menu5_label[] PROGMEM = "ATO Clear";
prog_char menu6_label[] PROGMEM = "Overheat Clear";
prog_char menu7_label[] PROGMEM = "PH Calibration";
prog_char menu8_label[] PROGMEM = "WLS Calibration";
prog_char menu9_label[] PROGMEM = "Date / Time";
// Group the menu entries together
PROGMEM const char *menu_items[] = {
menu1_label, menu2_label, menu3_label,
menu4_label, menu5_label, menu6_label,
menu7_label, menu8_label, menu9_label
};
// Vortech Defaults
byte vtPrevMode=0;
byte vtPrevSpeed=0;
byte vtPrevDuration=0;
// Default Mode
byte vtMode=Random2;
byte vtSpeed=45;
byte vtDuration=5;
// NTM mode
byte vtNTMSpeed=65;
byte vtNTMDuration=5;
// Night Mode
byte vtNightSpeed=20;
byte vtNightDuration=10;
boolean isNight=false;
boolean isFeeding=false;
boolean feedDelay=false;
boolean vtOverride=false;
boolean floatHigh=true;
boolean powerOutage=true;
byte acclTime=0;
SunLocation sl;
//Define Custom Memory Location
#define Mem_B_RefillATO 100
#define Mem_B_Vacation 101
#define Mem_B_AcclTime 102
#define Mem_B_ClearATO 103
//Define Relay Ports by Name
#define Return 1
#define Skimmer 2
#define WhiteLEDs 3
#define BlueLEDs 4
#define Extension 5
#define Heater 6
#define Refugium 7
#define Reactor 8
#define Unused1 Box1_Port1
#define Unused2 Box1_Port2
#define Vortech1 Box1_Port3
#define Vortech2 Box1_Port4
#define VortechUPS Box1_Port5
#define Unused3 Box1_Port6
#define DPump1 Box1_Port7
#define DPump2 Box1_Port8
////// Place global variable code above here
// Setup on controller startup/reset
void setup()
{
// This must be the first line
ReefAngel.Init(); //Initialize controller
// Initialize Menu
ReefAngel.InitMenu(pgm_read_word(&(menu_items[0])),SIZE(menu_items));
// Ports toggled in Feeding Mode
ReefAngel.FeedingModePorts = Port1Bit | Port2Bit | Port8Bit;
// Ports toggled in Water Change Mode
ReefAngel.WaterChangePorts = Port1Bit | Port2Bit | Port6Bit | Port8Bit;
// Ports toggled when Lights On / Off menu entry selected
ReefAngel.LightsOnPorts = Port3Bit | Port4Bit ;
// Ports turned off when Overheat temperature exceeded
ReefAngel.OverheatShutoffPorts = Port3Bit | Port4Bit | Port6Bit;
// Use T1 probe as temperature and overheat functions
ReefAngel.TempProbe = T1_PROBE;
ReefAngel.OverheatProbe = T1_PROBE;
// Set the Overheat temperature setting
InternalMemory.OverheatTemp_write( 820 );
// Ports that default on
ReefAngel.Relay.On( Return );
ReefAngel.Relay.On( Vortech1 );
ReefAngel.Relay.On( Vortech2 );
ReefAngel.Relay.On( VortechUPS );
// Ports that default off
ReefAngel.Relay.Off( Extension );
ReefAngel.Relay.Off( Unused1 );
ReefAngel.Relay.Off( Unused2 );
ReefAngel.Relay.Off( Unused3 );
////// Place additional initialization code below here
// Setup SunLocation class
sl.Init(-18.285833, 147.699722); // Great Barrier Reef
// What was our previous modes before we restarted?
vtPrevMode=InternalMemory.RFMode_read();
vtPrevSpeed=InternalMemory.RFSpeed_read();
vtPrevDuration=InternalMemory.RFDuration_read();
ReefAngel.CustomVar[7]=255;
////// Place additional initialization code above here
}
void loop()
{
// Default port modes. Use Memory settings for external control
ReefAngel.StandardHeater( Heater );
ReefAngel.DosingPumpRepeat1( DPump1 );
ReefAngel.DosingPumpRepeat2( DPump2 );
ReefAngel.StandardLights( WhiteLEDs );
ReefAngel.ActinicLights( BlueLEDs );
////// Place your custom code below here
// See if power is back on so DelayedOn ports will reset.
if (powerOutage && ReefAngel.Relay.IsRelayPresent(EXP1_RELAY))
{
powerOutage=false;
LastStart=now();
ReefAngel.CustomVar[1]=0;
}
ReefAngel.Relay.DelayedOn( Skimmer );
ReefAngel.Relay.DelayedOn( Reactor );
// We're on vacation! Use external pump to top off the top off.
if (InternalMemory.read( Mem_B_Vacation )==1) {
ReefAngel.WaterLevelATO( Extension,30,61,63 );
ReefAngel.CustomVar[3]=1;
} else {
ReefAngel.CustomVar[3]=0;
ReefAngel.Relay.Off( Extension );
}
// Real ATO Clear
if (InternalMemory.read( Mem_B_ClearATO )==1) {
ReefAngel.ATOClear();
}
// ATO Refill mode. Top off ATO reservoir until it's at 100%
if (InternalMemory.read( Mem_B_RefillATO )==1) {
if (ReefAngel.WaterLevel.GetLevel()<=100) {
ReefAngel.Relay.On( Extension );
ReefAngel.CustomVar[2]=1;
} else {
ReefAngel.Relay.Off( Extension );
InternalMemory.write( Mem_B_RefillATO, 0);
ReefAngel.CustomVar[2]=0;
}
}
// See if we are acclimating corals and decrement the countdown each night
static boolean acclCounterReady=false;
if ( acclCounterReady && now()%86400==0) {
acclTime--;
acclCounterReady=false;
InternalMemory.write( Mem_B_AcclTime, acclTime );
}
if ( now()%86400!=0 ) acclCounterReady=true;
// -9 hour difference for time zone. 472/506 seconds were calculation corrections
// The acclTime will adjust the sunrise/sunset if we are adjusting for new coral
sl.SetOffset(-9,472+(acclTime*240),-9,506-(acclTime*120));
// Calculate the new Sunrise / Sunset based on our GPS coordinates
sl.CheckAndUpdate();
// Let's make the time one number so we can figure out it's night or day...
int currTime=NumMins(hour(),minute());
int riseTime=NumMins(sl.GetRiseHour(),sl.GetRiseMinute());
int setTime=NumMins(sl.GetSetHour(),sl.GetSetMinute());
if ( (currTime <= riseTime) || (currTime >= setTime) ) isNight=true; else isNight=false;
if (isNight)
{
if ((hour()>=3) && (hour()<=5)) {
// Some complete darkness
ReefAngel.PWM.SetDaylight( 0 );
ReefAngel.PWM.SetActinic( 0 );
} else {
// Set moonlights to the MoonPhase
ReefAngel.PWM.SetDaylight( MoonPhase() );
ReefAngel.PWM.SetActinic( MoonPhase() );
}
// Vortech's to night mode.
if (vtOverride==false && isFeeding==false) {
setRFmode(Night,vtNightSpeed,vtNightDuration);
}
// Turn on refugium light opposite normal lights
ReefAngel.Relay.On( Refugium );
} else { // It's Daytime!
// Regular lights are controlled by Memory variables set in SunLocation class
ReefAngel.PWM.SetDaylight( 0 );
ReefAngel.PWM.SetActinic( 0 );
ReefAngel.Relay.Off( Refugium );
// Go back to our regularly scheduled program.
if (vtOverride==false && vtMode==Night) {
setRFmode(vtPrevMode,vtPrevSpeed,vtPrevDuration);
// Force the trigger to make sure we break feeding/night modes.
ReefAngel.Timer[1].ForceTrigger();
}
}
// Enable Feeding Mode flag
if (ReefAngel.DisplayedMenu==FEEDING_MODE) isFeeding=true;
// Turn on Refugium light during water change mode
if (ReefAngel.DisplayedMenu==WATERCHANGE_MODE) ReefAngel.Relay.On( Refugium );
// Enable ATOHigh flag on purpose during feed/water change mode so we don't get alerts.
if (ReefAngel.DisplayedMenu==FEEDING_MODE || ReefAngel.DisplayedMenu==WATERCHANGE_MODE) floatHigh=true;
/*** RF Modes ***/
// Here's what we do if we're just out of feeding mode...
if (ReefAngel.DisplayedMenu==DEFAULT_MENU && isFeeding ) {
isFeeding=false;
feedDelay=true; // This will let us know we want some extra time before Smart_NTM
setRFtimer(30); // Start Smart_NTM in 30 minutes...
} else if (vtOverride && ReefAngel.Timer[1].IsTriggered()) { // Our RF timer is over.
vtOverride=false; // Stop overriding the default RF mode
// First let's deal with that extra 30 minutes
if(feedDelay) {
feedDelay=false; // Reset the feedDelay flag
setRFmode(Smart_NTM,vtNTMSpeed,vtNTMDuration); // Smart_NTM time!
} else {
// Otherwise go to Previous settings
setRFmode(vtPrevMode,vtPrevSpeed,vtPrevDuration);
}
} else {
setRFmode(); // Update the mode if we change it remotely
}
// A little extra Smart_NTM never hurt anyone
if ( ((hour() == 15) && (minute() == 00) && (second() == 00) ) ) {
setRFmode(Smart_NTM,vtNTMSpeed,vtNTMDuration);
}
/*** End of RF modes ***/
// Turn off return pump if we run out of water!
if (ReefAngel.LowATO.IsActive()) {
bitClear(ReefAngel.Relay.RelayMaskOff,Return-1);
}
// Turn off return if we are somehow overflowing the sump
if (ReefAngel.HighATO.IsActive()) {
if (!floatHigh) {
floatHigh=true;
ReefAngel.CustomVar[0]=1;
bitClear(ReefAngel.Relay.RelayMaskOff,Return-1);
}
} else {
ReefAngel.CustomVar[0]=0;
floatHigh=false;
}
// Turn off Skimmer if Return pump is shutoff.
if (bitRead(ReefAngel.Relay.RelayMaskOff,Return-1)==0) {
bitClear(ReefAngel.Relay.RelayMaskOff,Skimmer-1);
}
// Power Outage - Only Return Pump should be active
if (!ReefAngel.Relay.IsRelayPresent(EXP1_RELAY)) // Expansion Relay NOT present
{
powerOutage=true;
ReefAngel.Relay.Off (Skimmer);
ReefAngel.Relay.Off (WhiteLEDs);
ReefAngel.Relay.Off (BlueLEDs);
ReefAngel.Relay.Off (Extension);
ReefAngel.Relay.Off (Heater);
ReefAngel.Relay.Off (Refugium);
ReefAngel.Relay.Off (Reactor);
ReefAngel.CustomVar[1]=1;
}
////// Place your custom code above here
// This should always be the last line
ReefAngel.Portal( "lnevo" );
ReefAngel.ShowInterface();
}
// Vortech Helper functions
void setRFmode(int mode, int speed, int duration) {
// Check if mode has changed
if (mode!=vtMode) {
vtPrevMode=vtMode;
vtMode=mode;
if (mode!=InternalMemory.RFMode_read()) {
InternalMemory.RFMode_write(mode);
}
// Fix for coming out of night mode
if (vtPrevMode==Night) {
ReefAngel.RF.UseMemory=false;
ReefAngel.RF.SetMode(Feeding_Stop,0,0);
ReefAngel.RF.UseMemory=true;
}
// If it's at night or we are setting NTM, do this only temporarily
if ( (isNight && vtMode != Night) || vtMode==Smart_NTM) {
setRFtimer(60);
}
}
// Check if speed has changed
if (speed!=vtSpeed) {
vtPrevSpeed=vtSpeed;
vtSpeed=speed;
if (speed!=InternalMemory.RFSpeed_read()) {
InternalMemory.RFSpeed_write(speed);
}
}
// Check if duration has changed
if (duration!=vtDuration) {
vtPrevDuration=vtDuration;
vtDuration=duration;
if (speed!=InternalMemory.RFSpeed_read()) {
InternalMemory.RFSpeed_write(speed);
}
}
}
void setRFmode() {
setRFmode(InternalMemory.RFMode_read(), InternalMemory.RFSpeed_read(), InternalMemory.RFDuration_read());
}
void setRFtimer(int minutes) {
ReefAngel.Timer[1].SetInterval(minutes*60);
ReefAngel.Timer[1].Start();
vtOverride=true;
}
// Menu Code
void MenuEntry1() {
ReefAngel.FeedingModeStart();
}
void MenuEntry2() {
ReefAngel.WaterChangeModeStart();
}
void MenuEntry3() {
byte mode,speed,duration;
byte prev_mode,prev_speed,prev_dur;
mode=vtMode;
mode++;
prev_mode=vtPrevMode; prev_speed=vtPrevSpeed; prev_dur=vtPrevDuration;
if (mode > 9 ) {
mode=0;
speed=50; duration=0; // Constant
} else if (mode == 1) {
speed=40; duration=0; // Lagoon
} else if (mode == 2) {
speed=45; duration=0; // Reef Crest
} else if (mode == 3) {
speed=55; duration=10; // Short Pulse
} else if (mode == 4) {
speed=55; duration=20; // Long Pulse
} else if (mode == 6) {
speed=50; duration=10; // Smart_TSM
} else if (mode == 5) {
speed=vtNTMSpeed; duration=vtNTMDuration; // Smart_NTM
} else if (mode == 7) {
speed=vtNightSpeed; duration=vtNightDuration; // Night
mode=9;
}
prev_mode=vtPrevMode; prev_speed=vtPrevSpeed; prev_dur=vtPrevDuration;
setRFmode(mode,speed,duration);
// If it's night time, don't overwrite the default daytime mode when using the menu
if (!isNight) {
vtPrevMode=prev_mode; vtPrevSpeed=prev_speed; vtPrevDuration=prev_dur;
}
ReefAngel.DisplayedMenu = RETURN_MAIN_MODE;
}
void MenuEntry4() {
if (isNight) { // Turn off the Refugium light
if (bitRead(ReefAngel.Relay.RelayMaskOff,Refugium-1)==1) {
bitClear(ReefAngel.Relay.RelayMaskOff,Refugium-1);
} else {
bitSet(ReefAngel.Relay.RelayMaskOff,Refugium-1);
}
} else { // Turn on the Refugium light
if (bitRead(ReefAngel.Relay.RelayMaskOn,Refugium-1)==1) {
bitClear(ReefAngel.Relay.RelayMaskOn,Refugium-1);
} else {
bitSet(ReefAngel.Relay.RelayMaskOn,Refugium-1);
}
}
ReefAngel.DisplayedMenu = RETURN_MAIN_MODE;
}
void MenuEntry5() {
ReefAngel.ATOClear();
ReefAngel.DisplayMenuEntry("Clear ATO Timeout");
}
void MenuEntry6() {
ReefAngel.OverheatClear();
ReefAngel.DisplayMenuEntry("Clear Overheat");
}
void MenuEntry7() {
ReefAngel.SetupCalibratePH();
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry8() {
ReefAngel.SetupCalibrateWaterLevel();
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry9() {
ReefAngel.SetupDateTime();
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
// Custom Main Screen
void DrawCustomMain() {
char buf[16];
byte x = 5;
byte y = 2;
byte t;
// Main Header
// ReefAngel.LCD.DrawText(DefaultFGColor, DefaultBGColor, 35, y,"Lee's Reef");
// Date+Time
ReefAngel.LCD.DrawDate(x+1, y);
ReefAngel.LCD.Clear(COLOR_BLACK, 1, y+9, 128, y+9);
// Param Header
y+=12;
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,x+5,y,"Temp:");
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,x+80, y, "PH:");
// Temp and PH
y+=2;
ConvertNumToString(buf, ReefAngel.Params.Temp[T2_PROBE], 10);
ReefAngel.LCD.DrawText(T2TempColor, DefaultBGColor, x+45, y, buf);
y+=6;
ConvertNumToString(buf, ReefAngel.Params.Temp[T1_PROBE], 10);
ReefAngel.LCD.DrawLargeText(T1TempColor, DefaultBGColor, x+5, y, buf, Num8x16);
ConvertNumToString(buf, ReefAngel.Params.PH, 100);
ReefAngel.LCD.DrawLargeText(PHColor, DefaultBGColor, x+80, y, buf, Num8x16);
y+=5;
ConvertNumToString(buf, ReefAngel.Params.Temp[T3_PROBE], 10);
ReefAngel.LCD.DrawText(T3TempColor, DefaultBGColor, x+45, y, buf);
pingSerial();
/// Display Sunrise / Sunset (to be calculated later...)
y+=15; t=x;
sprintf(buf, "%02d:%02d", sl.GetRiseHour(), sl.GetRiseMinute());
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,t,y,"Rise:"); t+=31;
ReefAngel.LCD.DrawText(COLOR_RED,DefaultBGColor,t,y,buf);
sprintf(buf, "%02d:%02d", sl.GetSetHour(), sl.GetSetMinute()); t+=36;
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,t,y,"Set:"); t+=25;
ReefAngel.LCD.DrawText(COLOR_RED,DefaultBGColor,t,y,buf);
pingSerial();
// MoonPhase
y+=10;
ReefAngel.LCD.DrawText(0,255,x,y,"Moon:");
ReefAngel.LCD.Clear(DefaultBGColor,x+32,y,x+(128-x),y+8);
ReefAngel.LCD.DrawText(COLOR_MAGENTA,255,x+32,y,MoonPhaseLabel());
pingSerial();
// MoonLight %
y+=10;
t = intlength(ReefAngel.PWM.GetDaylightValue()) + 1; t *= 5;
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,x,y,"MoonLights:");
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.PWM.GetDaylightValue(), DPColor, x+68, y, 1);
ReefAngel.LCD.DrawText(DPColor, DefaultBGColor, x+68+t, y, "%");
pingSerial();
// Display Water level
y+=10; t=x;
ConvertNumToString(buf, ReefAngel.WaterLevel.GetLevel(), 1);
strcat(buf," ");
ReefAngel.LCD.DrawText(DefaultFGColor,DefaultBGColor,x,y,"AT0 Level:"); t+=60;
ReefAngel.LCD.DrawText(DefaultFGColor,DefaultBGColor,t,y,buf);
// Vortech Mode
y+=10; t=x;
ReefAngel.LCD.DrawText(0,255,x,y,"RF:"); t+=20;
ReefAngel.LCD.Clear(DefaultBGColor,t,y,x+(128-x),y+8);
if (vtMode == 0) ReefAngel.LCD.DrawLargeText(COLOR_GREEN,255,t,y,"Constant");
else if(vtMode == 1) ReefAngel.LCD.DrawLargeText(COLOR_GOLD,255,t,y,"Lagoon");
else if (vtMode == 2) ReefAngel.LCD.DrawLargeText(COLOR_GOLD,255,t,y,"Reef Crest");
else if (vtMode == 3) ReefAngel.LCD.DrawLargeText(COLOR_RED,255,t,y,"Short Pulse");
else if (vtMode == 4) ReefAngel.LCD.DrawLargeText(COLOR_RED,255,t,y,"Long Pulse");
else if (vtMode == 5) ReefAngel.LCD.DrawLargeText(COLOR_MAGENTA,255,t,y,"Smart NTM");
else if (vtMode == 6) ReefAngel.LCD.DrawLargeText(COLOR_MAGENTA,255,t,y,"Tidal Swell");
else if (vtMode == 9) ReefAngel.LCD.DrawLargeText(COLOR_WHITE,0,t,y,"Night");
y+=10; t=x;
ReefAngel.LCD.DrawText(0,255,x,y,"RF Speed:"); t+=60;
ReefAngel.LCD.Clear(DefaultBGColor,t,y,x+(128-x),y+8);
ReefAngel.LCD.DrawText(COLOR_BLUE, DefaultBGColor,t,y,InternalMemory.RFSpeed_read()); t+=15;
ReefAngel.LCD.DrawText(COLOR_BLUE, DefaultBGColor,t,y,"/"); t+=10;
ReefAngel.LCD.DrawText(COLOR_BLUE, DefaultBGColor,t,y,InternalMemory.RFDuration_read());
pingSerial();
y+=15;
// Relays
byte TempRelay = ReefAngel.Relay.RelayData;
TempRelay &= ReefAngel.Relay.RelayMaskOff;
TempRelay |= ReefAngel.Relay.RelayMaskOn;
ReefAngel.LCD.DrawOutletBox(12, y, TempRelay);
pingSerial();
y+=12;
TempRelay = ReefAngel.Relay.RelayDataE[0];
TempRelay &= ReefAngel.Relay.RelayMaskOffE[0];
TempRelay |= ReefAngel.Relay.RelayMaskOnE[0];
ReefAngel.LCD.DrawOutletBox(12, y, TempRelay);
pingSerial();
}
void DrawCustomGraph() {
}
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 <RA_Colors.h>
#include <RA_CustomColors.h>
#include <RF.h>
#include <ReefAngel.h>
#include <SunLocation.h>
#include <WaterLevel.h>
////// Place global variable code below here
// Custom Menu Code
#include <avr/pgmspace.h>
prog_char menu1_label[] PROGMEM = "Feeding";
prog_char menu2_label[] PROGMEM = "Water Change";
prog_char menu3_label[] PROGMEM = "Vortech Mode";
prog_char menu4_label[] PROGMEM = "Refugium Light";
prog_char menu5_label[] PROGMEM = "ATO Clear";
prog_char menu6_label[] PROGMEM = "Overheat Clear";
prog_char menu7_label[] PROGMEM = "PH Calibration";
prog_char menu8_label[] PROGMEM = "WLS Calibration";
prog_char menu9_label[] PROGMEM = "Date / Time";
// Group the menu entries together
PROGMEM const char *menu_items[] = {
menu1_label, menu2_label, menu3_label,
menu4_label, menu5_label, menu6_label,
menu7_label, menu8_label, menu9_label
};
// Vortech Defaults
byte vtPrevMode=0;
byte vtPrevSpeed=0;
byte vtPrevDuration=0;
// Default Mode
byte vtMode=Random2;
byte vtSpeed=45;
byte vtDuration=5;
// NTM mode
byte vtNTMSpeed=65;
byte vtNTMDuration=5;
// Night Mode
byte vtNightSpeed=20;
byte vtNightDuration=10;
boolean isNight=false;
boolean isFeeding=false;
boolean feedDelay=false;
boolean vtOverride=false;
boolean floatHigh=true;
boolean powerOutage=true;
SunLocation sl;
byte acclDay=0;
byte vacationMode=0;
//Define Custom Memory Location
#define Mem_B_RefillATO 100
#define Mem_B_ClearATO 101
#define Mem_B_Vacation 102
#define Mem_B_AcclDay 103
#define Var_HighATO 0
#define Var_Power 1
#define Var_Vacation 2
#define Var_AcclDay 3
//Define Relay Ports by Name
#define Return 1
#define Skimmer 2
#define WhiteLEDs 3
#define BlueLEDs 4
#define Extension 5
#define Heater 6
#define Refugium 7
#define Reactor 8
#define Unused1 Box1_Port1
#define Unused2 Box1_Port2
#define Vortech1 Box1_Port3
#define Vortech2 Box1_Port4
#define VortechUPS Box1_Port5
#define Unused3 Box1_Port6
#define DPump1 Box1_Port7
#define DPump2 Box1_Port8
////// Place global variable code above here
// Setup on controller startup/reset
void setup()
{
// This must be the first line
ReefAngel.Init(); //Initialize controller
// Initialize Menu
ReefAngel.InitMenu(pgm_read_word(&(menu_items[0])),SIZE(menu_items));
// Ports toggled in Feeding Mode
ReefAngel.FeedingModePorts = Port1Bit | Port2Bit | Port8Bit;
// Ports toggled in Water Change Mode
ReefAngel.WaterChangePorts = Port1Bit | Port2Bit | Port6Bit | Port8Bit;
// Ports toggled when Lights On / Off menu entry selected
ReefAngel.LightsOnPorts = Port3Bit | Port4Bit ;
// Ports turned off when Overheat temperature exceeded
ReefAngel.OverheatShutoffPorts = Port3Bit | Port4Bit | Port6Bit;
// Use T1 probe as temperature and overheat functions
ReefAngel.TempProbe = T1_PROBE;
ReefAngel.OverheatProbe = T1_PROBE;
// Ports that default on
ReefAngel.Relay.On(Return);
ReefAngel.Relay.On(Vortech1);
ReefAngel.Relay.On(Vortech2);
ReefAngel.Relay.On(VortechUPS);
// Ports that default off
ReefAngel.Relay.Off(Extension);
ReefAngel.Relay.Off(Unused1);
ReefAngel.Relay.Off(Unused2);
ReefAngel.Relay.Off(Unused3);
////// Place additional initialization code below here
// What was our previous modes before we restarted?
vtPrevMode=InternalMemory.RFMode_read();
vtPrevSpeed=InternalMemory.RFSpeed_read();
vtPrevDuration=InternalMemory.RFDuration_read();
// Dummy CustomVar to activate portal feature
ReefAngel.CustomVar[7]=255;
////// Place additional initialization code above here
}
void loop()
{
// Default port modes. Use Memory settings for external control
ReefAngel.StandardHeater(Heater);
ReefAngel.DosingPumpRepeat1(DPump1);
ReefAngel.DosingPumpRepeat2(DPump2);
ReefAngel.StandardLights(WhiteLEDs);
ReefAngel.ActinicLights(BlueLEDs);
////// Place your custom code below here
// See if power is back on so DelayedOn ports will reset.
if (powerOutage && ReefAngel.Relay.IsRelayPresent(EXP1_RELAY))
{
powerOutage=false;
LastStart=now();
ReefAngel.CustomVar[Var_Power]=0;
}
ReefAngel.Relay.DelayedOn(Skimmer);
ReefAngel.Relay.DelayedOn(Reactor);
// Find out if we are on vacation
ReefAngel.CustomVar[Var_Vacation]=InternalMemory.read(Mem_B_Vacation);
vacationMode=ReefAngel.CustomVar[Var_Vacation];
// We're on vacation! Use external pump to top off the top off.
if (vacationMode==1) {
ReefAngel.WaterLevelATO(Extension,30,61,63);
} else {
ReefAngel.Relay.Off(Extension);
}
// Real ATO Clear
if (InternalMemory.read(Mem_B_ClearATO)==1) {
ReefAngel.ATOClear();
InternalMemory.write(Mem_B_ClearATO, 0);
}
// ATO Refill mode. Top off ATO reservoir until it's at 100%
if (InternalMemory.read(Mem_B_RefillATO)==1) {
if (ReefAngel.WaterLevel.GetLevel()<=100) {
ReefAngel.Relay.On(Extension);
} else {
ReefAngel.Relay.Off(Extension);
InternalMemory.write(Mem_B_RefillATO, 0);
}
}
// See if we are acclimating corals and decrement the countdown each night
static boolean acclCounterReady=false;
if (now()%SECS_PER_DAY!=0) acclCounterReady=true;
acclDay=InternalMemory.read(Mem_B_AcclDay);
ReefAngel.CustomVar[Var_AcclDay]=acclDay;
if (acclDay > 0) {
if (acclCounterReady && now()%SECS_PER_DAY==0) {
acclDay--;
acclCounterReady=false;
InternalMemory.write(Mem_B_AcclDay,acclDay);
}
}
// -9 hour difference for time zone. 472/506 seconds were calculation corrections
// The acclDay will adjust the sunrise/sunset if we are adjusting for new coral
sl.SetOffset(-9,472+(acclDay*240),-9,506-(acclDay*120));
// Calculate the new Sunrise / Sunset based on our GPS coordinates
sl.CheckAndUpdate();
// Let's make the time one number so we can figure out it's night or day...
int currTime=NumMins(hour(),minute());
int riseTime=NumMins(sl.GetRiseHour(),sl.GetRiseMinute());
int setTime=NumMins(sl.GetSetHour(),sl.GetSetMinute());
if ( (currTime <= riseTime) || (currTime >= setTime) ) isNight=true; else isNight=false;
if (isNight)
{
if ((hour()>=3) && (hour()<=4)) {
// Some complete darkness
ReefAngel.PWM.SetDaylight(0);
ReefAngel.PWM.SetActinic(0);
} else {
// Set moonlights to the MoonPhase
ReefAngel.PWM.SetDaylight(MoonPhase());
ReefAngel.PWM.SetActinic(MoonPhase());
}
// Vortech's to night mode.
if (vtOverride==false && isFeeding==false) {
setRFmode(Night,vtNightSpeed,vtNightDuration);
}
// Turn on refugium light opposite normal lights
ReefAngel.Relay.On(Refugium);
} else { // It's Daytime!
// Regular lights are controlled by Memory variables set in SunLocation class
ReefAngel.PWM.SetDaylight(0);
ReefAngel.PWM.SetActinic(0);
ReefAngel.Relay.Off(Refugium);
// Go back to our regularly scheduled program.
if (vtOverride==false && vtMode==Night) {
setRFmode(vtPrevMode,vtPrevSpeed,vtPrevDuration);
}
}
// Enable Feeding Mode flag
if (ReefAngel.DisplayedMenu==FEEDING_MODE) isFeeding=true;
// Turn on Refugium light during water change mode
if (ReefAngel.DisplayedMenu==WATERCHANGE_MODE) ReefAngel.Relay.On(Refugium);
// Enable ATOHigh flag on purpose during feed/water change mode so we don't get alerts.
if (ReefAngel.DisplayedMenu==FEEDING_MODE || ReefAngel.DisplayedMenu==WATERCHANGE_MODE) floatHigh=true;
// Here's what we do if we're just out of feeding mode...
if (ReefAngel.DisplayedMenu==DEFAULT_MENU && isFeeding) {
isFeeding=false;
feedDelay=true; // This will let us know we want some extra time before Smart_NTM
setRFtimer(30); // Start Smart_NTM in 30 minutes...
} else if (vtOverride && ReefAngel.Timer[1].IsTriggered()) { // Our RF timer is over.
vtOverride=false; // Stop overriding the default RF mode
// First let's deal with that extra 30 minutes
if(feedDelay) {
feedDelay=false; // Reset the feedDelay flag
setRFmode(Smart_NTM,vtNTMSpeed,vtNTMDuration); // Smart_NTM time!
} else {
// Otherwise go to Previous settings
setRFmode(vtPrevMode,vtPrevSpeed,vtPrevDuration);
}
} else {
setRFmode(); // Update the mode if we change it remotely
}
// A little extra Smart_NTM never hurt anyone
if ( ((hour() == 15) && (minute() == 00) && (second() == 00) ) ) {
setRFmode(Smart_NTM,vtNTMSpeed,vtNTMDuration);
}
// Turn off return pump if we run out of water!
if (ReefAngel.LowATO.IsActive()) {
bitClear(ReefAngel.Relay.RelayMaskOff,Return-1);
}
// Turn off return if we are somehow overflowing the sump
if (ReefAngel.HighATO.IsActive()) {
if (!floatHigh) {
floatHigh=true;
ReefAngel.CustomVar[Var_HighATO]=1;
bitClear(ReefAngel.Relay.RelayMaskOff,Return-1);
}
} else {
ReefAngel.CustomVar[Var_HighATO]=0;
floatHigh=false;
}
// Turn off Skimmer if Return pump is shutoff.
if (bitRead(ReefAngel.Relay.RelayMaskOff,Return-1)==0) {
bitClear(ReefAngel.Relay.RelayMaskOff,Skimmer-1);
}
// Power Outage - Only Return Pump should be active
if (!ReefAngel.Relay.IsRelayPresent(EXP1_RELAY)) // Expansion Relay NOT present
{
powerOutage=true;
ReefAngel.Relay.Off (Skimmer);
ReefAngel.Relay.Off (WhiteLEDs);
ReefAngel.Relay.Off (BlueLEDs);
ReefAngel.Relay.Off (Extension);
ReefAngel.Relay.Off (Heater);
ReefAngel.Relay.Off (Refugium);
ReefAngel.Relay.Off (Reactor);
ReefAngel.CustomVar[Var_Power]=1;
}
////// Place your custom code above here
// This should always be the last line
ReefAngel.Portal("lnevo");
ReefAngel.ShowInterface();
}
// Vortech Helper functions
void setRFmode(int mode, int speed, int duration) {
// Check if mode has changed
if (mode!=vtMode) {
vtPrevMode=vtMode;
vtMode=mode;
if (mode!=InternalMemory.RFMode_read()) {
InternalMemory.RFMode_write(mode);
}
// Fix for coming out of night mode
if (vtPrevMode==Night) {
ReefAngel.RF.UseMemory=false;
ReefAngel.RF.SetMode(Feeding_Stop,0,0);
ReefAngel.RF.UseMemory=true;
}
// If it's at night or we are setting NTM, do this only temporarily
if ( (isNight && vtMode != Night) || vtMode==Smart_NTM) {
setRFtimer(60);
}
}
// Check if speed has changed
if (speed!=vtSpeed) {
vtPrevSpeed=vtSpeed;
vtSpeed=speed;
if (speed!=InternalMemory.RFSpeed_read()) {
InternalMemory.RFSpeed_write(speed);
}
}
// Check if duration has changed
if (duration!=vtDuration) {
vtPrevDuration=vtDuration;
vtDuration=duration;
if (speed!=InternalMemory.RFSpeed_read()) {
InternalMemory.RFSpeed_write(speed);
}
}
}
void setRFmode() {
setRFmode(InternalMemory.RFMode_read(), InternalMemory.RFSpeed_read(), InternalMemory.RFDuration_read());
}
void setRFtimer(int minutes) {
ReefAngel.Timer[1].SetInterval(minutes*60);
ReefAngel.Timer[1].Start();
vtOverride=true;
}
// Menu Code
void MenuEntry1() {
ReefAngel.FeedingModeStart();
}
void MenuEntry2() {
ReefAngel.WaterChangeModeStart();
}
void MenuEntry3() {
byte mode,speed,duration;
byte prev_mode,prev_speed,prev_dur;
mode=vtMode;
mode++;
prev_mode=vtPrevMode; prev_speed=vtPrevSpeed; prev_dur=vtPrevDuration;
if (mode > 9) {
mode=0;
speed=50; duration=0; // Constant
} else if (mode == 1) {
speed=40; duration=0; // Lagoon
} else if (mode == 2) {
speed=45; duration=0; // Reef Crest
} else if (mode == 3) {
speed=55; duration=10; // Short Pulse
} else if (mode == 4) {
speed=55; duration=20; // Long Pulse
} else if (mode == 6) {
speed=50; duration=10; // Smart_TSM
} else if (mode == 5) {
speed=vtNTMSpeed; duration=vtNTMDuration; // Smart_NTM
} else if (mode == 7) {
speed=vtNightSpeed; duration=vtNightDuration; // Night
mode=9;
}
// Backup the previous modes. We don't want Night to become default...
prev_mode=vtPrevMode; prev_speed=vtPrevSpeed; prev_dur=vtPrevDuration;
setRFmode(mode,speed,duration);
// If it's night time, don't overwrite the default daytime mode when using the menu
if (!isNight) {
vtPrevMode=prev_mode; vtPrevSpeed=prev_speed; vtPrevDuration=prev_dur;
}
ReefAngel.DisplayedMenu = RETURN_MAIN_MODE;
}
void MenuEntry4() {
// Toggle the refugium light if we choose this menu entry.
// Behavior is opposite for night vs day.
if (isNight) { // Turn off the Refugium light
if (bitRead(ReefAngel.Relay.RelayMaskOff,Refugium-1)==1) {
bitClear(ReefAngel.Relay.RelayMaskOff,Refugium-1);
} else {
bitSet(ReefAngel.Relay.RelayMaskOff,Refugium-1);
}
} else { // Turn on the Refugium light
if (bitRead(ReefAngel.Relay.RelayMaskOn,Refugium-1)==1) {
bitClear(ReefAngel.Relay.RelayMaskOn,Refugium-1);
} else {
bitSet(ReefAngel.Relay.RelayMaskOn,Refugium-1);
}
}
ReefAngel.DisplayedMenu = RETURN_MAIN_MODE;
}
void MenuEntry5() {
ReefAngel.ATOClear();
ReefAngel.DisplayMenuEntry("Clear ATO Timeout");
}
void MenuEntry6() {
ReefAngel.OverheatClear();
ReefAngel.DisplayMenuEntry("Clear Overheat");
}
void MenuEntry7() {
ReefAngel.SetupCalibratePH();
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry8() {
ReefAngel.SetupCalibrateWaterLevel();
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry9() {
ReefAngel.SetupDateTime();
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
// Custom Main Screen
void DrawCustomMain() {
char buf[16];
byte x = 5;
byte y = 2;
byte t;
// Main Header
// ReefAngel.LCD.DrawText(DefaultFGColor, DefaultBGColor, 35, y,"Lee's Reef");
// Had no room for this anymore :(
// Date+Time
ReefAngel.LCD.DrawDate(x+1, y);
ReefAngel.LCD.Clear(COLOR_BLACK, 1, y+9, 128, y+9);
// Param Header
y+=12;
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,x+5,y,"Temp:");
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,x+80, y, "PH:");
// Temp and PH
y+=2;
ConvertNumToString(buf, ReefAngel.Params.Temp[T2_PROBE], 10);
ReefAngel.LCD.DrawText(T2TempColor, DefaultBGColor, x+45, y, buf);
y+=6;
ConvertNumToString(buf, ReefAngel.Params.Temp[T1_PROBE], 10);
ReefAngel.LCD.DrawLargeText(T1TempColor, DefaultBGColor, x+5, y, buf, Num8x16);
ConvertNumToString(buf, ReefAngel.Params.PH, 100);
ReefAngel.LCD.DrawLargeText(PHColor, DefaultBGColor, x+80, y, buf, Num8x16);
y+=5;
ConvertNumToString(buf, ReefAngel.Params.Temp[T3_PROBE], 10);
ReefAngel.LCD.DrawText(T3TempColor, DefaultBGColor, x+45, y, buf);
pingSerial();
/// Display Sunrise / Sunset (to be calculated later...)
y+=12; t=x;
sprintf(buf, "%02d:%02d", sl.GetRiseHour(), sl.GetRiseMinute());
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,t,y,"Rise:"); t+=31;
ReefAngel.LCD.DrawText(COLOR_RED,DefaultBGColor,t,y,buf);
sprintf(buf, "%02d:%02d", sl.GetSetHour(), sl.GetSetMinute()); t+=36;
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,t,y,"Set:"); t+=25;
ReefAngel.LCD.DrawText(COLOR_RED,DefaultBGColor,t,y,buf);
pingSerial();
// MoonPhase
y+=10;
ReefAngel.LCD.DrawText(0,255,x,y,"Moon:");
ReefAngel.LCD.Clear(DefaultBGColor,x+32,y,x+(128-x),y+8);
ReefAngel.LCD.DrawText(COLOR_MAGENTA,255,x+32,y,MoonPhaseLabel());
pingSerial();
// MoonLight %
y+=10;
t = intlength(ReefAngel.PWM.GetDaylightValue()) + 1; t *= 5;
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,x,y,"MoonLights:");
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.PWM.GetDaylightValue(), DPColor, x+68, y, 1);
ReefAngel.LCD.DrawText(DPColor, DefaultBGColor, x+68+t, y, "%");
pingSerial();
// Display Water level
y+=10; t=x;
ConvertNumToString(buf, ReefAngel.WaterLevel.GetLevel(), 1);
strcat(buf," ");
ReefAngel.LCD.DrawText(DefaultFGColor,DefaultBGColor,x,y,"AT0 Level:"); t+=60;
ReefAngel.LCD.DrawText(DefaultFGColor,DefaultBGColor,t,y,buf);
// Vortech Mode
y+=10; t=x;
ReefAngel.LCD.DrawText(0,255,x,y,"RF:"); t+=20;
ReefAngel.LCD.Clear(DefaultBGColor,t,y,x+(128-x),y+8);
if (vtMode == 0) ReefAngel.LCD.DrawLargeText(COLOR_GREEN,255,t,y,"Constant");
else if(vtMode == 1) ReefAngel.LCD.DrawLargeText(COLOR_GOLD,255,t,y,"Lagoon");
else if (vtMode == 2) ReefAngel.LCD.DrawLargeText(COLOR_GOLD,255,t,y,"Reef Crest");
else if (vtMode == 3) ReefAngel.LCD.DrawLargeText(COLOR_RED,255,t,y,"Short Pulse");
else if (vtMode == 4) ReefAngel.LCD.DrawLargeText(COLOR_RED,255,t,y,"Long Pulse");
else if (vtMode == 5) ReefAngel.LCD.DrawLargeText(COLOR_MAGENTA,255,t,y,"Smart NTM");
else if (vtMode == 6) ReefAngel.LCD.DrawLargeText(COLOR_MAGENTA,255,t,y,"Tidal Swell");
else if (vtMode == 9) ReefAngel.LCD.DrawLargeText(COLOR_WHITE,0,t,y,"Night");
y+=10; t=x;
ReefAngel.LCD.DrawText(0,255,x,y,"RF Speed:"); t+=60;
ReefAngel.LCD.Clear(DefaultBGColor,t,y,x+(128-x),y+8);
ReefAngel.LCD.DrawText(COLOR_BLUE, DefaultBGColor,t,y,InternalMemory.RFSpeed_read()); t+=15;
ReefAngel.LCD.DrawText(COLOR_BLUE, DefaultBGColor,t,y,"/"); t+=10;
ReefAngel.LCD.DrawText(COLOR_BLUE, DefaultBGColor,t,y,InternalMemory.RFDuration_read());
pingSerial();
// Display Water level
y+=10; t=x;
if (acclDay > 0) {
ConvertNumToString(buf, acclDay, 1);
strcat(buf," ");
ReefAngel.LCD.DrawText(DefaultFGColor,DefaultBGColor,x,y,"Acclimation Day:"); t+=100;
ReefAngel.LCD.DrawText(DefaultFGColor,DefaultBGColor,t,y,buf);
} else {
ReefAngel.LCD.Clear(DefaultBGColor,x,y,x+(128-x),y+8);
}
// Relays
y+=10; t=x+7;
byte TempRelay = ReefAngel.Relay.RelayData;
TempRelay &= ReefAngel.Relay.RelayMaskOff;
TempRelay |= ReefAngel.Relay.RelayMaskOn;
ReefAngel.LCD.DrawOutletBox(t, y, TempRelay);
pingSerial();
y+=12;
TempRelay = ReefAngel.Relay.RelayDataE[0];
TempRelay &= ReefAngel.Relay.RelayMaskOffE[0];
TempRelay |= ReefAngel.Relay.RelayMaskOnE[0];
ReefAngel.LCD.DrawOutletBox(t, y, TempRelay);
pingSerial();
}
void DrawCustomGraph() {
}