Code: Select all
ReefAngel.WaterLevelATO( Port1, 20, 75, 80 );
Code: Select all
ReefAngel.WaterLevelATO( Port1, 20, 75, 80 );
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 <ReefAngel.h>
#include <PH.h>
#include <WaterLevel.h>
#include <RF.h>
#include <Math.h>
#include <SoftwareSerial.h>
////// Place global variable code below here
////// Place global variable code above here
// Port1: ATO
// Port2: Empty
// Port3: Refugium light
// Port4: Daylight
// Port5: Return pump
// Port6: Pellets pump
// Port7: Skimmer
// Port8: Heater
// Expansion 1
// Port1: Lunar
// Port2: Dimmer
// Port3: Empty
// Port4: Empty
// Port5: Mg
// Port6: Ca
// Port7: Fan
// Port8: ATO
void setup()
{
// This must be the first line
ReefAngel.Init(); //Initialize controller
ReefAngel.SetTemperatureUnit(Celsius); // set to Celsius Temperature
ReefAngel.AddRANet();
ReefAngel.Relay.RANetFallBackE[1] = Port3Bit;
// ReefAngel.DDNS("phrusher");
// ReefAngel.Network.WifiAuthentication("phrusher:xxxxxxxx");
ReefAngel.Use2014Screen();
ReefAngel.Display24h();
ReefAngel.UseFlexiblePhCalibration();
// Ports toggled in Feeding Mode
ReefAngel.FeedingModePorts = Port1Bit | Port5Bit | Port7Bit | Port8Bit; // Ports toggled in Feeding Mode
ReefAngel.FeedingModePortsE[0] = Port3Bit | Port5Bit | Port6Bit | Port8Bit; // Ports toggled in Feeding Mode
// Ports toggled in Water Change Mode
ReefAngel.WaterChangePorts = Port1Bit | Port5Bit | Port7Bit; // Ports toggled in Water Change Mode
ReefAngel.WaterChangePortsE[0] = Port3Bit | Port5Bit | Port6Bit | Port8Bit; // Ports toggled in Water Change Mode
// Ports toggled when Lights On / Off menu entry selected
ReefAngel.LightsOnPorts = Port4Bit;
// Ports turned off when Overheat temperature exceeded
ReefAngel.OverheatShutoffPorts = Port4Bit | Port8Bit;
// Use T2 probe as temperature and overheat functions
ReefAngel.TempProbe = T2_PROBE;
ReefAngel.OverheatProbe = T2_PROBE;
// Ports that are always on
ReefAngel.Relay.On( Port5 ); // Return
ReefAngel.Relay.On( Port8 ); // Heater
ReefAngel.Relay.On( Box1_Port1 );
ReefAngel.Relay.On( Box1_Port2 );
InternalMemory.OverheatTemp_write( 290 ); // Set the Overheat temperature setting
////// Place additional initialization code below here
////// Place additional initialization code above here
}
void loop()
{
int moonphase = MoonPhase();
// Lights
ReefAngel.StandardLights( Port3, 15, 0, 7, 0 ); // Refugium
ReefAngel.StandardLights( Port4, 6, 0, 22, 00 ); // Daylight
ReefAngel.PWM.SetChannel( 0, moonphase); // Moonlight: Unmodified
ReefAngel.PWM.SetChannel( 1, PWMParabola(6,0, 20,30, 2, 85, 2) ); // Daylight: Blue
ReefAngel.PWM.SetChannel( 2, PWMParabola(7,0, 19,30, 2, 65, 0) ); // Daylight: White
ReefAngel.PWM.SetChannel( 4, 30 ); // Refugium light
ReefAngel.PWM.SetChannel( 5, 100 - PWMParabola(21,0, 7,0, 94, 99, 94) ); // Moonlight
// Dosing
ReefAngel.DosingPump( Box1_Port5, 1, 7, 00, 4 ); // 0.75 ml/sec Mg
ReefAngel.DosingPump( Box1_Port5, 1, 22, 00, 4 ); // 0.75 ml/sec Mg
ReefAngel.DosingPump( Box1_Port6, 2, 7, 01, 5 ); // 0.75 ml/sec Ca
ReefAngel.DosingPump( Box1_Port6, 2, 22, 01, 5 ); // 0.75 ml/sec Ca
// ATO
ReefAngel.WaterLevelATO( Port1, 20, 75, 80 );
if(ReefAngel.Params.Temp[T2_PROBE] > 260){
ReefAngel.Relay.Off( Port8 ); // Heater
} else {
ReefAngel.Relay.On( Port8 ); // Heater
}
ReefAngel.Relay.DelayedOn (Port7, 2); // Delay skimmer 2 minutes after feeding
////// Place your custom code below here
if ((hour() == 8 || hour() == 18) && minute() == 55 && second() == 0)
{
ReefAngel.FeedingModeStart();
}
if (ReefAngel.DisplayedMenu == FEEDING_MODE)
{
ReefAngel.PWM.SetDaylight( LongPulseMode(35, 45, 30, true ));
ReefAngel.PWM.SetActinic( LongPulseMode(35, 45, 30, false));
}
else if(ReefAngel.DisplayedMenu == WATERCHANGE_MODE)
{
ReefAngel.PWM.SetActinic(0);
ReefAngel.PWM.SetDaylight(0);
}
else if ((hour() == 9 || hour() == 19) && minute() <= 20)
{
WaveMakerSyncMillis(383, 75, 0); // After Feeding
}
else if (hour() >= 21 || hour() <= 6)
{
// Night mode
ReefAngel.PWM.SetDaylight( LongPulseMode(38, 50, 30, true ));
ReefAngel.PWM.SetActinic( LongPulseMode(38, 50, 30, false));
}
else
{
if(hour() >= 8 && hour() <= 19) {
if (minute() % 10 == 0) {
ReefAngel.PWM.SetDaylight( LongPulseMode(40, 85, 30, true )); // LongPulseMode at 40%, 85% 30s on sync mode
ReefAngel.PWM.SetActinic( LongPulseMode(40, 85, 30, false)); // LongPulseMode at 40%, 85% 30s on anti-sync mode
} else if (hour() >= 10 && hour() <= 16) {
ReefAngel.PWM.SetDaylight( ElseMode(80, 20, true )); // ElseMode at 80% +/- 20% on sync mode
ReefAngel.PWM.SetActinic( ElseMode(80, 20, false)); // ElseMode at 80% +/- 20% on anti-sync mode
} else {
ReefAngel.PWM.SetDaylight( ReefCrestMode(70, 15, true )); // ReefCrest at 70% +/- 15% on sync mode
ReefAngel.PWM.SetActinic( ReefCrestMode(70, 15, false)); // ReefCrest at 70% +/- 15% on anti-sync mode
}
} else {
ReefAngel.PWM.SetDaylight( LongPulseMode(40, 70, 60, true )); // LongPulseMode at 40%, 70% 60s on sync mode
ReefAngel.PWM.SetActinic( LongPulseMode(40, 70, 60, false)); // LongPulseMode at 40%, 70% 60s on anti-sync mode
}
}
////// Place your custom code above here
ReefAngel.Portal( "phrusher" );
// This should always be the last line
ReefAngel.ShowInterface();
}
// Wavemaker
/** Calculates the tidal flow.
*
* Ex. hour => flow
* 0 => 0 6 => 6 12 => 0 18 => 6
* 1 => 1 7 => 5 13 => 1 19 => 5
* 2 => 2 8 => 4 14 => 2 20 => 4
* 3 => 3 9 => 3 15 => 3 21 => 3
* 4 => 4 10 => 2 16 => 4 22 => 2
* 5 => 5 11 => 1 17 => 5 23 => 1
*
* \param hour: Hour in 24h format to calculate flow from
* \returns flow value
*/
int flow(int hour)
{
return (((hour/6) % 2) == 0 ? hour % 6 : 6 - hour % 6);
}
int pulsePower(int pulse, int maxPower, int minPower)
{
return (millis()%(pulse*2))<pulse ? maxPower : minPower;
}
/** Basic tidal simulation by gradually changing the opposing flow four times during 24h.
*
* By setting duration of opposing pumps it creates a directional flow in the tank that changes during one day.
*
* Ex. hour => pump01 : pump02 (duration in seconds)
* 0 => 2 : 14 6 => 14 : 2 12 => 2 : 14 18 => 14 : 2
* 1 => 4 : 12 7 => 12 : 4 13 => 4 : 12 19 => 12 : 4
* 2 => 6 : 10 8 => 10 : 6 14 => 6 : 10 20 => 10 : 6
* 3 => 8 : 8 9 => 8 : 8 15 => 8 : 8 21 => 8 : 8
* 4 => 10 : 6 10 => 6 : 10 16 => 10 : 6 22 => 6 : 10
* 5 => 12 : 4 11 => 4 : 12 17 => 12 : 4 23 => 4 : 12
*
* \param maxPower: The maximum pump power
* \param minPower: The minimum pump power
* \param pause: Length of the pause between each interval. Negative pause becomes overlap.
*/
void WaveMakerTidal(int maxPower, int minPower, int pause)
{
static boolean state = true;
static unsigned long nexttoggle=now();
long cycle=nexttoggle-now();
int pulse = 373;
if (cycle<0)
{
int duration = flow( hour() ) << 1; // 0 - 12
//int duration = flow( hour()); // 0 - 6
nexttoggle = now() + (state ? duration : (12-duration)) + 2 + pause; // flow->counter flow => 2->14
state = !state;
}
if (pause > 0 && cycle < pause)
{
ReefAngel.PWM.SetActinic(0);
ReefAngel.PWM.SetDaylight(0);
}
else if (pause < 0 && cycle < pause)
{
ReefAngel.PWM.SetActinic(maxPower);
ReefAngel.PWM.SetDaylight(maxPower);
}
else
{
//int power = (millis()%(pulse*2))<pulse ? maxPower : minPower;
int power = pulsePower(pulse, maxPower, minPower);
if(state){
ReefAngel.PWM.SetActinic(power);
ReefAngel.PWM.SetDaylight(0);
}
else {
ReefAngel.PWM.SetActinic(0);
ReefAngel.PWM.SetDaylight(power);
}
}
}
/** Toggles opposing pumps with a pause between each interval.
*
* \param power: The pump power
* \param duration: Duration of each interval
* \param pause: Length of the pause between each interval. If pause is negative it will work as an overlap.
*/
void WaveMakerPause(int power, int duration, int pause)
{
static boolean state = true;
static unsigned long nexttoggle=now();
long cycle=nexttoggle-now();
if (cycle<0)
{
nexttoggle = now() + duration;
state = !state;
}
if (pause > 0 && cycle < pause)
{
ReefAngel.PWM.SetActinic(0);
ReefAngel.PWM.SetDaylight(0);
}
else if(pause < 0 && cycle < pause)
{
ReefAngel.PWM.SetActinic(power);
ReefAngel.PWM.SetDaylight(power);
}
else {
if(state){
ReefAngel.PWM.SetActinic(power);
ReefAngel.PWM.SetDaylight(0);
}
else {
ReefAngel.PWM.SetActinic(0);
ReefAngel.PWM.SetDaylight(power);
}
}
}
void WaveMakerSyncMillis(long duration, int maxPower, int minPower)
{
if ((millis()%(duration*2))<duration)
{
ReefAngel.PWM.SetActinic(minPower);
ReefAngel.PWM.SetDaylight(minPower);
}
else {
ReefAngel.PWM.SetActinic(maxPower);
ReefAngel.PWM.SetDaylight(maxPower);
}
}
Code: Select all
// Dosing
ReefAngel.DosingPump( Box1_Port5, 1, 7, 00, 4 ); // 0.75 ml/sec Mg
ReefAngel.DosingPump( Box1_Port5, 1, 22, 00, 4 ); // 0.75 ml/sec Mg
ReefAngel.DosingPump( Box1_Port6, 2, 7, 01, 5 ); // 0.75 ml/sec Ca
ReefAngel.DosingPump( Box1_Port6, 2, 22, 01, 5 ); // 0.75 ml/sec Ca
I could do like that but it wouldn't be much funlnevo wrote:You can try using an if statements to make sure and at least get your ATO working. It will be sans timeout...
if (ReefAngel.WaterLevel.GetLevel() < X) ReefAngel.Relay.On(ATO_Port);
if (Reefangel.WaterLevel.GetLevel() > Y) ReefAngel.Relay.Off(ATO_Port);
Change X and Y and the ATO Port.
Code: Select all
WL: 73 WLATO.Timer: 262144 millis(): 282117 diff: 19973 IsTopping: 1 msTimeout: 20000
WL: 73 WLATO.Timer: 262144 millis(): 282140 diff: 19996 IsTopping: 1 msTimeout: 20000
WL: 73 WLATO.Timer: 262144 millis(): 282147 diff: 20003 IsTopping: 1 msTimeout: 20000
(millis() - WLATO.Timer) > msTimeout && WLATO.IsTopping() <-- This indicates the timeout
Code: Select all
WL: 74 WLATO.Timer: 316609 millis(): 316609 diff: 0 IsTopping: 1 msTimeout: 20000
WL: 74 WLATO.Timer: 316609 millis(): 316632 diff: 23 IsTopping: 1 msTimeout: 20000
WL: 74 WLATO.Timer: 316609 millis(): 316639 diff: 30 IsTopping: 1 msTimeout: 20000
WL: 74 WLATO.Timer: 316609 millis(): 316653 diff: 44 IsTopping: 1 msTimeout: 20000
WL: 74 WLATO.Timer: 316609 millis(): 316667 diff: 58 IsTopping: 1 msTimeout: 20000
WL: 74 WLATO.Timer: 316609 millis(): 316682 diff: 73 IsTopping: 1 msTimeout: 20000
WL: 74 WLATO.Timer: 316609 millis(): 316696 diff: 87 IsTopping: 1 msTimeout: 20000
WL: 74 WLATO.Timer: 316609 millis(): 316710 diff: 101 IsTopping: 1 msTimeout: 20000
WL: 74 WLATO.Timer: 316609 millis(): 316733 diff: 124 IsTopping: 1 msTimeout: 20000
WL: 74 WLATO.Timer: 316609 millis(): 316740 diff: 131 IsTopping: 1 msTimeout: 20000
WL: 74 WLATO.Timer: 316609 millis(): 316754 diff: 145 IsTopping: 1 msTimeout: 20000
WL: 74 WLATO.Timer: 316609 millis(): 316769 diff: 160 IsTopping: 1 msTimeout: 20000
WL: 74 WLATO.Timer: 262144 millis(): 316883 diff: 54739 IsTopping: 1 msTimeout: 20000
(millis() - WLATO.Timer) > msTimeout && WLATO.IsTopping() <-- This indicates the timeout
Code: Select all
void ReefAngelClass::WaterLevelATO(byte Channel, byte ATORelay, int ATOTimeout, byte LowLevel, byte HighLevel)
{
// Input: Relay port and timeout value (max number of seconds that ATO pump is allowed to run)
// Input: Low and High Water Level to start and stop ATO pump
unsigned long msTimeout = ATOTimeout * 1000;
byte waterlevel = WaterLevel.GetLevel(Channel);
/*
Is the low level is reached (meaning we need to top off) and are we not currently topping off
Then we set the timer to be now and start the topping pump
*/
if (waterlevel < LowLevel && (!WLATO.IsTopping()))
{
Serial.println("waterlevel < LowLevel && (!WLATO.IsTopping())");
WLATO.Timer = millis();
WLATO.StartTopping();
Relay.On(ATORelay);
}
// If the high level is reached, this is a safeguard to prevent over running of the top off pump
if (waterlevel >= HighLevel)
{
WLATO.StopTopping(); // stop the low ato timer
Relay.Off(ATORelay);
}
unsigned long milli = millis();
Serial.print("WL: ");
Serial.print(waterlevel);
Serial.print(" WLATO.Timer: ");
Serial.print(WLATO.Timer);
Serial.print(" millis(): ");
Serial.print(milli);
Serial.print(" diff: ");
Serial.print(milli - WLATO.Timer);
Serial.print(" IsTopping: ");
Serial.print(WLATO.IsTopping());
Serial.print(" msTimeout: ");
Serial.print(msTimeout);
Serial.println();
/*
If the current time minus the start time of the ATO pump is greater than the specified timeout value
AND the ATO pump is currently running:
We turn on the status LED and shut off the ATO pump
This prevents the ATO pump from continuously running.
*/
if ((millis() - WLATO.Timer) > msTimeout && WLATO.IsTopping())
{
Serial.println("(millis() - WLATO.Timer) > msTimeout && WLATO.IsTopping()");
Relay.Off(ATORelay);
LED.On();
bitSet(AlertFlags, ATOTimeOutFlag);
#ifdef ENABLE_EXCEED_FLAGS
if (InternalMemory.read(ATO_Exceed_Flag)==0)
InternalMemory.write(ATO_Exceed_Flag, 1);
#endif // ENABLE_EXCEED_FLAGS
#ifdef ENABLE_ATO_LOGGING
// bump the counter if a timeout occurs
AtoEventCount++;
if ( AtoEventCount >= MAX_ATO_LOG_EVENTS ) { AtoEventCount = 0; }
#endif // ENABLE_ATO_LOGGING
}
}