Reversing the ATO code

Do you have a question on how to do something.
Ask in here.
Post Reply
alexwbush
Posts: 327
Joined: Tue Mar 22, 2011 12:45 am
Location: San Diego, CA

Reversing the ATO code

Post by alexwbush »

I want to reprogram my ATO program to work in a more logical way. I am using single ATO. I don't like how the switch is upside down with the wires in the water. Here is the function called in the main pde:

Code: Select all

ReefAngel.SingleATOHigh(Port1);
and the code that I think I need to modify in ReefAngel.cpp

Code: Select all

void ReefAngelClass::SingleATO(bool bLow, byte ATORelay, byte byteTimeout, byte byteHrInterval)
{
    // if switch is active, stop the pump because the resevoir is full
    // when the switch is not active, we need to turn on the relay to fill up resevoir
    bool bCanRun = true;
    static int iLastTop = 0;
    if ( byteHrInterval )
    {
        int iSafeTop = NumMins(hour(), minute()) - iLastTop;
        if ( iSafeTop < 0 )
        {
            iSafeTop += 1440;
        }
        if ( iSafeTop < (byteHrInterval * 60) )
        {
            bCanRun = false;
        }
    }
    ReefAngel_ATOClass *ato;
    if ( bLow )
    {
        ato = &LowATO;
    }
    else
    {
        ato = &HighATO;
    }
    unsigned long t = byteTimeout;
    t *= 1000;
    if ( ato->IsActive() )
    {
        iLastTop = NumMins(hour(), minute());
        ato->StopTopping();
        Relay.Off(ATORelay);
    }
    else if ( !ato->IsTopping() )
    {
        if ( bCanRun )
        {
            ato->Timer = millis();
            ato->StartTopping();
            Relay.On(ATORelay);
        }
    }
    if ( (millis() - ato->Timer > t) && ato->IsTopping() )
    {
        LED.On();
        Relay.Off(ATORelay);
    }
}
any insight?
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Reversing the ATO code

Post by rimai »

I'm pretty sure that if you are using the SingleATO function, it should be pointing down and not up.
Only if you are using the StandardATO is that you have they pointing to opposite sides.
Roberto.
binder
Posts: 2871
Joined: Fri Mar 18, 2011 6:20 pm
Location: Illinois
Contact:

Re: Reversing the ATO code

Post by binder »

rimai wrote:I'm pretty sure that if you are using the SingleATO function, it should be pointing down and not up.
Only if you are using the StandardATO is that you have they pointing to opposite sides.
I'm pretty sure you are correct too. The "IsActive" code means that when the float switch is touching the contacts on the same side of the wires. Which means that the wires will be up and out of the water. I do not have access to test and confirm this right now, but I believe it is correct.

curt
YuppiWanna
Posts: 29
Joined: Sun Apr 17, 2011 6:46 pm

Re: Reversing the ATO code

Post by YuppiWanna »

The thing with the floats that come with Reef Angel is they're not reversable right?
Image
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Reversing the ATO code

Post by rimai »

Not reversable, but you could always program it to work the way you want.
Roberto.
alexwbush
Posts: 327
Joined: Tue Mar 22, 2011 12:45 am
Location: San Diego, CA

Re: Reversing the ATO code

Post by alexwbush »

So the SingleATOHigh function is opposite of what I want. I just rewired my ATO switches how I want them. Both face down and are in series. I intend to have them plugged into to "high ATO". How can I modify the code to make this work correctly? I tested it and at rest (both touching the bottom in this picture) nothing turns on. When I put either one of them up the circuit is broken and the port will turn on.

At the rest (both touching bottom as in the picture), I want the port to turn on. If either switch is floating up out of rest mode, I want the port to turn off. I've always had my ATO wired this way. The lower floating (off rest) is the normal water level. If it drops down and the float rests on the bottom, top off activates. If the lower switch is stuck for some reason and doesn't float up, when the top off gets to the upper float it will turn off once that switch floats.

Image

Please help. I am pretty sure this is going to require some coding. I will be coding as I wait, but I don't think there is a prebuilt function for this setup... which is strange because I thought this is how 80% of reefers have their ATO's setup.

I am using the development libraries.
alexwbush
Posts: 327
Joined: Tue Mar 22, 2011 12:45 am
Location: San Diego, CA

Re: Reversing the ATO code

Post by alexwbush »

Woo! I am starting to get the hang of programming!

Here's what I did:

Code: Select all

if(ReefAngel.HighATO.IsActive())
    {
        ReefAngel.Relay.On(Port1);
        ReefAngel.Relay.On(Box1_Port6);
    }
if(ReefAngel.HighATO.IsActive()==false)
    {
        ReefAngel.Relay.Off(Port1);
        ReefAngel.Relay.Off(Box1_Port6);
    }
Note: Box1_Port6 is for my water change system.

I'll be working on the automated water change over the next few weeks! Roberto, I'll email you for my other items.
astralmind
Posts: 99
Joined: Fri Apr 01, 2011 10:53 am

Re: Reversing the ATO code

Post by astralmind »

alexwbush wrote: At the rest (both touching bottom as in the picture), I want the port to turn on. If either switch is floating up out of rest mode, I want the port to turn off. I've always had my ATO wired this way. The lower floating (off rest) is the normal water level. If it drops down and the float rests on the bottom, top off activates. If the lower switch is stuck for some reason and doesn't float up, when the top off gets to the upper float it will turn off once that switch floats.

Please help. I am pretty sure this is going to require some coding. I will be coding as I wait, but I don't think there is a prebuilt function for this setup... which is strange because I thought this is how 80% of reefers have their ATO's setup.

I am using the development libraries.
Wait, I'm confused. What you are describing is how all ATO system I know of behave.

Main switch:

Triggers ATO pump when the water level goes low enough for the switch to close (ie, the ring part stops floating and touches the bottom making contact).

Secondary switch:

As a safety, if the other switch remains stuck in closed position, the high switch shutsdown the ATO if the water level reaches it (ie, the ring part starts floating, cutting contact).

All in all both switches behave identically, one is just a redundant safety.

I was under the impression that SingleATO took care of that as opposit to the standardATO function ? Esle, why would there be 2 functions that serve the exact same purpose?

That being said I just generated some code using singleATO (high and low) and it does appear to completely inversed.

Interval is how long it takes before the function can be activated again and timeout is the max amount of time the function will run regardless of the switch state correct ?

Some help on how to solve this would be immensly appreciated.

Thanks!
astralmind
Posts: 99
Joined: Fri Apr 01, 2011 10:53 am

Re: Reversing the ATO code

Post by astralmind »

Well, I had a look at both classes (Single and Standard) and thought it would be very simple to convert the StandardATO into what I (and I believe a few others) were looking for. Nothing spectacular and certainly not 100% safe so before you go on using this lets wait for Roberto or Curt who could validate it or certainly make it better.

For this to work you need to use the StandardATO function and modify it in ReefAngel.cpp (bad because it will be over written each time a new library update is published). Replace your StandardATO class with this one:

Code: Select all

void ReefAngelClass::StandardATO(byte ATORelay, int ATOTimeout)
{
    // Input:  Relay port and timeout value (max number of seconds that ATO pump is allowed to run)
	unsigned long TempTimeout = ATOTimeout;
	TempTimeout *= 1000;

	/*
	Is the low switch active (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 ( LowATO.IsActive() && ( !LowATO.IsTopping())&& HighATO.IsActive() )
    {
        LowATO.Timer = millis();
        LowATO.StartTopping();
        Relay.On(ATORelay);
    }
      
    /*
    Removed HighATO stop condition and replaced it with this statement. If one of the
    2 switches is NOT active while the Top off is ongoing, stop top off
    */

    if ( ((!LowATO.IsActive()) || !HighATO.IsActive()) && LowATO.IsTopping())
    {
		LowATO.StopTopping();  // stop the low ato timer
		Relay.Off(ATORelay);
    }

    /*
    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 contniously running.
    */
	if ( (millis()-LowATO.Timer > TempTimeout) && LowATO.IsTopping() )
	{
		LED.On();
		Relay.Off(ATORelay);
	}
}
All that was changed is the stop condition which instead of waiting for the HighATO to be triggered (upside down) simply checks if one or both switches aren't active anymore. The only disavantage (besides it residing in the core code) is that you can't set an interval when using StandardATO.


What do you guys think ? Anyways to do this in a standard PDE without butchering the original code ?
alexwbush
Posts: 327
Joined: Tue Mar 22, 2011 12:45 am
Location: San Diego, CA

Re: Reversing the ATO code

Post by alexwbush »

Initially I tried to modify the ReefAngel.cpp code to work with single ATO the way I have it build (see picture above) and I couldn't get it to work correctly. Then I was told that the code is designed such that the code was built to have the float switches upside down.

I ended up coding the way I posted above and it's worked great. I don't need the timer since I have the second float switch to catch a problem and having the timer may hurt you if you're away from home and can't reset it without doing so at the source. The only thing that could go wrong with my setup/code is if your sump were leaking or your skimmer went crazy and wet skimmed (which mine did), but even then if can only fill as much as the ATO has, which for me is 5 gal. I left my setup for a week and just recently adjusted the skimmer (big mistake) and it ended up skimming almost 5 gal out which was replaced by RO water. It lowered the salinity significantly and I was a bit worried while I was away. A salinity probe would have let me know this while I was gone (hint, hint Roberto), but it seems everything survived.
astralmind
Posts: 99
Joined: Fri Apr 01, 2011 10:53 am

Re: Reversing the ATO code

Post by astralmind »

alexwbush wrote:Initially I tried to modify the ReefAngel.cpp code to work with single ATO the way I have it build (see picture above) and I couldn't get it to work correctly. Then I was told that the code is designed such that the code was built to have the float switches upside down.

I ended up coding the way I posted above and it's worked great. I don't need the timer since I have the second float switch to catch a problem and having the timer may hurt you if you're away from home and can't reset it without doing so at the source. The only thing that could go wrong with my setup/code is if your sump were leaking or your skimmer went crazy and wet skimmed (which mine did), but even then if can only fill as much as the ATO has, which for me is 5 gal. I left my setup for a week and just recently adjusted the skimmer (big mistake) and it ended up skimming almost 5 gal out which was replaced by RO water. It lowered the salinity significantly and I was a bit worried while I was away. A salinity probe would have let me know this while I was gone (hint, hint Roberto), but it seems everything survived.
Ha yes a salinity probe will surely be a welcomed addition!

So I saw your code for the highATO which is very straight forward but how did you take care of the primary switch (low ATO) ?

What did you mean by having to reset the timer ? hmmm so the default is set to operate for 60 seconds and then stop regardless of the switch state. Do that mean that it won't restart again on its own ever ? That must have been the purpose of the Interval function, act as some kind of a reset option?.
binder
Posts: 2871
Joined: Fri Mar 18, 2011 6:20 pm
Location: Illinois
Contact:

Re: Reversing the ATO code

Post by binder »

astralmind wrote: Wait, I'm confused. What you are describing is how all ATO system I know of behave.

Main switch:

Triggers ATO pump when the water level goes low enough for the switch to close (ie, the ring part stops floating and touches the bottom making contact).

Secondary switch:

As a safety, if the other switch remains stuck in closed position, the high switch shutsdown the ATO if the water level reaches it (ie, the ring part starts floating, cutting contact).

All in all both switches behave identically, one is just a redundant safety.

I was under the impression that SingleATO took care of that as opposit to the standardATO function ? Esle, why would there be 2 functions that serve the exact same purpose?

That being said I just generated some code using singleATO (high and low) and it does appear to completely inversed.

Interval is how long it takes before the function can be activated again and timeout is the max amount of time the function will run regardless of the switch state correct ?
There seems to be some confusion about what is considered floating or not floating and what is considered active or not active. It's not just the people commenting here, it's just in general.
IsActive - Means the float is not touching the end with both wires coming out of it. So when the code says "ato->IsActive()" that means that the float is not touching the end with the wires.

With this being said, here is the way the StandardATO function works (it may be listed above but I'm re-listing it because of the discussion).
  • High switch mounted with wires at the bottom
  • Low switch mounted with the wires at the top
  • When water level lowers all the way to cause the low switch to be active (float is touching the opposite end with the 2 wires coming out of it), the ATO pump is turned on.
  • The ATO pump runs until the water level raises the low switch up from making contact, continues to raise the water level until the high switch is active (float touching the opposite end of the 2 wires coming out of it). The ATO pump shuts off when the high switch is active OR if the ATO Timeout value is exceeded. The timeout prevents the pump from running too long in case the reservoir runs dry or something else happens.
  • Water then evaporates out of the tank and lowers until the low switch is active.
  • Repeat process
The SingleATO function works with an individual switch only. So there is no failsafe built in. The only failsafe is the timeout value.
  • Switch mounted with 2 wires at bottom
  • Water level with the float at the top is the starting point.
  • When the water level drops, the float is no longer floating or active, so the ATO pump turns on.
  • It pumps in water until the float is active (touching the top end which is opposite the 2 wires) OR until the timeout value has exceeded. Then the pump shuts off.
  • The hour interval just means that the ATO pump can only be activated once every X (specified) hours. This is to prevent it from activating too many times. You don't have to specify this if you don't want to. You can safely put in 0 and the ATO pump will activate as often as it needs.
  • Repeat process
That should help clarify the 2 scenarios or sets of functions.

Yes, you are correct. Interval is the max time that the function can be activated again. Just pass in 0 to disable this check (like I stated above). Timeout is the max time that the pump will run during the current activation before the pump is shutoff. If this value is exceeded, then you either a) set it too short b) the reservoir is dry or c) the pump has failed/died/whatever and the switches will not tell the pump to stop. You will most likely not be triggering the activation again until the problem is fixed.

If you want to use the single ato functions and use the high switch as a failsafe, then you will have to look at the previous post by alex about how he coded is failsafe high switch into his PDE file. Here is his code:
I tweaked it to be an else statement because if it's active you do one thing and otherwise you do something else. It just looks better and there are less logical checks.

Code: Select all

if(ReefAngel.HighATO.IsActive())
    {
        ReefAngel.Relay.Off(Port1);
        ReefAngel.Relay.Off(Box1_Port6);
    }
else
    {
        ReefAngel.Relay.On(Port1);
        ReefAngel.Relay.On(Box1_Port6);
    }
This implies having the wires underwater (at the bottom).

Hope this helps.

curt
alexwbush
Posts: 327
Joined: Tue Mar 22, 2011 12:45 am
Location: San Diego, CA

Re: Reversing the ATO code

Post by alexwbush »

Thanks for simplifying my code curt. That makes sense. I'm a little rusty on my programming.
astralmind wrote:Ha yes a salinity probe will surely be a welcomed addition!

So I saw your code for the highATO which is very straight forward but how did you take care of the primary switch (low ATO) ?

What did you mean by having to reset the timer ? hmmm so the default is set to operate for 60 seconds and then stop regardless of the switch state. Do that mean that it won't restart again on its own ever ? That must have been the purpose of the Interval function, act as some kind of a reset option?.
I have my switches wired in series and plugged into the highATO receptical. That frees up my lowATO which I use to control my skimmer. My skimmer skims into a 2.5 or 5 gal bucket (depending on if I am out of town or not) and the skimmer will turn off if it fills the container... all part of my future auto water change setup and to keep my skimmer from going too crazy (which it already has one or two times).
astralmind
Posts: 99
Joined: Fri Apr 01, 2011 10:53 am

Re: Reversing the ATO code

Post by astralmind »

Thank you Curt for your detailed and very clear explanation aswell as Alex for your piece of code.

I will be using both low and high for now, with both switches in the upright position (wires upward). Whenever a switch floats, the port should be off since it means water as reached the proper level (low) or exceeded it and reached the second safety switch (high).

So in the end, if I get this right, this simple code in my PDE would do it:

Code: Select all

    if(ReefAngel.HighATO.IsActive() && ReefAngel.LowATO.IsActive())
    {
        ReefAngel.Relay.On(Port1);
    }
else
    {
        ReefAngel.Relay.Off(Port1);
    }

I've just uploaded the code and it seems to work as intended. That being said (and it could be just me who's way too tired to look be looking at this ;) ), it would mean that the IsActive state defines a switch that is not floating. With the above piece of code I could only get Port1 to turn on when both switches were hanging from their wires in an empty bin - exactly what I wanted.
binder
Posts: 2871
Joined: Fri Mar 18, 2011 6:20 pm
Location: Illinois
Contact:

Re: Reversing the ATO code

Post by binder »

astralmind wrote: So in the end, if I get this right, this simple code in my PDE would do it:

Code: Select all

    if(ReefAngel.HighATO.IsActive() && ReefAngel.LowATO.IsActive())
    {
        ReefAngel.Relay.On(Port1);
    }
else
    {
        ReefAngel.Relay.Off(Port1);
    }

I've just uploaded the code and it seems to work as intended. That being said (and it could be just me who's way too tired to look be looking at this ;) ), it would mean that the IsActive state defines a switch that is not floating. With the above piece of code I could only get Port1 to turn on when both switches were hanging from their wires in an empty bin - exactly what I wanted.
One comment I have is about the redundancy. If the bottom switch fails and never activates for whatever reason, then using the Low and High IsActive together will FAIL. That logic check will only be true when BOTH switches are active and if the low switch isn't working that will never happen. So you don't want your failsafe to use both switches, you want it to ONLY use your high switch.

It sounds like you want the water level to be at the low switch with the high one as a backup. So going back to your initial request, here would be some logic for you: (This will assume both switches are wired with their wires at the top)

Code: Select all

void ATOFailSafe(byte port)
{
	// Check for the low switch
	/*
	If the Low switch is active, meaning the float is opposite the end with the two wires, 
        we are empty so we should turn on the pump.  Otherwise, we are full, so turn off the port.
	*/
	if ( ReefAngel.LowATO.IsActive() )
	{
		ReefAngel.LowATO.StartTopping();
		ReefAngel.Relay.On(port);
	}
	else
	{
		ReefAngel.LowATO.StopTopping();
		ReefAngel.Relay.Off(port);
	}

	if ( ReefAngel.LowATO.IsTopping() && ! ReefAngel.HighATO.IsActive() )
	{
		// We have a problem
		/*
		The pump is running and topping but the low switch isn't shutting off the port.
		We must shutoff the port ourself.
		*/
		ReefAngel.Relay.Off(port);
		// Trigger some sort of alert, maybe an email or text message

		/*
		We did not indicate that the port is not topping anymore, we could do that manually
		OR we could not do it and replace the switch and have the controller do it for us.
		It's completely up to the user.
		At this point, it shouldn't matter because there is a problem with the switch and that 
		needs to be addressed.
		*/

	}
}
You can just copy and paste this function into your PDE file. Then inside your loop function, you can call it like this:

Code: Select all

void loop()
{
  // other functions
  ATOFailSafe(Port1);
}
This should handle your failsafe redundancy.

NOTE: This code does not use the timeouts at all and it does not use the hour interval. You would use this function instead of using the SingleATO or StandardATO functions.

Edited to indicate proper functionality with both wires at the top (coming out of the water) which is the reverse of how the SingleATO function works. SingleATO was based off of the high switch mounting/positioning from the StandardATO function.


curt
astralmind
Posts: 99
Joined: Fri Apr 01, 2011 10:53 am

Re: Reversing the ATO code

Post by astralmind »

Once again, thank you very much for all your time and patience Curt, appreciated. I'll be sure to try your code as soon as I get home.
binder wrote:

Code: Select all

if(ReefAngel.HighATO.IsActive() && ReefAngel.LowATO.IsActive())
    {
        ReefAngel.Relay.On(Port1);
    }
else
    {
        ReefAngel.Relay.Off(Port1);
    }

If both switches are mounted with their wires upward, then that code will not work properly. IsActive state defines a switch that IS floating (touching the end with the wires). So in your code you listed, when BOTH floats are up (touching the ends with the wires), you are turning on your pump and shutting it off when they are down. You have the logic backwards. It should be:
This is were things get extremely odd. Your instructions were perfectly clear in that regard but unless there is an hardware issue here my setup is indeed working backward. The IsActive state (turn port on) gets triggered when the float switch does not float (ie hangs at the bottom of the switch). If I have both switch in this position, the port is ON:
Image

as soon as one of the switches starts to float (even lifted a tiny bit), the current is shut off. I tested this numerous time with a lamp and it worked as described (also properly reflected on the RA screen).

Are my float switches "inversed" or am I simply insane ? :lol:
binder
Posts: 2871
Joined: Fri Mar 18, 2011 6:20 pm
Location: Illinois
Contact:

Re: Reversing the ATO code

Post by binder »

astralmind wrote: This is were things get extremely odd. Your instructions were perfectly clear in that regard but unless there is an hardware issue here my setup is indeed working backward. The IsActive state (turn port on) gets triggered when the float switch does not float (ie hangs at the bottom of the switch). If I have both switch in this position, the port is ON:
Image

as soon as one of the switches starts to float, the current is shut off. I tested this numerous time with a lamp and it worked as described (also properly reflected on the RA screen).

Are my float switches "inversed" or am I simply insane ? :lol:
No, you are not insane.

I was wrong. :ugeek: I emphasized this because I will be the first to admit when I'm wrong. I don't deal with the ATO code much and it's confusing.

I wrote a PDE file to test the status for me and confirm how the IsActive function works. Here is the PDE that I wrote to test it (also attached to this post):

Code: Select all

#include <ReefAngel_Features.h>
#include <ReefAngel_Globals.h>
#include <ReefAngel_Wifi.h>
#include <Wire.h>
#include <OneWire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <ReefAngel_EEPROM.h>
#include <ReefAngel_NokiaLCD.h>
#include <ReefAngel_ATO.h>
#include <ReefAngel_Joystick.h>
#include <ReefAngel_LED.h>
#include <ReefAngel_TempSensor.h>
#include <ReefAngel_Relay.h>
#include <ReefAngel_PWM.h>
#include <ReefAngel_Timer.h>
#include <ReefAngel_Memory.h>
#include <ReefAngel.h>

void setup()
{
    ReefAngel.Init();  //Initialize controller    
    ReefAngel.LCD.DrawText(DefaultFGColor, DefaultBGColor, 10, 10, "ATO Status Screen");
    ReefAngel.LCD.DrawText(DefaultFGColor, DefaultBGColor, 10, 40, "Low:");
    ReefAngel.LCD.DrawText(DefaultFGColor, DefaultBGColor, 10, 60, "High:");
}

byte lowcolor;
char lowstatus[10];
byte highcolor;
char highstatus[10];

void loop()
{
    if ( ReefAngel.LowATO.IsActive() )
    {
        lowcolor = COLOR_GREEN;
        strcpy(lowstatus, "ACTIVE");
    }
    else
    {
        lowcolor = COLOR_RED;
        strcpy(lowstatus, "INACTIVE");
    }
    
    if ( ReefAngel.HighATO.IsActive() )
    {
        highcolor = COLOR_GREEN;
        strcpy(highstatus, "ACTIVE");
    }
    else
    {
        highcolor = COLOR_RED;
        strcpy(highstatus, "INACTIVE");
    }
    
    ReefAngel.LCD.Clear(DefaultBGColor, 60, 40, 110, 48);
    ReefAngel.LCD.Clear(DefaultBGColor, 60, 60, 110, 68);
    ReefAngel.LCD.DrawText(lowcolor, DefaultBGColor, 60, 40, lowstatus);
    ReefAngel.LCD.DrawText(highcolor, DefaultBGColor, 60, 60, highstatus);
    delay(200);   
}
So, based on this, you are absolutely correct with your float switches. I will be going back through and editing my post to be correct so others won't be confused when they read it. Bear with me for the time being on that.

curt
Attachments
ATOStatusCheck.pde
ATO Status Check PDE
(1.57 KiB) Downloaded 505 times
astralmind
Posts: 99
Joined: Fri Apr 01, 2011 10:53 am

Re: Reversing the ATO code

Post by astralmind »

No worries Curt, I'm just happy that I got my sanity back :)

So in the end, the code I had written will be ok and will let me use timeouts, correct ?
binder
Posts: 2871
Joined: Fri Mar 18, 2011 6:20 pm
Location: Illinois
Contact:

Re: Reversing the ATO code

Post by binder »

astralmind wrote:No worries Curt, I'm just happy that I got my sanity back :)
It makes me lose my sanity too at times. hahaha
astralmind wrote:So in the end, the code I had written will be ok and will let me use timeouts, correct ?
The code you wrote would work but it wouldn't have a redundancy check like I mentioned a few posts ago. I have updated my code in the post to be correct now. It still does not have the timeouts.
So your code and my code does not incorporate the timeouts.

I'm honestly seriously considering changing the SingleATO function to have the float switches be mounted like the low switch in the StandardATO function (with the wires at the top). This would solve a lot of the confusion with everybody (myself included).

curt
astralmind
Posts: 99
Joined: Fri Apr 01, 2011 10:53 am

Re: Reversing the ATO code

Post by astralmind »

binder wrote:
astralmind wrote:So in the end, the code I had written will be ok and will let me use timeouts, correct ?
The code you wrote would work but it wouldn't have a redundancy check like I mentioned a few posts ago. I have updated my code in the post to be correct now. It still does not have the timeouts.
So your code and my code does not incorporate the timeouts.

I'm honestly seriously considering changing the SingleATO function to have the float switches be mounted like the low switch in the StandardATO function (with the wires at the top). This would solve a lot of the confusion with everybody (myself included).

curt
Your code definitly makes sens to me however, I still don't understand why mine would not work as a failsafe considering that we now know for sure that the IsActive state is when the water level drops. Since I am using and "AND" argument, the port will not be triggered ON unless both switches are in a IsActive state.

If the low switch was defective (ie stuck in an isActive state, not rising up with the water level), the water level would eventually reach the High switch and trip it, making it float and breaking the if condition, stopping the top off.

The only potential issues I see with this is having either the High or low switch broken and stuck in a floating state, that would stop the ATO from ever kicking in. However this same issue would also happen with your code as far as I understand. With both piece of codes the risks are of "never topping off" VS overflowing which is probably less of an issue.

In the end I'm asking because the memory on the RA seems to be very limited and if we can save some bytes than, lets do it :) Actually this is another concern all together but with my current extremely lite PDE (only WiFi and Temp checked in RAgen) and no addtionnal functions, I'm already pushing the limit.
alexwbush
Posts: 327
Joined: Tue Mar 22, 2011 12:45 am
Location: San Diego, CA

Re: Reversing the ATO code

Post by alexwbush »

I've been saying these switches were coded backwards for a while, but I think people thought I was that crazy old man in the village :lol:
astralmind
Posts: 99
Joined: Fri Apr 01, 2011 10:53 am

Re: Reversing the ATO code

Post by astralmind »

alexwbush wrote:I've been saying these switches were coded backwards for a while, but I think people thought I was that crazy old man in the village :lol:
make it 2 crazy old men in the village hehe :)

Having a great time learning about the code structure on this controller. I must say that the challenge is well worth the effort. I read through the Apex's 150 pages manual and found the "language" to be so restrictive and unclear at times.

Reef Angel sure rocks and the community behind it is a critical contributing factor. 8-)
chase
Posts: 101
Joined: Fri Sep 16, 2011 8:26 am

Re: Reversing the ATO code

Post by chase »

binder wrote: It sounds like you want the water level to be at the low switch with the high one as a backup. So going back to your initial request, here would be some logic for you: (This will assume both switches are wired with their wires at the top)

Code: Select all

void ATOFailSafe(byte port)
{
	// Check for the low switch
	/*
	If the Low switch is active, meaning the float is opposite the end with the two wires, 
        we are empty so we should turn on the pump.  Otherwise, we are full, so turn off the port.
	*/
	if ( ReefAngel.LowATO.IsActive() )
	{
		ReefAngel.LowATO.StartTopping();
		ReefAngel.Relay.On(port);
	}
	else
	{
		ReefAngel.LowATO.StopTopping();
		ReefAngel.Relay.Off(port);
	}

	if ( ReefAngel.LowATO.IsTopping() && ! ReefAngel.HighATO.IsActive() )
	{
		// We have a problem
		/*
		The pump is running and topping but the low switch isn't shutting off the port.
		We must shutoff the port ourself.
		*/
		ReefAngel.Relay.Off(port);
		// Trigger some sort of alert, maybe an email or text message

		/*
		We did not indicate that the port is not topping anymore, we could do that manually
		OR we could not do it and replace the switch and have the controller do it for us.
		It's completely up to the user.
		At this point, it shouldn't matter because there is a problem with the switch and that 
		needs to be addressed.
		*/

	}
}
You can just copy and paste this function into your PDE file. Then inside your loop function, you can call it like this:

Code: Select all

void loop()
{
  // other functions
  ATOFailSafe(Port1);
}
This should handle your failsafe redundancy.

NOTE: This code does not use the timeouts at all and it does not use the hour interval. You would use this function instead of using the SingleATO or StandardATO functions.

Edited to indicate proper functionality with both wires at the top (coming out of the water) which is the reverse of how the SingleATO function works. SingleATO was based off of the high switch mounting/positioning from the StandardATO function.


curt
Trying to get this working but I'm getting the following error when compiling:
(#define Refugium 8 is highlighted yellow)
default_ragen_pde_all_ato_test:42: error: expected ',' or '...' before numeric constant
default_ragen_pde_all_ato_test:45: error: expected initializer before 'void'

Here's my PDE:

Code: Select all

// Autogenerated file by RAGen (v1.0.4.92), (09/08/2011 09:54)
// default_ragen_pde_all_ato_test.pde
//
// This version designed for v0.8.5 Beta 12 or later

/* The following features are enabled for this PDE File: 
#define DisplayImages
#define WavemakerSetup
#define DateTimeSetup
#define VersionMenu
#define DirectTempSensor
#define DisplayLEDPWM
#define StandardLightSetup
*/

#include <ReefAngel_Features.h>
#include <ReefAngel_Globals.h>
#include <ReefAngel_Wifi.h>
#include <Wire.h>
#include <OneWire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <ReefAngel_EEPROM.h>
#include <ReefAngel_NokiaLCD.h>
#include <ReefAngel_ATO.h>
#include <ReefAngel_Joystick.h>
#include <ReefAngel_LED.h>
#include <ReefAngel_TempSensor.h>
#include <ReefAngel_Relay.h>
#include <ReefAngel_PWM.h>
#include <ReefAngel_Timer.h>
#include <ReefAngel_Memory.h>
#include <ReefAngel.h>

#define Daylight            1
#define ATO                 2
//#define Chiller             2
#define Heater              3
#define Return              4
#define WavemakerL          5
#define WavemakerR          6
#define LED                 7
#define Refugium            8

void setup()
void ATOFailSafe(byte ATO) //changed port to ATO
{
   // Check for the low switch
   /*
   If the Low switch is active, meaning the float is opposite the end with the two wires,
        we are empty so we should turn on the pump.  Otherwise, we are full, so turn off the port.
   */
   if ( ReefAngel.LowATO.IsActive() )
   {
      ReefAngel.LowATO.StartTopping();
      ReefAngel.Relay.On(ATO);
   }
   else
   {
      ReefAngel.LowATO.StopTopping();
      ReefAngel.Relay.Off(ATO);
   }

   if ( ReefAngel.LowATO.IsTopping() && ! ReefAngel.HighATO.IsActive() )
   {
      // We have a problem
      /*
      The pump is running and topping but the low switch isn't shutting off the port.
      We must shutoff the port ourself.
      */
      ReefAngel.Relay.Off(ATO);
      // Trigger some sort of alert, maybe an email or text message

      /*
      We did not indicate that the port is not topping anymore, we could do that manually
      OR we could not do it and replace the switch and have the controller do it for us.
      It's completely up to the user.
      At this point, it shouldn't matter because there is a problem with the switch and that
      needs to be addressed.
      */
 }

{
   randomSeed(analogRead(0)); //wm stuff  
    ReefAngel.Init();  //Initialize controller   
    ReefAngel.FeedingModePorts = B00001000;
    ReefAngel.WaterChangePorts = B00000000;
    ReefAngel.OverheatShutoffPorts = B00000101;
    ReefAngel.LightsOnPorts = B00000001;
    // Ports that are always on
    ReefAngel.Relay.On(Return); //port 4
   //wm stuff
    ReefAngel.Timer[1].SetInterval(random(15,35));
    ReefAngel.Timer[1].Start();  
    ReefAngel.Relay.On(WavemakerL);
}

}



void loop()
{
    ReefAngel.ShowInterface();
    ReefAngel.StandardGUI(); //web connection
//    ReefAngel.StandardFan(Chiller,775,783); Removed for ATO function
    ReefAngel.StandardHeater(Heater,768,771);
    ReefAngel.StandardLights(Daylight,9,0,19,30);  //Daylight schedule 9:00am - 7:30pm
    ReefAngel.StandardLights(Refugium,21,0,9,0);  //Refugium schedule 9:00pm - 9:00am
    ReefAngel.StandardLights(LED,8,30,22,0);  //LED schedule 8:30am - 10:00pm   
    ATOFailSafe(ATO); //ATO Stuff                       
    //Wavemaker stuff
    if ( ReefAngel.Timer[1].IsTriggered() )
      {
        ReefAngel.Timer[1].SetInterval(random(15,30));
        ReefAngel.Timer[1].Start();
        ReefAngel.Relay.Toggle(WavemakerL); //port 5
        ReefAngel.Relay.Toggle(WavemakerR); //port 6
       }
/*    Old ATO stuff
     if(ReefAngel.LowATO.IsActive())
        {
            ReefAngel.Relay.On(ATO); //port 7
        }
        else
        {
            ReefAngel.Relay.Off(ATO);
        }    
*/
}
Thanks!!
Last edited by chase on Fri Oct 07, 2011 10:07 am, edited 1 time in total.
Image
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Reversing the ATO code

Post by rimai »

You can't use:

Code: Select all

#define LED                 7
It's a reserved word for a the LED Class :( Sorry.
Choose a different name
Roberto.
chase
Posts: 101
Joined: Fri Sep 16, 2011 8:26 am

Re: Reversing the ATO code

Post by chase »

rimai wrote:You can't use:

Code: Select all

#define LED                 7
It's a reserved word for a the LED Class :( Sorry.
Choose a different name
Hmm, changed LED to Moonlight and I still get the same error(s). It compiles without the ATO code binder suggested (including the define LED reference) which is what I've been running for a while now with no issues.
Image
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Reversing the ATO code

Post by rimai »

Ahhh...
After closer look, I had to change some stuff around.
Try this:

Code: Select all

// Autogenerated file by RAGen (v1.0.4.92), (09/08/2011 09:54)
// ATO_TEST.pde
//
// This version designed for v0.8.5 Beta 12 or later

/* The following features are enabled for this PDE File: 
#define DisplayImages
#define WavemakerSetup
#define DateTimeSetup
#define VersionMenu
#define DirectTempSensor
#define DisplayLEDPWM
#define StandardLightSetup
*/

#include <ReefAngel_Features.h>
#include <ReefAngel_Globals.h>
#include <ReefAngel_Wifi.h>
#include <Wire.h>
#include <OneWire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <ReefAngel_EEPROM.h>
#include <ReefAngel_NokiaLCD.h>
#include <ReefAngel_ATO.h>
#include <ReefAngel_Joystick.h>
#include <ReefAngel_LED.h>
#include <ReefAngel_TempSensor.h>
#include <ReefAngel_Relay.h>
#include <ReefAngel_PWM.h>
#include <ReefAngel_Timer.h>
#include <ReefAngel_Memory.h>
#include <ReefAngel.h>

#define Daylight            1
#define AutoTopOff          2
//#define Chiller             2
#define Heater              3
#define Return              4
#define WavemakerL          5
#define WavemakerR          6
#define LED1                7
#define Refugium            8

void setup()
{
   randomSeed(analogRead(0)); //wm stuff  
    ReefAngel.Init();  //Initialize controller   
    ReefAngel.FeedingModePorts = B00001000;
    ReefAngel.WaterChangePorts = B00000000;
    ReefAngel.OverheatShutoffPorts = B00000101;
    ReefAngel.LightsOnPorts = B00000001;
    // Ports that are always on
    ReefAngel.Relay.On(Return); //port 4
   //wm stuff
    ReefAngel.Timer[1].SetInterval(random(15,35));
    ReefAngel.Timer[1].Start();  
    ReefAngel.Relay.On(WavemakerL);
}

void loop()
{
    ReefAngel.ShowInterface();
//    ReefAngel.StandardFan(Chiller,775,783); Removed for ATO function
    ReefAngel.StandardHeater(Heater,768,771);
    ReefAngel.StandardLights(Daylight,9,0,19,30);  //Daylight schedule 9:00am - 7:30pm
    ReefAngel.StandardLights(Refugium,21,0,9,0);  //Refugium schedule 9:00pm - 9:00am
    ReefAngel.StandardLights(LED1,8,30,22,0);  //LED schedule 8:30am - 10:00pm   
    ATOFailSafe(AutoTopOff); //ATO Stuff                       
    //Wavemaker stuff
    if ( ReefAngel.Timer[1].IsTriggered() )
      {
        ReefAngel.Timer[1].SetInterval(random(15,30));
        ReefAngel.Timer[1].Start();
        ReefAngel.Relay.Toggle(WavemakerL); //port 5
        ReefAngel.Relay.Toggle(WavemakerR); //port 6
       }
/*    Old ATO stuff
     if(ReefAngel.LowATO.IsActive())
        {
            ReefAngel.Relay.On(ATO); //port 7
        }
        else
        {
            ReefAngel.Relay.Off(ATO);
        }    
*/
}

void ATOFailSafe(byte ATO) //changed port to ATO
{
   // Check for the low switch
   /*
   If the Low switch is active, meaning the float is opposite the end with the two wires,
        we are empty so we should turn on the pump.  Otherwise, we are full, so turn off the port.
   */
   if ( ReefAngel.LowATO.IsActive() )
   {
      ReefAngel.LowATO.StartTopping();
      ReefAngel.Relay.On(ATO);
   }
   else
   {
      ReefAngel.LowATO.StopTopping();
      ReefAngel.Relay.Off(ATO);
   }

   if ( ReefAngel.LowATO.IsTopping() && ! ReefAngel.HighATO.IsActive() )
   {
      // We have a problem
      /*
      The pump is running and topping but the low switch isn't shutting off the port.
      We must shutoff the port ourself.
      */
      ReefAngel.Relay.Off(ATO);
      // Trigger some sort of alert, maybe an email or text message

      /*
      We did not indicate that the port is not topping anymore, we could do that manually
      OR we could not do it and replace the switch and have the controller do it for us.
      It's completely up to the user.
      At this point, it shouldn't matter because there is a problem with the switch and that
      needs to be addressed.
      */
  }
}
Roberto.
chase
Posts: 101
Joined: Fri Sep 16, 2011 8:26 am

Re: Reversing the ATO code

Post by chase »

Winner- TY much!! Gonna upload it now... :D
Image
Post Reply