ATO code is not working properly.

Do you have a question on how to do something.
Ask in here.
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

ATO code is not working properly.

Post by Sacohen »

I have been trying to finesse my ATO settings.

A while back lnevo gave me some code to keep the ATO from kicking in for 10 min after a water change.
It never worked the way it should but it didn't cause any problems either.

Last week I switched my ATO Pump from the Relay to the power expansion unit and since then it seems that it is randomly turning on for a period of 30 sec or so.

This has been messing with my salinity. Bringing it down to about 29ppt from 35ppt. Not good.

To keep the ATO from turning on I had unplugged the ATO for a day or so and them I added this line that Roberto gave me a while back, but never used.

Code: Select all

if (ReefAngel.Params.Salinity<335) ReefAngel.Relay.Off(ATO_Pump );
It worked great.

I just did a water change and again the ATO turned on 2 time for about 30 seconds each when everything was in the correct parameters. Water level was 32 or above and salinity was 34.8.

Right now I have the ATO Pump unplugged, but as far as I can see it seems to be turning on after the pumps come back on or after a reboot of a code update.

My full code is below.
Thanks so much, in advance, for your help.

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>

// Define Relay Ports by Name
#define Actinic_Lights     1
#define Day_Lights         2
#define Unused             3
#define Pumps              4
#define Sump_Fan           5
#define DeNit_Pump         6
#define DeNit_Doser        7
#define Unused             8

#define ATO_Pump           Box1_Port1
#define Moon_Lights        Box1_Port2
#define Unused             Box1_Port3
#define Unused             Box1_Port4
#define Unused             Box1_Port5
#define Unused             Box1_Port6
#define Unused             Box1_Port7
#define Unused             Box1_Port8


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

unsigned long ATOUpdate=0;
////// 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 = 0;
// Ports toggled in Water Change Mode
ReefAngel.WaterChangePorts = Port4Bit;
ReefAngel.WaterChangePortsE[0] = Port1Bit;
// Ports toggled when Lights On / Off menu entry selected
ReefAngel.LightsOnPorts = Port1Bit | Port2Bit;
// Ports turned off when Overheat temperature exceeded
ReefAngel.OverheatShutoffPorts = Port1Bit | Port2Bit;
// Use T2 probe as temperature and overheat functions
ReefAngel.TempProbe = T1_PROBE;
ReefAngel.OverheatProbe = T1_PROBE;
// Set the Overheat temperature setting
InternalMemory.OverheatTemp_write( 825 );
//Set Standard Menu
ReefAngel.AddStandardMenu();

// Feeeding and Water Change mode speed
ReefAngel.DCPump.FeedingSpeed=20;
ReefAngel.DCPump.WaterChangeSpeed=0;

// Ports that are always on
ReefAngel.Relay.On( Port4 );

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


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

void loop()
{
ReefAngel.StandardLights( Actinic_Lights,12,0,22,0 );
ReefAngel.StandardLights( Day_Lights,13,0,21,0 );
ReefAngel.Relay.Set( Moon_Lights, !ReefAngel.Relay.Status( Actinic_Lights ) );
ReefAngel.StandardLights( Sump_Fan,13,0,21,0 );
ReefAngel.Relay.Set(DeNit_Doser,(now()-3600)%21600<1200); // Runs for 1200s every 21600 seconds
ReefAngel.Relay.Set(DeNit_Pump,((now()-3600)-1200)%21600<1200); // Runs for 1200s every 21600 seconds with 1200s offset
// ReefAngel.Relay.DelayedOn( ATO_Pump,10 );
// ReefAngel.WaterLevelATO(ATO_Pump,720,32,32); // Enable ATO the ATO

//Disable ATO if Salinity is below 33.5
if (ReefAngel.Params.Salinity<335) ReefAngel.Relay.Off(ATO_Pump);

// Delay WL ATO after water change.
static time_t wcTimer;
if (ReefAngel.DisplayedMenu == WATERCHANGE_MODE) wcTimer=now();
if (now()-wcTimer > 0 && now()-wcTimer < 600) {
ReefAngel.WaterLevelATO(ATO_Pump,720,0,1);
} else {
ReefAngel.WaterLevelATO(ATO_Pump,720,32,32);
}

if (ReefAngel.Relay.Status(DeNit_Doser)) // Check to see if  is on and update time is empty
{ 
ATOUpdate = now(); // If so, set the update time to now
} 

if (now() - ATOUpdate < 120) // If it hasnt been 120 seconds turn off the port
{ 
ReefAngel.WaterLevelATO(ATO_Pump,720,0,1);
}
  if (ReefAngel.DCPump.Mode==Custom)
  {
  ReefAngel.PWM.SetActinic( ElseMode(40,20,true ));                     // ElseMode on sync mode, 40 +/- 20%
  }
if( ReefAngel.DisplayedMenu==FEEDING_MODE ) ReefAngel.PWM.SetActinic(20);
if( ReefAngel.DisplayedMenu==WATERCHANGE_MODE ) ReefAngel.PWM.SetActinic(0);
if (hour()<12 || hour()>=22) ReefAngel.PWM.SetActinic(30);
////// Place your custom code below here


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

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

void DrawCustomMain()
{
int x,y;
char text[10];
// Parameters
#if defined DisplayLEDPWM && ! defined RemoveAllLights
ReefAngel.LCD.DrawMonitor( 15, 20, ReefAngel.Params,
ReefAngel.PWM.GetDaylightValue(), ReefAngel.PWM.GetActinicValue() );
#else // defined DisplayLEDPWM && ! defined RemoveAllLights
ReefAngel.LCD.DrawMonitor( 15, 20, ReefAngel.Params );
#endif // defined DisplayLEDPWM && ! defined RemoveAllLights
pingSerial();

// Water Level
ReefAngel.LCD.DrawText( COLOR_DARKGOLDENROD,DefaultBGColor,75,66, "WL:" );
ReefAngel.LCD.DrawText( COLOR_DARKGOLDENROD,DefaultBGColor,99,66, ReefAngel.WaterLevel.GetLevel() );
  ConvertNumToString(text, ReefAngel.Params.Salinity, 10);
  strcat(text,"  ");
  ReefAngel.LCD.DrawText(DefaultFGColor,DefaultBGColor,39,75,"Salinity:");
  ReefAngel.LCD.DrawText(DefaultFGColor,DefaultBGColor,99,75,text);
pingSerial();

// Main Relay Box
byte TempRelay = ReefAngel.Relay.RelayData;
TempRelay &= ReefAngel.Relay.RelayMaskOff;
TempRelay |= ReefAngel.Relay.RelayMaskOn;
ReefAngel.LCD.DrawOutletBox( 12, 92, TempRelay );
pingSerial();
TempRelay = ReefAngel.Relay.RelayDataE[0];
TempRelay &= ReefAngel.Relay.RelayMaskOffE[0];
TempRelay |= ReefAngel.Relay.RelayMaskOnE[0];
ReefAngel.LCD.DrawOutletBox(12, 104, TempRelay);

// Date and Time
ReefAngel.LCD.DrawDate( 6, 122 );
pingSerial();
}

void DrawCustomGraph()
{
}
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( 500, 3000);           // Set the initial delay
  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(500,5000);                        // If so, come up with a new delay
    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;
  }
}
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: ATO code is not working properly.

Post by Sacohen »

Really no input on this problem?
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: ATO code is not working properly.

Post by lnevo »

Your code is complicated and scarey to look at... things that should have worked were not... that's why you have the strange WaterLevelATO line

ReefAngel.WaterLevelATO(ATO_Pump,720,0,1);

I don't even know where to start troubleshooting this one..
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: ATO code is not working properly.

Post by Sacohen »

I know and I'm open to redoing it, but I don't know where to begin.

That ReefAngel.WaterLevelATO(ATO_Pump,720,0,1); line was a compilation of your and cosmith71 work (that was actually cosmith71 line)

It was all working properly when I had my Tom's Aqualifter running on the Relay box, when I switched over to the ATO pump I got from Roberto (running on the same port on the relay box) it seemed a bit strange.

When I moved the ATO Pump off of the Relay box and on to the Power Expansion Unit that's when it really started going crazy.

My Salinity dropped from about 34 ppt to 28 ppt over a 2 day period and my water level was up in the 405 range when it is normally at 32.

I just don't understand why switching from the Tom's Aqualifter to the ATO Pump would have changed things.

The coding did not change that much. I just changed the hard coded port #'s (Port8) in the code to be Labeled ports like you have in your code.
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: ATO code is not working properly.

Post by lnevo »

I'm open to helping you redoing it....

Let's do this.. post your full code.

Summarize in english with pseudo logic the steps we need to recreate...
i.e.

11:05 de-nitrator turns on (ato disabled)
11:25 de-nitrator turns off
11:30 ato re-enabled if salinity less than X

I'll try and see if we can start over with something cleaner and more direct.

Thanks
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: ATO code is not working properly.

Post by Sacohen »

Great. Thanks a lot. I'll try to get it together in the next couple of days.
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: ATO code is not working properly.

Post by Sacohen »

Lee;

Here is my current code...

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>

// Define Relay Ports by Name
#define Actinic_Lights     1
#define Day_Lights         2
#define Unused             3
#define Pumps              4
#define Sump_Fan           5
#define DeNit_Pump         6
#define DeNit_Doser        7
#define Unused             8

#define ATO_Pump           Box1_Port1
#define Moon_Lights        Box1_Port2
#define Unused             Box1_Port3
#define Unused             Box1_Port4
#define Unused             Box1_Port5
#define Unused             Box1_Port6
#define Unused             Box1_Port7
#define Unused             Box1_Port8


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

unsigned long ATOUpdate=0;
////// 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 = 0;
// Ports toggled in Water Change Mode
ReefAngel.WaterChangePorts = Port4Bit;
ReefAngel.WaterChangePortsE[0] = Port1Bit;
// Ports toggled when Lights On / Off menu entry selected
ReefAngel.LightsOnPorts = Port1Bit | Port2Bit;
// Ports turned off when Overheat temperature exceeded
ReefAngel.OverheatShutoffPorts = Port1Bit | Port2Bit;
// Use T2 probe as temperature and overheat functions
ReefAngel.TempProbe = T1_PROBE;
ReefAngel.OverheatProbe = T1_PROBE;
// Set the Overheat temperature setting
InternalMemory.OverheatTemp_write( 825 );
//Set Standard Menu
ReefAngel.AddStandardMenu();

// Feeeding and Water Change mode speed
ReefAngel.DCPump.FeedingSpeed=20;
ReefAngel.DCPump.WaterChangeSpeed=0;

// Ports that are always on
ReefAngel.Relay.On( Port4 );

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


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

void loop()
{
ReefAngel.StandardLights( Actinic_Lights,12,0,22,0 );
ReefAngel.StandardLights( Day_Lights,13,0,21,0 );
ReefAngel.Relay.Set( Moon_Lights, !ReefAngel.Relay.Status( Actinic_Lights ) );
ReefAngel.StandardLights( Sump_Fan,13,0,21,0 );
ReefAngel.Relay.Set(DeNit_Doser,(now()-3600)%21600<1200); // Runs for 1200s every 21600 seconds
ReefAngel.Relay.Set(DeNit_Pump,((now()-3600)-1200)%21600<1200); // Runs for 1200s every 21600 seconds with 1200s offset
ReefAngel.WaterLevelATO(ATO_Pump,720,32,32); // Enable ATO the ATO
if (ReefAngel.Relay.Status(DeNit_Pump)) // Check to see if DeNit Pump is on and update time is empty
{ 
ATOUpdate = now(); // If so, set the update time to now
} 

if (now() - ATOUpdate < 120) // If it hasnt been 120 seconds turn off the port
{ 
ReefAngel.WaterLevelATO(ATO_Pump,720,0,1);
}
//Disable ATO if Salinity is below 33.5
if (ReefAngel.Params.Salinity<335) ReefAngel.Relay.Off(ATO_Pump);

  if (ReefAngel.DCPump.Mode==Custom)
  {
  ReefAngel.PWM.SetActinic( ElseMode(40,20,true ));                     // ElseMode on sync mode, 40 +/- 20%
  }
if( ReefAngel.DisplayedMenu==FEEDING_MODE ) ReefAngel.PWM.SetActinic(20);
if( ReefAngel.DisplayedMenu==WATERCHANGE_MODE ) ReefAngel.PWM.SetActinic(0);
if (hour()<12 || hour()>=22) ReefAngel.PWM.SetActinic(30);
////// Place your custom code below here


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

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

void DrawCustomMain()
{
int x,y;
char text[10];
// Parameters
#if defined DisplayLEDPWM && ! defined RemoveAllLights
ReefAngel.LCD.DrawMonitor( 15, 20, ReefAngel.Params,
ReefAngel.PWM.GetDaylightValue(), ReefAngel.PWM.GetActinicValue() );
#else // defined DisplayLEDPWM && ! defined RemoveAllLights
ReefAngel.LCD.DrawMonitor( 15, 20, ReefAngel.Params );
#endif // defined DisplayLEDPWM && ! defined RemoveAllLights
pingSerial();

// Water Level
ReefAngel.LCD.DrawText( COLOR_DARKGOLDENROD,DefaultBGColor,75,66, "WL:" );
ReefAngel.LCD.DrawText( COLOR_DARKGOLDENROD,DefaultBGColor,99,66, ReefAngel.WaterLevel.GetLevel() );
  ConvertNumToString(text, ReefAngel.Params.Salinity, 10);
  strcat(text,"  ");
  ReefAngel.LCD.DrawText(DefaultFGColor,DefaultBGColor,39,75,"Salinity:");
  ReefAngel.LCD.DrawText(DefaultFGColor,DefaultBGColor,99,75,text);
pingSerial();

// Main Relay Box
byte TempRelay = ReefAngel.Relay.RelayData;
TempRelay &= ReefAngel.Relay.RelayMaskOff;
TempRelay |= ReefAngel.Relay.RelayMaskOn;
ReefAngel.LCD.DrawOutletBox( 12, 92, TempRelay );
pingSerial();
TempRelay = ReefAngel.Relay.RelayDataE[0];
TempRelay &= ReefAngel.Relay.RelayMaskOffE[0];
TempRelay |= ReefAngel.Relay.RelayMaskOnE[0];
ReefAngel.LCD.DrawOutletBox(12, 104, TempRelay);

// Date and Time
ReefAngel.LCD.DrawDate( 6, 122 );
pingSerial();
}

void DrawCustomGraph()
{
}
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( 500, 3000);           // Set the initial delay
  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(500,5000);                        // If so, come up with a new delay
    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;
  }
}
This is what needs to happen, I hope it makes sense.

01:00 DeNit_Pump turns on (ATO_Pump disabled)

01:20 DeNit_Pump turns off and DeNit_Doser turns on.

01:25 ATO_Pump enabled if Water Level is below 32% and disabled if above 32%
ReefAngel.WaterLevelATO(ATO_Pump,720,32,32); // Enable ATO the ATO

01:40 DeNit_Doser turns off.

The whole process repeats every 6 hours (IE 1 AM, 7 AM, 1 PM and 7 PM).

This needs to be easy enough for me to add additional cycles if I needed to.
IE Right now I know that I would need to change the 21600 in the code to be 10800 if I wanted to run it every 3 hours.

I would like to build in that the ATO is disabled if any of these parameters are met.
Salinity < 33.5
ATO High is On (IsActive) or floating. I have the ATO pointing down and the wires up, but I flipped the float over so it would behave the way I want it to.

I also want to build in that the ATO is disabled or delayed for 10 min after a water change until I get the water level where it should be.
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: ATO code is not working properly.

Post by lnevo »

I think I know what your issues are... however I'd like to review a few points...
Right now I have the ATO Pump unplugged, but as far as I can see it seems to be turning on after the pumps come back on or after a reboot of a code update.
Can you describe that better? After waterchange/feeding modes? After reboot or code update... if you manually unplug and replug in same thing? Does it ever go off, or stays in on position?

Also...

Code: Select all

 ReefAngel.WaterLevelATO(ATO_Pump,720,32,32); // Enable ATO the ATO
I do not recommend having such a tight threshold. The WaterLevel sensor tends to bounce around a little and this could easily be messing things up. Can we put a range. I'd suggest 31 33? or maybe you could do 32 34?

And finally, you seem to have DCPump setup, but you aren't using it... You have to define a pump and what mode it's in. For your case..

Code: Select all

ReefAngel.DCPump.ActinicChannel=Sync;
Then you woudn't need these two lines:

Code: Select all

if( ReefAngel.DisplayedMenu==FEEDING_MODE ) ReefAngel.PWM.SetActinic(20);
if( ReefAngel.DisplayedMenu==WATERCHANGE_MODE ) ReefAngel.PWM.SetActinic(0);
as they'd be taken care of by this:

Code: Select all

// Feeeding and Water Change mode speed
ReefAngel.DCPump.FeedingSpeed=20;
ReefAngel.DCPump.WaterChangeSpeed=0;
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: ATO code is not working properly.

Post by Sacohen »

lnevo wrote:I think I know what your issues are... however I'd like to review a few points...
Right now I have the ATO Pump unplugged, but as far as I can see it seems to be turning on after the pumps come back on or after a reboot of a code update.
Can you describe that better? After waterchange/feeding modes? After reboot or code update... if you manually unplug and replug in same thing? Does it ever go off, or stays in on position?

The pump has been unplugged for over a week now so I'm trying to remember exactly what was going one.
I never really pinned it down to begin with.
It would go on for about 30 seconds after a code update (that's what I mean by reboot, I really don't reboot the head unit at all), after water changes and replugging it.

I don't recall it happening after Feeding.

Before I unplugged it my salinity was always around 34 to 35 ppt then one day it dropped to 28.

I don't know if it stayed on or just kept going on an off. I think it kept going on and off because I remember looking at the Relay Activity and seeing a bunch of on/off spikes.

It should not have gone on at all because the water level was fine and even if it did go on once it got back above 32% it should not have gone on again.

There were several times I remember hearing it on and looking at the portal or app and saying the water level is fine it shouldn't be on.
lnevo wrote:Also...

Code: Select all

 ReefAngel.WaterLevelATO(ATO_Pump,720,32,32); // Enable ATO the ATO
I do not recommend having such a tight threshold. The WaterLevel sensor tends to bounce around a little and this could easily be messing things up. Can we put a range. I'd suggest 31 33? or maybe you could do 32 34?
The threshold works fine and was perfect when I was using my Tom's Aqualifter.
The WaterLevel Pipe does not move. I have it pretty secure.

I drilled out the stop on a 1/2" PVC T and then cut a slit in it the width of my sump acrylic.
Slipped the 1/2" tube thru there and have it resting against the bottom.

Image

Image
lnevo wrote:And finally, you seem to have DCPump setup, but you aren't using it... You have to define a pump and what mode it's in. For your case..

Code: Select all

ReefAngel.DCPump.ActinicChannel=Sync;
Then you woudn't need these two lines:

Code: Select all

if( ReefAngel.DisplayedMenu==FEEDING_MODE ) ReefAngel.PWM.SetActinic(20);
if( ReefAngel.DisplayedMenu==WATERCHANGE_MODE ) ReefAngel.PWM.SetActinic(0);
as they'd be taken care of by this:

Code: Select all

// Feeeding and Water Change mode speed
ReefAngel.DCPump.FeedingSpeed=20;
ReefAngel.DCPump.WaterChangeSpeed=0;
I never truly understood how the DCPump code worked.
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: ATO code is not working properly.

Post by lnevo »

The problem with having an if statement around ATO code is that the condition could fail (meaning now more successful if) and the ATO code has already triggered a pump on condition... because your not still suceeding the WaterLevelATO function does not run and pump gets stuck on. I still would like your OK to put a different threshold :)

The better mechanism would be to give the default water level without any if statement and then in the if statements you could override the pump. I'll work on some code to play with soon.

I'll modify your DCPump mode to work properly. Then the other modes will work for you too :)
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: ATO code is not working properly.

Post by Sacohen »

That's fine.

Do what you think will work and we'll test it and tweak what needs to be tweaked.
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: ATO code is not working properly.

Post by lnevo »

So, I rewrote the code to hopefully make it more straight forward. I also added the DCPump functionality. Please test it, it should do your ElseMode when it's setup for Custom on the portal. It should switch to other modes as well. Night time it should stay at 30% constant. As far as adding the random code from paulturner, let's make that an exercise once we know everything is working.. it should be pretty straight forward now if you look at his code, since you're function is much closer to his now.

In the end, I reviewed and reviewed and reviewed to figure out where the extra on time for the ATO was happening and I believe it is that tight threshold I mentioned previously. This is why.. With such a tight threshold, the water level sensor fluctuates frequently (at least mine does..) So even if it's mostly at 32%..there are blips where it may read 31 and 33. The 31 is the important one here. Especially as water is evaporating because we're sitting on the edge of 32... Now, this will cause the pump to cycle very frequently, and what I believe is happening is that if your controller reboots (from a code update...) or a watchdog timer failure, then the relay could very easily be in an on state while the controller reboots.

So, for the same theory that we put a hi/low threshold for a heater we would do the same here. We want the ATO pump to come on ever X amount of time and put in a little bit of extra so that we're not constantly cycling. I set the WaterLevelATO at 32%-34%, but I would recommend increasing that to at least a spread of 3%. This would accommodate the fluctuations as they can easily be +/- 1. I would also look at the timeout.. Do you really want a 12 minute timeout? How long would it take to increase the sump by 3% Pad that a little and that should be your timeout.

Anyway, without further ado (this was compiled so I know it shouldn't give any errors..) Please test out this code.

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>

// Define Relay Ports by Name
#define Actinic_Lights     1
#define Day_Lights         2
#define Unused             3
#define Pumps              4
#define Sump_Fan           5
#define DeNit_Pump         6
#define DeNit_Doser        7
#define Unused             8

#define ATO_Pump           Box1_Port1
#define Moon_Lights        Box1_Port2
#define Unused             Box1_Port3
#define Unused             Box1_Port4
#define Unused             Box1_Port5
#define Unused             Box1_Port6
#define Unused             Box1_Port7
#define Unused             Box1_Port8


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

// Does not need to be global.
// unsigned long ATOUpdate=0;

////// 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 = 0;
// Ports toggled in Water Change Mode
ReefAngel.WaterChangePorts = Port4Bit;
ReefAngel.WaterChangePortsE[0] = Port1Bit;
// Ports toggled when Lights On / Off menu entry selected
ReefAngel.LightsOnPorts = Port1Bit | Port2Bit;
// Ports turned off when Overheat temperature exceeded
ReefAngel.OverheatShutoffPorts = Port1Bit | Port2Bit;
// Use T2 probe as temperature and overheat functions
ReefAngel.TempProbe = T1_PROBE;
ReefAngel.OverheatProbe = T1_PROBE;
// Set the Overheat temperature setting
InternalMemory.OverheatTemp_write( 825 );
//Set Standard Menu
ReefAngel.AddStandardMenu();

// Feeeding and Water Change mode speed
ReefAngel.DCPump.FeedingSpeed=20;
ReefAngel.DCPump.WaterChangeSpeed=0;
ReefAngel.DCPump.ActinicChannel=Sync; // Now you're pump will be affected by the portal settings.

// Ports that are always on
ReefAngel.Relay.On( Pumps );

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


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

void loop()
{
  ReefAngel.StandardLights( Actinic_Lights,12,0,22,0 );
  ReefAngel.StandardLights( Day_Lights,13,0,21,0 );
  ReefAngel.StandardLights( Sump_Fan,13,0,21,0 );

  ////// Place your custom code below here
  ReefAngel.Relay.Set( Moon_Lights, !ReefAngel.Relay.Status( Actinic_Lights ) );

  ReefAngel.Relay.Set(DeNit_Doser,(now()-3600)%21600<1200);       // Runs for 1200s every 21600 seconds
  ReefAngel.Relay.Set(DeNit_Pump,((now()-3600)-1200)%21600<1200); // Runs for 1200s every 21600 seconds with 1200s offset

  // ReefAngel.Relay.DelayedOn( ATO_Pump,10 );
  // ReefAngel.WaterLevelATO(ATO_Pump,720,32,32); // Enable ATO the ATO

  // Delay WL ATO after water change and DeNit_Dosing
  static time_t wcTimer=0;
  static time_t denitTimer=0;
  
  if (ReefAngel.DisplayedMenu == WATERCHANGE_MODE) wcTimer=now();
  if (ReefAngel.Relay.Status(DeNit_Doser)) denitTimer=now();
  
  // Start with defined WaterLevel ATO 
  ReefAngel.WaterLevelATO(ATO_Pump,720,32,34); 
  // You should see a much more stable pump usage with a wider threshold 32-34.
  // Also since the water level measure can fluctuate it could lead to a lot of on/off cycling
  // which could also cause the relay to be on more often and it we reboot, we may maintain the state we don't want...
  // Especially if it could take up to 30 seconds to reboot :)
  
  // First 10 minutes after WC disable ATO
  if (now()-wcTimer > 0 && now()-wcTimer < 600)
    ReefAngel.Relay.Off(ATO_Pump); 

  // First 5 minutes after DeNit_Doser was on
  if (now()-denitTimer > 0 && now()-denitTimer < 300)
    ReefAngel.Relay.Off(ATO_Pump); 

  // Disable ATO if Salinity is below 33.5. 
  if (ReefAngel.Params.Salinity<335) 
    ReefAngel.Relay.Off(ATO_Pump); 
    
  // Disable ATO if ATO High IsActive()
  if (ReefAngel.HighATO.IsActive()) 
    ReefAngel.Relay.Off(ATO_Pump);
    
  // Modified to use the DCPump class
  if (hour()<12 || hour()>=22) {
    ReefAngel.DCPump.UseMemory=false;                
    ReefAngel.DCPump.Mode=Constant;                  
    ReefAngel.DCPump.Speed=30;
  } else if (InternalMemory.DCPumpMode_read()==Custom) {
    ReefAngel.DCPump.UseMemory=false;
    ReefAngel.DCPump.Mode=Constant;                  // Won't really be constant. See next line.
    ReefAngel.DCPump.Speed=ElseMode(40,20,true );    // ElseMode on sync mode, 40 +/- 20%
  } else  {
    ReefAngel.DCPump.UseMemory=true;                 // Use whatever is in the portal
  }

  // No longer necessary since we've defined the speeds for these modes in setup();
  //
  // if( ReefAngel.DisplayedMenu==FEEDING_MODE ) ReefAngel.PWM.SetActinic(20);
  // if( ReefAngel.DisplayedMenu==WATERCHANGE_MODE ) ReefAngel.PWM.SetActinic(0);

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

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

void DrawCustomMain()
{
int x,y;
char text[10];
// Parameters
#if defined DisplayLEDPWM && ! defined RemoveAllLights
ReefAngel.LCD.DrawMonitor( 15, 20, ReefAngel.Params,
ReefAngel.PWM.GetDaylightValue(), ReefAngel.PWM.GetActinicValue() );
#else // defined DisplayLEDPWM && ! defined RemoveAllLights
ReefAngel.LCD.DrawMonitor( 15, 20, ReefAngel.Params );
#endif // defined DisplayLEDPWM && ! defined RemoveAllLights
pingSerial();

// Water Level
ReefAngel.LCD.DrawText( COLOR_DARKGOLDENROD,DefaultBGColor,75,66, "WL:" );
ReefAngel.LCD.DrawText( COLOR_DARKGOLDENROD,DefaultBGColor,99,66, ReefAngel.WaterLevel.GetLevel() );
  ConvertNumToString(text, ReefAngel.Params.Salinity, 10);
  strcat(text,"  ");
  ReefAngel.LCD.DrawText(DefaultFGColor,DefaultBGColor,39,75,"Salinity:");
  ReefAngel.LCD.DrawText(DefaultFGColor,DefaultBGColor,99,75,text);
pingSerial();

// Main Relay Box
byte TempRelay = ReefAngel.Relay.RelayData;
TempRelay &= ReefAngel.Relay.RelayMaskOff;
TempRelay |= ReefAngel.Relay.RelayMaskOn;
ReefAngel.LCD.DrawOutletBox( 12, 92, TempRelay );
pingSerial();
TempRelay = ReefAngel.Relay.RelayDataE[0];
TempRelay &= ReefAngel.Relay.RelayMaskOffE[0];
TempRelay |= ReefAngel.Relay.RelayMaskOnE[0];
ReefAngel.LCD.DrawOutletBox(12, 104, TempRelay);

// Date and Time
ReefAngel.LCD.DrawDate( 6, 122 );
pingSerial();
}

void DrawCustomGraph()
{
}
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( 500, 3000);           // Set the initial delay
  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(500,5000);                        // If so, come up with a new delay
    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;
  }
}
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: ATO code is not working properly.

Post by lnevo »

Speaking of heaters... where is your heater? With all those extra ports it would be a shame to not have a backup on your heater. Unless you don't use one and you're lights keep your tank nice and warm?
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: ATO code is not working properly.

Post by Sacohen »

First let me say thank you very much for the work you put into this :)

Correct. I don't use a heater.
Being in south Florida I have a hard enough time keeping it at 78° even though I would like it a bit lower than that.
I'm actually picking up a chiller today. Got a real nice deal on a slightly used 1/10hp for $100.

The code looks great.

I probably won't upload it and test it until the weekend when I can be around and see if everything is happening correctly.

2 question.

I added a 2nd Jebao pump (1 WP-40 and 1 WP-25) will they both be controlled the same from the portal?\

It looks like I may need to add this...

Code: Select all

// Feeeding and Water Change mode speed
ReefAngel.DCPump.FeedingSpeed=20;
ReefAngel.DCPump.WaterChangeSpeed=0;
ReefAngel.DCPump.ActinicChannel=Sync; // Now you're pump will be affected by the portal settings.
ReefAngel.DCPump.DaylightChannel=AntiSync; // Now you're pump will be affected by the portal settings.

What If I wanted to have the the WP-40 at 40 +/- 20% and the WP-25 at 80 +/- 20%?
Since it is a smaller pump it can run higher.
I also found that if I have the WP-25 at 20 for feeding and 0 for Water Change it will freeze and not run at all until it is power cycled.

I have it at 80 +/- 20% when in else mode and 50 for feeding and water change.
It is low enough in the tank that it won't suck air when the tank is partially drained for a WC.

As far as the ATO timeout , my old Aqua Lifter would take about 10 min to bring back to the proper level. ( I think I had it ad 32,34 or 30, 32 before setting it to 32,32).

I'm currently using the dosing pump that Roberto sells in the store it is rated at 0.75 ml/sec where as the Aqualifter was 3 1/2 gallons per hour.

Sorry, I hope this doesn't make things tougher.
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

ATO code is not working properly.

Post by lnevo »

You could either run the wp25 manually the way you did before...or just let it run same as your 40 and find nice middle ground. You have the code right to activate it with the DCPump class. You could also beg Roberto to add a per channel offset to handle mixed pumps. I've done it in my custom code so i can set the offset on my anti sync pump..maybe that would be easier for roberto to implement (an antisync offset). I'd do it just dont have the time lately.

I still recommend going to a 3% split just didnt know which way you wanted to expand it. So please keep this in mind. Keep me posted, should be around this weekend if problems arise.
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: ATO code is not working properly.

Post by Sacohen »

OK. I'm sure Roberto will see this and take note of the recommendation.

A 3% split I would probably do 31 to 34.

Thanks I'll let you know how things work out, or if something is not working that I can't figure out.
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: ATO code is not working properly.

Post by Sacohen »

I uploaded the code earlier today so I could watch the 1pm water exchange and it did not work properly.

At 1pm when the pump kicked in for the De-nit water exchange I heard the AT pump kick in.

It stayed on for the 20 min water exchange cycle and then it shut off.

Image

I did change the code a bit, but nothing that would affect the water exchange and the only thing I changed on the ATO was the water level percentage spread to 31-34.

Here is the modified code....

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>

// Define Relay Ports by Name
#define Actinic_Lights     1
#define Day_Lights         2
#define Unused             3
#define Pumps              4
#define Sump_Fan           5
#define DeNit_Pump         6
#define DeNit_Doser        7
#define Unused             8

#define ATO_Pump           Box1_Port1
#define Moon_Lights        Box1_Port2
#define Unused             Box1_Port3
#define Unused             Box1_Port4
#define Unused             Box1_Port5
#define Unused             Box1_Port6
#define Unused             Box1_Port7
#define Unused             Box1_Port8


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

// Does not need to be global.
// unsigned long ATOUpdate=0;

////// 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 = 0;
// Ports toggled in Water Change Mode
ReefAngel.WaterChangePorts = Port4Bit;
ReefAngel.WaterChangePortsE[0] = Port1Bit;
// Ports toggled when Lights On / Off menu entry selected
ReefAngel.LightsOnPorts = Port1Bit | Port2Bit;
// Ports turned off when Overheat temperature exceeded
ReefAngel.OverheatShutoffPorts = Port1Bit | Port2Bit;
// Use T2 probe as temperature and overheat functions
ReefAngel.TempProbe = T1_PROBE;
ReefAngel.OverheatProbe = T1_PROBE;
// Set the Overheat temperature setting
InternalMemory.OverheatTemp_write( 825 );
//Set Standard Menu
ReefAngel.AddStandardMenu();

// Feeeding and Water Change mode speed
ReefAngel.DCPump.FeedingSpeed=20;
ReefAngel.DCPump.WaterChangeSpeed=0;
ReefAngel.DCPump.ActinicChannel=true; // Now you're pump will be affected by the portal settings.
ReefAngel.DCPump.DaylightChannel=false; // Now you're pump will be affected by the portal settings.

// Ports that are always on
ReefAngel.Relay.On( Pumps );

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


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

void loop()
{
  ReefAngel.StandardLights( Actinic_Lights,12,0,22,0 );
  ReefAngel.StandardLights( Day_Lights,13,0,21,0 );
  ReefAngel.StandardLights( Sump_Fan,13,0,21,0 );

  ////// Place your custom code below here
  ReefAngel.Relay.Set( Moon_Lights, !ReefAngel.Relay.Status( Actinic_Lights ) );

  ReefAngel.Relay.Set(DeNit_Doser,(now()-3600)%21600<1200);       // Runs for 1200s every 21600 seconds
  ReefAngel.Relay.Set(DeNit_Pump,((now()-3600)-1200)%21600<1200); // Runs for 1200s every 21600 seconds with 1200s offset

  // ReefAngel.Relay.DelayedOn( ATO_Pump,10 );
  // ReefAngel.WaterLevelATO(ATO_Pump,720,32,32); // Enable ATO the ATO

  // Delay WL ATO after water change and DeNit_Dosing
  static time_t wcTimer=0;
  static time_t denitTimer=0;
  
  if (ReefAngel.DisplayedMenu == WATERCHANGE_MODE) wcTimer=now();
  if (ReefAngel.Relay.Status(DeNit_Doser)) denitTimer=now();
  
  // Start with defined WaterLevel ATO 
  ReefAngel.WaterLevelATO(ATO_Pump,720,31,34); 
  // You should see a much more stable pump usage with a wider threshold 32-34.
  // Also since the water level measure can fluctuate it could lead to a lot of on/off cycling
  // which could also cause the relay to be on more often and it we reboot, we may maintain the state we don't want...
  // Especially if it could take up to 30 seconds to reboot :)
  
  // First 10 minutes after WC disable ATO
  if (now()-wcTimer > 0 && now()-wcTimer < 600)
    ReefAngel.Relay.Off(ATO_Pump); 

  // First 5 minutes after DeNit_Doser was on
  if (now()-denitTimer > 0 && now()-denitTimer < 300)
    ReefAngel.Relay.Off(ATO_Pump); 

  // Disable ATO if Salinity is below 33.5. 
  if (ReefAngel.Params.Salinity<335) 
    ReefAngel.Relay.Off(ATO_Pump); 
    
  // Disable ATO if ATO High IsActive()
  if (ReefAngel.HighATO.IsActive()) 
    ReefAngel.Relay.Off(ATO_Pump);
    
  // Modified to use the DCPump class
  if (hour()<12 || hour()>=22) {
    ReefAngel.DCPump.UseMemory=false;                
    ReefAngel.DCPump.Mode=Constant;                  
    ReefAngel.DCPump.Speed=30;
  } else if (InternalMemory.DCPumpMode_read()==Custom) {
    ReefAngel.DCPump.UseMemory=false;
    ReefAngel.DCPump.Mode=Constant;                  // Won't really be constant. See next line.
    ReefAngel.DCPump.Speed=ElseMode(50,20,true );    // ElseMode on sync mode, 50 +/- 20%
  } else  {
    ReefAngel.DCPump.UseMemory=true;                 // Use whatever is in the portal
  }

  // No longer necessary since we've defined the speeds for these modes in setup();
  //
  // if( ReefAngel.DisplayedMenu==FEEDING_MODE ) ReefAngel.PWM.SetActinic(20);
  // if( ReefAngel.DisplayedMenu==WATERCHANGE_MODE ) ReefAngel.PWM.SetActinic(0);

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

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

void DrawCustomMain()
{
int x,y;
char text[10];
// Parameters
#if defined DisplayLEDPWM && ! defined RemoveAllLights
ReefAngel.LCD.DrawMonitor( 15, 20, ReefAngel.Params,
ReefAngel.PWM.GetDaylightValue(), ReefAngel.PWM.GetActinicValue() );
#else // defined DisplayLEDPWM && ! defined RemoveAllLights
ReefAngel.LCD.DrawMonitor( 15, 20, ReefAngel.Params );
#endif // defined DisplayLEDPWM && ! defined RemoveAllLights
pingSerial();

// Water Level
ReefAngel.LCD.DrawText( COLOR_DARKGOLDENROD,DefaultBGColor,75,66, "WL:" );
ReefAngel.LCD.DrawText( COLOR_DARKGOLDENROD,DefaultBGColor,99,66, ReefAngel.WaterLevel.GetLevel() );
  ConvertNumToString(text, ReefAngel.Params.Salinity, 10);
  strcat(text,"  ");
  ReefAngel.LCD.DrawText(DefaultFGColor,DefaultBGColor,39,75,"Salinity:");
  ReefAngel.LCD.DrawText(DefaultFGColor,DefaultBGColor,99,75,text);
pingSerial();

// Main Relay Box
byte TempRelay = ReefAngel.Relay.RelayData;
TempRelay &= ReefAngel.Relay.RelayMaskOff;
TempRelay |= ReefAngel.Relay.RelayMaskOn;
ReefAngel.LCD.DrawOutletBox( 12, 92, TempRelay );
pingSerial();
TempRelay = ReefAngel.Relay.RelayDataE[0];
TempRelay &= ReefAngel.Relay.RelayMaskOffE[0];
TempRelay |= ReefAngel.Relay.RelayMaskOnE[0];
ReefAngel.LCD.DrawOutletBox(12, 104, TempRelay);

// Date and Time
ReefAngel.LCD.DrawDate( 6, 122 );
pingSerial();
}

void DrawCustomGraph()
{
}
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( 500, 3000);           // Set the initial delay
  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(500,5000);                        // If so, come up with a new delay
    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;
  }
}
Thanks again for your hard work on it.
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: ATO code is not working properly.

Post by lnevo »

Look at the code...your denit pump turns on first (-1200 seconds) ...the ato is disabled when the doser is on...i think you need to change the logic for that. Change when denitTimer=now() to the device you want it disabled for.
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: ATO code is not working properly.

Post by lnevo »

It also looks like we need another condition when your denitrator thing is on...

The denitrate process is 20 or 40 minutes total? During that...when should ato be on if at all?
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: ATO code is not working properly.

Post by lnevo »

Ok i think we're just missing the disabled ato when the denit pump is on.

Just add another disable condition...

if(ReefAngel.Relay.Status(Denit_Pump))
ReefAngel.Relay.Off(ATO_Pump);
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: ATO code is not working properly.

Post by Sacohen »

lnevo wrote:Look at the code...your denit pump turns on first (-1200 seconds) ...the ato is disabled when the doser is on...i think you need to change the logic for that. Change when denitTimer=now() to the device you want it disabled for.
Your saying that the ATO is enabled when the "DeNit_Pump" is on and disabled when the "DeNit_Doser" is on?

That is backwards.

The De-nitrification process is 2 20 min parts.

The 1st is 20 min water exchange with the "DeNit_Pump" that the ATO should be disabled for.
The 2nd is 20 min of dosing the Nitragone food with the "DeNit_Doser"

Code: Select all

[quote="lnevo"]Ok i think we're just missing the disabled ato when the denit pump is on.

Just add another disable condition...

if(ReefAngel.Relay.Status(Denit_Pump))
  ReefAngel.Relay.Off(ATO_Pump);[/quote]
I don't think it is needed. the point of this is to disable the ATO when the DeNit_Pump is on doing the water exchange and the level in the sump is lowered.

I'll change it and see what happens.
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: ATO code is not working properly.

Post by lnevo »

No i reread everything you don't need to change just add the two lines i gave you...

But i don't know that i did the reenable properly.

Im doing this from my phone so its hard to review...apologies
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: ATO code is not working properly.

Post by lnevo »

Give me a minute...getting online
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: ATO code is not working properly.

Post by lnevo »

Ok, I see the issue...

I was not disabling the ATO pump when the DeNit_Pump was on... that's what I tried to do with the last two lines I gave you... there is a better solution.

Try this code

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>

// Define Relay Ports by Name
#define Actinic_Lights     1
#define Day_Lights         2
#define Unused             3
#define Pumps              4
#define Sump_Fan           5
#define DeNit_Pump         6
#define DeNit_Doser        7
#define Unused             8

#define ATO_Pump           Box1_Port1
#define Moon_Lights        Box1_Port2
#define Unused             Box1_Port3
#define Unused             Box1_Port4
#define Unused             Box1_Port5
#define Unused             Box1_Port6
#define Unused             Box1_Port7
#define Unused             Box1_Port8


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

// Does not need to be global.
// unsigned long ATOUpdate=0;

////// 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 = 0;
// Ports toggled in Water Change Mode
ReefAngel.WaterChangePorts = Port4Bit;
ReefAngel.WaterChangePortsE[0] = Port1Bit;
// Ports toggled when Lights On / Off menu entry selected
ReefAngel.LightsOnPorts = Port1Bit | Port2Bit;
// Ports turned off when Overheat temperature exceeded
ReefAngel.OverheatShutoffPorts = Port1Bit | Port2Bit;
// Use T2 probe as temperature and overheat functions
ReefAngel.TempProbe = T1_PROBE;
ReefAngel.OverheatProbe = T1_PROBE;
// Set the Overheat temperature setting
InternalMemory.OverheatTemp_write( 825 );
//Set Standard Menu
ReefAngel.AddStandardMenu();

// Feeeding and Water Change mode speed
ReefAngel.DCPump.FeedingSpeed=20;
ReefAngel.DCPump.WaterChangeSpeed=0;
ReefAngel.DCPump.ActinicChannel=Sync; // Now you're pump will be affected by the portal settings.

// Ports that are always on
ReefAngel.Relay.On( Pumps );

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


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

void loop()
{
  ReefAngel.StandardLights( Actinic_Lights,12,0,22,0 );
  ReefAngel.StandardLights( Day_Lights,13,0,21,0 );
  ReefAngel.StandardLights( Sump_Fan,13,0,21,0 );

  ////// Place your custom code below here
  ReefAngel.Relay.Set( Moon_Lights, !ReefAngel.Relay.Status( Actinic_Lights ) );

  ReefAngel.Relay.Set(DeNit_Doser,(now()-3600)%21600<1200);       // Runs for 1200s every 21600 seconds
  ReefAngel.Relay.Set(DeNit_Pump,((now()-3600)-1200)%21600<1200); // Runs for 1200s every 21600 seconds with 1200s offset

  // ReefAngel.Relay.DelayedOn( ATO_Pump,10 );
  // ReefAngel.WaterLevelATO(ATO_Pump,720,32,32); // Enable ATO the ATO

  // Delay WL ATO after water change and DeNit_Dosing
  static time_t wcTimer=0;
  static time_t denitTimer=0;
  
  if (ReefAngel.DisplayedMenu == WATERCHANGE_MODE) wcTimer=now();
  if (ReefAngel.Relay.Status(DeNit_Pump)) denitTimer=now();
  
  // Start with defined WaterLevel ATO 
  ReefAngel.WaterLevelATO(ATO_Pump,720,32,34); 
  // You should see a much more stable pump usage with a wider threshold 32-34.
  // Also since the water level measure can fluctuate it could lead to a lot of on/off cycling
  // which could also cause the relay to be on more often and it we reboot, we may maintain the state we don't want...
  // Especially if it could take up to 30 seconds to reboot :)
  
  // First 10 minutes after WC disable ATO
  if (now()-wcTimer >= 0 && now()-wcTimer < 600)
    ReefAngel.Relay.Off(ATO_Pump); 

  // First 5 minutes after DeNit_Doser was on
  if (now()-denitTimer >= 0 && now()-denitTimer < 300)
    ReefAngel.Relay.Off(ATO_Pump); 

  // Disable ATO if Salinity is below 33.5. 
  if (ReefAngel.Params.Salinity<335) 
    ReefAngel.Relay.Off(ATO_Pump); 
    
  // Disable ATO if ATO High IsActive()
  if (ReefAngel.HighATO.IsActive()) 
    ReefAngel.Relay.Off(ATO_Pump);
    
  // Modified to use the DCPump class
  if (hour()<12 || hour()>=22) {
    ReefAngel.DCPump.UseMemory=false;                
    ReefAngel.DCPump.Mode=Constant;                  
    ReefAngel.DCPump.Speed=30;
  } else if (InternalMemory.DCPumpMode_read()==Custom) {
    ReefAngel.DCPump.UseMemory=false;
    ReefAngel.DCPump.Mode=Constant;                  // Won't really be constant. See next line.
    ReefAngel.DCPump.Speed=ElseMode(40,20,true );    // ElseMode on sync mode, 40 +/- 20%
  } else  {
    ReefAngel.DCPump.UseMemory=true;                 // Use whatever is in the portal
  }

  // No longer necessary since we've defined the speeds for these modes in setup();
  //
  // if( ReefAngel.DisplayedMenu==FEEDING_MODE ) ReefAngel.PWM.SetActinic(20);
  // if( ReefAngel.DisplayedMenu==WATERCHANGE_MODE ) ReefAngel.PWM.SetActinic(0);

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

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

void DrawCustomMain()
{
int x,y;
char text[10];
// Parameters
#if defined DisplayLEDPWM && ! defined RemoveAllLights
ReefAngel.LCD.DrawMonitor( 15, 20, ReefAngel.Params,
ReefAngel.PWM.GetDaylightValue(), ReefAngel.PWM.GetActinicValue() );
#else // defined DisplayLEDPWM && ! defined RemoveAllLights
ReefAngel.LCD.DrawMonitor( 15, 20, ReefAngel.Params );
#endif // defined DisplayLEDPWM && ! defined RemoveAllLights
pingSerial();

// Water Level
ReefAngel.LCD.DrawText( COLOR_DARKGOLDENROD,DefaultBGColor,75,66, "WL:" );
ReefAngel.LCD.DrawText( COLOR_DARKGOLDENROD,DefaultBGColor,99,66, ReefAngel.WaterLevel.GetLevel() );
  ConvertNumToString(text, ReefAngel.Params.Salinity, 10);
  strcat(text,"  ");
  ReefAngel.LCD.DrawText(DefaultFGColor,DefaultBGColor,39,75,"Salinity:");
  ReefAngel.LCD.DrawText(DefaultFGColor,DefaultBGColor,99,75,text);
pingSerial();

// Main Relay Box
byte TempRelay = ReefAngel.Relay.RelayData;
TempRelay &= ReefAngel.Relay.RelayMaskOff;
TempRelay |= ReefAngel.Relay.RelayMaskOn;
ReefAngel.LCD.DrawOutletBox( 12, 92, TempRelay );
pingSerial();
TempRelay = ReefAngel.Relay.RelayDataE[0];
TempRelay &= ReefAngel.Relay.RelayMaskOffE[0];
TempRelay |= ReefAngel.Relay.RelayMaskOnE[0];
ReefAngel.LCD.DrawOutletBox(12, 104, TempRelay);

// Date and Time
ReefAngel.LCD.DrawDate( 6, 122 );
pingSerial();
}

void DrawCustomGraph()
{
}
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( 500, 3000);           // Set the initial delay
  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(500,5000);                        // If so, come up with a new delay
    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;
  }
}
I changed two things. I start the timer now when the DeNit_Pump turns on. And keep it off till 5 minutes after. I also had an error in that I was doing > 0 but it should have been >= 0. This would have caused the ATO to stay on during WC and would have prevented the ATO from being disabled when we want as well. Since while DeNit_Pump is on denitTimer is going to be = now() and now()-denitTimer is going to equal 0 during the first DeNitrating step..

Sorry for the confusion in the last few posts. Please try this set. Test with the water change mode. If that works we should be good for the next DeNitrate run.
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: ATO code is not working properly.

Post by Sacohen »

I'm leaving for a Marlins game with my son in a bit.
I'll try it tomorrow.

Thanks again.
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: ATO code is not working properly.

Post by lnevo »

No problem. I'm pretty confident in the state now.it was my bad I missed the initial disabling. Plus the WC bit too. That would have been ugly ;)

Good luck, have fun at the game.
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: ATO code is not working properly.

Post by Sacohen »

Sorry man. The 7pm de-nit cycle started and the water level dropped to 30% and the ATO pump kicked in.
Something still isn't right here.
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: ATO code is not working properly.

Post by lnevo »

Wtf...i need another set of eyes on this thing...roberto am i missing something that waterlevelato is doing? Am i doing something stupid w timer...this has the best of me..
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: ATO code is not working properly.

Post by lnevo »

Can you tell me if its working in wc mode at least?
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: ATO code is not working properly.

Post by Sacohen »

I'm not sure what WC mode is going to do. When the pumps shut off a portion of the tank is going to back siphon into the sump and raise the water level.

Maybe I'm missing something?

The only way to see if the ATO is re-enabling 5 min after the water exchange ends would be for me to actually take some water out of the tank and lower the level in the sump.

The WC mode that I had asked for a while back was for when I do a WC and I did not put the right amount of SW back into the tank, I didn't want the ATO to start putting fresh water in the tank.

I don't think the ATO is re-enabling. The portal & phone are showing. 33% and the pump has not kicked in.
Post Reply