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>
#include <DCPump.h>
#include <WiFiAlert.h>
// Custom menus
#include <avr/pgmspace.h>
prog_char menu1_label[] PROGMEM = "Feeding Mode";
prog_char menu2_label[] PROGMEM = "Coral Feeding";
prog_char menu3_label[] PROGMEM = "Water Change";
prog_char menu4_label[] PROGMEM = "ATO Clear";
prog_char menu5_label[] PROGMEM = "Overheat Clear";
prog_char menu6_label[] PROGMEM = "PH Calibration";
prog_char menu7_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
};
// Define Custom Memory Locations
#define Mem_B_MaintGFO 145
#define Mem_B_MaintCal 146
#define Mem_B_MaintAlk 147
#define Mem_B_MaintWC 148
#define Mem_B_MaintATO 149
#define Mem_B_MaintFeeding 150
#define Mem_B_MaintSkimmer 151
#define Mem_B_PrintDebug 198
#define Mem_B_ResetMemory 199
void init_memory() {
InternalMemory.write(Mem_B_ResetMemory,false);
}
#define NUMBERS_8x16
////// Place global variable code below here
int ScreenID=1;
////// Place global variable code above here
// Setup on controller startup/reset
void setup()
{
// This must be the first line
ReefAngel.Init();
//Initialize controller
ReefAngel.InitMenu(pgm_read_word(&(menu_items[0])),SIZE(menu_items)); // Initialize Menu
// Ports toggled in Feeding Mode
ReefAngel.FeedingModePorts = Port3Bit | Port5Bit | Port7Bit | Port8Bit;
// Ports toggled in Water Change Mode
ReefAngel.WaterChangePorts = Port2Bit | Port3Bit | Port7Bit | Port8Bit;
// Ports toggled when Lights On / Off menu entry selected
ReefAngel.LightsOnPorts = 0;
// Ports turned off when Overheat temperature exceeded
ReefAngel.OverheatShutoffPorts = Port4Bit;
// Use T1 probe as temperature and overheat functions
ReefAngel.TempProbe = T1_PROBE;
ReefAngel.OverheatProbe = T1_PROBE;
ReefAngel.AddWifi();
// Set the Overheat temperature setting
InternalMemory.OverheatTemp_write( 830 );
// Feeeding and Water Change mode speed
ReefAngel.DCPump.FeedingSpeed=0;
ReefAngel.DCPump.WaterChangeSpeed=30;
// Ports that default on
ReefAngel.Relay.On( Port1 ); ////Jebao Wavemaker
ReefAngel.Relay.On( Port3 ); ////Reactor
ReefAngel.Relay.On( Port7 ); ////Filter
ReefAngel.Relay.On( Port8 ); ////Skimmer
// Ports that default off
ReefAngel.Relay.Off( Port5 );
////// Place additional initialization code below here
ReefAngel.RF.UseMemory=false;
randomSeed(now()/SECS_PER_DAY);
if (InternalMemory.read(Mem_B_ResetMemory))
init_memory();
////// Place additional initialization code above here
}
void powerHead() {ReefAngel.WavemakerRandom(Port5,2,5);} // Turn Port5 on/off random cycles that lasts from 5 to 10 secs
void loop()
{
////// Place your custom code below here
ReefAngel.StandardHeater( Port4,780,785 );
ReefAngel.StandardFan ( Port6,785,786 );
//ATO runs for up to 4 min every 2 hours
ReefAngel.SingleATO( true,Port2,240,2 );
ReefAngel.DCPump.DaylightChannel = Sync;
//Jebao Post Feeding, ReefCrest and Night Time modes
static unsigned long feeding;
if (ReefAngel.DisplayedMenu==FEEDING_MODE) feeding=now();
if (now()-feeding<3600) {
// Continue NTM for the 60 minutes
ReefAngel.PWM.SetDaylight( NutrientTransportMode(40,65,900,true) ); // Nutrient Transport on sync mode
powerHead();
}
//vacation mode
if ((hour()>9 && hour()<21))
{
ReefAngel.PWM.SetDaylight( ShortPulseMode(0,80,900,true));
powerHead();
}
else
{
ReefAngel.PWM.SetDaylight( LongPulseMode(0,50,2,true));
powerHead();
}
//ATO timeout alert
ReefAngel.CustomVar[0]=InternalMemory.read(ATO_Single_Exceed_Flag);
ReefAngel.CustomVar[7]=255;
////// Place your custom code above here
// This should always be the last line
ReefAngel.Portal("ReefingHavoc");
ReefAngel.ShowInterface();
}
// Menu Code
void MenuEntry1(){
ReefAngel.FeedingModeStart();
}
void MenuEntry2() //"Feed Coral"
{
// Turns off all pumps (only heater is on) for 15 minuts. Skimmer will turn on for 15 minutes
// followd by all pumps.
// clear the screen
ReefAngel.ClearScreen(DefaultBGColor);
ReefAngel.LCD.DrawText(COLOR_MIDNIGHTBLUE, DefaultBGColor, 5, 10, "Coral Feeding");
ReefAngel.Relay.Off(Port1);
ReefAngel.Relay.Off(Port3);
ReefAngel.Relay.Off(Port5);
ReefAngel.Relay.Off(Port7);
ReefAngel.Relay.Off(Port8);
ReefAngel.Relay.Write();
char msg[8];
bool done = false;
int t;
byte row;
for ( byte i = 0; i < 2; i++ )
{
sprintf(msg, "Phase %d", i+1);
// leave a blank row and start on the 3rd line
row = MENU_START_ROW*(i+3);
ReefAngel.LCD.DrawText(DefaultFGColor, DefaultBGColor, MENU_START_COL, row, msg);
if ( i == 1 )
{
// second time through, we enter phase 2, so shutoff the wavemaker now
ReefAngel.PWM.SetDaylight( ShortPulseMode(0,45,900,true) );
ReefAngel.Relay.On(Port1);
ReefAngel.Relay.On(Port8);
ReefAngel.Relay.Write();
}
// start the feeding timer
ReefAngel.Timer[FEEDING_TIMER].Start();
do
{
// just loop until the joystick button is pressed or the timer is triggered
// then break out of the loop and proceed
#if defined WDT || defined WDT_FORCE
wdt_reset();
#endif // defined WDT || defined WDT_FORCE
// update the timer on the screen
t = ReefAngel.Timer[FEEDING_TIMER].Trigger - now();
if ( (t >= 0) && ! ReefAngel.Timer[FEEDING_TIMER].IsTriggered() )
{
ReefAngel.LCD.Clear(DefaultBGColor,60+(intlength(t)*5),row,100,row+8);
ReefAngel.LCD.DrawText(DefaultFGColor,DefaultBGColor,60,row,t);
delay(200); // to keep from redraw flicker on timer
}
else
{
done = true;
}
if ( ReefAngel.Joystick.IsButtonPressed() )
{
// joystick button pressed, so we stop
done = true;
}
}
while ( ! done );
#if defined WDT || defined WDT_FORCE
wdt_reset();
#endif // defined WDT || defined WDT_FORCE
// reset the variable for the inner do while loop
done = false;
}
// Restore ports & return to the main screen
ReefAngel.Relay.On(Port3);
ReefAngel.Relay.On(Port5);
ReefAngel.Relay.On(Port7);
ReefAngel.Relay.Write();
ReefAngel.ExitMenu();
}
void MenuEntry3() {
ReefAngel.WaterChangeModeStart();
ReefAngel.Timer[FEEDING_TIMER].Start();
if(ReefAngel.Timer[FEEDING_TIMER].Trigger - now() >= 0)
{
ReefAngel.PWM.SetDaylight( NutrientTransportMode(30,60,900,true)); // Nutrient Transport on sync mode
}
else
ReefAngel.PWM.SetDaylight( LongPulseMode(0,45,2,true));
}
void MenuEntry4() {
ReefAngel.ATOClear();
ReefAngel.DisplayMenuEntry("Clear ATO Timeout");
}
void MenuEntry5() {
ReefAngel.OverheatClear();
ReefAngel.DisplayMenuEntry("Clear Overheat");
}
void MenuEntry6() {
ReefAngel.SetupCalibratePH();
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry7() {
ReefAngel.SetupDateTime();
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
// Custom Main Screen
void DrawCustomMain() {
const int NumScreens=3;
static boolean drawGraph=true;
// Main Header
ReefAngel.LCD.DrawText(COLOR_DARKSLATEBLUE, DefaultBGColor, 30, 2 , "SPENCER'S REEF");
ReefAngel.LCD.DrawDate(5,112);
ReefAngel.LCD.Clear(COLOR_BLACK, 1, 11, 128, 11);
// Param Header
DrawParams(5,14);
switch (ScreenID) {
case 0:
{
if (drawGraph) {
ReefAngel.LCD.DrawGraph(5,40);
drawGraph=false;
}
break;
}
case 1:
{
DrawStatus(5,40);
break;
}
}
// Date+Time
// ReefAngel.LCD.DrawDate(5,122);
if (ReefAngel.Joystick.IsLeft()) {
ReefAngel.ClearScreen(DefaultBGColor);
ScreenID--;
drawGraph=true;
}
if (ReefAngel.Joystick.IsRight()) {
ReefAngel.ClearScreen(DefaultBGColor);
ScreenID++;
drawGraph=true;
}
if (ScreenID<0) ScreenID=NumScreens-1;
if (ScreenID>=NumScreens) ScreenID=0;
}
void DrawCustomGraph() {
if (ScreenID==0)
ReefAngel.LCD.DrawGraph(5, 40);
}
void DrawParams(int x, int y) {
char buf[16];
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);
}
void DrawStatus(int x, int y) {
int t=x;
ReefAngel.LCD.DrawLargeText(COLOR_INDIGO,DefaultBGColor,15,y,"High",Font8x16);
ReefAngel.LCD.DrawLargeText(COLOR_INDIGO,DefaultBGColor,85,y,"Low",Font8x16);
if (ReefAngel.HighATO.IsActive()) {
ReefAngel.LCD.FillCircle(55,y+3,5,COLOR_GREEN);
}
else {
ReefAngel.LCD.FillCircle(55,y+3,5,COLOR_RED);
}
if (ReefAngel.LowATO.IsActive()) {
ReefAngel.LCD.FillCircle(70,y+3,5,COLOR_GREEN);
}
else {
ReefAngel.LCD.FillCircle(70,y+3,5,COLOR_RED);
}
y+=12;
}