Page 1 of 1

Custom Variables

Posted: Mon Sep 30, 2013 8:05 am
by ecam

Code: Select all

    void LogDosingPumps() {
      static time_t pumpTimer[numDPumps];
      static boolean pumpStatus[numDPumps];
      float rate;

      for (int i=0;i< numDPumps;i++) {
        if (ReefAngel.Relay.Status(pumpRelays[i])) {
          if (!pumpStatus[i]) {
            pumpTimer[i]=now()-pumpTimer[i]; // Pump was off, timer is now a time
            pumpStatus[i]=true;
          }
        } else {
          if (pumpStatus[i]) {
            pumpTimer[i]=now()-pumpTimer[i]; // Pump was on, timer is now a timer
            pumpStatus[i]=false;
       
            rate=(float)CalVol[i]/CalTime[i];

            // Report How much volume has been dosed per day.
            // Could make this in minutes... excercise for the reader..
            ReefAngel.CustomVar[2]=pumpTimer[0]*rate;
            ReefAngel.CustomVar[3]=pumpTimer[1]*rate; 
          }
        }
     
        // Clear timer at end of day
        if (now()%SECS_PER_DAY==SECS_PER_DAY-1) pumpTimer[i]=0;
      } 
    }
Using this code I've been watching my Custom variables on the portal. Field 1 and 3 havent changed from 1. So is this code working for the dosers? Is this a count that will tell me how many times the relay has triggered or how many MLs of buffers has been dosed. Just trying to understand what im looking for..

Thank you

Re: Custom Variables

Posted: Mon Sep 30, 2013 8:14 am
by lnevo
This code if i recall correctly logs the volume in ml. And then backs up that value from the previous day to the second set of variables.

Re: Custom Variables

Posted: Mon Sep 30, 2013 12:05 pm
by ecam
Current code

Code: Select all

    #include <RA_ATO.h>
    #include <RF.h>
    #include <ReefAngel_Features.h>
    #include <Globals.h>
    #include <RA_Wifi.h>
    #include <Wire.h>
    #include <OneWire.h>
    #include <Time.h>
    #include <DS1307RTC.h>fafa
    #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>fa
    #include <IO.h>
    #include <ORP.h>
    #include <PH.h>
    #include <WaterLevel.h>
    #include <ReefAngel.h>

    ////// Place global variable code below here
      byte myRFMode=0;
        byte myRFDuration=0;
        byte myRFSpeed=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.WaterChangePorts = Port1Bit | Port8Bit; // Turn off Ports 5 and 6 when Feeding Mode is activated
      ReefAngel.FeedingModePorts = Port1Bit | Port6Bit | Port8Bit; // Turn off Ports 1, 6, 7 and 8 when Water Change Mode is activated
      ReefAngel.LightsOnPorts = Port2Bit | Port3Bit | Port4Bit| Port5Bit;
      ReefAngel.OverheatShutoffPorts = Port2Bit |Port3Bit | Port4Bit | Port5Bit | Port7Bit; // Turn off Ports 3,
        ReefAngel.TempProbe = T3_PROBE;
        ReefAngel.OverheatProbe = T3_PROBE;
        // Set the Overheat temperature setting
        InternalMemory.OverheatTemp_write( 825 );




        // Ports that are always on
        ReefAngel.Relay.On( Port1 );
        ReefAngel.Relay.On( Box1_Port2 );  // Razor Led
        ReefAngel.Relay.On( Box1_Port4 ); // Sump Equipment - UV, Pump
        ReefAngel.Relay.On( Box1_Port5 ); // MP40s   
        ReefAngel.Relay.On( Box1_Port6 ); // JBJ
        ////// Place additional initialization code below here
       

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

    void loop()
    {
      //  Port1 Return pump...  on all the time!!!
          ReefAngel.Relay.Set( Port2, !ReefAngel.Relay.Status( Port4 ) ); //Refuge
      //  Port3 ...  not used
          ReefAngel.StandardLights( Port4,10,0,20,0 ); //ATI Actinic
          ReefAngel.StandardLights( Port5,11,0,19,0 );  //ATI Daylight
          ReefAngel.StandardLights( Port6,10,0,20,0 );  //ATI Fan
          ReefAngel.StandardHeater( Port7,778,790 ); //Heater
          ReefAngel.Relay.DelayedOn( Port8,2 ); //Skimmer
         
          //box 2
          ReefAngel.Relay.Off( Box1_Port1); // Lunar Hub Not used   Port #9
    //   Box1_Port2 Razor_LED (Sump)...  on all the time!!!      Port #10
          ReefAngel.Relay.Off( Box1_Port3); // Start with the relay off       Port #11
                  if (hour()>=5 && hour()<10) ReefAngel.Relay.On(Box1_Port3); // Moonlight Between 5-10am turn the relay on
                  if (hour()>=20 && hour()<=23) ReefAngel.Relay.On(Box1_Port3); // From 8pm-Midnight turn the relay on

    //   Box1_Port4 Ecotech MP_40 Pumps  on all the time!!!      Port #12
    //   Box1_Port5 Razor_LED (Sump)...  on all the time!!!      Port #13
    //   Box1_Port6 JBJ ATO ...          on all the time!!!      Port #14
         ReefAngel.Relay.Off( Box1_Port7);  // ALK Doser ...      Port #15
         ReefAngel.Relay.Off( Box1_Port8);  // Calc Doser ...     Port #16


    ReefAngel.PWM.SetDaylight( MoonPhase() );

    // ReefAngel.PWM.SetDaylight(PWMParabola(20,0,23,0,0, MoonPhase(),0 ));



        ////// Place your custom code below here
       
       
          ReefAngel.RF.UseMemory = false;
          if (hour()>=6 && hour()<11)
            myRFSetMode(ReefCrest,85,10);
          else if (hour()>=11 && hour()<13)
            myRFSetMode(ReefCrest,85,10);
          else if (hour()>=13 && hour()<16)
            myRFSetMode(Smart_NTM,85,15);
          else if (hour()>=16 && hour()<19)
            myRFSetMode(ReefCrest,65,10);
          else
            myRFSetMode(Lagoon,40,10);
             
         
           
        // Hardcode PH calibrations
         //ReefAngel.PHMin=544; // PH7.0
         //ReefAngel.PHMax=830; // PH10.0

         RunDosingPumps();
         LogDosingPumps();
        ////// Place your custom code above here

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

    void DrawCustomMain()
    {

        pingSerial();

        // Parameters
    #if defined DisplayLEDPWM && ! defined RemoveAllLights
        ReefAngel.LCD.DrawMonitor( 15, 48, ReefAngel.Params,
        ReefAngel.PWM.GetDaylightValue(), ReefAngel.PWM.GetActinicValue() );
    #else // defined DisplayLEDPWM && ! defined RemoveAllLights
        ReefAngel.LCD.DrawMonitor( 15, 48, ReefAngel.Params );
    #endif // defined DisplayLEDPWM && ! defined RemoveAllLights
        pingSerial();

        // Main Relay Box
        byte TempRelay = ReefAngel.Relay.RelayData;
        TempRelay &= ReefAngel.Relay.RelayMaskOff;
        TempRelay |= ReefAngel.Relay.RelayMaskOn;
        ReefAngel.LCD.DrawOutletBox( 12, 94, TempRelay );
        pingSerial();

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

    /////////////////////////////////////////
    // Define Your dosing pumps
    /////////////////////////////////////////
    #define numDPumps 2
    byte pumpRelays[numDPumps]={ Box1_Port7, Box1_Port8 };
    int DPVolume[numDPumps]={ 3, 3 } ; // 1ml for each alk and calcium
    int DPRepeat[numDPumps]={ 240, 240 } ; // Repeat every 4 hrs 5x a day
    /////////////////////////////////////////
    // Define Calibration here
    /////////////////////////////////////////
    int CalTime[numDPumps]={ 600, 600 }; // 10 minutes / 10 minutes
    int CalVol[numDPumps]={ 350, 300 }; // 350ml / 300ml... .58 / .5

    /////////////////////////////////////////
    // Function: RunDosingPumps()
    /////////////////////////////////////////
    void RunDosingPumps() {
      float rate;
      int calcTime[numDPumps];

      for (int i=0;i < numDPumps; i++) {
        rate=(float)CalVol[i]/CalTime[i];
        calcTime[i]=DPVolume[i]/rate/(1440/DPRepeat[i]);

        // Run the pumps
        ReefAngel.DosingPumpRepeat(pumpRelays[i], i*20, DPRepeat[i], calcTime[i]); // Offset between each pump is 20 minutes
      }

      // Display Time calculated in portal
      ReefAngel.CustomVar[0]=calcTime[0];
      ReefAngel.CustomVar[1]=calcTime[1];
    }

    /////////////////////////////////////////
    // Function: LogDosingPumps()
    /////////////////////////////////////////
    void LogDosingPumps() {
      static time_t pumpTimer[numDPumps];
      static boolean pumpStatus[numDPumps];
      float rate;

      for (int i=0;i< numDPumps;i++) {
        if (ReefAngel.Relay.Status(pumpRelays[i])) {
          if (!pumpStatus[i]) {
            pumpTimer[i]=now()-pumpTimer[i]; // Pump was off, timer is now a time
            pumpStatus[i]=true;
          }
        } else {
          if (pumpStatus[i]) {
            pumpTimer[i]=now()-pumpTimer[i]; // Pump was on, timer is now a timer
            pumpStatus[i]=false;
       
            rate=(float)CalVol[i]/CalTime[i];

            // Report How much volume has been dosed per day.
            // Could make this in minutes... excercise for the reader..
            ReefAngel.CustomVar[2]=pumpTimer[0]*rate;
            ReefAngel.CustomVar[3]=pumpTimer[1]*rate; 
          }
        }
     
        // Clear timer at end of day
        if (now()%SECS_PER_DAY==SECS_PER_DAY-1) pumpTimer[i]=0;
      } 
    }


        void DrawCustomGraph()
        {
        }

        void myRFSetMode(byte m, byte s, byte d)
        {
          if (m!=myRFMode || s!=myRFSpeed || d!=myRFDuration || millis()<5000)
          {
            myRFMode=m;
            myRFSpeed=s;
            myRFDuration=d;
            ReefAngel.RF.SetMode(m,s,d);
          }
        }


Re: Custom Variables

Posted: Mon Sep 30, 2013 1:18 pm
by lnevo
Question for you. Can you confirm the date/time on your RA. Second, were you having rebooting (time travel) issues that you're working on with Roberto on? Some of the data in your custom variables seems a little eratic, and just trying to see if we're overlapping with the other issues. Sorry if I'm mixing up your case with another. Also if you could let me know any intentional reboots over the past two days will help me troubleshoot...

Posted: Mon Sep 30, 2013 1:23 pm
by egadgetjnr
lnevo wrote:Question for you. Can you confirm the date/time on your RA. Second, were you having rebooting (time travel) issues that you're working on with Roberto on? Some of the data in your custom variables seems a little eratic, and just trying to see if we're overlapping with the other issues. Sorry if I'm mixing up your case with another. Also if you could let me know any intentional reboots over the past two days will help me troubleshoot...
Hey Lee, that's me who has the time travelling RA. :p it appears to be the dimming module that caused it.

Edit: it appears that more then just me might be having the time travel issue? I just saw a post then someone mentioned it. Lol

Re: Custom Variables

Posted: Mon Sep 30, 2013 3:56 pm
by lnevo
Ok here's what's happening...based on the code above you are only set to dose 3ml every 4 hours (that's 6x per day...you commented it was 5x) this equates to .5 ml per dosage....

Now the calibration settings you have calculate one pump at .58 ml/sec and the other at .5ml/sec... We'll come back to that...

The code above puts the calculated time in C0 and C1 and then C2 and C3 are the amount of ml dosed. Now looking at your parameters, C0 is not coming up....meaning it's getting 0's and C1 is sticking at 1.

C1 is sticking at 1 because it is set to dose .5ml per dosage and it takes 1 second to do that.

3 ml / .5ml/sec / 6 doses = 1

C0 is sticking at 0 because when you divide 3ml by .58ml/sec divided by 6 doses you get less than 1 (.86 seconds) which rounds to 0. Now we could go into millisecond dosing...but who wants to do that really...

The bouncing of C2 and C3 I believe are due to reboots...

I would one confirm your dosing pump flow rate 30ml and 35ml per minute are pretty fast for dosing pumps...but not unheard of.. Second I would raise the 3ml to something more measurable. Then examine C0 and C1 again to see if they meet your requirements.

Re: Custom Variables

Posted: Mon Sep 30, 2013 5:12 pm
by ecam
Okay so just tested my calibration and .58 and .5 are correct for the dosing. on one pump o got 350 mls in 600 seconds (10 mins) and 309 mls in 600 mls in the other.

CO C1 didnt change while i ran the pump. however, c2 and c3 did change to reflect the volume dosed but its showing45 and 48 respectively. this should be showing 356 and 305.

Re: Custom Variables

Posted: Mon Sep 30, 2013 5:26 pm
by lnevo
As i said c0 and c1 are the time per dose based on your calibration. Of you change 3ml to 30ml you will see c0 and c1 change.

Re: Custom Variables

Posted: Mon Sep 30, 2013 5:29 pm
by lnevo
Why should they be showing the numbers you said? They will show ml not seconds. Those variables are bytes (0-255) if thy are displaying seconds they will roll over...they should show based on how many seconds they are run for times the rate they were calculated at. 45 and 48 sound right if you ran them for close to 10 minutes...

Re: Custom Variables

Posted: Mon Sep 30, 2013 5:34 pm
by lnevo
Also keep in mind due to rounding (.86 was showing 0...) the number will be less...

A .5ml/sec pump running 10 minutes would be 50ml so round down and be off by a second or two and you've got 48...

The .58ml/sec pump running for 10 minutes should have pumped 58ml so unless you were timing that they filled 10ml then it would be under 10 minutes...and again some rounding. Could explain the difference...

I used to have a routine that calibrated each pump for exactly 10 minutes then you could measure the exact volume (with an accurate device or scale 1ml = 1g). I'll try and dig it up.

But i think you are on track and working properly.

If you change the 3ml or have the volume pull from memory you can adjust the volume on the fly..

Re: Custom Variables

Posted: Mon Sep 30, 2013 5:56 pm
by ecam
Lee the pumps running for 600 seconds at an average of .54 ml/s would result in the 350 and 300 respectively. so the numbers still dont add up

lnevo wrote:Also keep in mind due to rounding (.86 was showing 0...) the number will be less...

A .5ml/sec pump running 10 minutes would be 50ml so round down and be off by a second or two and you've got 48...

The .58ml/sec pump running for 10 minutes should have pumped 58ml so unless you were timing that they filled 10ml then it would be under 10 minutes...and again some rounding. Could explain the difference...

I used to have a routine that calibrated each pump for exactly 10 minutes then you could measure the exact volume (with an accurate device or scale 1ml = 1g). I'll try and dig it up.

But i think you are on track and working properly.

If you change the 3ml or have the volume pull from memory you can adjust the volume on the fly..

Re: Custom Variables

Posted: Mon Sep 30, 2013 6:52 pm
by lnevo
If you are dosing that many ml than you are surpassing the variable and rolling over the 255

Re: Custom Variables

Posted: Mon Sep 30, 2013 10:44 pm
by ecam
Any solutions? This is RA doser I'm using I can't be the only one with this problem. Can I extend the count beyond 255?

Re: Custom Variables

Posted: Tue Oct 01, 2013 4:03 am
by lnevo
Yes we just have to come up with one..

But how much are you plan ing to dose. Set your ra to 15ml and watch the charts..it should be very reliable..

Re: Custom Variables

Posted: Tue Oct 01, 2013 9:19 am
by ecam
lnevo wrote:Yes we just have to come up with one..

But how much are you plan ing to dose. Set your ra to 15ml and watch the charts..it should be very reliable..

im trying to calibrate my system now. that is why im startin low. I guess i should just have it does the 15 mls once a day for now till i need to increase. is that what you are suggesting/

Re: Custom Variables

Posted: Tue Oct 01, 2013 9:26 am
by lnevo
What I'm saying is that 3 is too low and the time that you calibrate is running over our counter. In order to get the details of what is curerntly logged to C0-C3 we need numbers that work. Currently one pump is not dosing anything. If you probably increase to 4ml it would show something in C0.... then at each dose you should see it increment 1ml in C2/C3. Because of the speed of pump1 is why you getting a value of 0 and therefore not dosing one of your 2 part additives.

If you're nervous, I would suggest manually dosing for now and using Ro/Di to confirm that your dosing is doing what you want. Then you can put the numbers to whatever you need to confirm them.

Re: Custom Variables

Posted: Tue Oct 01, 2013 4:15 pm
by ecam
Lee, so I changed the code to test. I have it set to dose 4mls every minute w\ a 1 minute offset. Its not running at all. been waiting for 30 mins. any ideas

Code: Select all

#include <Relay.h>

    #include <RA_ATO.h>
    #include <RF.h>
    #include <ReefAngel_Features.h>
    #include <Globals.h>
    #include <RA_Wifi.h>
    #include <Wire.h>
    #include <OneWire.h>
    #include <Time.h>
    #include <DS1307RTC.h>fafa
    #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>fa
    #include <IO.h>
    #include <ORP.h>
    #include <PH.h>
    #include <WaterLevel.h>
    #include <ReefAngel.h>

    ////// Place global variable code below here
      byte myRFMode=0;
        byte myRFDuration=0;
        byte myRFSpeed=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.WaterChangePorts = Port1Bit | Port8Bit; // Turn off Ports 5 and 6 when Feeding Mode is activated
      ReefAngel.FeedingModePorts = Port1Bit | Port6Bit | Port8Bit; // Turn off Ports 1, 6, 7 and 8 when Water Change Mode is activated
      ReefAngel.LightsOnPorts = Port2Bit | Port3Bit | Port4Bit| Port5Bit;
      ReefAngel.OverheatShutoffPorts = Port2Bit |Port3Bit | Port4Bit | Port5Bit | Port7Bit; // Turn off Ports 3,
        ReefAngel.TempProbe = T3_PROBE;
        ReefAngel.OverheatProbe = T3_PROBE;
        // Set the Overheat temperature setting
        InternalMemory.OverheatTemp_write( 825 );




        // Ports that are always on
        ReefAngel.Relay.On( Port1 );
        ReefAngel.Relay.On( Box1_Port2 );  // Razor Led
        ReefAngel.Relay.On( Box1_Port4 ); // Sump Equipment - UV, Pump
        ReefAngel.Relay.On( Box1_Port5 ); // MP40s   
        ReefAngel.Relay.On( Box1_Port6 ); // JBJ
        ////// Place additional initialization code below here
       

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

    void loop()
    {
      //  Port1 Return pump...  on all the time!!!
          ReefAngel.Relay.Set( Port2, !ReefAngel.Relay.Status( Port4 ) ); //Refuge
      //  Port3 ...  not used
          ReefAngel.StandardLights( Port4,10,0,20,0 ); //ATI Actinic
          ReefAngel.StandardLights( Port5,11,0,19,0 );  //ATI Daylight
          ReefAngel.StandardLights( Port6,10,0,20,0 );  //ATI Fan
          ReefAngel.StandardHeater( Port7,778,790 ); //Heater
          ReefAngel.Relay.DelayedOn( Port8,2 ); //Skimmer
         
          //box 2
          ReefAngel.Relay.Off( Box1_Port1); // Lunar Hub Not used   Port #9
    //   Box1_Port2 Razor_LED (Sump)...  on all the time!!!      Port #10
          ReefAngel.Relay.Off( Box1_Port3); // Start with the relay off       Port #11
                  if (hour()>=5 && hour()<10) ReefAngel.Relay.On(Box1_Port3); // Moonlight Between 5-10am turn the relay on
                  if (hour()>=20 && hour()<=23) ReefAngel.Relay.On(Box1_Port3); // From 8pm-Midnight turn the relay on

    //   Box1_Port4 Ecotech MP_40 Pumps  on all the time!!!      Port #12
    //   Box1_Port5 Razor_LED (Sump)...  on all the time!!!      Port #13
    //   Box1_Port6 JBJ ATO ...          on all the time!!!      Port #14
         ReefAngel.Relay.Off( Box1_Port7);  // ALK Doser ...      Port #15
         ReefAngel.Relay.Off( Box1_Port8);  // Calc Doser ...     Port #16


    ReefAngel.PWM.SetDaylight( MoonPhase() );

    // ReefAngel.PWM.SetDaylight(PWMParabola(20,0,23,0,0, MoonPhase(),0 ));



        ////// Place your custom code below here
       
       
          ReefAngel.RF.UseMemory = false;
          if (hour()>=6 && hour()<11)
            myRFSetMode(ReefCrest,85,10);
          else if (hour()>=11 && hour()<13)
            myRFSetMode(ReefCrest,85,10);
          else if (hour()>=13 && hour()<16)
            myRFSetMode(Smart_NTM,85,15);
          else if (hour()>=16 && hour()<19)
            myRFSetMode(ReefCrest,65,10);
          else
            myRFSetMode(Lagoon,40,10);
             
         
           
        // Hardcode PH calibrations
         //ReefAngel.PHMin=544; // PH7.0
         //ReefAngel.PHMax=830; // PH10.0

         RunDosingPumps();
         LogDosingPumps();
        ////// Place your custom code above here

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

    void DrawCustomMain()
    {

        pingSerial();

        // Parameters
    #if defined DisplayLEDPWM && ! defined RemoveAllLights
        ReefAngel.LCD.DrawMonitor( 15, 48, ReefAngel.Params,
        ReefAngel.PWM.GetDaylightValue(), ReefAngel.PWM.GetActinicValue() );
    #else // defined DisplayLEDPWM && ! defined RemoveAllLights
        ReefAngel.LCD.DrawMonitor( 15, 48, ReefAngel.Params );
    #endif // defined DisplayLEDPWM && ! defined RemoveAllLights
        pingSerial();

        // Main Relay Box
        byte TempRelay = ReefAngel.Relay.RelayData;
        TempRelay &= ReefAngel.Relay.RelayMaskOff;
        TempRelay |= ReefAngel.Relay.RelayMaskOn;
        ReefAngel.LCD.DrawOutletBox( 12, 94, TempRelay );
        pingSerial();

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

    /////////////////////////////////////////
    // Define Your dosing pumps
    /////////////////////////////////////////
    #define numDPumps 2
    byte pumpRelays[numDPumps]={ Box1_Port7, Box1_Port8 };
    int DPVolume[numDPumps]={ 4, 4 } ; // 1ml for each alk and calcium
    int DPRepeat[numDPumps]={ 1, 1 } ; // Repeat every 4 hrs 6x a day ----in mins
    /////////////////////////////////////////
    // Define Calibration here
    /////////////////////////////////////////
    int CalTime[numDPumps]={ 600, 600 }; // 10 minutes / 10 minutes
    int CalVol[numDPumps]={ 350, 300 }; // 350ml / 300ml... .58 / .5

    /////////////////////////////////////////
    // Function: RunDosingPumps()
    /////////////////////////////////////////
    void RunDosingPumps() {
      float rate;
      int calcTime[numDPumps];

      for (int i=0;i < numDPumps; i++) {
        rate=(float)CalVol[i]/CalTime[i];
        calcTime[i]=DPVolume[i]/rate/(1440/DPRepeat[i]);

        // Run the pumps
        ReefAngel.DosingPumpRepeat(pumpRelays[i], i*1, DPRepeat[i], calcTime[i]); // Offset between each pump is 20 minutes
      }

      // Display Time calculated in portal
      ReefAngel.CustomVar[0]=calcTime[0];
      ReefAngel.CustomVar[1]=calcTime[1];
    }

    /////////////////////////////////////////
    // Function: LogDosingPumps()
    /////////////////////////////////////////
    void LogDosingPumps() {
      static time_t pumpTimer[numDPumps];
      static boolean pumpStatus[numDPumps];
      float rate;

      for (int i=0;i< numDPumps;i++) {
        if (ReefAngel.Relay.Status(pumpRelays[i])) {
          if (!pumpStatus[i]) {
            pumpTimer[i]=now()-pumpTimer[i]; // Pump was off, timer is now a time
            pumpStatus[i]=true;
          }
        } else {
          if (pumpStatus[i]) {
            pumpTimer[i]=now()-pumpTimer[i]; // Pump was on, timer is now a timer
            pumpStatus[i]=false;
       
            rate=(float)CalVol[i]/CalTime[i];

            // Report How much volume has been dosed per day.
            // Could make this in minutes... excercise for the reader..
            ReefAngel.CustomVar[2]=pumpTimer[0]*rate;
            ReefAngel.CustomVar[3]=pumpTimer[1]*rate; 
          }
        }
     
        // Clear timer at end of day
        if (now()%SECS_PER_DAY==SECS_PER_DAY-1) pumpTimer[i]=0;
      } 
    }


        void DrawCustomGraph()
        {
        }

        void myRFSetMode(byte m, byte s, byte d)
        {
          if (m!=myRFMode || s!=myRFSpeed || d!=myRFDuration || millis()<5000)
          {
            myRFMode=m;
            myRFSpeed=s;
            myRFDuration=d;
            ReefAngel.RF.SetMode(m,s,d);
          }
        }

Re: Custom Variables

Posted: Tue Oct 01, 2013 4:26 pm
by lnevo
Lol no you dont...

You have it set to dose 4ml over the course of 24 hours in 1 second intervals...

That will be 0 again...

Its volume / rate / number of doses

At 1 sec you have 1440 doses per day!!!

Re: Custom Variables

Posted: Thu Oct 03, 2013 12:00 pm
by ecam
Lee, thanks for all the help. Its working great so far. Not time for the next project. Going to memory

Re: Custom Variables

Posted: Fri Oct 04, 2013 10:12 am
by rossbryant1956
Hey Lee

Studying your dosing code. What are doing here?

#define VO_RefillATO Box2_Port1
#define VO_EnableATO Box2_Port2
#define VO_StartFill Box2_Port3
#define VO_Vacation Box2_Port4
#define VO_AutoFeed Box2_Port5
#define VO_Unused Box2_Port6
#define VO_Calibrate Box2_Port7
#define VO_LockPorts Box2_Port8

Are these virtual outlets? Is there a post where you've discussed this? Thx

Re: Custom Variables

Posted: Fri Oct 04, 2013 12:51 pm
by lnevo
Yes the VO represents Virtual Outlet in my naming convention. They are outlets that don't exist physically that I use to trigger activity in some of my functions. Mainly I use the RefillATO and EnableATO. The RefillATO fills my ato reservoir until it hits 100% and the EnableATO function is part of my water change that turns my auxilliary pump in my new SW into an ATO as I drain the tank with my reactor pump :)

Vacation and AutoFeed are tied to the memory location as well but an easy way to see/change the status of those modes.

Calibrate is the import one when it comes to dosing. It's used in conjunction with the LockPorts relay. Basically my dosing pumps can not be masked on / off in the portal or on the phone apps. If a mask is detected its removed immediately before the relay gets a chance to actually turn on. This prevents the dreaded oops my alk was on all day... Now my calibration on the other hand requires that you can turn on and off the ports. So first I unlock the ports by turning off the lock port relay. Then I turn on the calibration switch. Now I can manually turn on/off the dosing pumps and fill a container to whatever volume I want. Then if I want to save the changes, I turn off the calibration and then lock the ports. If I want to scrap the calibration, I turn off the lock ports and the timers are scrapped.

Now the nice thing about the calibration is it reuses some of the code in the LogDosing function to keep track of how long the relay was on. So at the end of the routine when I measure let's say 10ml of fluid, however long the pump was on while calibration relay was on is what is stored in memory for the calibration time. The time and volume determine the rate and my DosingPumps function uses the volume you specifcy to calculate how long to dose based on the calibration values.

Sorry if that was long and involved. But overall the virtual outlets are great. They are a fantastic method to trigger a function you want to happen in the RA without having to fiddle with memory to trigger it.

Re: Custom Variables

Posted: Fri Oct 04, 2013 3:55 pm
by rossbryant1956
Dude, you are really scary... Thx. :?

Re: Custom Variables

Posted: Fri Oct 04, 2013 4:16 pm
by lnevo
Uhm...thanks? :)