Page 1 of 2
More troubles.. Why didn't it go in to feeding mode?
Posted: Wed Jul 20, 2016 5:40 am
by Smotz
A little background - I am in the process of upgrading my 60 to a 120. I bought an additional RA (this one analog) and I am in the process of slowly migrating all the modules.
I have this code which puts the RA in to feeding mode at 7:30am. It works on the 60 but is not working on the 120.
Code: Select all
if ( ((hour() == 7)) && (minute() == 30) &&(second() == 0) ) ReefAngel.FeedingModeStart();
Re: More troubles.. Why didn't it go in to feeding mode?
Posted: Wed Jul 20, 2016 9:59 am
by rimai
Same code?
Can you post the entire code you uploaded in the 120?
Re: More troubles.. Why didn't it go in to feeding mode?
Posted: Wed Jul 20, 2016 11:35 am
by Smotz
rimai wrote:Same code?
Can you post the entire code you uploaded in the 120?
absolutely, and thank you. Mind you, I've only witnessed it not going in to feed mode this morning. I will keep an eye on it.
Code: Select all
//// Port 1 Heater
//// Port 2 ATO pump
//// Port 3 Feeder
//// Port 4 Protein Skimmer
//// Port 5 Return Pump
//// Port 6 Wavemakers
//// Port 7 UV Sterilizer
//// Port 8 Cabinet Light
//// BOX 1 PORT 1 Calcium Doser
//// BOX 1 PORT 2 Alkalinity Doser
//// BOX 1 PORT 8 Sump Fan
//// BOX 1 PORT 8 Fans
//// Probe T1 SUMP
//// Probe T2 Tank
//// Probe T3 Canopy
#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 <DCPump.h>
////// Place global variable code below here
#define Heater Port1
#define Topoff Port2
#define Feeder Port3
#define Skimmer Port4
#define Return Port5
#define Wave Port6
#define UVlight Port7
#define Fugelight Port8
#define CanopyFan Box1_Port8
#define CalcDose Box1_Port1
#define AlkDose Box1_Port2
#define SumpFan Box1_Port7
#define FugelightBit 1<<7
#define UVlightBit 1<<6
#define WaveBit 1<<5
#define ReturnBit 1<<4
#define SkimmerBit 1<<3
#define FeederBit 1<<2
#define TopoffBit 1<<1
#define HeaterBit 1<<0
static byte wpMode;
static byte wpWavStr;
static byte wpWavOff;
////// Place global variable code above here
void setup()
{
// This must be the first line
ReefAngel.Init(); //Initialize controller
ReefAngel.Use2014Screen(); // Let's use 2014 Screen
ReefAngel.AddMultiChannelWaterLevelExpansion(); // Multi-Channel Water Level Expansion Module
ReefAngel.Network.WifiAuthentication("Smotz:-------------");
// Ports toggled in Feeding Mode
ReefAngel.FeedingModePorts = SkimmerBit | ReturnBit | TopoffBit | UVlightBit;
// Ports toggled in Water Change Mode
ReefAngel.WaterChangePorts = HeaterBit | SkimmerBit | ReturnBit | TopoffBit | WaveBit | UVlightBit | FeederBit;
// Ports toggled when Lights On / Off menu entry selected
ReefAngel.LightsOnPorts = FugelightBit;
// Ports turned off when Overheat temperature exceeded
ReefAngel.OverheatShutoffPorts = HeaterBit | TopoffBit | SkimmerBit | ReturnBit | WaveBit | UVlightBit | FeederBit;
// Use T2 (Tank) probe as temperature and overheat functions
ReefAngel.TempProbe = T2_PROBE;
ReefAngel.OverheatProbe = T2_PROBE;
// Ports that are always off
ReefAngel.Relay.Off( Feeder );
ReefAngel.Relay.Off( Topoff );
// Ports that are always on
ReefAngel.Relay.On( Box1_Port3 );
ReefAngel.Relay.On( Box1_Port4 );
ReefAngel.Relay.On( Box1_Port5 );
ReefAngel.Relay.On( Box1_Port6 );
ReefAngel.Relay.On( Box1_Port7 );
// DCPUMP
ReefAngel.DCPump.FeedingSpeed=35;
ReefAngel.DCPump.WaterChangeSpeed=0;
ReefAngel.DCPump.ActinicChannel=Sync;
ReefAngel.DCPump.DaylightChannel=AntiSync;
////// Place additional initialization code below here
////// Place additional initialization code above here
}
void loop()
{
ReefAngel.Relay.On( Return );
ReefAngel.Relay.On( Wave );
ReefAngel.Relay.Off( Feeder );
ReefAngel.MoonLights( Fugelight );
ReefAngel.StandardHeater( Heater );
ReefAngel.StandardFan( SumpFan );
////// Place your custom code below here
// Main Top Off
ReefAngel.WaterLevelATO(1,Topoff,15,85,95);
// just to be safe if the water level gets to 140 or greater, turn off the topoff.
// if (ReefAngel.WaterLevel.GetLevel(1)<=85) ReefAngel.Relay.On(Topoff); // Obsolete code
// if (ReefAngel.WaterLevel.GetLevel(1)>=95) ReefAngel.Relay.Off(Topoff); // Obsolete code
if ( ReefAngel.WaterLevel.GetLevel(1) >= 140 ) ReefAngel.Relay.Override (Topoff,0);
// End Main Top Off
//Dosing
ReefAngel.DosingPumpRepeat1( CalcDose );
ReefAngel.DosingPumpRepeat2( AlkDose );
//// 30,20 = 17.5 ml day
//// ReefAngel.DosingPumpRepeat(CalcDose,0,30,20);
//// ReefAngel.DosingPumpRepeat(AlkDose,10,30,20);
// Turn on Canopy Fans when the temp of T3 (Canopy) gets above 85.0 degrees
if ( ReefAngel.Params.Temp[T3_PROBE] >= 850 ) ReefAngel.Relay.On( CanopyFan );
// Turn off Canopy Fans when the temp of T2 (Canopy) gets below 80.0 degrees
if ( ReefAngel.Params.Temp[T3_PROBE] < 800 ) ReefAngel.Relay.Off( CanopyFan );
// Make Salinity and PH calibration changes on the fly without reboot
// ReefAngel.SalMax=InternalMemory.SalMax_read();
// ReefAngel.PHMin=InternalMemory.PHMin_read();
// ReefAngel.PHMax=InternalMemory.PHMax_read();
ReefAngel.Relay.DelayedOn(Skimmer,5);
// Buzzer if temp is too high or low, or waterlevel 1 is too high or too low.
if (ReefAngel.DisplayedMenu!=WATERCHANGE_MODE && ReefAngel.DisplayedMenu!=FEEDING_MODE) // Only check if not Feeding Mode or Water Change Mode
{
if ( ReefAngel.Params.Temp[T2_PROBE] < 700 || ReefAngel.Params.Temp[T2_PROBE] > 850 || ReefAngel.WaterLevel.GetLevel(1) > 140 || ReefAngel.WaterLevel.GetLevel(1) < 70)
{
pinMode(lowATOPin,OUTPUT);
digitalWrite(lowATOPin,HIGH);
}
else
{
pinMode(lowATOPin,OUTPUT);
digitalWrite(lowATOPin,LOW);
}}
// Turn the fugelight on if the return is off
if (ReefAngel.Relay.Status ( Return ) == 0) ReefAngel.Relay.On( Fugelight );
// EMERGENCY SUMP WATER LEVEL BELOW 25% AND WATERCHANGE MODE IS NOT ON AND WAIT FOR CONTROLLER TO BE ON FOR 5 SECONDS
// if ( ReefAngel.WaterLevel.GetLevel(1) <= 25 && ReefAngel.DisplayedMenu!=WATERCHANGE_MODE && millis() > 5000)
// {
// ReefAngel.Relay.Override(Return,0);
// ReefAngel.Relay.Override(Skimmer,0);
// ReefAngel.Relay.Override(UVlight,0);
// ReefAngel.Relay.Override(Feeder,0);
// ReefAngel.Relay.Override(CalcDose,0);
// ReefAngel.Relay.Override(AlkDose,0);
// ReefAngel.Relay.Override(Fugelight,1);
// }
// END EMERGENCY WATER LEVEL ROUTINE
// Feeding Mode
// if the hour is 7a and minute is 30 and seconds is 0 start the feeding mode
if ( ((hour() == 7)) && (minute() == 30) &&(second() == 0) ) ReefAngel.FeedingModeStart();
if ( ((hour() == 7)) && (minute() == 31) &&(second() == 0) ) ReefAngel.Relay.On(Feeder); //TURN FEEDER RELAY ON at 7:31:00
if ( ((hour() == 7)) && (minute() == 31) &&(second() == 5) ) ReefAngel.Relay.Off(Feeder); //TURN FEEDER RELAY OFF at 7:31:02
if ( ((hour() == 7)) && (minute() == 33) &&(second() == 0) ) ReefAngel.Relay.On(Feeder); //TURN FEEDER RELAY ON at 7:33:00
if ( ((hour() == 7)) && (minute() == 33) &&(second() == 5) ) ReefAngel.Relay.Off(Feeder); //TURN FEEDER RELAY OFF at 7:33:02
// end feeding mode
// Custom Wave Routine
if (InternalMemory.DCPumpMode_read()==11)
{
ReefAngel.DCPump.UseMemory=false;
// set the wpMode based on what time it is
if ( (hour() >= 2) && (hour() < 5) ) wpMode=1; // from 2am - 5am
if ( (hour() >= 5) && (hour() < 8) ) wpMode=2; // from 5am - 8am
if ( (hour() >= 8) && (hour() < 11) ) wpMode=4; // from 8am - 11am Nutrient Transport
if ( (hour() >= 11) && (hour() < 14) ) wpMode=2; // from 11a - 2pm
if ( (hour() >= 14) && (hour() < 17) ) wpMode=3; // from 2pm - 5pm
if ( (hour() >= 17) && (hour() < 20) ) wpMode=2; // from 5pm - 8pm
if ( (hour() >= 20) && (hour() < 23) ) wpMode=3; // from 8pm - 11p
if (hour() >= 23) wpMode=2; // from 11pm - midnight
if (hour() < 2) wpMode=1; // from midnight - 2am
switch (wpMode)
{
case 1: wpWavStr=35; wpWavOff=10; break; //Night Mode
case 2: wpWavStr=37; wpWavOff=4; break;
case 3: wpWavStr=42; wpWavOff=7; break;
case 4: wpWavStr=50; wpWavOff=10; break; //Nutrient Transport
default: wpWavStr=35; wpWavOff=2;
}
// Night Mode
if (wpMode==1) ReefAngel.DCPump.SetMode (Gyre, wpWavStr, wpWavOff);
//If 8am - 11am, Nutrient Transport
if (wpMode==4) ReefAngel.DCPump.SetMode (NutrientTransport, wpWavStr,wpWavOff);
//Wave for everything else
if (wpMode!=4 && wpMode!=1) ReefAngel.DCPump.SetMode (Else, wpWavStr, wpWavOff);
}
else ReefAngel.DCPump.UseMemory = true; // If it's not custom mode on the portal, then do what mode the portal says.
// End Custom Wave Routine
// Only turn on UV Sterilizer between 11pm and 3am
if ( (hour() >= 3) && (hour() < 23) ) // from 3a - 11p
ReefAngel.Relay.Off(UVlight);
else ReefAngel.Relay.On(UVlight);
////// Place your custom code above here
// This should always be the last line
ReefAngel.Portal( "Smotz" );
ReefAngel.ShowInterface();
}
void DrawCustomMain()
{
// Parameters
#if defined DisplayLEDPWM && ! defined RemoveAllLights
ReefAngel.LCD.DrawMonitor( 15, 5, ReefAngel.Params,
ReefAngel.PWM.GetDaylightValue(), ReefAngel.PWM.GetActinicValue() );
#else // defined DisplayLEDPWM && ! defined RemoveAllLights
ReefAngel.LCD.DrawMonitor( 15, 5, ReefAngel.Params );
#endif // defined DisplayLEDPWM && ! defined RemoveAllLights
pingSerial();
// Salinity
// ReefAngel.LCD.DrawText( COLOR_DARKKHAKI,DefaultBGColor,20,80, "SAL:" );
// ReefAngel.LCD.DrawText( COLOR_DARKKHAKI,DefaultBGColor,44,80, ReefAngel.Params.Salinity );
// pingSerial();
// Main Relay Box
byte TempRelay = ReefAngel.Relay.RelayData;
TempRelay &= ReefAngel.Relay.RelayMaskOff;
TempRelay |= ReefAngel.Relay.RelayMaskOn;
ReefAngel.LCD.DrawOutletBox( 12, 95, TempRelay );
pingSerial();
// Relay Expansion
TempRelay = ReefAngel.Relay.RelayDataE[0];
TempRelay &= ReefAngel.Relay.RelayMaskOffE[0];
TempRelay |= ReefAngel.Relay.RelayMaskOnE[0];
ReefAngel.LCD.DrawOutletBox( 12, 105, TempRelay );
pingSerial();
// Date and Time
ReefAngel.LCD.DrawDate( 6, 122 );
pingSerial();
//draw the mode on the screen
char buf[16];
char buf2[16];
// char buf3[32];
sprintf(buf,"ELSE %d%% +/- %d%%",wpWavStr,wpWavOff);
sprintf(buf2,"Wave Mode = %d%",wpMode);
// sprintf(buf3,"Return Power = %d%",InternalMemory.LEDPWMActinic_read());
// ReefAngel.LCD.DrawText(0,255,10,40,buf3);
ReefAngel.LCD.DrawText(0,255,20,60,buf);
ReefAngel.LCD.DrawText(0,255,20,50,buf2);
}
void DrawCustomGraph()
{
}
Re: More troubles.. Why didn't it go in to feeding mode?
Posted: Thu Jul 21, 2016 6:03 am
by Smotz
Went in to feeding this morning. Just a quirk maybe?
Re: More troubles.. Why didn't it go in to feeding mode?
Posted: Fri Jul 22, 2016 4:36 am
by Smotz
No feeding mode this morning.
Re: More troubles.. Why didn't it go in to feeding mode?
Posted: Fri Jul 22, 2016 9:01 am
by re76
Let me preface this by saying I don't own a ReefAngel yet, but I do have a lot of Arduino, C and C++ experience.
I'm not sure what the cycle time of the code is, but seeing how everything in an Arduino is in one giant loop, there is going to be some sort of periodicity for when individual checks are run. It is highly unlikely that that the period is more than 1 second, but MAYBE if it is, then this could explain why your seeing this issue.
In the first line of your feeder code you have:
Code: Select all
if ( ((hour() == 7)) && (minute() == 30) &&(second() == 0) )
So that code is only going to run if second == 0 exactly. If the cycle time of your code is more than 1 second than there is a possibility that it might get missed. One thing you could do would be to write something like this:
Code: Select all
unsigned long feedStartTS = 0;
// Grab timestamp if we don't have one, and it's the right time
// This should only run once at 7:30 or slightly after
if ( (feedStartTS == 0) && (hour() == 7) && (minute() >= 30) ) {
feedStartTS = millis();
}
if (feedStartTS) {
deltaTS = millis() - feedStartTS;
if ( deltaTS >= 600000 ) { // 10 minutes has elapsed
// Do something
// Set timestamp to 0 so we stop doing feeder stuff since this is the last stage
feedStartTS = 0;
} else if ( deltaTS >= 300000 ) { // 5 minutes has elapsed
// Do something
} else if ( deltaTS >= 120000 ) { // 2 minutes has elapsed
// Do something
} else if ( deltaTS >= 60000 ) { // 1 minute has elapsed
// Do something
} else {
// Start feeding mode
}
}
I wrote this code off the cuff and have not tested it. Try it at your own risk. It probably won't even compile initially. I just wanted to write it as a solution for what might not even be your issue. As an outsider though, since I don't have a ReefAngel, it is the only issue I can see with your code.
Notice with this code the if statements flow in reverse order, meaning the last thing you do happens first. One of the assumptions I am making with this code is that it is OK to call the "//Do something" code more than once as it will be continuously called until we enter the next stage.
Re: More troubles.. Why didn't it go in to feeding mode?
Posted: Fri Jul 22, 2016 3:38 pm
by lnevo
Or easier just take off the second() test altogether.
Re: More troubles.. Why didn't it go in to feeding mode?
Posted: Fri Jul 22, 2016 5:04 pm
by re76
lnevo wrote:Or easier just take off the second() test altogether.
That would work too, but it looks like he is trying to turn things on for amounts of time that are less than a minute. Which means he will need to use something smaller than a minute.
Re: More troubles.. Why didn't it go in to feeding mode?
Posted: Fri Jul 22, 2016 7:39 pm
by lnevo
Starting feeding mode wouldnt be a problem to continue running for the minute. Think about it, there's as much potential of it going multiple times in that second already.
Re: More troubles.. Why didn't it go in to feeding mode?
Posted: Fri Jul 22, 2016 7:59 pm
by re76
lnevo wrote:Starting feeding mode wouldnt be a problem to continue running for the minute. Think about it, there's as much potential of it going multiple times in that second already.
I should have been more specific it isn't for feed mode that he needs the sub-minute resolution it is for his auto-feeder. He is turning it on for only five seconds, and then turning it off. I agree that getting rid of the seconds() for the feed mode would work but he will still need it for the auto feeder part.
Re: More troubles.. Why didn't it go in to feeding mode?
Posted: Fri Jul 22, 2016 8:01 pm
by lnevo
Smotz wrote:No feeding mode this morning.
Mode... Not feeder.
But even if its an autofeeder. It usually is a hack to close the relay. It usually will only trigger one feeding for a button press so no need to have a timer. If it holds the button for one second or one minute it should be fine. At least with an eheim.
Re: More troubles.. Why didn't it go in to feeding mode?
Posted: Sat Jul 23, 2016 6:00 am
by Smotz
thanks all. I will remove the seconds from the feed mode and see if that helps. Yes the other part is the autofeeder and that doesn't seem to be a problem.
Re: More troubles.. Why didn't it go in to feeding mode?
Posted: Sat Jul 23, 2016 8:20 am
by re76
Give this a shot, but keep in mind that if it was in fact the problem, you might now have the same exact problem with the feeder too since you are also using seconds in those lines! This is the point I was trying to make. It would be really bad if your feeder turned on but you happened to miss the specific second where you are trying to turn it off, and then it never turns off!
Make sure you keep an eye on this! At a minimum I would change the line where you turn the feeder off to be a greater than or equal check on seconds, that way you know you will be guaranteed to turn the feeder off. I would rather miss turning the feeder on than miss turning it off and pouring a ton of food into the tank.
Re: More troubles.. Why didn't it go in to feeding mode?
Posted: Sat Jul 23, 2016 10:11 am
by lnevo
Look at the function I have for my Swabbie and autofeeder. It follows what re76's example is doing too
Re: More troubles.. Why didn't it go in to feeding mode?
Posted: Sun Jul 24, 2016 6:22 am
by Smotz
re76 wrote:Give this a shot, but keep in mind that if it was in fact the problem, you might now have the same exact problem with the feeder too since you are also using seconds in those lines! This is the point I was trying to make. It would be really bad if your feeder turned on but you happened to miss the specific second where you are trying to turn it off, and then it never turns off!
Make sure you keep an eye on this! At a minimum I would change the line where you turn the feeder off to be a greater than or equal check on seconds, that way you know you will be guaranteed to turn the feeder off. I would rather miss turning the feeder on than miss turning it off and pouring a ton of food into the tank.
Odd because it worked for years on my other (PWM) RA. As a matter of fact, it still does. I think this new RA may be 'sluggish' - is that even possible ?
Re: More troubles.. Why didn't it go in to feeding mode?
Posted: Sun Jul 24, 2016 6:28 am
by Smotz
lnevo wrote:Look at the function I have for my Swabbie and autofeeder. It follows what re76's example is doing too
Dude, your code is too advanced. I could barely read it.
Re: More troubles.. Why didn't it go in to feeding mode?
Posted: Sun Jul 24, 2016 6:35 am
by re76
Smotz wrote:re76 wrote:Give this a shot, but keep in mind that if it was in fact the problem, you might now have the same exact problem with the feeder too since you are also using seconds in those lines! This is the point I was trying to make. It would be really bad if your feeder turned on but you happened to miss the specific second where you are trying to turn it off, and then it never turns off!
Make sure you keep an eye on this! At a minimum I would change the line where you turn the feeder off to be a greater than or equal check on seconds, that way you know you will be guaranteed to turn the feeder off. I would rather miss turning the feeder on than miss turning it off and pouring a ton of food into the tank.
Odd because it worked for years on my other (PWM) RA. As a matter of fact, it still does. I think this new RA may be 'sluggish' - is that even possible ?
Have you added more extensions and functionality since then?
Re: More troubles.. Why didn't it go in to feeding mode?
Posted: Sun Jul 24, 2016 6:38 am
by Smotz
re76 wrote:Give this a shot, but keep in mind that if it was in fact the problem, you might now have the same exact problem with the feeder too since you are also using seconds in those lines! This is the point I was trying to make. It would be really bad if your feeder turned on but you happened to miss the specific second where you are trying to turn it off, and then it never turns off!
Make sure you keep an eye on this! At a minimum I would change the line where you turn the feeder off to be a greater than or equal check on seconds, that way you know you will be guaranteed to turn the feeder off. I would rather miss turning the feeder on than miss turning it off and pouring a ton of food into the tank.
It 'should' never dump the feeder continually. The relay is a "button push" - the feeder rotates once upon pressing it.
Re: More troubles.. Why didn't it go in to feeding mode?
Posted: Sun Jul 24, 2016 6:40 am
by Smotz
re76 wrote:Smotz wrote:re76 wrote:Give this a shot, but keep in mind that if it was in fact the problem, you might now have the same exact problem with the feeder too since you are also using seconds in those lines! This is the point I was trying to make. It would be really bad if your feeder turned on but you happened to miss the specific second where you are trying to turn it off, and then it never turns off!
Make sure you keep an eye on this! At a minimum I would change the line where you turn the feeder off to be a greater than or equal check on seconds, that way you know you will be guaranteed to turn the feeder off. I would rather miss turning the feeder on than miss turning it off and pouring a ton of food into the tank.
Odd because it worked for years on my other (PWM) RA. As a matter of fact, it still does. I think this new RA may be 'sluggish' - is that even possible ?
Have you added more extensions and functionality since then?
Not sure I understand your question? I have been slowly moving the modules from my PWM RA to the Analog RA.
Standard stuff - 2 relay boxes, multi water level, expansion hub, wifi, bluetooth
Re: More troubles.. Why didn't it go in to feeding mode?
Posted: Sun Jul 24, 2016 6:43 am
by re76
Smotz wrote:re76 wrote:Give this a shot, but keep in mind that if it was in fact the problem, you might now have the same exact problem with the feeder too since you are also using seconds in those lines! This is the point I was trying to make. It would be really bad if your feeder turned on but you happened to miss the specific second where you are trying to turn it off, and then it never turns off!
Make sure you keep an eye on this! At a minimum I would change the line where you turn the feeder off to be a greater than or equal check on seconds, that way you know you will be guaranteed to turn the feeder off. I would rather miss turning the feeder on than miss turning it off and pouring a ton of food into the tank.
It 'should' never dump the feeder continually. The relay is a "button push" - the feeder rotates once upon pressing it.
That is good to know. I am not a Reef Angel expert by any means, and in most non-reef angel cases I've encountered setting an output high would leave it on until you set it low again. My background is in embedded software for medical devices though where everything is super strict so I have a tendency to be extra careful...
Re: More troubles.. Why didn't it go in to feeding mode?
Posted: Sun Jul 24, 2016 7:03 am
by Smotz
re76 wrote:Smotz wrote:re76 wrote:Give this a shot, but keep in mind that if it was in fact the problem, you might now have the same exact problem with the feeder too since you are also using seconds in those lines! This is the point I was trying to make. It would be really bad if your feeder turned on but you happened to miss the specific second where you are trying to turn it off, and then it never turns off!
Make sure you keep an eye on this! At a minimum I would change the line where you turn the feeder off to be a greater than or equal check on seconds, that way you know you will be guaranteed to turn the feeder off. I would rather miss turning the feeder on than miss turning it off and pouring a ton of food into the tank.
It 'should' never dump the feeder continually. The relay is a "button push" - the feeder rotates once upon pressing it.
That is good to know. I am not a Reef Angel expert by any means, and in most non-reef angel cases I've encountered setting an output high would leave it on until you set it low again. My background is in embedded software for medical devices though where everything is super strict so I have a tendency to be extra careful...
Well, your help is very much appreciated. I think you nailed it when you said it is 'missing the second'. I suspect this RA may be 'sluggish' or something.
Re: More troubles.. Why didn't it go in to feeding mode?
Posted: Sun Jul 24, 2016 7:30 am
by re76
To clarify a bit. The Reef Angel is based off of the Arduino platform. The Arduino tries to makes things simple for the end user by having only two important functions that are needed: a setup() function and loop() function.
The loop function gets called by the arduino as much as possible. If you have a really basic loop function then it might be able to call it 1000 times a second. It can't call it again though until the loop function is finished from the last time it was called. So as your loop() gets more and more code in it it will be getting called less times every second.
Not to mention for every new extension you add to the RA there is more library code to support it. As an end user you don't see this a lot unless you go looking for it. This is why I asked if you had added more extensions or features. As you add complexity to your code it is going to run a bit slower. This isn't necessarily a bad thing, it just is. It is a standard understood trade off for all embedded systems whether they are using Arduino or not.
There is a concept in software development called defensive programming. It is the idea that you make your code robust enough to handle unforeseen conditions. This is why I am a big advocate of using >= or <= instead of == wherever possible. You sometimes have to work your logic a bit differently but it usually isn't a lot more work, and it ensures that if for some crazy reason you don't catch something on the first loop through you will get it on the second time around, and will never just miss it totally like you can with ==.
Hope this makes sense and isn't just causing more confusion!
Re: More troubles.. Why didn't it go in to feeding mode?
Posted: Sun Jul 24, 2016 10:02 am
by lnevo
Your code was good just sometimes we foresake complexity for ease of troubleshooting and readability
welcome to the club
Re: More troubles.. Why didn't it go in to feeding mode?
Posted: Tue Jul 26, 2016 5:13 pm
by Smotz
re76 wrote:To clarify a bit. The Reef Angel is based off of the Arduino platform. The Arduino tries to makes things simple for the end user by having only two important functions that are needed: a setup() function and loop() function.
The loop function gets called by the arduino as much as possible. If you have a really basic loop function then it might be able to call it 1000 times a second. It can't call it again though until the loop function is finished from the last time it was called. So as your loop() gets more and more code in it it will be getting called less times every second.
Not to mention for every new extension you add to the RA there is more library code to support it. As an end user you don't see this a lot unless you go looking for it. This is why I asked if you had added more extensions or features. As you add complexity to your code it is going to run a bit slower. This isn't necessarily a bad thing, it just is. It is a standard understood trade off for all embedded systems whether they are using Arduino or not.
There is a concept in software development called defensive programming. It is the idea that you make your code robust enough to handle unforeseen conditions. This is why I am a big advocate of using >= or <= instead of == wherever possible. You sometimes have to work your logic a bit differently but it usually isn't a lot more work, and it ensures that if for some crazy reason you don't catch something on the first loop through you will get it on the second time around, and will never just miss it totally like you can with ==.
Hope this makes sense and isn't just causing more confusion!
Hi!
Working off your example and a good amount of reading I put the below code together in an effort to be more efficient. I am trying to set the feeding mode twice a day and bounce the feeding relay for 10 seconds.
I set "static time_t NoteTime=millis();" as a global variable so I can call it in other parts of the code.
Code: Select all
[code]//FEEDING MODE
// Begin Feeding Mode
if ( ((hour() == 7)) && (minute() == 30) || ((hour() == 18)) && (minute() == 00)) {
ReefAngel.FeedingModeStart(); // FEEDING MODE @ 7:30 AM or 6:00 PM
NoteTime = millis();
unsigned long DeltaTS = millis() - NoteTime;
if ( DeltaTS >= 60000 ) ReefAngel.Relay.On(Feeder); // turn on after 1 minute
if ( DeltaTS >= 70000 ) ReefAngel.Relay.On(Feeder); // turn off shortly after
if ( DeltaTS >= 120000 ) ReefAngel.Relay.On(Feeder); // turn on after 2 minutes
if ( DeltaTS >= 130000 ) ReefAngel.Relay.On(Feeder); // turn off shortly after
}
[/code]
Re: More troubles.. Why didn't it go in to feeding mode?
Posted: Wed Jul 27, 2016 4:18 am
by re76
This is a really good start a few things though. I wouldn't use time_t, if you are intending it to store the output of a call to millis() you might want to change it to static unsigned long, which is what millis() returns. As far as I know time_t only has second accuracy and not millisecond accuracy so I'm not sure what your deltaTS will have in it after the subtraction since you are subtracting two different types.
Next up is your logic for the timing of the feeding relay. You should be using if-else-if statements. You only want one thing to happen every time, not multiple. As you have written above, if your DeltaTS is bigger than 130000 then all of those cases would trigger, which I don't think is what you want.
Take a look at the code I posted previously again and notice how I used several if-else-if statements. Also notice how I have the case with the biggest deltaTS first. That is on purpose so that it doesn't do multiple cases on each pass through he code.
Next, somewhere in this code you need to add a check to make sure you don't ALWAYS run this code. There are several ways to do this. You could use a Boolean variable that you set to true in your "begin feeding mode" code and then set to false in your last step where you turn your feeder off. Then wrap all of the feede logic in a big if statement that checks that variable.
Finally, and this is me being nitpicky, you probably don't need to be using a static variable here. All of the user code is in the arduino loop() function, you will probably never use NoteTime out of loop() so it would probably be fine to not be static. It is good practice to avoid static variables where possible.
Also You are always turning the feeder on. Some of those should be an off call.
Sorry I can't write any code examples for you, I am writing this on my phone. Let me know if I need to elaborate more about anything!
Sent from my iPhone using Tapatalk
Re: More troubles.. Why didn't it go in to feeding mode?
Posted: Wed Jul 27, 2016 4:32 am
by Smotz
This is great! Learning..
You're right - I am always turning it on - that was a CTRL-C error
After reading what you wrote 3 times I now understand that all of my cases will trigger @ 130000. I will work on the else statements.
Regarding the use of the static global variable - I am actually going to use it a few times in the code - like for my ATO - I want to ensure it waits several seconds after feeding and waterchange mode before it checks for the ATO timeout. For instance, I have this code also:
Code: Select all
if (ReefAngel.WaterLevel.GetLevel(1) <= 25 && ReefAngel.DisplayedMenu!=WATERCHANGE_MODE)
{
NoteTime = millis();
unsigned long DeltaTS = millis() - NoteTime;
if ( DeltaTS >= 15000 )
{
ReefAngel.Relay.Override(Return,0);
ReefAngel.Relay.Override(Skimmer,0);
ReefAngel.Relay.Override(UVlight,0);
ReefAngel.Relay.Override(Feeder,0);
ReefAngel.Relay.Override(CalcDose,0);
ReefAngel.Relay.Override(AlkDose,0);
ReefAngel.Relay.Override(Fugelight,1);
pinMode(lowATOPin,OUTPUT); //Buzzer
digitalWrite(lowATOPin,HIGH); //Buzzer
}}
// END EMERGENCY WATER LEVEL ROUTINE
More troubles.. Why didn't it go in to feeding mode?
Posted: Wed Jul 27, 2016 5:05 am
by lnevo
It doesn't need to be static if you set it every time to millis() but it may need to be global only if you are using it in other functions outside of loop. If you are setting it once and want it retained like a flag that you want to set if something happens then you'll want to use static.
Also time_t is an unsigned long so no difference here.
Re: More troubles.. Why didn't it go in to feeding mode?
Posted: Wed Jul 27, 2016 6:02 am
by re76
lnevo wrote:It doesn't need to be static if you set it every time to millis() but it may need to be global only if you are using it in other functions outside of loop. If you are setting it once and want it retained like a flag that you want to set if something happens then you'll want to use static.
Also time_t is an unsigned long so no difference here.
You are correct that time_t is an unsigned long, and it will work in this scenario. It is intended however to work with the time.h library which stores the seconds since epoch (seconds since 1970), which is a lot of seconds. Hence why it is an unsigned long. The call to millis() returns the millisecond counter (also very big).
By making a new type just for the time library, it helps keep track of what the variable is intended to be used for. When I see someone using time_t to store the millisecond counter value, it makes me worried they will try to use it with the time library somewhere down the line and not understand why it isn't working.
It is fine to keep using it as long as you don't try to use it with any of the functions in time.h, but for readability and code clarity I still think unsigned long is the better choice.
Re: More troubles.. Why didn't it go in to feeding mode?
Posted: Wed Jul 27, 2016 6:04 am
by lnevo
Fair point.
Re: More troubles.. Why didn't it go in to feeding mode?
Posted: Wed Jul 27, 2016 6:30 am
by Smotz
here is my updated code with the else's incorporated
Code: Select all
//FEEDING MODE
// Begin Feeding Mode
if (((hour() == 7)) && (minute() == 30) || (hour() == 18) && (minute() == 00)) {
ReefAngel.FeedingModeStart(); // FEEDING MODE @ 7:30 AM or 6:00 PM
NoteTime = millis();
unsigned long DeltaTS = millis() - NoteTime;
if ( DeltaTS >= 130000 ) ReefAngel.Relay.Off(Feeder); // turn off 2 minutes 10 secs
else
if ( DeltaTS >= 120000 ) ReefAngel.Relay.On(Feeder); // turn on after 2 minutes
else
if ( DeltaTS >= 70000 ) ReefAngel.Relay.Off(Feeder); // turn off 1 min 10 secs
else
if ( DeltaTS >= 60000 ) ReefAngel.Relay.On(Feeder); // turn on after 1 minute
}