Dosing Pump not running on Schedule

Do you have a question on how to do something.
Ask in here.
kirkwood
Posts: 173
Joined: Mon Apr 29, 2013 6:50 am

Re: Dosing Pump not running on Schedule

Post by kirkwood »

Inevo,

I loaded in the code you posted. Where do I find the data it is tallying? I don't know what the "Custom main function" is.

thanks
Image
User avatar
cosmith71
Posts: 1432
Joined: Fri Mar 29, 2013 3:51 pm
Location: Oklahoma City

Re: Dosing Pump not running on Schedule

Post by cosmith71 »

rimai wrote: Or, you could code an expansion outlet port to be triggered on dosing pump port, but it would stay on for more than 5 minutes.
How might this be coded? Using an actual port, or a virtual one?

--Colin
rimai
Posts: 12857
Joined: Fri Mar 18, 2011 6:47 pm

Re: Dosing Pump not running on Schedule

Post by rimai »

kirkwood wrote:Inevo,

I loaded in the code you posted. Where do I find the data it is tallying? I don't know what the "Custom main function" is.

thanks
Take a look at this thread about Custom Main screens:
http://forum.reefangel.com/viewtopic.php?f=14&t=109

Basically a way to create your own screen
Roberto.
rimai
Posts: 12857
Joined: Fri Mar 18, 2011 6:47 pm

Re: Dosing Pump not running on Schedule

Post by rimai »

cosmith71 wrote:
rimai wrote: Or, you could code an expansion outlet port to be triggered on dosing pump port, but it would stay on for more than 5 minutes.
How might this be coded? Using an actual port, or a virtual one?

--Colin
It's actually an actual port, but could be considered as virtual, because you are using a port from a relay box that you don't have the physical box itself.
For example, if you code anything for Box1_Port1, it will use port1 of the expansion box 1, but if you don't have that physical box, nothing will be turned on/off, but as far as the controller is concerned, it is treating as if it was there.
Roberto.
User avatar
cosmith71
Posts: 1432
Joined: Fri Mar 29, 2013 3:51 pm
Location: Oklahoma City

Re: Dosing Pump not running on Schedule

Post by cosmith71 »

rimai wrote:
cosmith71 wrote:
rimai wrote: Or, you could code an expansion outlet port to be triggered on dosing pump port, but it would stay on for more than 5 minutes.
How might this be coded? Using an actual port, or a virtual one?

--Colin
It's actually an actual port, but could be considered as virtual, because you are using a port from a relay box that you don't have the physical box itself.
For example, if you code anything for Box1_Port1, it will use port1 of the expansion box 1, but if you don't have that physical box, nothing will be turned on/off, but as far as the controller is concerned, it is treating as if it was there.
OK, got that part. Is there an easy way to turn on a port for a specified amount of time?

if (ReefAngel.Relay.Status(AlkPump))
{ Turn on another port for 5 minutes } // not sure what this functinon would be

--Colin
rimai
Posts: 12857
Joined: Fri Mar 18, 2011 6:47 pm

Re: Dosing Pump not running on Schedule

Post by rimai »

The easy way to do without having to declare new variables is to use the timers, but we only have 2 available.
Timer[1] and Timer[2].
The other option is to declare a new global variable that holds the time the change has happened.
Something like this:

Code: Select all

unsigned long LastUpdate=0;
..
..
..
void loop()
{
  if (ReefAngel.Relay.Status(AlkPump) && LastUpdate==0) 
  {
    LastUpdate=now();
  }
  if (now()-LastUpdate>=300 && LastUpdate!=0)
  {
    LastUpdate=0;
    // Do something;
  }
}
Roberto.
User avatar
cosmith71
Posts: 1432
Joined: Fri Mar 29, 2013 3:51 pm
Location: Oklahoma City

Re: Dosing Pump not running on Schedule

Post by cosmith71 »

It's too late at night for me to wrap my head around this. I think I have the tools I need. I'll work on it Monday when I'm off again. I think it'll be a fun project for me. :mrgreen:

--Colin
User avatar
lnevo
Posts: 5422
Joined: Fri Jul 20, 2012 9:42 am

Dosing Pump not running on Schedule

Post by lnevo »

Roberto,

What were you thinking on how to instantiate 8 different calibrations? From a menu? What would you use to pass in which relay we were calibrating?

The function I wrote does my two pumps at the same time.

Just trying to figure out how the interaction would work.
rimai
Posts: 12857
Joined: Fri Mar 18, 2011 6:47 pm

Re: Dosing Pump not running on Schedule

Post by rimai »

I didn't think of anything :(
I've been focusing on the touch unit and the upcoming products... sorry...
Roberto.
User avatar
cosmith71
Posts: 1432
Joined: Fri Mar 29, 2013 3:51 pm
Location: Oklahoma City

Re: Dosing Pump not running on Schedule

Post by cosmith71 »

Roberto, how does now() work? What does it return?

Thanks,

--Colin
rimai
Posts: 12857
Joined: Fri Mar 18, 2011 6:47 pm

Re: Dosing Pump not running on Schedule

Post by rimai »

It returns unix time, which is often called epoch time too.
Basically it is number of seconds from 01/01/1970.
Roberto.
kirkwood
Posts: 173
Joined: Mon Apr 29, 2013 6:50 am

Re: Dosing Pump not running on Schedule

Post by kirkwood »

kirkwood wrote:Inevo,

I loaded in the code you posted. Where do I find the data it is tallying? I don't know what the "Custom main function" is.

thanks
so do I have to create a custom mainscreen to be able to utilize the code that I just added?
Image
User avatar
cosmith71
Posts: 1432
Joined: Fri Mar 29, 2013 3:51 pm
Location: Oklahoma City

Re: Dosing Pump not running on Schedule

Post by cosmith71 »

lnevo wrote:Ok, try this...

Move this section above the setup where it says to put global code here...

Code: Select all

  
////// Place global variable code below here
time_t running1, running2;
You can leave this section in your loop();

Code: Select all

  // Reset the counter each day
  if (now()%SECS_PER_DAY==0) {
    running1=0;
    running2=0;
  }  
  
  // If the Dosing Pump 1 is on and it's a new second...
  if (ReefAngel.Relay.Status(DPump1) && (millis()%1000==0)) {
    running1++; // increment the counter;
  }

  // If the Dosing Pump is on and it's a new second...
  if (ReefAngel.Relay.Status(DPump2) && (millis()%1000==0)) {
    running2++; // increment the counter;
  }
  
  // Normalize and assign to CustomVar for reporting on the portal
  ReefAngel.CustomVar[0]=running1/60; // Number of Minutes for DPump1
  ReefAngel.CustomVar[1]=running1%60; // Number of Seconds for DPump1
  ReefAngel.CustomVar[2]=running2/60; // Number of Minutes for DPump2
  ReefAngel.CustomVar[3]=running2%60; // Number of Seconds for DPump2
You can now access running1 and running2 in your CustomMain function. If you want minutes and seconds look at the CustomVar assignments for how to do that, otherwise you could just display total seconds of running.

As far as ml, I'll try and get some time to do that later... I'm actually working on some code to store my calibration number and use a ml setting instead of second setting to distribute the amount throughout the day automatically.
Lee, I'm using the custom webchart and the android app to check this and all I get back from C0-C3 are zeros. Am I doing something wrong?

--Colin
User avatar
cosmith71
Posts: 1432
Joined: Fri Mar 29, 2013 3:51 pm
Location: Oklahoma City

Re: Dosing Pump not running on Schedule

Post by cosmith71 »

rimai wrote:You would have to make the running time longer than 5 minutes if you want it to show in the relay activity 100% of the time.
Or, you could code an expansion outlet port to be triggered on dosing pump port, but it would stay on for more than 5 minutes.
Done!

Code under "////// Place global variable code below here"

Code: Select all

unsigned long LastUpdate1=0;
unsigned long LastUpdate2=0;
Code in loop()

Code: Select all

if (ReefAngel.Relay.Status(AlkPump) && LastUpdate1==0)
    {
      LastUpdate1 = now();
      ReefAngel.Relay.On (Box2_Port1);
    }
    if (now() - LastUpdate1 >= 360 && LastUpdate1 != 0)
    {
      LastUpdate1 = 0;
      ReefAngel.Relay.Off (Box2_Port1);
    }
    
    if (ReefAngel.Relay.Status(CalPump) && LastUpdate2==0)
    {
      LastUpdate2 = now();
      ReefAngel.Relay.On (Box2_Port2);
    }
    if (now() - LastUpdate2 >= 360 && LastUpdate2 != 0)
    {
      LastUpdate2 = 0;
      ReefAngel.Relay.Off (Box2_Port2);
    }
Note, Box2 doesn't physically exist. Works like a charm. I doesn't give me times, but does let the portal relay chart tell me that the pumps came on.

--Colin
rimai
Posts: 12857
Joined: Fri Mar 18, 2011 6:47 pm

Re: Dosing Pump not running on Schedule

Post by rimai »

Cool!! :)
Roberto.
User avatar
cosmith71
Posts: 1432
Joined: Fri Mar 29, 2013 3:51 pm
Location: Oklahoma City

Re: Dosing Pump not running on Schedule

Post by cosmith71 »

I liked it so much I set it up for my ATO as well. Now my code is cluttered. Time to figure out how to move it into a function... :geek:

I was a Comp Sci major 20 or so years ago. I never finished it. I'd forgotten how much fun coding can be. :ugeek:

--Colin
User avatar
lnevo
Posts: 5422
Joined: Fri Jul 20, 2012 9:42 am

Re: Dosing Pump not running on Schedule

Post by lnevo »

So I'm thinking of switching to volume based. The only caveat is I think we also need to store the volume calibrated against. So for Roberto's case, using a 1cup kitchen measuring cup, you could set the volume to 236ml (1cup = 236.588ml). We can trigger a timer when mask on is set and stop the counter when mask off is set. Whatever the value of the timer is the number of seconds to fill that volume. We can have an time_t timers[] and the calibration function can take a byte ports[] as the argument. this way the function can calibrate all the pumps at once, or one at a time.

In a menu mode, you could show all the pumps that have been activated and the time and have an OK or Cancel button to save the settings. Or if you already know the rate and want to just plug it in you could just write the values to memory.

This would only work well if you have the wifi module...otherwise the menu becomes a lot more complicated...

Anyway, I'm going to change my code to go the volume route. I'm going to use the WiFiAlert method now to send me the time result...btw, this might be a good method for kirkwood...you can get an email each time your doser goes off with the total time / ml dosed each session...
User avatar
lnevo
Posts: 5422
Joined: Fri Jul 20, 2012 9:42 am

Re: Dosing Pump not running on Schedule

Post by lnevo »

Ok, here's the function I wrote up to dose by volume or dose by time. If memory is flagged to dose by volume then it updates the DPTimer variable for that pump with the calculated time per dose. If not, it updates the memory location with how much volume should be dosed per day. This should make it easy to switch back and forth if needed. Also, should be easily adaptable to many dosing pumps, although you might want some by time and some by volume. still have to work on the new calibration function.

Once again this is test code, it has not even been compiled yet...

Code: Select all

void DosingPumps() {
  const byte numPumps=2;
  byte pump[numPumps] = { DPump1, DPump2 };
  
  int memTimer[numPumps] = { Mem_B_DP1Timer, Mem_B_DP2Timer };
  int memRepeat[numPumps] = { Mem_I_DP1RepeatInterval, Mem_I_DP2RepeatInterval };
  int memCalibrateVol[numPumps] = { Mem_I_Calibrate1Vol, Mem_I_Calibrate2Vol };
  int memCalibrateTime[numPumps] = { Mem_I_Calibrate1Time, Mem_I_Calibrate2Time };
  int memPumpVolume[numPumps] = { Mem_I_Pump1Vol, Mem_I_Pump2Vol };

  for (int i=0;i < numPumps; i++) {
    float pumpRate=InternalMemory.read_int(memCalibrateVol[i])/InternalMemory.read_int(memCalibrateTime[i]);
    int doseTime=InternalMemory.read_int(memTimer[i]);
    int repeatTime=InternalMemory.read_int(memRepeat[i]);
    int totalVolume=pumpRate*(doseTime*(1440/repeatTime));    
    int calcTime=(InternalMemory.read_int(memPumpVolume[i])*pumpRate)/(1440/repeatTime);

    if (InternalMemory.read(Mem_B_DoseByVolume)) {
      if (doseTime!=calcTime) 
        InternalMemory.write_int(memTimer[i], doseTime=calcTime); 
    } else {
      if (doseTime!=calcTime)
        InternalMemory.write_int(memPumpVolume[i], totalVolume);
    }
    
    ReefAngel.DosingPumpRepeat(pump[i], i*5, repeatTime, doseTime);
  }
}
User avatar
lnevo
Posts: 5422
Joined: Fri Jul 20, 2012 9:42 am

Re: Dosing Pump not running on Schedule

Post by lnevo »

Fixed the compile issues in the code above.
User avatar
lnevo
Posts: 5422
Joined: Fri Jul 20, 2012 9:42 am

Re: Dosing Pump not running on Schedule

Post by lnevo »

Ok. calculations are working.. Not sure if I changed much except cast one float and had to change a multiply to divide :)

So if the mem location is set to dose by volume, when you change the volume memory field, it will update the timer for that dosing pump. Inversely if you update the timer when it's set to dose by time, it will update the volume memory location with the total volume for the day.

Still need to fix this so you can do either without needing to choose dose by volume or not... hmmm

Edit: Logging/Reporting... done. Method to cancel the calibration... done.

Anyway, here's some code to play with...

Code: Select all

// Definitions for dosing pumps
#define numDPumps 2
byte pump[numDPumps]={ DPump1, DPump2 };
byte varReport[numDPumps]={ Var_DPump1, Var_DPump2 };
int memDPTime[numDPumps]={ Mem_B_DP1Timer, Mem_B_DP2Timer };
int memDPVolume[numDPumps]={ Mem_I_DP1Volume, Mem_I_DP2Volume };
int memDPRepeat[numDPumps]={ Mem_I_DP1RepeatInterval, Mem_I_DP2RepeatInterval };
int memCalTime[numDPumps]={ Mem_I_CalDP1Time, Mem_I_CalDP2Time };
int memCalVol[numDPumps]={ Mem_I_CalDP1Vol, Mem_I_CalDP2Vol };

void RunDosingPumps() {
  int doseTime, repeatTime, calcTime, totalVolume;
  float rate;
  
  for (int i=0;i < numDPumps; i++) {
    doseTime=InternalMemory.read_int(memDPTime[i]);
    repeatTime=InternalMemory.read_int(memDPRepeat[i]);
    rate=(float)InternalMemory.read_int(memCalVol[i])/InternalMemory.read_int(memCalTime[i]);
    calcTime=(InternalMemory.read_int(memDPVolume[i])/rate)/(1440/repeatTime);
    totalVolume=rate*(doseTime*(1440/repeatTime));    
    
    if (InternalMemory.read(Mem_B_DoseByVolume)) {
      if (doseTime!=calcTime) 
        InternalMemory.write_int(memDPTime[i], doseTime=calcTime); 
    } else {
      if (doseTime!=calcTime)
        InternalMemory.write_int(memDPVolume[i], totalVolume);
    }
    
    // Make sure we're not calibrating
    if (!ReefAngel.Relay.Status(VO_Calibrate)) 
      ReefAngel.DosingPumpRepeat(pump[i], i*5, repeatTime, doseTime);
  }
}

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

  for (int i=0;i< numDPumps;i++) {
    if (ReefAngel.Relay.Status(pump[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)InternalMemory.read_int(memCalVol[i])/InternalMemory.read_int(memCalTime[i]);
        ReefAngel.CustomVar[varReport[i]]=pumpTimer[i]*rate;
      }
    }

    if (now()%SECS_PER_DAY==SECS_PER_DAY-1) pumpTimer[i]=0; // Clear timer at end of day
  }  
}

void CalibrateDPumps() {
  static time_t pumpTimer[numDPumps];
  static boolean pumpStatus[numDPumps];
  static boolean running;
      
  if (ReefAngel.Relay.Status(VO_Calibrate)) { 
    running=true;
    
    for (int i=0;i < numDPumps;i++) {
      if (ReefAngel.Relay.Status(pump[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;
        }
      }
    }      
  } else {
    if (running) {
      running=false;
      
      for (int i=0;i < numDPumps;i++) {
        if (pumpTimer[i]>0 && !ReefAngel.Relay.Status(VO_LockPorts)) {
          InternalMemory.write_int(memCalTime[i], pumpTimer[i]); 
        }
        ReefAngel.Relay.Override(pump[i],2); // Go back to auto mode 
        pumpStatus[i]=false;
        pumpTimer[i]=0;
      }
    }
  }    
}
User avatar
lnevo
Posts: 5422
Joined: Fri Jul 20, 2012 9:42 am

Re: Dosing Pump not running on Schedule

Post by lnevo »

FYI, this code relies on a few things that I have added to the libraries but aren't available yet. If you want to use this let me know and I can either point you to my git repo for the current branch to pull, or how to work around the missing pieces,
User avatar
lnevo
Posts: 5422
Joined: Fri Jul 20, 2012 9:42 am

Re: Dosing Pump not running on Schedule

Post by lnevo »

Ok, I took out the dependencies to WiFiAlert and the mask commands I added. I needed a solution anyway for the logging (which could have been on or a mask...) so I used the same mechanism in the calibration routine. So this should be usable by anyone now.

Also, since we are now calculating the rate of flow and are able to determine volume.. I think we can safely store the amount dosed in a byte and publish it to the portal.... if it wraps, it wraps :) But this should provide good monitoring for those who want to monitor their dosing routine.
User avatar
cosmith71
Posts: 1432
Joined: Fri Mar 29, 2013 3:51 pm
Location: Oklahoma City

Re: Dosing Pump not running on Schedule

Post by cosmith71 »

lnevo wrote:Ok, I took out the dependencies to WiFiAlert and the mask commands I added. I needed a solution anyway for the logging (which could have been on or a mask...) so I used the same mechanism in the calibration routine. So this should be usable by anyone now.

Also, since we are now calculating the rate of flow and are able to determine volume.. I think we can safely store the amount dosed in a byte and publish it to the portal.... if it wraps, it wraps :) But this should provide good monitoring for those who want to monitor their dosing routine.
This is the code in the last post on page 4? Might play with it over the weekend.

--Colin
User avatar
cosmith71
Posts: 1432
Joined: Fri Mar 29, 2013 3:51 pm
Location: Oklahoma City

Re: Dosing Pump not running on Schedule

Post by cosmith71 »

Where does VO_Calibrate come from?

--Colin
User avatar
lnevo
Posts: 5422
Joined: Fri Jul 20, 2012 9:42 am

Re: Dosing Pump not running on Schedule

Post by lnevo »

Yea. The trick in using it is defining all the memory locations needed, but otherwise *should* be plug and play. I should be around to help if you get stuck on anything... There may be another version by the weekend though, as I have a few more tests to run, but I'm pretty pleased with it at the moment.
User avatar
cosmith71
Posts: 1432
Joined: Fri Mar 29, 2013 3:51 pm
Location: Oklahoma City

Re: Dosing Pump not running on Schedule

Post by cosmith71 »

lnevo wrote:Yea. The trick in using it is defining all the memory locations needed, but otherwise *should* be plug and play. I should be around to help if you get stuck on anything... There may be another version by the weekend though, as I have a few more tests to run, but I'm pretty pleased with it at the moment.
Which locations are available? Is it 100-199?

--Colin
User avatar
lnevo
Posts: 5422
Joined: Fri Jul 20, 2012 9:42 am

Re: Dosing Pump not running on Schedule

Post by lnevo »

You should use my INO (in my signature) as a reference for some of those defines :)

VO_Calibrate is a virtual (non-existent) outlet. You could use any unused outlet or change the conditional to use a memory location as a trigger. I use two ports to control the calibration process. One that locks the ports and one to start calibration mode. If I lock the ports before I turn off calibration mode, then the values are not saved. If I turn off calibration mode first then the time values are saved to memory.

Good question, and I guess where it might get tricky for some.
User avatar
lnevo
Posts: 5422
Joined: Fri Jul 20, 2012 9:42 am

Re: Dosing Pump not running on Schedule

Post by lnevo »

cosmith71 wrote:
lnevo wrote:Yea. The trick in using it is defining all the memory locations needed, but otherwise *should* be plug and play. I should be around to help if you get stuck on anything... There may be another version by the weekend though, as I have a few more tests to run, but I'm pretty pleased with it at the moment.
Which locations are available? Is it 100-199?

--Colin
Yeah, those should be free to use if you aren't already. The built-ins start at 200.
User avatar
lnevo
Posts: 5422
Joined: Fri Jul 20, 2012 9:42 am

Re: Dosing Pump not running on Schedule

Post by lnevo »

Ok, for anyone testing, I've got all the bugs I think sorted out. The nice thing is that you can now update the volume memory location OR the DPTimer in the portal. If you change the volume, the new time is calculated and updated so you can see the change and the dosage amount in the portal. If you change the time however, it will get rounded to the nearest ml. So for instance if I put 68 seconds in the timer, it will calculate the volume of ml that will produce which will then be updated in memory. It will then recalculate the amount of time necessary to get that dosage which would then be 65 seconds. This is a precision issue since we can't store floats in memory (yet hehehe) But either way, the volume method would be the more accurate means to adjust at this point, but the functionality is in place.

Anyway, if anyone wants to play with this, here is the latest round of code:

Be aware, you will need to change the triggers in the calibration routine. Either declare ports that you are not using and they will appear in the portal as if you had an expansion relay or change the conditionals to use memory settings, or if you're brave, you could write a menu interface to turn on calibration and off. That part may get tricky so let me know if you have any questions.

Code: Select all

// Definitions for dosing pumps
#define numDPumps 2
byte pump[numDPumps]={ DPump1, DPump2 };
byte varReport[numDPumps]={ Var_DPump1, Var_DPump2 };
int memDPTime[numDPumps]={ Mem_B_DP1Timer, Mem_B_DP2Timer };
int memDPVolume[numDPumps]={ Mem_I_DP1Volume, Mem_I_DP2Volume };
int memDPRepeat[numDPumps]={ Mem_I_DP1RepeatInterval, Mem_I_DP2RepeatInterval };
int memCalTime[numDPumps]={ Mem_I_CalDP1Time, Mem_I_CalDP2Time };
int memCalVol[numDPumps]={ Mem_I_CalDP1Vol, Mem_I_CalDP2Vol };

void RunDosingPumps() {
  float rate;
  int dpTime, dpRepeat, calcTime, totalVolume;

  static int doseTime[numDPumps]={ 
    InternalMemory.read(memDPTime[0]), 
    InternalMemory.read(memDPTime[1]) 
  };
  
  for (int i=0;i < numDPumps; i++) {
    dpTime=InternalMemory.read(memDPTime[i]);
    dpRepeat=InternalMemory.read_int(memDPRepeat[i]);
    rate=(float)InternalMemory.read_int(memCalVol[i])/InternalMemory.read_int(memCalTime[i]);
    calcTime=(InternalMemory.read_int(memDPVolume[i])/rate)/(1440/dpRepeat);
    totalVolume=rate*(dpTime*(1440/dpRepeat)); 

    if (dpTime!=doseTime[i]) { // Memory has changed.
        InternalMemory.write_int(memDPVolume[i], totalVolume); // Update volume
        doseTime[i]=dpTime;
    } else if (dpTime!=calcTime) { // Calculated time has changed.
        InternalMemory.write(memDPTime[i], calcTime); // Update time
        doseTime[i]=calcTime;
    }

    // Make sure we're not calibrating
    if (!ReefAngel.Relay.Status(VO_Calibrate)) 
      ReefAngel.DosingPumpRepeat(pump[i], i*5, dpRepeat, doseTime[i]);
  }
}

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

  for (int i=0;i< numDPumps;i++) {
    if (ReefAngel.Relay.Status(pump[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)InternalMemory.read_int(memCalVol[i])/InternalMemory.read_int(memCalTime[i]);
        ReefAngel.CustomVar[varReport[i]]=pumpTimer[i]*rate;
      }
    }

    if (now()%SECS_PER_DAY==SECS_PER_DAY-1) pumpTimer[i]=0; // Clear timer at end of day
  }  
}

void CalibrateDPumps() {
  static time_t pumpTimer[numDPumps];
  static boolean pumpStatus[numDPumps];
  static boolean running=false;
      
  if (ReefAngel.Relay.Status(VO_Calibrate)) { 
    running=true;
    
    for (int i=0;i < numDPumps;i++) {
      if (ReefAngel.Relay.Status(pump[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;
        }
      }
    }      
  } else {
    if (running) {
      running=false;
      
      for (int i=0;i < numDPumps;i++) {
        if (pumpTimer[i]>0 && !ReefAngel.Relay.Status(VO_LockPorts)) {
          InternalMemory.write_int(memCalTime[i], pumpTimer[i]); 
        }
        ReefAngel.Relay.Override(pump[i],2); // Go back to auto mode 
        pumpStatus[i]=false;
        pumpTimer[i]=0;
      }
    }
  }    
}
kirkwood
Posts: 173
Joined: Mon Apr 29, 2013 6:50 am

Re: Dosing Pump not running on Schedule

Post by kirkwood »

lnevo wrote:Ok, try this...

Move this section above the setup where it says to put global code here...

Code: Select all

  
////// Place global variable code below here
time_t running1, running2;
You can leave this section in your loop();

Code: Select all

  // Reset the counter each day
  if (now()%SECS_PER_DAY==0) {
    running1=0;
    running2=0;
  }  
  
  // If the Dosing Pump 1 is on and it's a new second...
  if (ReefAngel.Relay.Status(DPump1) && (millis()%1000==0)) {
    running1++; // increment the counter;
  }

  // If the Dosing Pump is on and it's a new second...
  if (ReefAngel.Relay.Status(DPump2) && (millis()%1000==0)) {
    running2++; // increment the counter;
  }
  
  // Normalize and assign to CustomVar for reporting on the portal
  ReefAngel.CustomVar[0]=running1/60; // Number of Minutes for DPump1
  ReefAngel.CustomVar[1]=running1%60; // Number of Seconds for DPump1
  ReefAngel.CustomVar[2]=running2/60; // Number of Minutes for DPump2
  ReefAngel.CustomVar[3]=running2%60; // Number of Seconds for DPump2
You can now access running1 and running2 in your CustomMain function. If you want minutes and seconds look at the CustomVar assignments for how to do that, otherwise you could just display total seconds of running.

As far as ml, I'll try and get some time to do that later... I'm actually working on some code to store my calibration number and use a ml setting instead of second setting to distribute the amount throughout the day automatically.

I used this code and I don't get any value in the custom field 0 or 2. I do get a value in custom field 1 and 3. From reading the code it looks like fields 1 and 3 are for seconds. I usually get a reading that is a pretty small number while I'expect to see something that consistently approaches 60 before resetting. Seems like the minute fields are not funcitoning properl. How can I fix?
Image
Post Reply