Page 1 of 1

Kirkwood's Code - Dosing/ATO Pump Timers, Icecap Backup Batt

Posted: Sun Mar 19, 2017 5:30 pm
by kirkwood
Wanted to share my code with the community. The highlights are the dosing and ATO pump timers. I use the dosing pump timers to ensure the pumps always run correctly. The ATO timer is especially helpful. I know when the pump has run over 100 minutes that it is time to change the 5 gallon top-off reservoir. When I'm out of town for a couple weeks I use this timer to notify the neighbor to swap reservoir jugs.

I recently installed the Icecap backup battery for the Jebao PH and added code to put the PH to 0 speed instead of turning off during feeding mode and water change mode.

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 <DCPump.h>
#include <ReefAngel.h>

////// Place global variable code below here


////// Place global variable code above here


void setup()
{
    // This must be the first line
    ReefAngel.Init();  //Initialize controller
    // Ports toggled in Feeding Mode
    ReefAngel.FeedingModePorts =  Port8Bit;
    // Ports toggled in Water Change Mode
    ReefAngel.WaterChangePorts = Port3Bit | Port4Bit | Port6Bit | Port7Bit | Port8Bit;
    // Ports toggled when Lights On / Off menu entry selected
    ReefAngel.LightsOnPorts = Port1Bit | Port2Bit;
    // Ports turned off when Overheat temperature exceeded
    ReefAngel.OverheatShutoffPorts = Port1Bit | Port2Bit | 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( 825 );



    // Ports that are always on
    ReefAngel.Relay.On( Port1 );
    ReefAngel.Relay.On( Port2 );
    ReefAngel.Relay.On( Port5 );
    ReefAngel.Relay.On( Port8 );

    ////// Place additional initialization code below here
    

    ////// Place additional initialization code above here
}

void loop()
{    
    ReefAngel.DosingPumpRepeat( Port3,0,120,224 );  // dose ALK 224 seconds 12x/day
    ReefAngel.DosingPumpRepeat( Port4,60,120,300 );  // dose CAL 300 seconds 12x/day
    ReefAngel.StandardHeater( Port6,770,773 );
    ReefAngel.StandardATO( Port7,900 );
    ////// Place your custom code below here

//Start Feeding Mode at 20:30 - NONE
if ( (now()%86400==73800) ) {
  ReefAngel.FeedingModeStart();
}

//Track ALK, CAL, and ATO dosing pumps
const byte numPumps=3;
byte pump[numPumps] = { Port3, Port4, Port7 };
byte portalMinutes[numPumps] = { 0, 2, 4 };
byte portalSeconds[numPumps] = { 1, 3, 5 };

static time_t pumpTimer[numPumps];
static boolean pumpStatus[numPumps];
static boolean atoDisabled;
  
for (int i=0;i< numPumps;i++) {
  if (ReefAngel.Relay.Status(pump[i])) {
    if (!pumpStatus[i]) {
      pumpTimer[i]=now()-pumpTimer[i]; // Pump was off, timer is now a time
      pumpStatus[i]=true;
    }
  } else {
    if (pumpStatus[i]) {
      pumpTimer[i]=now()-pumpTimer[i]; // Pump was on, timer is now a timer
      pumpStatus[i]=false;

      // Normalize and assign to CustomVar for reporting on the portal
      ReefAngel.CustomVar[portalMinutes[i]]=pumpTimer[i]/60; // Number of Minutes
//      ReefAngel.CustomVar[portalSeconds[i]]=pumpTimer[i]%60; // Number of Seconds
    }
  }
}

static boolean clearTimer;
if (now()%SECS_PER_DAY!=SECS_PER_DAY-1) clearTimer=true;
if ( (now()%SECS_PER_DAY==SECS_PER_DAY-1) && clearTimer==true) {
// Backup timers to portal variable
ReefAngel.CustomVar[portalSeconds[0]] = pumpTimer[0]/60;
ReefAngel.CustomVar[portalSeconds[1]] = pumpTimer[1]/60;
ReefAngel.CustomVar[portalSeconds[2]] = pumpTimer[2]/60;
pumpTimer[0]=0; // Clear timer for Port3
pumpTimer[1]=0; // Clear timer for Port4
clearTimer=false;
}
if (bitRead(ReefAngel.Relay.RelayMaskOn, 6)==1) { // ATO relay was forced on
atoDisabled=true; // don't want to change the variable names yet.. but you may want to to make it clearer..
} 
if (atoDisabled && (bitRead(ReefAngel.Relay.RelayMaskOn, 6)==0)) { // ATO override has been cleared
pumpTimer[2]=0; // Clear timer for ATOPort
atoDisabled=false;
}
ReefAngel.Relay.Set(Port5,now()%19800!=0);

//Jebao speed 0 on feeding/water change modes to prevent Icecap battery from turning on  
if (ReefAngel.DisplayedMenu==FEEDING_MODE || ReefAngel.DisplayedMenu==WATERCHANGE_MODE)
{
  ReefAngel.PWM.SetDaylight( 0 );
  ReefAngel.PWM.SetActinic( 0);
}
else if (hour()>=7 && hour()<8)
{
  ReefAngel.PWM.SetDaylight( LongPulseMode(40,55,10,true) ); // Long pulse hi/low 60%40% 10s pulse on sync mode
  ReefAngel.PWM.SetActinic( LongPulseMode(40,55,10,false) ); // Long pulse hi/low 60%40% 10s pulse on anti-sync mode
}
else if (hour()>=8 && hour()<11)
{
  ReefAngel.PWM.SetDaylight( SineMode(30,70,300,true) ); // Sine mode low/hi 40%95% on 5 minute cycle on sync mode
  ReefAngel.PWM.SetActinic( SineMode(30,70,300,false) ); // Sine mode low/hi 40%95% on 5 minute cycle on anti-sync mode
}
else if (hour()>=11 && hour()<14)
{
  ReefAngel.PWM.SetDaylight( ShortPulseMode(0,80,500,true) ); // Short pulse at 60% with 200ms pulse on sync mode
  ReefAngel.PWM.SetActinic( ShortPulseMode(0,80,500,false) ); // Short pulse at 60% with 200ms pulse on anti-sync mode
}
else if (hour()>=14 && hour()<16)
{ 
  ReefAngel.PWM.SetDaylight( ReefCrestMode(60,25,true) ); // ReefCrest on 50% with +/-10% on sync mode
  ReefAngel.PWM.SetActinic( ReefCrestMode(60,25,false) ); // ReefCrest on 50% with +/-10% on sync mode
}
else if (hour()>=16 && hour()<18)
{
  ReefAngel.PWM.SetDaylight( SineMode(30,70,300,true) ); // Sine mode low/hi 40%95% on 5 minute cycle on sync mode
  ReefAngel.PWM.SetActinic( SineMode(30,70,300,false) ); // Sine mode low/hi 40%95% on 5 minute cycle on anti-sync mode
}
else if (hour()>=18 && hour()<20)
{
  ReefAngel.PWM.SetDaylight( TidalSwellMode(70,true) ); // TidalSwell at 70% on sync mode
  ReefAngel.PWM.SetActinic( TidalSwellMode(70,false) ); // TidalSwell at 70% on anti-sync mode
}  
else if (hour()>=20 && hour()<21)
{
  ReefAngel.PWM.SetDaylight( ShortPulseMode(0,80,500,true) ); // TidalSwell at 70% on sync mode
  ReefAngel.PWM.SetActinic( ShortPulseMode(0,80,500,false) ); // TidalSwell at 70% on anti-sync mode
}  
else if (hour()>=21 && hour()<23)
{ 
  ReefAngel.PWM.SetDaylight( ReefCrestMode(60,25,true) ); // ReefCrest on 50% with +/-10% on sync mode
  ReefAngel.PWM.SetActinic( ReefCrestMode(60,25,false) ); // ReefCrest on 50% with +/-10% on sync mode
}
else
{
  ReefAngel.PWM.SetDaylight( ShortPulseMode(0,50,300,true) ); // Short pulse at 60% with 200ms pulse on sync mode
  ReefAngel.PWM.SetActinic( ShortPulseMode(0,50,300,false) ); // Short pulse at 60% with 200ms pulse on anti-sync mode
}

    ////// Place your custom code above here

    // This should always be the last line
    ReefAngel.Portal( "kirkwood" );
    ReefAngel.ShowInterface();
}