Dosing pump and "in the internal memory"

Basic / Standard Reef Angel hardware
Post Reply
discocarp
Posts: 21
Joined: Fri Oct 05, 2012 9:13 am

Dosing pump and "in the internal memory"

Post by discocarp »

I'm (finally) getting going with my Reef Angel. I'm mostly playing around and learning right now.

Step 1 was to get my kalk dosing pump running. Using the wizard I got this all worked out with the "in the code" memory setting. No problem.

So now I wanted to try "in the internal memory". What happens to my variables here? It now calls DosingPumpRepeat1 instead of DosingPumpRepeat, but I see no place in the code (not the wizard) to change the values now.

My goal here (besides just learning) is to be able to change the dosing pump variables from the head unit rather than with the computer hooked up.
rimai
Posts: 12857
Joined: Fri Mar 18, 2011 6:47 pm

Re: Dosing pump and "in the internal memory"

Post by rimai »

If you are using internal memory, you have to change those values using the Portal or smart phone apps.
Roberto.
discocarp
Posts: 21
Joined: Fri Oct 05, 2012 9:13 am

Re: Dosing pump and "in the internal memory"

Post by discocarp »

So I can't set up menus to control it with the joystick?
rimai
Posts: 12857
Joined: Fri Mar 18, 2011 6:47 pm

Re: Dosing pump and "in the internal memory"

Post by rimai »

You can if you code your own menu system.
There is nothing in the libraries created for that.
It's much easier to do that through one of the apps that we never focused on creating a menu system for that.
You can also use the Client if you don't have the wifi attachment.
Roberto.
discocarp
Posts: 21
Joined: Fri Oct 05, 2012 9:13 am

Re: Dosing pump and "in the internal memory"

Post by discocarp »

I have the wifi (but haven't played with it yet), but would really like everything to also be controllable with the joystick too unless it is an absolute nightmare.

I was peeking around the code and found ReefAngelClass::SetupOption, which I think edits a parameter when called from a menu event. I'm not sure how to set up a custom menu, I'll have to read more first. I found DosingPumpRepeat1 uses InternalMemory.DP1RepeatInterval_read() and InternalMemory.DP1Timer_read(), so I assume those are the ones I edit with SetupOption? And DP2 versions too (but no DP3 so I'd have to figure that out if I wanted a third pump setup this way). Am I generally on the right track here?
rimai
Posts: 12857
Joined: Fri Mar 18, 2011 6:47 pm

Re: Dosing pump and "in the internal memory"

Post by rimai »

Correct...
There is someone else trying to get 3 pumps into internal memory too.
Maybe you guys can collaborate together too :)
He's using custom memories because of the 3rd pump, but you could use the ones you mentioned for DP1 and DP2 and then use custom for DP3... Up to you. Whatever makes it easier for you.
I did something similar to what you mentioned on another project...
Here is the menu entry I used, except it was temperature, but it is a good start for you to change it to DP stuff:

Code: Select all

void MenuEntry2()
{
  boolean bDone=false;
  int u=InternalMemory.HeaterTempOn_read();
  do
  {
    wdt_reset();
    ReefAngel.LCD.DrawText(COLOR_BLACK, COLOR_WHITE, 10, 10,"Heater Temperature");
  
    ReefAngel.LCD.DrawText(COLOR_BLACK, COLOR_WHITE, 10, 100,"Up/Down to Change");
    ReefAngel.LCD.DrawText(COLOR_BLACK, COLOR_WHITE, 10, 110,"Press to Confirm");
    char t[10];
    ConvertNumToString(t, u, 10);
    strcat(t,"  ");  
    ReefAngel.LCD.DrawText(COLOR_CRIMSON, COLOR_WHITE, 57, 55,t);
    ReefAngel.LCD.DrawText(COLOR_CRIMSON,COLOR_WHITE, 65, 45, "^");
    ReefAngel.LCD.DrawText(COLOR_CRIMSON,COLOR_WHITE, 65, 65, "`");  
    if (ReefAngel.Joystick.IsUp())
    {
      u++;
    }
    if (ReefAngel.Joystick.IsDown())
    {
      u--;
    }
    if (u>999) u=0;
    if (u<0) u=999;    
    if (ReefAngel.Joystick.IsButtonPressed())
    {
      InternalMemory.HeaterTempOn_write(u);
      heatertemp=u;
      bDone=true;
    }
  }
  while(!bDone);
  ReefAngel.DisplayedMenu=RETURN_MAIN_MODE;  }

Roberto.
discocarp
Posts: 21
Joined: Fri Oct 05, 2012 9:13 am

Re: Dosing pump and "in the internal memory"

Post by discocarp »

Thanks. Looks like the next step for me is to figure out how to replace the menu.
discocarp
Posts: 21
Joined: Fri Oct 05, 2012 9:13 am

Re: Dosing pump and "in the internal memory"

Post by discocarp »

Thanks, that looks very helpful. I got a little distracted by my tunzes, but this is next on the list.
discocarp
Posts: 21
Joined: Fri Oct 05, 2012 9:13 am

Re: Dosing pump and "in the internal memory"

Post by discocarp »

So I got the sample custom menu put in. No problem. But now I can't get it out. I put the menu code in a #ifdef to disable it. Then I deleted the 2 lines in ReefAngelFeatures but when I go to upload it changes them back automatically and then tells me it can't find my menu functions. Any ideas? I'd like to be able to go back and forth to the standard menu and the custom one until I get it all worked out.
discocarp
Posts: 21
Joined: Fri Oct 05, 2012 9:13 am

Re: Dosing pump and "in the internal memory"

Post by discocarp »

It seems like it is just autodetecting the number of menu entries in my INO and changing the ReefAngelFeatures.h to match, even if they're inside disabled #ifdef's. Easy enough to work around that.
rimai
Posts: 12857
Joined: Fri Mar 18, 2011 6:47 pm

Re: Dosing pump and "in the internal memory"

Post by rimai »

Correct.
It auto-detects and will apply even if it is inside comments or #ifdef.
Roberto.
discocarp
Posts: 21
Joined: Fri Oct 05, 2012 9:13 am

Re: Dosing pump and "in the internal memory"

Post by discocarp »

So I got a custom int in InternalMemory set up, and created a custom menu that can edit it. Woohoo. The next step is to write something to pick which variable I'm editing. Thanks for all the help. I'm statrting to get a good feel for things.
discocarp
Posts: 21
Joined: Fri Oct 05, 2012 9:13 am

Re: Dosing pump and "in the internal memory"

Post by discocarp »

I have a few questions:

What is PROGMEM when declaring variables? When should I be using it?

How much internal memory do I have, and what addresses are safe to use?

what is wdt_reset? Do I need this in my menu input loops?

Do I need to call pingSerial in my menu input loops?

Is there anything else I should be calling in my input loops?
rimai
Posts: 12857
Joined: Fri Mar 18, 2011 6:47 pm

Re: Dosing pump and "in the internal memory"

Post by rimai »

http://arduino.cc/en/Reference/PROGMEM
Depends on which RA you have.
You have 1K on standard RA and 4K on RA+
watchdog is required to be executed within 1 second or it reboots the controller.
http://www.nongnu.org/avr-libc/user-man ... chdog.html
pingSerial takes care of wifi serial data handling.
Roberto.
discocarp
Posts: 21
Joined: Fri Oct 05, 2012 9:13 am

Re: Dosing pump and "in the internal memory"

Post by discocarp »

I have the RA+.

So then there is much more memory space with PROGMEM, but the stuff needs to stay constant. Perfect for what I need.

I learned about the watchdog the hard way. :)

I'm still confused about pingSerial. I am inside a loop waiting for joystick input, where I had to add the wdt_reset. I don't have the wifi installed yet, but when I do (very soon) should I be calling pingSerial there too?

And on the internal memory (InternalMemory.read), where should I start my numbering?
rimai
Posts: 12857
Joined: Fri Mar 18, 2011 6:47 pm

Re: Dosing pump and "in the internal memory"

Post by rimai »

Yes, you will need pingSerial, or you may not get the wifi commands to work while you are inside the menu.
You should be good to use memory location 100 to 200 or above 1024.
Roberto.
discocarp
Posts: 21
Joined: Fri Oct 05, 2012 9:13 am

Re: Dosing pump and "in the internal memory"

Post by discocarp »

Thanks for all your help getting started.

I got the custom menu added, lots of constant arrays into the PROGMEM, added 3 more dosing pumps that dose by a daily amount and a pump rate, both those variables into internal memory for all 3 pumps, and a configurable variable editor into the menu.

Whew. :)
User avatar
DrewPalmer04
Posts: 818
Joined: Tue May 29, 2012 2:12 pm
Location: Christopher, IL

Re: Dosing pump and "in the internal memory"

Post by DrewPalmer04 »

Your code?
Out for now...but not over.

VISIT: Ethernet Module/Wifi Alternative
discocarp
Posts: 21
Joined: Fri Oct 05, 2012 9:13 am

Re: Dosing pump and "in the internal memory"

Post by discocarp »

I wouldn't consider this final code. I'd like to clean it up and test it a little more, but it seems to be working fine. If you have wifi, search for ping_Serial and uncomment it out. I don't have my wifi set up yet. That's next on the list.

Code: Select all

#include <ReefAngel_Features.h>
#include <Globals.h>
#include <RA_Wifi.h>
#include <Wire.h>
#include <OneWire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <InternalEEPROM.h>
#include <RA_NokiaLCD.h>
#include <RA_ATO.h>
#include <RA_Joystick.h>
#include <LED.h>
#include <RA_TempSensor.h>
#include <Relay.h>
#include <RA_PWM.h>
#include <Timer.h>
#include <Memory.h>
#include <InternalEEPROM.h>
#include <RA_Colors.h>
#include <RA_CustomColors.h>
#include <Salinity.h>
#include <RF.h>
#include <IO.h>
#include <ORP.h>
#include <AI.h>
#include <PH.h>
#include <WaterLevel.h>
#include <ReefAngel.h>

#include <avr/pgmspace.h>
////// Place global variable code below here


// Create the menu entries         
// menu text <= 20 chars
prog_char menu1_label[] PROGMEM = "Feeding";
prog_char menu2_label[] PROGMEM = "Water Change";
prog_char menu3_label[] PROGMEM = "ATO Clear";
prog_char menu4_label[] PROGMEM = "Overheat Clear";
prog_char menu5_label[] PROGMEM = "PH Calibration";
prog_char menu6_label[] PROGMEM = "Date / Time";
prog_char menu7_label[] PROGMEM = "Version";
prog_char menu8_label[] PROGMEM = "Variables";
prog_char menu9_label[] PROGMEM = "Reserved";

// Group the menu entries together
PROGMEM const char *menu_items[] = {
menu1_label, menu2_label, menu3_label,
menu4_label, menu5_label, menu6_label,
menu7_label, menu8_label, menu9_label
};

#define DOSER3_PORT Port1
#define DOSER4_PORT Port2
#define DOSER5_PORT Port3

#define IM_DOSER3AMOUNT 120 // int16
#define IM_DOSER3RATE 122 // int16
#define IM_DOSER4AMOUNT 124 // int16
#define IM_DOSER4RATE 126 // int16
#define IM_DOSER5AMOUNT 128 // int16
#define IM_DOSER5RATE 130 // int16


// Number of variables to edit, The PROGMEM arrays below must match
#define IMEDIT_COUNT 6

// comment this out to turn off the ok/cancel button for variable editing
#define IMEDIT_OKCANCEL

// all IMEDIT strings must be <= 20 chars

prog_char imedit_name_0[] PROGMEM = "Doser 3 Amount";
prog_char imedit_name_1[] PROGMEM = "Doser 3 Rate";
prog_char imedit_name_2[] PROGMEM = "Doser 4 Amount";
prog_char imedit_name_3[] PROGMEM = "Doser 4 Rate";
prog_char imedit_name_4[] PROGMEM = "Doser 5 Amount";
prog_char imedit_name_5[] PROGMEM = "Doser 5 Rate";

PROGMEM const char *imedit_name[] = {
  imedit_name_0, imedit_name_1, imedit_name_2, imedit_name_3, imedit_name_4, imedit_name_5
};

prog_char imedit_aux1_0[] PROGMEM = "mL/day";
prog_char imedit_aux1_1[] PROGMEM = "mL/min";

PROGMEM const char *imedit_aux1[] = {
  imedit_aux1_0, imedit_aux1_1, imedit_aux1_0, imedit_aux1_1, imedit_aux1_0, imedit_aux1_1 // reuse the doser unit strings for 3 dosers
};

PROGMEM prog_int16_t imedit_mempos[] = {
  IM_DOSER3AMOUNT, IM_DOSER3RATE, IM_DOSER4AMOUNT, IM_DOSER4RATE, IM_DOSER5AMOUNT, IM_DOSER5RATE
};

PROGMEM prog_char imedit_isbyte[] = {
  0, 0, 0, 0, 0, 0
};

PROGMEM prog_int16_t imedit_min[] = {
  0, 0, 0, 0, 0, 0
};

PROGMEM prog_int16_t imedit_max[] = {
  32767, 32767, 32767, 32767, 32767, 32767
};

PROGMEM prog_int16_t imedit_format[] = {
  1, 10, 1, 10, 1, 10
};

void RequiredForInputLoops() {
  wdt_reset(); // watch dog timer reset, just leave this here
  //**todo** enable ping_Serial() when wifi hooked up
  //ping_Serial(); // handle wifi events
}

boolean IMEDIT_get_isbyte(int pos) {
  if (pgm_read_byte(&(imedit_isbyte[pos]))!=0) return true;
  return false;
}

int IMEDIT_get_format(int pos) {
  return pgm_read_word(&(imedit_format[pos]));
}

int IMEDIT_get_mempos(int pos) {
  return pgm_read_word(&(imedit_mempos[pos]));
}

int IMEDIT_get_min(int pos) {
  return pgm_read_word(&(imedit_min[pos]));
}

int IMEDIT_get_max(int pos) {
  return pgm_read_word(&(imedit_max[pos]));
}

void IMEdit_get_name(char *dest, int pos) {
  int ptr;
  ptr = pgm_read_word(&(imedit_name[pos]));
  strcpy_P(dest, (char*)ptr);  
}

void IMEdit_get_aux1(char *dest, int pos) {
  int ptr;
  ptr = pgm_read_word(&(imedit_aux1[pos]));
  strcpy_P(dest, (char*)ptr);  
}

void IMEdit_EditorByIMPos(int pos) {
  char name[21];
  char aux1[21];
  
  IMEdit_get_name(name,pos);  
  IMEdit_get_aux1(aux1,pos);  
  
  IMEdit_Editor(name,
                aux1,"","",
                IMEDIT_get_min(pos),
                IMEDIT_get_max(pos), 
                IMEDIT_get_mempos(pos), 
                IMEDIT_get_isbyte(pos), 
                IMEDIT_get_format(pos));  
}


void IMEdit_Picker() {
  int pos=0;
  boolean done=false;
  boolean redraw=true;
  int i,j,y;
  char str[21];
  
  while (!done) {
    RequiredForInputLoops();
    
    // Draw the list with the item at pos at the center of the screen 
    // 11 items on screen 
    if (redraw) {
      redraw=false;
      y=10;
      for (i=pos-5; i<=pos+5; i++) {
        if ((i<0)||(i>IMEDIT_COUNT)) {
          ReefAngel.LCD.DrawText(COLOR_BLACK, COLOR_WHITE, 10, y, "                    ");
        } else if (i==IMEDIT_COUNT) {
          if (i==pos) 
            ReefAngel.LCD.DrawText(COLOR_WHITE, COLOR_BLUE, 10, y, "Exit                ");
          else 
            ReefAngel.LCD.DrawText(COLOR_BLACK, COLOR_WHITE, 10, y, "Exit                ");          
        } else {
          IMEdit_get_name(str,i);
          int len=strlen(str);
          for (j=0; j<20-len; j++) {
            strcat(str," ");
          }
          if (i==pos) 
            ReefAngel.LCD.DrawText(COLOR_WHITE, COLOR_BLUE, 10, y, str);
          else 
            ReefAngel.LCD.DrawText(COLOR_BLACK, COLOR_WHITE, 10, y, str);
        }
        
        y+=10;
      }
    }
    
    if (ReefAngel.Joystick.IsUp()) {
      if (pos > 0) {
        pos--;
        redraw=true;
      } else if (pos==0) {
        pos=IMEDIT_COUNT;
        redraw=true;
      }
    }
    
    if (ReefAngel.Joystick.IsLeft()) {
      pos-=5;
      if (pos<0) pos=0;
      redraw=true;
    }
    
    if (ReefAngel.Joystick.IsDown()) {
      if (pos < IMEDIT_COUNT) {
        pos++;
        redraw=true;
      } else if (pos==IMEDIT_COUNT) {
        pos=0;
        redraw=true;
      }
    }

    if (ReefAngel.Joystick.IsRight()) {
      pos+=5;
      if (pos > IMEDIT_COUNT) pos=IMEDIT_COUNT;
      redraw=true;
    }
    
    if (ReefAngel.Joystick.IsButtonPressed()) {
      if (pos==IMEDIT_COUNT) {
        // Exit selected
        done=true;
      } else {
        ReefAngel.LCD.Clear(COLOR_WHITE,1,1,132,132);
        IMEdit_EditorByIMPos(pos);
        ReefAngel.LCD.Clear(COLOR_WHITE,1,1,132,132);
        redraw=true;
      }
    }
  }
  
}

void IMEdit_Editor(char *Name, char *auxline1, char *auxline2, char *auxline3, int minval, int maxval, int memorypos, boolean is_byte, int format) {
  int val;
  char str[10];
  int x;
  boolean redraw=true;
  boolean done=false;
  
  // read the variable from memory
  if (!is_byte) {     
    val=InternalMemory.read_int(memorypos);
  } else {
    val=InternalMemory.read(memorypos);
  }
  
  // constrain it based on min/max
  if (val<minval) val=minval;
  if (val>maxval) val=maxval;
  
     
     
  // set up the stepping
  int step=1;
  int maxstep=10000;
  while (maxstep > maxval) {
    maxstep /= 10;
  }

#define IMEDIT_VAR_Y 70    
#define IMEDIT_STEP_Y 105


  // draw the header and footer
  ReefAngel.LCD.DrawText(COLOR_WHITE, COLOR_BLUE, 6, 10, "                    ");    
  x=66-3*strlen(Name); // center text
  ReefAngel.LCD.DrawText(COLOR_WHITE, COLOR_BLUE, x, 10, Name);
  ReefAngel.LCD.DrawText(COLOR_BLACK, COLOR_WHITE, 10, 20, auxline1);
  ReefAngel.LCD.DrawText(COLOR_BLACK, COLOR_WHITE, 10, 30, auxline2);
  ReefAngel.LCD.DrawText(COLOR_BLACK, COLOR_WHITE, 10, 40, auxline3);
                   
  //x=66-3*strlen("Press when done"); // center text
  //x=66-3*15=21
  ReefAngel.LCD.DrawText(COLOR_BLACK, COLOR_WHITE, 21, 120,"Press when done"); 
  
  // input loop
  while (!done) {
    RequiredForInputLoops();

    if (redraw) {
      redraw=false;
      
      // draw variable
      ConvertNumToString(str, val, format);
      x=66-3*strlen(str); // center text
      ReefAngel.LCD.Clear(COLOR_BLUE,33,IMEDIT_VAR_Y-16,98,IMEDIT_VAR_Y+22);
      ReefAngel.LCD.DrawText(COLOR_WHITE, COLOR_BLUE, 39, IMEDIT_VAR_Y-8, "    ^    ");
      ReefAngel.LCD.DrawText(COLOR_WHITE, COLOR_BLUE, 39, IMEDIT_VAR_Y+8, "    `    "); 
      ReefAngel.LCD.DrawText(COLOR_WHITE, COLOR_BLUE, x, IMEDIT_VAR_Y, str);    
      
      // draw step
      ConvertNumToString(str, step, format);    
      x=strlen(str);
      x=66-3*x;
      ReefAngel.LCD.Clear(COLOR_WHITE,40,IMEDIT_STEP_Y-1,92,IMEDIT_STEP_Y+10);
      ReefAngel.LCD.DrawText(COLOR_BLACK, COLOR_WHITE, 57, IMEDIT_STEP_Y-8, "+/-");
      ReefAngel.LCD.DrawText(COLOR_BLACK, COLOR_WHITE, x, IMEDIT_STEP_Y, str);    
      ReefAngel.LCD.DrawText(COLOR_BLACK, COLOR_WHITE, 33, IMEDIT_STEP_Y, "<");
      ReefAngel.LCD.DrawText(COLOR_BLACK, COLOR_WHITE, 93, IMEDIT_STEP_Y, ">");
      
      
    }
    
    if (ReefAngel.Joystick.IsUp()) {
      // increase variable
      if (maxval - step < val) 
        val=maxval;
      else 
        val+=step;
      redraw=true;
    }
    
    if (ReefAngel.Joystick.IsDown()) {
      // decrease variable
      if (minval + step > val) 
        val=minval;
      else
        val-=step;
      redraw=true;
    }
    
    if (ReefAngel.Joystick.IsRight()) {
      // increase step
      if (step==maxstep) step=1;
      else step*=10;
      redraw=true;
    }
    
    if (ReefAngel.Joystick.IsLeft()) {
      // decrease step
      if (step==1) step=maxstep;
      else step/=10;
      redraw=true;
    }
    
    if (ReefAngel.Joystick.IsButtonPressed()) {

#ifdef IMEDIT_OKCANCEL      
      // switch to ok/cancel mode
      
      while (ReefAngel.Joystick.IsButtonPressed()); // don't start until joystick is lifted
      
      boolean isok=true;

      ReefAngel.LCD.Clear(COLOR_WHITE,1,IMEDIT_STEP_Y-9,132,132);
      
      while (!done) {
        RequiredForInputLoops();
        
        if (isok) {
          ReefAngel.LCD.DrawText(COLOR_WHITE, COLOR_BLUE, 12, 110,"   Ok   ");
          ReefAngel.LCD.DrawText(COLOR_BLACK, COLOR_WHITE, 72, 110," Cancel ");
        } else {
          ReefAngel.LCD.DrawText(COLOR_BLACK, COLOR_WHITE, 12, 110,"   Ok   ");
          ReefAngel.LCD.DrawText(COLOR_WHITE, COLOR_BLUE, 72, 110," Cancel ");
        }
        
        if (ReefAngel.Joystick.IsRight()||ReefAngel.Joystick.IsLeft()||ReefAngel.Joystick.IsUp()||ReefAngel.Joystick.IsDown()) {
          isok=!isok;
        }
        
       
        if (ReefAngel.Joystick.IsButtonPressed()) {
          done=true; // this ends 2 while loops, taking us outside the outer loop
        }
      } // end while
 
#else
    isok=true;
    done=true;
#endif
    if (isok) {
      // just set the variable, no ok/cancel
      if (is_byte)
        InternalMemory.write(memorypos,byte(val));
      else       
        InternalMemory.write_int(memorypos,val);
    }
      

    } //end if button pressed
  
  } // end while
  
}


void MenuEntry1()
{
  ReefAngel.FeedingModeStart();
}

void MenuEntry2()
{
  ReefAngel.WaterChangeModeStart();
}
void MenuEntry3()
{
  ReefAngel.ATOClear();
  ReefAngel.DisplayMenuEntry("Clear ATO Timeout");
}
void MenuEntry4()
{
  ReefAngel.OverheatClear();
  ReefAngel.DisplayMenuEntry("Clear Overheat");
}
void MenuEntry5()
{
  ReefAngel.SetupCalibratePH();
  ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry6()
{
  ReefAngel.SetupDateTime();
  ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry7()
{
  ReefAngel.DisplayVersion();
}

void MenuEntry8()
{
  IMEdit_Picker();
  ReefAngel.DisplayedMenu=ALT_SCREEN_MODE;
}

void MenuEntry9()
{
  // Not yet implemented
  ReefAngel.DisplayedMenu=RETURN_MAIN_MODE; 
}


void setup()
{
    // This must be the first line
    ReefAngel.Init();  //Initialize controller
    
    

    ReefAngel.InitMenu(pgm_read_word(&(menu_items[0])),SIZE(menu_items));
    //ReefAngel.AddStandardMenu();  // Add Standard Menu


    // Ports toggled in Feeding Mode
    ReefAngel.FeedingModePorts = 0;
    // Ports toggled in Water Change Mode
    ReefAngel.WaterChangePorts = 0;
    // Ports toggled when Lights On / Off menu entry selected
    ReefAngel.LightsOnPorts = 0;
    // Ports turned off when Overheat temperature exceeded
    ReefAngel.OverheatShutoffPorts = 0;
    // Use T1 probe as temperature and overheat functions
    ReefAngel.TempProbe = T1_PROBE;
    ReefAngel.OverheatProbe = T1_PROBE;
    // Set the Overheat temperature setting
    InternalMemory.OverheatTemp_write( 840 );


    // Ports that are always on

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

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


void RunDosers345() {
   double dose; // applied every 15 minutes, 96 times per day
   double rate;
   int tmp;
   
   
   tmp=InternalMemory.read_int(IM_DOSER3AMOUNT);   
   if (tmp > 0) {
     dose=double(tmp);
     rate=double(InternalMemory.read_int(IM_DOSER3RATE))/10.0;
     
     dose=(60.0*dose)/(96.0*rate); // now it is in seconds per 15 minute dose
     dose=dose + 0.5; // round to int properly
     tmp=int(dose);
     
     ReefAngel.DosingPumpRepeat(DOSER3_PORT,0,15,tmp);   
   }
   
   tmp=InternalMemory.read_int(IM_DOSER4AMOUNT);   
   if (tmp > 0) {
     dose=double(tmp);
     rate=double(InternalMemory.read_int(IM_DOSER4RATE))/10.0;
     
     dose=(60.0*dose)/(96.0*rate); // now it is in seconds per 15 minute dose
     dose=dose + 0.5; // round to int properly
     tmp=int(dose);
     
     ReefAngel.DosingPumpRepeat(DOSER4_PORT,5,15,tmp);   
   }
   
   tmp=InternalMemory.read_int(IM_DOSER5AMOUNT);   
   if (tmp > 0) {
     dose=double(tmp);
     rate=double(InternalMemory.read_int(IM_DOSER5RATE))/10.0;
     
     dose=(60.0*dose)/(96.0*rate); // now it is in seconds per 15 minute dose
     dose=dose + 0.5; // round to int properly
     tmp=int(dose);
     
     ReefAngel.DosingPumpRepeat(DOSER5_PORT,10,15,tmp);   
   }
   
}


void loop()
{
    
 
    
    RunDosers345();


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

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



Post Reply