Eheim autofeeder

Request new hardware or ideas for the controller
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: Eheim autofeeder

Post by Sacohen »

So I've done some looking at this and other Auto Feeder threads and this is the code I've come up with.

Code: Select all

static unsigned long feeding = 0;

if ((now()%SECS_PER_DAY==64800)) //if it is 6 pm
{
ReefAngel.FeedingModeStart(); //START FEEDING MODE
}

if (ReefAngel.DisplayedMenu==FEEDING_MODE)
{
if ( feeding == 0 ) {
feeding = now(); //set the time of the start of feeding to variable feeding
}

if ((now()-feeding>=60) && (now()-feeding<=61)) //if between 60 and 61 seconds has past
{
ReefAngel.Relay.On(Feeder); //TURN FEEDER RELAY ON
}
else 
{
ReefAngel.Relay.Off(Feeder); //TURN FEEDER RELAY OFF
}
} else {
if ( feeding > 0 ) {
feeding = 0;
}
}
The Relay in the feeder will be triggered off my Power Expansion Module Port #3, which I will set up like this...

Code: Select all

// Define Relay Ports by Name
#define Actinic_Lights     1
#define Day_Lights         2
#define Unused             3
#define Pumps              4
#define Sump_Fan           5
#define DeNit_Doser        6
#define DeNit_Pump         7
#define Unused             8

#define ATO_Pump           Box1_Port1
#define Moon_Lights        Box1_Port2
#define Feeder             Box1_Port3
#define Unused             Box1_Port4
#define Unused             Box1_Port5
#define Unused             Box1_Port6
#define Unused             Box1_Port7
#define Dummy              Box1_Port8
Lee you are the most familiar with my code (since you just reworked it for me).
Does this look good?
It looks like this will drop the power on the Jebao pumps like turning on Feeding Mode from the head unit or the Andriod App. Is that correct?
Will it work with the NTM that is set up to run after a feeding?
Will this work if I wanted to do a manual feeding from the RA head unit or the Andriod App?
If not I guess I could always do a manual trigger on the Feeder Port.

Am I asking to many questions, just tell me to shut up :).
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: Eheim autofeeder

Post by lnevo »

It looks fine and should trigger everything you currently do with Feeding mode. The call to FeedingModeStart() is the same as hitting the feeding button in the apps/portal or with joystick. Good job!
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: Eheim autofeeder

Post by Sacohen »

Thank you. Again the work was done already (I think by you actually for someone else) I just took it and modified it a bit.
Piper
Posts: 296
Joined: Fri Jul 20, 2012 7:13 am
Location: Oakley, CA

Re: Eheim autofeeder

Post by Piper »

egadgetjnr wrote: Hey piper, how did you use it with you IO module? I want to do something similar for my ozone but at the moment only have it setup to power a 12v wall wart relay to trigger it on and off. Could you take some photos and possibly show some code on how you coded it? I just can't get my head around how you use the IO module to trigger the relay or switch.
Will do. If not tonight, I can get to it tomorrow night.
egadgetjnr
Posts: 54
Joined: Wed Jul 18, 2012 1:32 pm

Re: Eheim autofeeder

Post by egadgetjnr »

Piper wrote: Will do. If not tonight, I can get to it tomorrow night.
No worries. Thank you
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: Eheim autofeeder

Post by Sacohen »

Got my feeder today. It's much smaller than I thought.
Will probably mod and set it up this weekend.

Thanks for the help.
Piper
Posts: 296
Joined: Fri Jul 20, 2012 7:13 am
Location: Oakley, CA

Re: Eheim autofeeder

Post by Piper »

Piper wrote:
egadgetjnr wrote: Hey piper, how did you use it with you IO module? I want to do something similar for my ozone but at the moment only have it setup to power a 12v wall wart relay to trigger it on and off. Could you take some photos and possibly show some code on how you coded it? I just can't get my head around how you use the IO module to trigger the relay or switch.
Will do. If not tonight, I can get to it tomorrow night.
I had a chance to get to this tonight. I'm 90% sure this is the code I uploaded to my I/O module. I basically copied/pasted what Roberto and others put together and haven't really modified much at all.

Code: Select all

#include <Wire.h>
#include <avr/wdt.h>

byte IOports[] ={3,5,6,9,10,11};
byte ChannelValue[] = {0,0,0,0,0,0};
byte cmdnum=255;
byte datanum=255;

byte IOOut=0;

void setup() {
  wdt_enable(WDTO_1S);
  Wire.onReceive(receiveEvent);
  Wire.onRequest(requestEvent);
  Wire.begin(9);
  for (int a=0; a<6; a++) {
    pinMode(IOports[a],INPUT);
    digitalWrite(IOports[a],HIGH); //pull up resistor
    // digitalWrite(IOports[a],LOW); //pull up resistor
  }
}

void loop() {
  wdt_reset();
  if (cmdnum != 255) {
    ProcessCMD(cmdnum,datanum);   
    cmdnum=255;
    datanum=255;
  }
}

void requestEvent() {
  IOOut=0;
  for (int a=0; a<6; a++) {
    IOOut += digitalRead(IOports[a])<<a; //pull up resistor
  }
  Wire.write(IOOut);
}

void receiveEvent(int howMany) {
  wdt_reset();
  if (howMany == 5) {
    byte cmd1, cmd2, cmd3, cmd4, cmd5;
    cmd1=Wire.read();
    cmd2=Wire.read();
    cmd3=Wire.read();
    cmd4=Wire.read();
    cmd5=Wire.read();
    if (cmd1=='$' && cmd2=='$' && cmd3=='$') {
      cmdnum=cmd4;
      datanum=cmd5;
      //Serial.println(cmd4,DEC);
      //Serial.println(cmd5,DEC);
    }
  }
  else {
    for (int a=0; a<howMany; a++) {
      Wire.read();
    }
  }
}

void ProcessCMD(byte cmd, byte data) {
  wdt_reset();
  // Individual Channel
  if (cmd>=0 && cmd<=5) {
    ChannelValue[cmd]=data;
    pinMode(IOports[cmd],OUTPUT);
    analogWrite(IOports[cmd],data);
  }
}

I also added this to the very bottom of my INO file:

Code: Select all

// *****************************************************************************
// * I/O Expansion
// *****************************************************************************

void IOSetChannel( byte channel, boolean status) {
  Wire.beginTransmission(I2CIO);
  Wire.write("$");
  Wire.write("$");
  Wire.write("$");
  Wire.write(channel);
  Wire.write(status?255:0);
  Wire.endTransmission(); 
}
I use this in my INO to listen for button presses:

Code: Select all


// Just below my includes I define my I/O ports:
// I/O Module Constants
#define IO_Port_1    0
#define IO_Port_2    1
#define IO_Port_3    2
#define IO_Port_4    3
#define IO_Port_5    4
#define IO_Port_6    5

// .......

// I have this in my loop to monitor my I/O ports:
    // Check to see if we hit the feeding mode button to trigger the relay
    // If so, set it back to low and clear the flag
    if (ioAutoFeederRelayTriggered == true) {
      IOSetChannel(IO_Port_1,LOW); // Sets channel 0 to LOW
      ioAutoFeederRelayTriggered = false;
    }

    if(!ReefAngel.IO.GetChannel(IO_Port_5)) {
      // ReefAngel.FeedingModeStart();
      IOSetChannel(IO_Port_1,HIGH); // Sets channel 0 to HIGH
      ioAutoFeederRelayTriggered = true;
    }
    
    // Start/Stop Feeding Mode
    if(!ReefAngel.IO.GetChannel(IO_Port_3)) {
      if (!ReefAngel.DisplayedMenu==FEEDING_MODE) {
        ReefAngel.FeedingModeStart();
      }
      else {
        ButtonPress++;
      }
    }
    
    // Start/Stop Water Change Mode
    if(!ReefAngel.IO.GetChannel(IO_Port_4)) {
      if (!ReefAngel.DisplayedMenu==WATERCHANGE_MODE) {
        ReefAngel.WaterChangeModeStart();
      }
      else{
         ButtonPress++;
      }
    }

    // Trigger Nutrient Export Mode
    if(!ReefAngel.IO.GetChannel(IO_Port_6)) {
      triggerNutrientExportMode();
      //ButtonPress++;
    }

I put 4 small tact switches into a small Radio Shack enclosure and velcro'd that inside my canopy door. That feeds down to my I/O module sitting in a cabinet next to my tank. The buttons are wired into ports 3 through 6 (counting from 1 as #defined above, not 0). If the first button is pressed (IO_Port_3) that will put the tank into feeding mode. Button 2/IO_Port_4 the tank goes into water change mode.

Pressing button 3/IO_Port_5 is what actually triggers the feeder. I have a 5v relay connected to IO_Port_1 (port 0). When you press button 3 it sets IO_Port_1 to high with this: IOSetChannel(IO_Port_1,HIGH);. That sends ~5v to the relay which is wired to both sides of the tact switch on the feeder which triggers it to feed/rotate. I also set a flag so I can check to see if IO_Port_1 is high so I can set it back to low and shut off the relay. You can also eliminate the flags with something along the lines of this:

Code: Select all

    if (ReefAngel.IO.GetChannel(IO_Port_1)) {
      IOSetChannel(IO_Port_1,LOW); // Sets channel 0 to LOW
    }
and save a little memory. I just haven't gotten around to fixing that yet myself.

I do have a couple of other problems/TODOs to take care of but I've been too busy lately. I need to "debounce" my buttons. Sometimes I'll get multiple presses when I hit a button once. I'm running a modified version of the dev branch of the libs and the feeding mode and water change mode are not working like they did when I was on the current libs. All are minor issues which wont change the basic concept.

Let me know if you still want pictures. I have the I/O module and related enclosures stuffed in the back of my cabinet. I need to dig them out to get good pics.

~Charlie
ozworld
Posts: 6
Joined: Fri Jun 07, 2013 1:14 pm

Re: Eheim autofeeder

Post by ozworld »

dcartier wrote:I bought one of these for use over Christmas. I installed a micro 5V relay inside and ran a cable out with an 2 pin ATO connector on it. It worked great. Kept things fed for a week.

Dennis
I also used a small 5V relay inside and ran a thermostat 4 in 1 cable (2 for the 3v power supply and 2 to the ATO port). My questions is: what code can I use to trigger the ATO high port to enable the relay? (I have a Reef Angel + Controller).
Thanks!
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: Eheim autofeeder

Post by Sacohen »

I have the code in one of my posts at the top of this page.
You just need to modify it to work with whatever port you are going to use to trigger it.
ozworld
Posts: 6
Joined: Fri Jun 07, 2013 1:14 pm

Re: Eheim autofeeder

Post by ozworld »

Thanks Steve, what I'm looking for is the actual trigger for the ATO High port that is connected to the auto feeder relay.
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: Eheim autofeeder

Post by Sacohen »

I don't know about that. I'm not doing it that way. I'm using the Power Expansion Module to send a 12v trigger to a 12v relay that will close the circuit of the feed button.
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: Eheim autofeeder

Post by Sacohen »

So what actually triggers the relay here?
I know I'm going to use port #3 on my Power control module (#define Feeder Box1_Port3) to send the 12v to the relay, but I don't see where Port #3 is referenced in the code.

Code: Select all

static unsigned long feeding = 0;

if ((now()%SECS_PER_DAY==64800)) //if it is 6 pm
{
ReefAngel.FeedingModeStart(); //START FEEDING MODE
}

if (ReefAngel.DisplayedMenu==FEEDING_MODE)
{
if ( feeding == 0 ) {
feeding = now(); //set the time of the start of feeding to variable feeding
}

if ((now()-feeding>=60) && (now()-feeding<=61)) //if between 60 and 61 seconds has past
{
ReefAngel.Relay.On(Feeder); //TURN FEEDER RELAY ON
}
else 
{
ReefAngel.Relay.Off(Feeder); //TURN FEEDER RELAY OFF
}
} else {
if ( feeding > 0 ) {
feeding = 0;
}
}

Code: Select all

// Define Relay Ports by Name
#define Actinic_Lights     1
#define Day_Lights         2
#define Unused             3
#define Pumps              4
#define Sump_Fan           5
#define DeNit_Doser        6
#define DeNit_Pump         7
#define Unused             8

#define ATO_Pump           Box1_Port1
#define Moon_Lights        Box1_Port2
#define Feeder             Box1_Port3
#define Unused             Box1_Port4
#define Unused             Box1_Port5
#define Unused             Box1_Port6
#define Unused             Box1_Port7
#define Dummy              Box1_Port8
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: Eheim autofeeder

Post by lnevo »

Is that my code?

ReefAngel.Relay.On(Feeder);

That powers the wall wart and then powers the relay...
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: Eheim autofeeder

Post by Sacohen »

I think it is your code. I had been looking at all the threads when the topic first came out and I found this one that I liked.

So since I have Box1_Port3 defined as Feeder it should trigger the port on my Power Control Module.

I had Port 3 defined as Feeder and plugged a shop light into it so I could visually see it come on and nothing happened.
Is it to fast to trigger a light?
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: Eheim autofeeder

Post by lnevo »

Its only on for one second.. You can increase it look for 60 and 61
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: Eheim autofeeder

Post by Sacohen »

That's what I thought. 1 second should be enough for me to see a flash of light but I changed it to 60 and 700 so it should be on for just over 11 min.

Nothing came on.

The port and light both work because I can manually turn the port on from my phone and the light come on.

So something isn't right.

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 <Humidity.h>
#include <DCPump.h>
#include <ReefAngel.h>

// Define Relay Ports by Name
#define Actinic_Lights     1
#define Day_Lights         2
#define Feeder             3
#define Pumps              4
#define Sump_Fan           5
#define DeNit_Doser        6
#define DeNit_Pump         7
#define Unused             8

#define ATO_Pump           Box1_Port1
#define Moon_Lights        Box1_Port2
#define Unused             Box1_Port3
#define Unused             Box1_Port4
#define Unused             Box1_Port5
#define Unused             Box1_Port6
#define Unused             Box1_Port7
#define Dummy              Box1_Port8


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

// Does not need to be global.
// unsigned long ATOUpdate=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.FeedingModePorts = 0;
// Ports toggled in Water Change Mode
ReefAngel.WaterChangePorts = Port4Bit;
ReefAngel.WaterChangePortsE[0] = Port1Bit;
// Ports toggled when Lights On / Off menu entry selected
ReefAngel.LightsOnPorts = Port1Bit | Port2Bit;
// Ports turned off when Overheat temperature exceeded
ReefAngel.OverheatShutoffPorts = Port1Bit | Port2Bit;
// Use T2 probe as temperature and overheat functions
ReefAngel.TempProbe = T1_PROBE;
ReefAngel.OverheatProbe = T1_PROBE;
// Set the Overheat temperature setting
InternalMemory.OverheatTemp_write( 825 );
//Set Standard Menu
ReefAngel.AddStandardMenu();

ReefAngel.Use2014Screen();  // Let's use 2014 Screen 
// Feeeding and Water Change mode speed
ReefAngel.DCPump.FeedingSpeed=0;
ReefAngel.DCPump.WaterChangeSpeed=0;
ReefAngel.DCPump.ActinicChannel=Sync; // Now you're pump will be affected by the portal settings.
ReefAngel.DCPump.DaylightChannel=AntiSync; // Now you're pump will be affected by the portal settings.

// Ports that are always on
ReefAngel.Relay.On( Pumps );
ReefAngel.Relay.On( Dummy );

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


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

void loop()
{
  ReefAngel.StandardLights( Actinic_Lights,12,0,22,0 );
  ReefAngel.StandardLights( Day_Lights,13,0,21,0 );
  ReefAngel.StandardLights( Sump_Fan,13,0,21,0 );
  ReefAngel.WaterLevelATO(ATO_Pump,720,29,32); 
  
  ////// Place your custom code below here
  ReefAngel.Relay.Set( Moon_Lights, !ReefAngel.Relay.Status( Actinic_Lights ) );

  // DeNitrate Routine
  int DeNit_Offset=3600; 
  int DeNit_Repeat=21600;
  int DeNit_Doser_Offset=1200;
  int DeNit_Doser_Runtime=1200;
  int DeNit_Pump_Runtime=1200;
  int DeNit_ATO_Offtime=1500;

  // Pump comes on first
  ReefAngel.Relay.Set(DeNit_Pump,(now()-3600)%21600<1200);       // Runs for 1200s every 21600 seconds  
  // Doser comes on second
  ReefAngel.Relay.Set(DeNit_Doser,((now()-3600)-1200)%21600<1200); // Runs for 1200s every 21600 seconds with 1200s offset
  
  // Disable ATO
if ( (now()-3600)%21600<1500) ReefAngel.WaterLevelATO(ATO_Pump,720,0,1);

  // Delay WL ATO after water change and DeNit_Dosing
  static time_t wcTimer=0;
  if (ReefAngel.DisplayedMenu == WATERCHANGE_MODE) wcTimer=now();

  // First 10 minutes after WC disable ATO
  if (now()-wcTimer >= 0 && now()-wcTimer < 600)
    ReefAngel.WaterLevelATO(ATO_Pump,720,0,1);

    // Track Salinity low duration
    static unsigned long lastGoodSal;
    static boolean lowSalFlag;
   
    // Salinity is good, update counter
    if (ReefAngel.Params.Salinity>=335) lastGoodSal=now(); 
    
    // Counter hasn't been updating in 300 seconds..
    if (now()-lastGoodSal>300) {
      lowSalFlag=true; // Salinity is definitely below 33.5
    } else {
      lowSalFlag=false; // Salinity back to normal
    }
    
    // Disable ATO if lowSalFlag is true
    if (lowSalFlag) ReefAngel.WaterLevelATO(ATO_Pump,720,0,1);
    
  // Disable ATO if ATO High IsActive()
  if (ReefAngel.HighATO.IsActive()) 
    ReefAngel.WaterLevelATO(ATO_Pump,720,0,1);
    

// Add random mode if we set to Mode to Custom in portal
static int rmode;
static boolean changeMode=true;

// Add Else Mode definition..
const int Else=16;

// These are the modes we can cycle through. You can add more and even repeat...
byte modes[] = { ReefCrest, Lagoon, Constant, TidalSwell, ShortPulse, LongPulse, Else };

if (now()%SECS_PER_DAY==0 || changeMode==true) { // Change at midnight or if controller rebooted
rmode=random(100)%sizeof(modes); // Change the mode once per day to pick from our array
changeMode=false;
}

// Set timer when in feeding mode
static unsigned long feeding = 0;

if ((now()%SECS_PER_DAY==30600)) //if it is 8:30pm
{
ReefAngel.FeedingModeStart(); //START FEEDING MODE
}

if (ReefAngel.DisplayedMenu==FEEDING_MODE)
{
if ( feeding == 0 ) {
feeding = now(); //set the time of the start of feeding to variable feeding
}

if ((now()-feeding>=60) && (now()-feeding<=700)) //if between 60 and 700 seconds has past
{
ReefAngel.Relay.On(Feeder); //TURN FEEDER RELAY ON
}
else 
{
ReefAngel.Relay.Off(Feeder); //TURN FEEDER RELAY OFF
}
} else {
if ( feeding > 0 ) {
feeding = 0;
}
}

if (ReefAngel.DisplayedMenu==FEEDING_MODE) feeding=now();

if (now()-feeding<3600) { 
  // Continue NTM for the 60 minutes
  ReefAngel.DCPump.UseMemory=false;
  ReefAngel.DCPump.Duration=InternalMemory.DCPumpDuration_read();
  ReefAngel.DCPump.Mode=NutrientTransport;
} else if (now()%SECS_PER_DAY<43200 || now()%SECS_PER_DAY>=79200) { // 12pm / 10pm
  // Night mode (go to 30%)
  ReefAngel.DCPump.UseMemory=false;
  ReefAngel.DCPump.Duration=InternalMemory.DCPumpDuration_read();
  ReefAngel.DCPump.Mode=Constant;
  ReefAngel.DCPump.Speed=30;
} else if (InternalMemory.DCPumpMode_read()==11) { 
  // Custom Mode and nothing else going on
  ReefAngel.DCPump.UseMemory=false;
  ReefAngel.DCPump.Duration=InternalMemory.DCPumpDuration_read();
  if (rmode==Else) {
    ReefAngel.DCPump.UseMemory=false;
    ReefAngel.DCPump.Mode=Constant;
    ReefAngel.DCPump.Speed=ElseMode(InternalMemory.DCPumpSpeed_read(),20,true );    // ElseMode on sync mode, Portal Speed Setting +/- 20%
  } else {
    ReefAngel.DCPump.Mode=modes[rmode];  // Put the mode to the random mode :)
    ReefAngel.DCPump.Speed=InternalMemory.DCPumpSpeed_read(); // Set speed from portal
  }
} else {
  ReefAngel.DCPump.UseMemory=true; // Will reset all values from memory
}

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

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

void DrawCustomMain()
{
int x,y;
char text[10];
// Parameters
#if defined DisplayLEDPWM && ! defined RemoveAllLights
ReefAngel.LCD.DrawMonitor( 15, 20, ReefAngel.Params,
ReefAngel.PWM.GetDaylightValue(), ReefAngel.PWM.GetActinicValue() );
#else // defined DisplayLEDPWM && ! defined RemoveAllLights
ReefAngel.LCD.DrawMonitor( 15, 20, ReefAngel.Params );
#endif // defined DisplayLEDPWM && ! defined RemoveAllLights
pingSerial();

// Water Level
ReefAngel.LCD.DrawText( COLOR_DARKGOLDENROD,DefaultBGColor,75,66, "WL:" );
ReefAngel.LCD.DrawText( COLOR_DARKGOLDENROD,DefaultBGColor,99,66, ReefAngel.WaterLevel.GetLevel() );
  ConvertNumToString(text, ReefAngel.Params.Salinity, 10);
  strcat(text,"  ");
  ReefAngel.LCD.DrawText(DefaultFGColor,DefaultBGColor,39,75,"Salinity:");
  ReefAngel.LCD.DrawText(DefaultFGColor,DefaultBGColor,99,75,text);
pingSerial();

// Main Relay Box
byte TempRelay = ReefAngel.Relay.RelayData;
TempRelay &= ReefAngel.Relay.RelayMaskOff;
TempRelay |= ReefAngel.Relay.RelayMaskOn;
ReefAngel.LCD.DrawOutletBox( 12, 92, TempRelay );
pingSerial();
TempRelay = ReefAngel.Relay.RelayDataE[0];
TempRelay &= ReefAngel.Relay.RelayMaskOffE[0];
TempRelay |= ReefAngel.Relay.RelayMaskOnE[0];
ReefAngel.LCD.DrawOutletBox(12, 104, TempRelay);

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

void DrawCustomGraph()
{
}
byte ElseMode( byte MidPoint, byte Offset, boolean WaveSync )
{
  // Static's only initialize the first time they are called
  static unsigned long LastChange=millis();        // Set the inital time that the last change occurred
  static int Delay = random( 500, 3000);           // Set the initial delay
  static int NewSpeed = MidPoint;                  // Set the initial speed
  static int AntiSpeed = MidPoint;                 // Set the initial anti sync speed
  if ((millis()-LastChange) > Delay)               // Check if the delay has elapsed
  {
    Delay=random(500,5000);                        // If so, come up with a new delay
    int ChangeUp = random(Offset);                 // Amount to go up or down
    if (random(100)<50)                            // 50/50 chance of speed going up or going down
    {
      NewSpeed = MidPoint - ChangeUp;
      AntiSpeed = MidPoint + ChangeUp;
    }
    else
    {
      NewSpeed = MidPoint + ChangeUp;
      AntiSpeed = MidPoint - ChangeUp;
    }
    LastChange=millis();                           // Reset the time of the last change
  }
  if (WaveSync)
  {
    return NewSpeed;
  }
  else
  {
    return AntiSpeed;
  }
}
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: Eheim autofeeder

Post by lnevo »

You've got a wierd section in there that sets feeding to 0 if its greater than 0. That resets the variable so it never gets > 60...

Its in a wierd else all by itself and it seems like it may have been part of the dcpump feeding section i cant tell...
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: Eheim autofeeder

Post by Sacohen »

Are you talking about this?

static unsigned long feeding = 0;

if ((now()%SECS_PER_DAY==64800)) //if it is 6 pm
{
ReefAngel.FeedingModeStart(); //START FEEDING MODE
}

if (ReefAngel.DisplayedMenu==FEEDING_MODE)
{
if ( feeding == 0 ) {
feeding = now(); //set the time of the start of feeding to variable feeding
}

if ((now()-feeding>=60) && (now()-feeding<=61)) //if between 60 and 61 seconds has past
{
ReefAngel.Relay.On(Feeder); //TURN FEEDER RELAY ON
}
else
{
ReefAngel.Relay.Off(Feeder); //TURN FEEDER RELAY OFF
}
} else {
if ( feeding > 0 ) {
feeding = 0;

}
}

I thought that was a little strange too, but I wasn't sure about it.
It wasn't part of the of the dcpump feeding section, that was in the code that I had found for the auto feeder that I posted here a while back.

The DCpump feeding was like this before I added the autofeed code.

// Set timer when in feeding mode
static unsigned long feeding;
if (ReefAngel.DisplayedMenu==FEEDING_MODE) feeding=now();

I put the Auto Feed code here.

if (now()-feeding<3600) {
// Continue NTM for the 60 minutes
ReefAngel.DCPump.UseMemory=false;
ReefAngel.DCPump.Duration=InternalMemory.DCPumpDuration_read();
ReefAngel.DCPump.Mode=NutrientTransport;
} else if (now()%SECS_PER_DAY<43200 || now()%SECS_PER_DAY>=79200) { // 12pm / 10pm
// Night mode (go to 30%)
ReefAngel.DCPump.UseMemory=false;
ReefAngel.DCPump.Duration=InternalMemory.DCPumpDuration_read();
ReefAngel.DCPump.Mode=Constant;
ReefAngel.DCPump.Speed=30;
} else if (InternalMemory.DCPumpMode_read()==11) {
// Custom Mode and nothing else going on
ReefAngel.DCPump.UseMemory=false;
ReefAngel.DCPump.Duration=InternalMemory.DCPumpDuration_read();
if (rmode==Else) {
ReefAngel.DCPump.UseMemory=false;
ReefAngel.DCPump.Mode=Constant;
ReefAngel.DCPump.Speed=ElseMode(InternalMemory.DCPumpSpeed_read(),20,true ); // ElseMode on sync mode, Portal Speed Setting +/- 20%
} else {
ReefAngel.DCPump.Mode=modes[rmode]; // Put the mode to the random mode :)
ReefAngel.DCPump.Speed=InternalMemory.DCPumpSpeed_read(); // Set speed from portal
}
} else {
ReefAngel.DCPump.UseMemory=true; // Will reset all values from memory
}

Should I remove the

else {
if ( feeding > 0 ) {
feeding = 0;
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: Eheim autofeeder

Post by lnevo »

Yes
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: Eheim autofeeder

Post by Sacohen »

Ok. I'm at the Drs with Seth for a wellness checkup.
I'll try it when I get home.

Sent from my HTC One VX using Tapatalk
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: Eheim autofeeder

Post by Sacohen »

I removed the following and changed the trigger time to noon and it still did not come on.

Removed code

else {
if ( feeding > 0 ) {
feeding = 0;
}
}
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: Eheim autofeeder

Post by lnevo »

You have two functions setting and the dcpump one maintains feeding=now() while in feeding mode. Change the eheimm to use a different variable name instead of feeding.
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: Eheim autofeeder

Post by lnevo »

Thats why the code was there to reset feeding to 0...so will probably need to readd that with the new variable name.
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: Eheim autofeeder

Post by Sacohen »

Ok. I'll give it a try

Sent from my HTC One VX using Tapatalk
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: Eheim autofeeder

Post by Sacohen »

Thank fixed it. Thank you for the help Lee.

I still don't really get coding. I thought since both the Auto Feeder routine and the DCpump feed routine both started with unsigned long feeding I could combine them into one section.
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: Eheim autofeeder

Post by lnevo »

Its the behavior of how i used the feeding variable. In the dcpump version i keep updating it to now() while feeding mode is active.

The code would have triggered eventually (one minute after feeding mode finished).

The feeder one only changes feeding to now when you first enter feeding mode.

We can make them both work off the same variable, just need to change some timings. Once you get things where you want let me know when you update your thread and I'll take a look at how to do that.
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: Eheim autofeeder

Post by Sacohen »

Ok. I haven't had luck soldering the relay to the feeder switch. Right now I have the feeder and RA in sync (well close) so when the feeder kicks in the RA thinks it triggered it and slows down the pumps. I just want to get something in place when I go on vacation in 2 weeks.

Sent from my HTC One VX using Tapatalk
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: Eheim autofeeder

Post by Sacohen »

The port is triggering as is should, but the RA is not going into Feed Mode like it does when I start fee mode thru the head unit or the App.

The pumps don't slow down, I don't see the 10 min countdown on the head unit and the system doesn't go into NTM after the 10 min feeding.

Is that because they need to be working off the same variable like you said above?

My current code with the exception of the Auto feed is in my sig.

Do you need the whole thing as is now?
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

Re: Eheim autofeeder

Post by lnevo »

Let me see what you have now. I think you may have renamed something wrong...
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: Eheim autofeeder

Post by Sacohen »

Here is the code as it is now in the RA.

I renamed the function from feeding to autofeeding in the Auto feeder section

Code: Select all

[code][code]#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 <Humidity.h>
#include <DCPump.h>
#include <ReefAngel.h>

// Define Relay Ports by Name
#define Actinic_Lights     1
#define Day_Lights         2
#define Unused             3
#define Pumps              4
#define Sump_Fan           5
#define DeNit_Doser        6
#define DeNit_Pump         7
#define Unused             8

#define ATO_Pump           Box1_Port1
#define Moon_Lights        Box1_Port2
#define Feeder             Box1_Port3
#define Unused             Box1_Port4
#define Unused             Box1_Port5
#define Unused             Box1_Port6
#define Unused             Box1_Port7
#define Dummy              Box1_Port8


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

// Does not need to be global.
// unsigned long ATOUpdate=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.FeedingModePorts = 0;
// Ports toggled in Water Change Mode
ReefAngel.WaterChangePorts = Port4Bit;
ReefAngel.WaterChangePortsE[0] = Port1Bit;
// Ports toggled when Lights On / Off menu entry selected
ReefAngel.LightsOnPorts = Port1Bit | Port2Bit;
// Ports turned off when Overheat temperature exceeded
ReefAngel.OverheatShutoffPorts = Port1Bit | Port2Bit;
// Use T2 probe as temperature and overheat functions
ReefAngel.TempProbe = T1_PROBE;
ReefAngel.OverheatProbe = T1_PROBE;
// Set the Overheat temperature setting
InternalMemory.OverheatTemp_write( 825 );
//Set Standard Menu
ReefAngel.AddStandardMenu();

// Feeeding and Water Change mode speed
ReefAngel.DCPump.FeedingSpeed=0;
ReefAngel.DCPump.WaterChangeSpeed=0;
ReefAngel.DCPump.ActinicChannel=Sync; // Now you're pump will be affected by the portal settings.
ReefAngel.DCPump.DaylightChannel=AntiSync; // Now you're pump will be affected by the portal settings.

// Ports that are always on
ReefAngel.Relay.On( Pumps );
ReefAngel.Relay.On( Dummy );

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


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

void loop()
{
  ReefAngel.StandardLights( Actinic_Lights,12,0,22,0 );
  ReefAngel.StandardLights( Day_Lights,13,0,21,0 );
  ReefAngel.StandardLights( Sump_Fan,13,0,21,0 );
  ReefAngel.WaterLevelATO(ATO_Pump,720,31,34); 

  ////// Place your custom code below here
  ReefAngel.Relay.Set( Moon_Lights, !ReefAngel.Relay.Status( Actinic_Lights ) );
  
  //AutoFeeder
static unsigned long autofeeding = 0;

if ((now()%SECS_PER_DAY==64800)) //if it is 6 pm
{
ReefAngel.FeedingModeStart(); //START FEEDING MODE
}

if (ReefAngel.DisplayedMenu==FEEDING_MODE)
{
if ( autofeeding == 0 ) {
autofeeding = now(); //set the time of the start of feeding to variable feeding
}

if ((now()-autofeeding>=60) && (now()-autofeeding<=61)) //if between 60 and 61 seconds has past
{
ReefAngel.Relay.On(Feeder); //TURN FEEDER RELAY ON
}
else 
{
ReefAngel.Relay.Off(Feeder); //TURN FEEDER RELAY OFF
}
} else {
if ( autofeeding > 0 ) {
autofeeding = 0;
}
}
  // DeNitrate Routine
  int DeNit_Offset=3600; 
  int DeNit_Repeat=21600;
  int DeNit_Doser_Offset=1200;
  int DeNit_Doser_Runtime=1200;
  int DeNit_Pump_Runtime=1200;
  int DeNit_ATO_Offtime=1500;

  // Pump comes on first
  ReefAngel.Relay.Set(DeNit_Pump,(now()-3600)%21600<1200);       // Runs for 1200s every 21600 seconds  
  // Doser comes on second
  ReefAngel.Relay.Set(DeNit_Doser,((now()-3600)-1200)%21600<1200); // Runs for 1200s every 21600 seconds with 1200s offset
  
  // Disable ATO
if ( (now()-3600)%21600<1500) ReefAngel.WaterLevelATO(ATO_Pump,720,0,1);

  // Delay WL ATO after water change and DeNit_Dosing
  static time_t wcTimer=0;
  if (ReefAngel.DisplayedMenu == WATERCHANGE_MODE) wcTimer=now();

  // First 10 minutes after WC disable ATO
  if (now()-wcTimer >= 0 && now()-wcTimer < 600)
    ReefAngel.WaterLevelATO(ATO_Pump,720,0,1);

    // Track Salinity low duration
    static unsigned long lastGoodSal;
    static boolean lowSalFlag;
   
    // Salinity is good, update counter
    if (ReefAngel.Params.Salinity>=335) lastGoodSal=now(); 
    
    // Counter hasn't been updating in 300 seconds..
    if (now()-lastGoodSal>300) {
      lowSalFlag=true; // Salinity is definitely below 33.5
    } else {
      lowSalFlag=false; // Salinity back to normal
    }
    
    // Disable ATO if lowSalFlag is true
    if (lowSalFlag) ReefAngel.WaterLevelATO(ATO_Pump,720,0,1);
    
  // Disable ATO if ATO High IsActive()
  if (ReefAngel.HighATO.IsActive()) 
    ReefAngel.WaterLevelATO(ATO_Pump,720,0,1);
    

// Add random mode if we set to Mode to Custom in portal
static int rmode;
static boolean changeMode=true;

// Add Else Mode definition..
const int Else=16;

// These are the modes we can cycle through. You can add more and even repeat...
byte modes[] = { ReefCrest, Lagoon, Constant, TidalSwell, ShortPulse, LongPulse, Else };

if (now()%SECS_PER_DAY==0 || changeMode==true) { // Change at midnight or if controller rebooted
rmode=random(100)%sizeof(modes); // Change the mode once per day to pick from our array
changeMode=false;
}

// Set timer when in feeding mode
static unsigned long feeding;
if (ReefAngel.DisplayedMenu==FEEDING_MODE) feeding=now();

if (now()-feeding<3600) { 
  // Continue NTM for the 60 minutes
  ReefAngel.DCPump.UseMemory=false;
  ReefAngel.DCPump.Duration=InternalMemory.DCPumpDuration_read();
  ReefAngel.DCPump.Mode=NutrientTransport;
} else if (now()%SECS_PER_DAY<43200 || now()%SECS_PER_DAY>=79200) { // 12pm / 10pm
  // Night mode (go to 30%)
  ReefAngel.DCPump.UseMemory=false;
  ReefAngel.DCPump.Duration=InternalMemory.DCPumpDuration_read();
  ReefAngel.DCPump.Mode=Constant;
  ReefAngel.DCPump.Speed=30;
} else if (InternalMemory.DCPumpMode_read()==11) { 
  // Custom Mode and nothing else going on
  ReefAngel.DCPump.UseMemory=false;
  ReefAngel.DCPump.Duration=InternalMemory.DCPumpDuration_read();
  if (rmode==Else) {
    ReefAngel.DCPump.UseMemory=false;
    ReefAngel.DCPump.Mode=Constant;
    ReefAngel.DCPump.Speed=ElseMode(InternalMemory.DCPumpSpeed_read(),20,true );    // ElseMode on sync mode, Portal Speed Setting +/- 20%
  } else {
    ReefAngel.DCPump.Mode=modes[rmode];  // Put the mode to the random mode :)
    ReefAngel.DCPump.Speed=InternalMemory.DCPumpSpeed_read(); // Set speed from portal
  }
} else {
  ReefAngel.DCPump.UseMemory=true; // Will reset all values from memory
}

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

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

void DrawCustomMain()
{
int x,y;
char text[10];
// Parameters
#if defined DisplayLEDPWM && ! defined RemoveAllLights
ReefAngel.LCD.DrawMonitor( 15, 20, ReefAngel.Params,
ReefAngel.PWM.GetDaylightValue(), ReefAngel.PWM.GetActinicValue() );
#else // defined DisplayLEDPWM && ! defined RemoveAllLights
ReefAngel.LCD.DrawMonitor( 15, 20, ReefAngel.Params );
#endif // defined DisplayLEDPWM && ! defined RemoveAllLights
pingSerial();

// Water Level
ReefAngel.LCD.DrawText( COLOR_DARKGOLDENROD,DefaultBGColor,75,66, "WL:" );
ReefAngel.LCD.DrawText( COLOR_DARKGOLDENROD,DefaultBGColor,99,66, ReefAngel.WaterLevel.GetLevel() );
  ConvertNumToString(text, ReefAngel.Params.Salinity, 10);
  strcat(text,"  ");
  ReefAngel.LCD.DrawText(DefaultFGColor,DefaultBGColor,39,75,"Salinity:");
  ReefAngel.LCD.DrawText(DefaultFGColor,DefaultBGColor,99,75,text);
pingSerial();

// Main Relay Box
byte TempRelay = ReefAngel.Relay.RelayData;
TempRelay &= ReefAngel.Relay.RelayMaskOff;
TempRelay |= ReefAngel.Relay.RelayMaskOn;
ReefAngel.LCD.DrawOutletBox( 12, 92, TempRelay );
pingSerial();
TempRelay = ReefAngel.Relay.RelayDataE[0];
TempRelay &= ReefAngel.Relay.RelayMaskOffE[0];
TempRelay |= ReefAngel.Relay.RelayMaskOnE[0];
ReefAngel.LCD.DrawOutletBox(12, 104, TempRelay);

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

void DrawCustomGraph()
{
}
byte ElseMode( byte MidPoint, byte Offset, boolean WaveSync )
{
  // Static's only initialize the first time they are called
  static unsigned long LastChange=millis();        // Set the inital time that the last change occurred
  static int Delay = random( 500, 3000);           // Set the initial delay
  static int NewSpeed = MidPoint;                  // Set the initial speed
  static int AntiSpeed = MidPoint;                 // Set the initial anti sync speed
  if ((millis()-LastChange) > Delay)               // Check if the delay has elapsed
  {
    Delay=random(500,5000);                        // If so, come up with a new delay
    int ChangeUp = random(Offset);                 // Amount to go up or down
    if (random(100)<50)                            // 50/50 chance of speed going up or going down
    {
      NewSpeed = MidPoint - ChangeUp;
      AntiSpeed = MidPoint + ChangeUp;
    }
    else
    {
      NewSpeed = MidPoint + ChangeUp;
      AntiSpeed = MidPoint - ChangeUp;
    }
    LastChange=millis();                           // Reset the time of the last change
  }
  if (WaveSync)
  {
    return NewSpeed;
  }
  else
  {
    return AntiSpeed;
  }
}
[/code][/code]
Post Reply