Code: Select all
#include <ReefAngel_Features.h>
#include <Globals.h>
#include <RA_Wifi.h>
#include <Wire.h>
#include <OneWire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <InternalEEPROM.h>
#include <RA_NokiaLCD.h>
#include <RA_ATO.h>
#include <RA_Joystick.h>
#include <LED.h>
#include <RA_TempSensor.h>
#include <Relay.h>
#include <RA_PWM.h>
#include <Timer.h>
#include <Memory.h>
#include <InternalEEPROM.h>
#include <RA_Colors.h>
#include <RA_CustomColors.h>
#include <Salinity.h>
#include <RF.h>
#include <IO.h>
#include <ORP.h>
#include <AI.h>
#include <PH.h>
#include <WaterLevel.h>
#include <Humidity.h>
#include <DCPump.h>
#include <ReefAngel.h>
////// Notes
/// PWM Random Wave Mode
/// Parabola
/// NTM
/// CarbPhos
/// Coral Acclimation Code
/// WP40 Delay when return pump turns on
////// Place global variable code below here
////// Memory Locations used by all formulas
#define Mem_B_AcclDay 100 // Acclimation Day
#define Mem_B_AcclDuration 101 // Days in Accl Cycle
#define Mem_B_SlopeStart 102 // Slopestart for White and Blue channels
/////// Memory Locations used by Blue Formula
#define Mem_B_AcclStartEndBlue 105 // Acclimation starting Slope end%
#define Mem_B_SlopeEndBlue 106 // slope End%
////// Memory Locations used by White Formula
#define Mem_B_AcclStartEndWhite 110 // Acclimation starting Slope end%
#define Mem_B_SlopeEndWhite 111 // Slope End%
////// Place global variable code above here
void setup()
{
// This must be the first line
ReefAngel.Init(); //Initialize controller
ReefAngel.AddStandardMenu(); // Add Standard Menu
ReefAngel.Use2014Screen(); // Let's use 2014 Screen
///// ReefAngel.AddPHExpansion(); // pH Expansion Module
// Ports toggled in Feeding Mode
ReefAngel.FeedingModePorts = Port3Bit;
// Ports toggled in Water Change Mode
ReefAngel.WaterChangePorts = Port2Bit | Port3Bit | Port4Bit | Port5Bit | Port8Bit;
// Ports toggled when Lights On / Off menu entry selected
ReefAngel.LightsOnPorts = Port2Bit | Port4Bit | Port8Bit;
// Ports turned off when Overheat temperature exceeded
ReefAngel.OverheatShutoffPorts = Port1Bit;
// 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( Port3 );
ReefAngel.Relay.On( Port7 );
////// Place additional initialization code below here
//Custom Port Labels
ReefAngel.CustomLabels[0]="Heater";
ReefAngel.CustomLabels[1]="BlueLED";
ReefAngel.CustomLabels[2]="ReturnPump";
ReefAngel.CustomLabels[3]="WhiteLED";
ReefAngel.CustomLabels[4]="KalkATO";
ReefAngel.CustomLabels[5]="CarbPhos";
ReefAngel.CustomLabels[6]="WP40";
ReefAngel.CustomLabels[7]="Refugium";
////// Place additional initialization code above here
}
void loop()
{
ReefAngel.StandardHeater( Port1 );
ReefAngel.StandardLights( Port2,9,1,22,29 );
ReefAngel.StandardLights( Port4,10,1,21,29 );
ReefAngel.SingleATO( true,Port5,1800,1 );
ReefAngel.StandardLights( Port8,20,30,11,0 );
ReefAngel.Relay.DelayedOn( Port7,3 );
////// Place your custom code below here
JebaoRandomMode();
MediaFilter();
LEDschedule();
WP40Delay();
////// Place your custom code above here
// This should always be the last line
ReefAngel.Portal("ReEfnWrX","*******");
ReefAngel.ShowInterface();
}
void JebaoRandomMode() {
static unsigned long feeding;
// Set timer when in feeding mode
if (now()%SECS_PER_DAY<28800 || now()%SECS_PER_DAY>=81000) { // 10pm -> 10am
ReefAngel.PWM.SetDaylight( ElseMode(35,0,true) ); // Night mode (go to 30%)
ReefAngel.PWM.SetActinic( ElseMode(35,0,false) );
}
else if (now()%SECS_PER_DAY>=28800 && now()%SECS_PER_DAY<=81000) { // 10:30am - 10:30 pm
static byte randMode=10;
if (now()%SECS_PER_DAY==28800 || now()%SECS_PER_DAY==46800 || now()%SECS_PER_DAY==55800 || now()%SECS_PER_DAY==64800 || now()%SECS_PER_DAY==73800) randMode=random(1,11);
if (randMode==1) {
ReefAngel.PWM.SetDaylight( SineMode(35,60,85,true) );
ReefAngel.PWM.SetActinic( SineMode(35,60,85,false) ); // Sine 40-75
} if (randMode==2) {
ReefAngel.PWM.SetDaylight( ElseMode(50,15,true) ); // Else 40-80
ReefAngel.PWM.SetActinic( ElseMode(50,15,false) );
} if (randMode==3) {
ReefAngel.PWM.SetDaylight( TidalSwellMode(60,true) ); // Tidal 80
ReefAngel.PWM.SetActinic( TidalSwellMode(60,false) );
} if (randMode==4) {
ReefAngel.PWM.SetDaylight( LongPulseMode(35,55,60,true) ); // Long 25-65
ReefAngel.PWM.SetActinic( LongPulseMode(35,55,60,false) );
} if (randMode==5) {
ReefAngel.PWM.SetDaylight( ReefCrestMode(50,20,true) ); // Reef 45-65
ReefAngel.PWM.SetActinic( ReefCrestMode(50,20,false) );
} if (randMode==6) {
ReefAngel.PWM.SetDaylight( SineMode(32,55,180,true) ); // Sine 30-70
ReefAngel.PWM.SetActinic( SineMode(32,55,180,false) );
} if (randMode==7) {
ReefAngel.PWM.SetDaylight( ElseMode(60,10,true) ); // Else 35-65
ReefAngel.PWM.SetActinic( ElseMode(60,10,false) );
} if (randMode==8) {
ReefAngel.PWM.SetDaylight( TidalSwellMode(65,true) ); // Tidal 80
ReefAngel.PWM.SetActinic( TidalSwellMode(65,false) );
} if (randMode==9) {
ReefAngel.PWM.SetDaylight( LongPulseMode(35,60,900,true) ); // Long 40-50
ReefAngel.PWM.SetActinic( LongPulseMode(35,60,900,false) );
} if (randMode==10) {
ReefAngel.PWM.SetDaylight( ReefCrestMode(40,10,true) ); // Reef 35-55
ReefAngel.PWM.SetActinic( ReefCrestMode(40,10,false) );
}
}
if (ReefAngel.DisplayedMenu==FEEDING_MODE) {
feeding=now();
ReefAngel.PWM.SetDaylight( LongPulseMode(0,40,10,false) );
ReefAngel.PWM.SetActinic( LongPulseMode(0,65,10,false) );
}
if (now()%SECS_PER_DAY>=34200 && now()%SECS_PER_DAY<43200) {
ReefAngel.PWM.SetDaylight( NutrientTransportMode(0,70,400,false) );
ReefAngel.PWM.SetActinic( NutrientTransportMode(0,80,400,false) );
}
}
void MediaFilter() {
// if ((now()%SECS_PER_DAY>=34200 && now()%SECS_PER_DAY<=46800) || (now()%SECS_PER_DAY>=79200 && now()%SECS_PER_DAY<=86399)) {
if (now()%SECS_PER_DAY>=36000 && now()%SECS_PER_DAY<=48600) {
ReefAngel.Relay.On( Port6 );
}
else ReefAngel.Relay.Off( Port6 );
}
void LEDschedule() {
////////// LED Dimming Acclimation Cycle and your standard LED schedule
////////// Variables used for all channels
byte acclDay = InternalMemory.read(Mem_B_AcclDay); // What day in the acclimation cycle it is
byte acclDuration = InternalMemory.read(Mem_B_AcclDuration); // Acclimation Duration in days
byte startPercent = InternalMemory.read(Mem_B_SlopeStart); // Normal start% being used by all 3 channels
////////// Blue Channel Variables
byte acclStartEndBlue = InternalMemory.read(Mem_B_AcclStartEndBlue); // Starting End% for Acclimation cycle
float acclendPercentBlue = InternalMemory.read(Mem_B_SlopeEndBlue); // Your target Blue end% once acclimation is complete
////////// Blue Channel Formula
float acclPercentPerDayBlue = (acclendPercentBlue - acclStartEndBlue) / acclDuration; // How much your Blue end% rises per acclimation day
float acclFactorBlue = acclDay * acclPercentPerDayBlue; // endPercentBlue will be offset by this much. If acclDay = 0 then this value will be 0
byte endPercentBlue = acclendPercentBlue - acclFactorBlue; // Your final Blue end% for the day
////////// White Channel Variables
byte acclStartEndWhite = InternalMemory.read(Mem_B_AcclStartEndWhite); // Starting End% for Acclimation cycle
float acclEndPercentWhite = InternalMemory.read(Mem_B_SlopeEndWhite); // Your target White end% once acclimation is complete
////////// White Channel Formula
float acclPercentPerDayWhite= (acclEndPercentWhite - acclStartEndWhite) / acclDuration; // How much your White end% rises per acclimation day
float acclFactorWhite = acclDay * acclPercentPerDayWhite; // endPercentWhite will be offset by this much. If acclDay = 0 then this value will be 0
byte endPercentWhite = acclEndPercentWhite - acclFactorWhite;
////////// Your standard PWM Dimming code using the variables above to determine start% and end%
ReefAngel.PWM.SetChannel( 2, PWMParabola(9,0,22,0,startPercent,endPercentBlue,0) ); // BLUE Right
ReefAngel.PWM.SetChannel( 3, PWMParabola(9,30,22,30,startPercent,endPercentBlue,0) ); // BLUE Left
ReefAngel.PWM.SetChannel( 1, PWMParabola(10,0,21,0,startPercent,endPercentWhite,0) ); // White Right
ReefAngel.PWM.SetChannel( 0, PWMParabola(10,30,21,30,startPercent,endPercentWhite,0) ); // White Left
////////// At the end of the day, we need to decrement the acclimation counter.
static boolean acclCounterReady=false; // We need a boolean so we only do this once per day
if (now()%SECS_PER_DAY!=0) acclCounterReady=true; // If it's not midnight we'll get the boolean ready
if (now()%SECS_PER_DAY==0 && acclCounterReady && acclDay>0) { // It's midnight, our bool is true and acclDay is more than 0
acclDay--; // Reduce the counter
acclCounterReady=false; // Reset the boolean flag
InternalMemory.write(Mem_B_AcclDay,acclDay); // Update memory
}
}
void WP40Delay() {
static unsigned long lastPortOff=now()-180;
static boolean lastPortStatus=true;
if (!lastPortStatus && ReefAngel.Relay.Status(Port3))
{
lastPortOff=now();
}
lastPortStatus=ReefAngel.Relay.Status(Port3);
ReefAngel.Relay.Set(Port7,now()-lastPortOff>180);
}
byte ElseMode( byte MidPoint, byte Offset, boolean WaveSync )
{
////////// Static's only initialize the first time they are called
static unsigned long LastChange=millis(); // Set the inital time that the last change occurred
static int Delay = random(2000,3000); // Set the initial delay - default 500, 3000
static int NewSpeed = MidPoint; // Set the initial speed
static int AntiSpeed = MidPoint; // Set the initial anti sync speed
if ((millis()-LastChange) > Delay) // Check if the delay has elapsed
{
Delay=random(2000,10000); // If so, come up with a new delay - default - 500, 5000
int ChangeUp = random(Offset); // Amount to go up or down
if (random(100)<50) // 50/50 chance of speed going up or going down
{
NewSpeed = MidPoint - ChangeUp;
AntiSpeed = MidPoint + ChangeUp;
}
else
{
NewSpeed = MidPoint + ChangeUp;
AntiSpeed = MidPoint - ChangeUp;
}
LastChange=millis(); // Reset the time of the last change
}
if (WaveSync)
{
return NewSpeed;
}
else
{
return AntiSpeed;
}
}