RO/DI valve

Do you have a question on how to do something.
Ask in here.
Post Reply
Ismaclst
Posts: 250
Joined: Wed Jan 28, 2015 5:17 pm

RO/DI valve

Post by Ismaclst »

I bought a 12V solenoid to turn the water off and on to my RO unit. I will be using the water level expansion to tell it when to turn on. When the water reaches 1% in my ATO container, I want it to turn on port 5. Once it hits 90%, I would like for it to turn off port 5. This is using channel 1 of the water level expansion. I came up with a code but not sure if its the correct way to go about it.

Code: Select all

   
    if (ReefAngel.WaterLevel.GetLevel(1)>90)
    ReefAngel.Relay.Off(Port5);
   if (ReefAngel.WaterLevel.GetLevel(1)<1)
    ReefAngel.Relay.On(Port5);
Image
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: RO/DI valve

Post by lnevo »

Look at my function RefillATO in my INO. I'm doing exactly this but solved a few problems. I can probably strip it and make it easier to integrate for you.
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: RO/DI valve

Post by lnevo »

I have a virtual port I toggle to initiate it manually and if the water level is below the waterlevel ato memory location at 8pm I initiate the refill also. Once it's on I use the waterlevel ato function so I can still leverage the ATO timeout in addition. The RO line is also attached to a float valve so a few redundancies :)
Ismaclst
Posts: 250
Joined: Wed Jan 28, 2015 5:17 pm

Re: RO/DI valve

Post by Ismaclst »

I think I found it, but not sure what all of it means.

Code: Select all

// ATO Refill mode. Top off ATO reservoir until it's at 100%    
void RefillATO() {
  static boolean refillActive=false;
  static WiFiAlert refillAlert;
  byte level, prevRate;

  if (ReefAngel.Relay.Status(VO_EnableATO) || ReefAngel.Relay.Status(VO_Vacation)) {
    ReefAngel.Relay.Auto(VO_RefillATO); 
  }

  level=ReefAngel.WaterLevel.GetLevel();
  
  if (ReefAngel.Relay.Status(VO_RefillATO)) {
    if (level<100) {
      ReefAngel.Relay.On(Extension);
      refillActive=true;
    } else {
      ReefAngel.Relay.Auto(VO_RefillATO);
      refillAlert.Send("ATO+Reservoir+is+full.");
    }
  } else {
    if (refillActive) {
      prevRate=InternalMemory.read(Mem_B_LogPrevATO)-InternalMemory.read(Mem_B_LogATO);
      InternalMemory.write(Mem_B_LogPrevATO, level+prevRate);
      InternalMemory.write(Mem_B_LogATO, level+1);
      if (InternalMemory.read(Mem_B_MaintATO) > 0) // Reset last ATO counter 
        InternalMemory.write(Mem_B_MaintATO,0);

      ReefAngel.Relay.Off(Extension);
      refillActive=false;
    }
  }
Image
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: RO/DI valve

Post by lnevo »

I'll strip down some of the unneeded stuff and comment it up for you. It should help...

Oh also, your post was an older function. I've made some adjustments for this to work better.

Code: Select all

/* Set this to whatever port you want to use to trigger your refill. It could be an 
    unused port or a port on a non-existant box. If you use a non-existant box 
    you will end up with an extra relay box. If you don't want that we could modify 
    to use the same port as your solenoid valve. 
*/
#define VO_RefillATO Box2_Port1 

// Set this to the port your solenoid is on.
#define ROSolenoid Port5

void RefillATO() {
  static boolean refillActive=false; // Flag to determine if we've initiated the refill.
  static WiFiAlert refillAlert; // Object to send status updates
  byte level=ReefAngel.WaterLevel.GetLevel(); // Current level 
  byte lowLevel=InternalMemory.WaterLevelLow_read(); // Use InternalMemory locations - set this in the portal
  byte highLevel=InternalMemory.WaterLevelHigh_read(); // Use InternalMemory locations - set this in the portal
   
  // Every day at 8pm I'm going to check the water level. If it's lower than the low point, we'll trigger the refill. 
  // If not, we'll wait for the next day. If you want to change time, you can change 20 to whatever hour you want
  if (now()%SECS_PER_DAY==20*SECS_PER_HOUR && level<lowLevel) { 
      ReefAngel.Relay.Override(VO_RefillATO,1); // We turn on the refill port.
  }
  
  if (ReefAngel.Relay.Status(VO_RefillATO)) { // If the refill port is On. 
    if (level<=highLevel) { // And the level is less than where we want to be...
      
      // This is where we use the ATO function to refill the reservoir now. 
      ReefAngel.WaterLevelATO(ROSolenoid,InternalMemory.ATOExtendedTimeout_read(),highLevel-1,highLevel); 
      /* Since we've activated this mode once we've reached the lowLevel in memory,
      we can essentially ignore the ATO Low Level moving forward or until it times out.
      We only really care about the High Level at this point. It is as if we were using
      a SingleATO function. This also allows us to override the lowlevel when we want 
      to manually top off the reservoir. It also prevents a mis-read on the sensor from 
      causing the ATO to StopTopping() and wait again till it hits the lowlevel to restart. */
      
      if (!refillActive) // If this is our first time starting then send the message that we're starting.
        refillAlert.Send("ATO+Refill+is+starting.",true);
      refillActive=true; // We've started
    } else {
      ReefAngel.Relay.Auto(VO_RefillATO); // Disable the virtual port
      ReefAngel.Relay.Off(ROSolenoid); // Make sure the solenoid is off
      refillAlert.Send("ATO+Refill+is+complete.",true); // Refill is completed send a message.
    }
  } else {
    if (refillActive) { // The refill has ended
      ReefAngel.Relay.Off(ROSolenoid); // Ensure the solenoid is off
      refillActive=false; // Reset the refilling flag. 
    }
  }
}
If you don't want to use memory you can replace the InternalMemory calls to static numbers but these are standard locations that you can set in the ATO screen in the portal.
Ismaclst
Posts: 250
Joined: Wed Jan 28, 2015 5:17 pm

Re: RO/DI valve

Post by Ismaclst »

Thanks, I appreciate it. Yeah, I really don't want to use the memory in my code.
Image
Ismaclst
Posts: 250
Joined: Wed Jan 28, 2015 5:17 pm

Re: RO/DI valve

Post by Ismaclst »

I'm still pretty confused on how all of this works. How does it know that I'm using channel 3 for the ATO container to tell it to turn on port 5? Also, why does it check everyday to see if it's low or not? I just assumed that when it reached 1% that it would turn port 5 on and after it reached 90% it would turn off.
Image
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: RO/DI valve

Post by lnevo »

Oh you have the multiwater level sensor? that's an easy modification.

It checks every day at a certain time because I wanted to be home when it fills and make sure it's only for a certain duration. I also have another controller downstairs that does a membrane flush a few minutes before 8pm to make sure there is no stale water in the unit.

Anyway to set it to use Channel 3, we can just change the WaterLevelATO call to this:

Code: Select all

      ReefAngel.WaterLevelATO(3, ROSolenoid,InternalMemory.ATOExtendedTimeout_read(),highLevel-1,highLevel); 
If you want to remove the time restriction and keep the manual top off, then change this block

Code: Select all

  if (now()%SECS_PER_DAY==20*SECS_PER_HOUR && level<lowLevel) { 
      ReefAngel.Relay.Override(VO_RefillATO,1); // We turn on the refill port.
  }
to this

Code: Select all

  if (level<lowLevel) { 
      ReefAngel.Relay.Override(VO_RefillATO,1); // We turn on the refill port.
  }
If you want to remove the manual top off, then it may need a little more cleanup. But hopefully this answers your questions.
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: RO/DI valve

Post by lnevo »

Oh and you may want to consider starting at higher than 1. For one we look for things to happen when they are less than 1 which is 0 which you might also get if the sensor were to get disconnected. Also you may already take this into account, but if your level is that low when we kick in the ato, and let's say the RO was shutoff or something, you'd have less grace period to correct it.

At the end of the day, if you just wanted to be like the code you had above but give you the ATO timeout and work accordingly you could just use the WaterLevelATO function as we do within the code.

Code: Select all

ReefAngel.WaterLevelATO(3, ROSolenoid,3600,1,90); 
Sorry if I complicated the whole mess. I thought you would like having the additional functionality that I added :)
Ismaclst
Posts: 250
Joined: Wed Jan 28, 2015 5:17 pm

Re: RO/DI valve

Post by Ismaclst »

No problem. I appreciate the help you have given me. I will post some more pics on reef hackers group once I'm finished plumbing my mixing station.
Image
Ismaclst
Posts: 250
Joined: Wed Jan 28, 2015 5:17 pm

Re: RO/DI valve

Post by Ismaclst »

lnevo wrote:Oh and you may want to consider starting at higher than 1. For one we look for things to happen when they are less than 1 which is 0 which you might also get if the sensor were to get disconnected. Also you may already take this into account, but if your level is that low when we kick in the ato, and let's say the RO was shutoff or something, you'd have less grace period to correct it.

At the end of the day, if you just wanted to be like the code you had above but give you the ATO timeout and work accordingly you could just use the WaterLevelATO function as we do within the code.

Code: Select all

ReefAngel.WaterLevelATO(3, ROSolenoid,3600,1,90); 
Sorry if I complicated the whole mess. I thought you would like having the additional functionality that I added :)
That code would work, just not sure how long it would take to refill my 10 gallon ATO container. I see what you are saying about having a grace period so I won't run out of water before it has a chance to refill. The pipe doesn't go all the way to the bottom of the container. So once it hit's 1%, I still have about 3 inches of water left, so hopefully that will give it enough time for the water to refill.
Image
Ismaclst
Posts: 250
Joined: Wed Jan 28, 2015 5:17 pm

Re: RO/DI valve

Post by Ismaclst »

I think my code is not quite right. I wanted the RO/DI valve to turn on when it was lower than 1% and to stay on until it reached 87%. Once it hit 87% it was suppose to stay off until it was lower than 1% again. I turned the port an manually and left it for awhile. When I went to put the port back to auto, which would have turned it off, it turned it back on even though my level was around 70%. Here is the code I'm using for it:

Code: Select all

 if (ReefAngel.WaterLevel.GetLevel(3)>87) //ATO Reservoir
    ReefAngel.Relay.Off(Port5);
  if (ReefAngel.WaterLevel.GetLevel(3)<1)
    ReefAngel.Relay.On(Port5);
Image
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: RO/DI valve

Post by rimai »

70% is still below 87%.
It will only turn off when it is over 87%
Roberto.
Ismaclst
Posts: 250
Joined: Wed Jan 28, 2015 5:17 pm

Re: RO/DI valve

Post by Ismaclst »

I know. It worked like it should the first time it ran. The problem is that, that container that has the water level sensor was not in the process of refilling. I was trying to fill another container, so that's why I manually turned the port on. When I went to turn it back to auto, it automatically turn the port on instead of off.
Image
Ismaclst
Posts: 250
Joined: Wed Jan 28, 2015 5:17 pm

Re: RO/DI valve

Post by Ismaclst »

Ok, I manually filled up my ato reservoir so it would be past 87%. The port did turn off. How could I change my code so I could manually turn on the port and it won't restart the process of refilling?
Image
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: RO/DI valve

Post by rimai »

Your code will only turn on/off when level is above 87 or below 1.
Anything in between is last state.
If you override on, it will stay on. If you override off, it will stay off.
Roberto.
Ismaclst
Posts: 250
Joined: Wed Jan 28, 2015 5:17 pm

Re: RO/DI valve

Post by Ismaclst »

What can I change in my code to allow me to toggle the port to manual without resetting the refilling process
Image
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: RO/DI valve

Post by lnevo »

Code: Select all

  if (level<lowLevel) { 
      ReefAngel.Relay.Override(VO_RefillATO,1); // We turn on the refill port.
  }
I believe you have to turn this port back to auto otherwise you've triggered refill mode and it will stay on until the level is reached.

I think it might be worth a checkpoint to post your full code.
Ismaclst
Posts: 250
Joined: Wed Jan 28, 2015 5:17 pm

Re: RO/DI valve

Post by Ismaclst »

Here is my full 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 <Tide.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 <PAR.h>
#include <ReefAngel.h>



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


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

Tide tide;

void setup()
{
  // This must be the first line
  ReefAngel.Init();  //Initialize controller
  ReefAngel.Use2014Screen();  // Let's use 2014 Screen
  ReefAngel.DDNS("Damien"); 
  ReefAngel.AddMultiChannelWaterLevelExpansion();  // Multi-Channel Water Level Expanion Module
  // Ports toggled in Feeding Mode
  ReefAngel.FeedingModePorts = Port1Bit | Port6Bit;
  // Ports toggled in Water Change Mode
  ReefAngel.WaterChangePorts = Port1Bit | Port2Bit | Port3Bit | Port4Bit | Port6Bit | Port7Bit | Port8Bit;
  // Ports toggled when Lights On / Off menu entry selected
  ReefAngel.LightsOnPorts = Port5Bit;
  // Ports turned off when Overheat temperature exceeded
  ReefAngel.OverheatShutoffPorts = Port3Bit;
  // Use T1 probe as temperature and overheat functions
  ReefAngel.TempProbe = T1_PROBE;
  ReefAngel.OverheatProbe = T1_PROBE;
  // Set the Overheat temperature setting
  InternalMemory.OverheatTemp_write( 800 );
  InternalMemory.WaterLevelMax_write(1800);        


  // Feeeding and Water Change mode speed


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

  tide.Init(55,10,30);
  tide.SetWaveLength(12+SECS_PER_HOUR);
  ////// Place additional initialization code below here


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

void loop()
{
  ReefAngel.StandardHeater( Port3,780,785 );
  ReefAngel.WaterLevelATO(4,Port4,240,28,31); 
  ReefAngel.Relay.Set(Port8, (now()%(6*SECS_PER_HOUR))<(30*SECS_PER_MIN));

  ////// Place your custom code below here

  if (ReefAngel.WaterLevel.GetLevel(1)<5) //Disable the port until overriden manually
    ReefAngel.Relay.Override(Port8,0);    //Saltwater Reservoir
  if (ReefAngel.WaterLevel.GetLevel(1)>80)   // Set port back to auto
    ReefAngel.Relay.Override(Port8,2); 

  if (ReefAngel.WaterLevel.GetLevel(2)>80) //Overflow
    ReefAngel.Relay.Off(Port1);
  else
    ReefAngel.Relay.On(Port1);

  if (ReefAngel.WaterLevel.GetLevel(3)>87) //ATO Reservoir
    ReefAngel.Relay.Off(Port5);
  if (ReefAngel.WaterLevel.GetLevel(3)<1)
    ReefAngel.Relay.On(Port5);

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

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



byte setMaxspect(byte minSpeed, byte maxSpeed, boolean PulseSync)
{
  int reverse_speed=0;
  int forward_speed=45;
  
   // swap between forward and reverse every X seconds 
   reverse_speed = ShortPulseMode(0,100,ReefAngel.DCPump.Duration*2,true); 
   if (reverse_speed == 100) {
     //
     // while we are going in reverse increase the speed by 10 
     forward_speed = ShortPulseMode(35+10, 60+10,ReefAngel.DCPump.Duration,true);
   } else {
     //
     // while we are going forward set speed to 25-40 to keep
     // from blowing corals off the rocks
     forward_speed = ShortPulseMode(35,70, ReefAngel.DCPump.Duration, true);
  }

  if (PulseSync) {
    return forward_speed;
  } else {
    return reverse_speed;
  }
}
Image
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: RO/DI valve

Post by lnevo »

I would make a small change here just to make sure it defaults to Off. Other than that the overrides should work as normal.

Code: Select all

  ReefAngel.Relay.Off(Port5); // Default to Off

  if (ReefAngel.WaterLevel.GetLevel(3)>87) //ATO Reservoir
    ReefAngel.Relay.Off(Port5);
  if (ReefAngel.WaterLevel.GetLevel(3)<1)
    ReefAngel.Relay.On(Port5);
It shouldn't be needed but just for some sanity. Test and let us know.
Ismaclst
Posts: 250
Joined: Wed Jan 28, 2015 5:17 pm

Re: RO/DI valve

Post by Ismaclst »

lnevo wrote:

Code: Select all

  if (level<lowLevel) { 
      ReefAngel.Relay.Override(VO_RefillATO,1); // We turn on the refill port.
  }
I believe you have to turn this port back to auto otherwise you've triggered refill mode and it will stay on until the level is reached.

I think it might be worth a checkpoint to post your full code.
When I added this part to my code I had a few errors. It said lowLevel, level and VO_RefillATO was not declared in the scope.
Image
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: RO/DI valve

Post by lnevo »

That makes no sense because that code is not in the post from 3/14 that I used...
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: RO/DI valve

Post by lnevo »

Looks like you were reading an old post.
Ismaclst
Posts: 250
Joined: Wed Jan 28, 2015 5:17 pm

Re: RO/DI valve

Post by Ismaclst »

Oh, sorry. I thought you wanted me to add both of them to my code. Sorry about that.
Image
Ismaclst
Posts: 250
Joined: Wed Jan 28, 2015 5:17 pm

Re: RO/DI valve

Post by Ismaclst »

Ok, it seems to be working fine now. Thanks for your help!
Image
Post Reply