Why does my RA go into feeding mode randomly
Re: Why does my RA go into feeding mode randomly
You have to open the Arduino app by right clicking and do Show package contents..i can check the path for you later tonight.
Re: Why does my RA go into feeding mode randomly
Okay I found the path. Thanks! Plugged in the RF module again to (without updating the source) to see what happens. I moved the usb cable as well to another one on the hub. Before it was right next to the one that was connected to the relay expansion. I'll see if I have anymore random feeding modes, if I do, I'll try the replacement code.
Re: Why does my RA go into feeding mode randomly
I'm having the exact same issue, random feeding mode, as the others have reported. I replaced my twi.c file as well and will report back if the issue remains so that we can gather more data. Thanks guys.
Re: Why does my RA go into feeding mode randomly
My RA just went into feeding mode again on its own. This was after replacing the twi.c file and re-uploading my ino.
Here's a pic of my relay activity in case it helps. You can see the history of the random feeding mode by looking at my Return pump behavior (orange). It's tied to my skimmer (purple).
and my code:
Here's a pic of my relay activity in case it helps. You can see the history of the random feeding mode by looking at my Return pump behavior (orange). It's tied to my skimmer (purple).
and my code:
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 <RA_Colors.h>
#include <RA_CustomColors.h>
#include <RF.h>
#include <ReefAngel.h>
#include <SunLocation.h>
#include <WaterLevel.h>
#include <Tide.h>
#include <Moon.h>
#include <WiFiAlert.h>
#include <InternalEEPROM.h>
#include <avr/wdt.h>
// Custom menus
#include <avr/pgmspace.h>
prog_char menu1_label[] PROGMEM = "Refugium Light";
prog_char menu2_label[] PROGMEM = "Feeding Mode";
prog_char menu3_label[] PROGMEM = "Water Change";
prog_char menu4_label[] PROGMEM = "Vortech Mode";
prog_char menu5_label[] PROGMEM = "ATO Clear";
prog_char menu6_label[] PROGMEM = "Overheat Clear";
prog_char menu7_label[] PROGMEM = "PH Calibration";
prog_char menu8_label[] PROGMEM = "WLS Calibration";
prog_char menu9_label[] PROGMEM = "Date / Time";
// 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 Custom Memory Locations
#define Mem_B_MoonSlope 100
// #define Mem_B_Vacation 101
// #define Mem_B_AutoFeed 102
// #define Mem_B_AutoFeedPress 103
// #define Mem_B_AutoFeedRepeat 104
// #define Mem_B_AutoFeedOffset 105
#define Mem_I_WCFillTime 106
#define Mem_I_Latitude 108
#define Mem_I_Longitude 110
// #define Mem_B_AcclRiseOffset 112
// #define Mem_B_AcclSetOffset 113
// #define Mem_B_AcclDay 114
// #define Mem_B_SwabbieRepeat 115
// #define Mem_B_SwabbieTime 116
#define Mem_B_TideMin 117
#define Mem_B_TideMax 118
#define Mem_B_PumpOffset 119
#define Mem_B_FeedingRF 120
#define Mem_B_NightRF 121
#define Mem_B_NightSpeed 122
#define Mem_B_NightDuration 123
#define Mem_B_NTMSpeed 124
#define Mem_B_NTMDuration 125
#define Mem_B_NTMDelay 126
#define Mem_B_NTMTime 127
#define Mem_I_CalDP1Vol 128
#define Mem_I_CalDP1Time 130
#define Mem_I_DP1Volume 132
#define Mem_I_CalDP2Vol 134
#define Mem_I_CalDP2Time 136
#define Mem_I_DP2Volume 138
// #define Mem_B_LogATO 140
// #define Mem_B_LogPrevATO 141
// #define Mem_B_RateAlarm 142
#define Mem_B_TideMode 143
// #define Mem_B_MaintGAC 144
// #define Mem_B_MaintGFO 145
// #define Mem_B_MaintCal 146
// #define Mem_B_MaintAlk 147
// #define Mem_B_MaintWC 148
// #define Mem_B_MaintATO 149
// #define Mem_B_MaintFeeding 150
// #define Mem_B_MaintSkimmer 151
// #define Mem_B_MaintSocks 152
// #define Mem_B_MaintWCVol 153
#define Mem_I_CalDP3Vol 154
#define Mem_I_CalDP3Time 156
#define Mem_I_DP3Volume 158
#define Mem_B_PrintDebug 198
#define Mem_B_ResetMemory 199
void init_memory() {
// Initialize Custom Memory Locations
InternalMemory.write(Mem_B_MoonSlope,60);
//InternalMemory.write(Mem_B_Vacation,false);
//InternalMemory.write(Mem_B_AutoFeed,true);
//InternalMemory.write(Mem_B_AutoFeedPress,2);
//InternalMemory.write(Mem_B_AutoFeedRepeat,4);
//InternalMemory.write(Mem_B_AutoFeedOffset,3);
InternalMemory.write_int(Mem_I_WCFillTime,240);
InternalMemory.write_int(Mem_I_Latitude,31);
InternalMemory.write_int(Mem_I_Longitude,-118);
//InternalMemory.write(Mem_B_AcclRiseOffset,4);
//InternalMemory.write(Mem_B_AcclSetOffset,2);
//InternalMemory.write(Mem_B_AcclDay,0);
//InternalMemory.write(Mem_B_SwabbieRepeat,6);
//InternalMemory.write(Mem_B_SwabbieTime,1);
InternalMemory.write(Mem_B_TideMin,10);
InternalMemory.write(Mem_B_TideMax,30);
//InternalMemory.write(Mem_B_PumpOffset,70);
InternalMemory.write(Mem_B_FeedingRF,true);
InternalMemory.write(Mem_B_NightRF,false);
InternalMemory.write(Mem_B_NightSpeed,30);
InternalMemory.write(Mem_B_NightDuration,10);
InternalMemory.write(Mem_B_NTMSpeed,65);
InternalMemory.write(Mem_B_NTMDuration,5);
InternalMemory.write(Mem_B_NTMDelay,15);
InternalMemory.write(Mem_B_NTMTime,150);
InternalMemory.write_int(Mem_I_CalDP1Vol,11);
InternalMemory.write_int(Mem_I_CalDP1Time,600);
InternalMemory.write_int(Mem_I_DP1Volume,30);
InternalMemory.write_int(Mem_I_CalDP2Vol,11);
InternalMemory.write_int(Mem_I_CalDP2Time,600);
InternalMemory.write_int(Mem_I_DP2Volume,30);
InternalMemory.write_int(Mem_I_CalDP3Vol,3);
InternalMemory.write_int(Mem_I_CalDP3Time,270);
InternalMemory.write_int(Mem_I_DP3Volume,0);
//InternalMemory.write(Mem_B_RateAlarm,15);
InternalMemory.write(Mem_B_TideMode,0);
//InternalMemory.write(Mem_B_LogATO,0);
//InternalMemory.write(Mem_B_LogPrevATO,0);
// InternalMemory.write(Mem_B_MaintGAC,0);
// InternalMemory.write(Mem_B_MaintGFO,0);
// InternalMemory.write(Mem_B_MaintCal,0);
// InternalMemory.write(Mem_B_MaintAlk,0);
//InternalMemory.write(Mem_B_MaintWC,0);
//InternalMemory.write(Mem_B_MaintATO,0);
//InternalMemory.write(Mem_B_MaintFeeding,0);
//InternalMemory.write(Mem_B_MaintSkimmer,0);
//InternalMemory.write(Mem_B_MaintSocks,0);
InternalMemory.write(Mem_B_ResetMemory,false);
}
#define NUMBERS_8x16
// Define Portal Variables
#define Var_Feedings 0
#define Var_DPump1 1
#define Var_DPump2 2
#define Var_AcclDay 3
#define Var_Tide 4
#define Var_TideMode 5
#define Var_LogATO 6
#define Var_WCVol 7
// Define Relay Ports by Name
#define RightLED 1
#define ATOSump 2
#define MidLED 3
#define Heater 4
#define Skimmer 5
#define SumpCirc 6
#define Return 7
#define WaveRight 8
//#define WhiteLEDs 3
//#define BlueLEDs 4
//#define Extension 5
//#define Refugium 7
//#define Reactor 8
#define LeftLED Box1_Port1
#define Vortech1 Box1_Port2
#define Reflights Box1_Port3
#define Dosing Box1_Port4
#define TBD2 Box1_Port5
#define WaveLeft Box1_Port6
#define Feeder Box1_Port7
#define ATOres Box1_Port8
//#define Swabbie Box1_Port1
//#define Feeder Box1_Port2
//#define Vortech2 Box1_Port4
//#define VortechUPS Box1_Port5
//#define Unused Box1_Port6
//#define DPump1 Box1_Port7
//#define DPump2 Box1_Port8
#define VO_RefillATO Box2_Port1
#define VO_EnableATO Box2_Port2
#define VO_StartFill Box2_Port3
#define VO_Vacation Box2_Port4
#define VO_AutoFeed Box2_Port5
#define VO_Unused Box2_Port6
#define VO_Calibrate Box2_Port7
#define VO_LockPorts Box2_Port8
////// Place global variable code below here
boolean dosing=false;
byte vtechmode;
//boolean bFeeding=false;
// Custom classes
SunLocation sun;
Tide tide;
// Vortech Variables
byte vtMode, vtSpeed, vtDuration;
// Needs to be global for DrawCustomGraph()
int ScreenID=1;
////// Place global variable code above here
// Setup on controller startup/reset
void setup()
{
// This must be the first line
//wdt_enable(WDTO_1S);
ReefAngel.Init(); //Initialize controller
ReefAngel.InitMenu(pgm_read_word(&(menu_items[0])),SIZE(menu_items)); // Initialize Menu
ReefAngel.AddWaterLevelExpansion(); // Water Level Expansion Module
// Ports toggled in Feeding Mode
ReefAngel.FeedingModePorts = Port7Bit | Port5Bit ;
ReefAngel.FeedingModePortsE[0] = 0;
// Ports toggled in Water Change Mode
ReefAngel.WaterChangePorts = Port4Bit | Port5Bit | Port6Bit | Port7Bit | Port8Bit;
ReefAngel.WaterChangePortsE[0] = Port2Bit;
// Ports toggled when Lights On / Off menu entry selected
ReefAngel.LightsOnPorts = Box1_Port3;
// Ports turned off when Overheat temperature exceeded
ReefAngel.OverheatShutoffPorts = Port4Bit ;
ReefAngel.OverheatShutoffPortsE[0] = 0;
// Use T1 probe as temperature and overheat functions
ReefAngel.TempProbe = T1_PROBE;
ReefAngel.OverheatProbe = T1_PROBE;
// Ports that default on
ReefAngel.Relay.On(Return);
ReefAngel.Relay.On(ATOSump);
ReefAngel.Relay.On(Vortech1);
ReefAngel.Relay.On(SumpCirc);
//ReefAngel.Relay.On(VortechUPS);
//ReefAngel.Relay.On(VO_LockPorts);
// Ports that default off
//ReefAngel.Relay.Off(Extension);
//ReefAngel.Relay.Off(Swabbie);
//ReefAngel.Relay.Off(Feeder);
//ReefAngel.Relay.Off(Unused);
////// Place additional initialization code below here
ReefAngel.RF.UseMemory=false;
randomSeed(now()/SECS_PER_DAY);
if (InternalMemory.read(Mem_B_ResetMemory))
init_memory();
////// Place additional initialization code above here
}
void loop()
{
//ReefAngel.MoonLights(Refugium);
//ReefAngel.ActinicLights(BlueLEDs);
//ReefAngel.StandardLights(WhiteLEDs);
ReefAngel.StandardHeater( (Heater),751,780 );
//ReefAngel.StandardLights( (Skimmer),0,0,20,0 );
ReefAngel.StandardLights( (WaveRight),6,0,11,30 );
ReefAngel.DosingPumpRepeat( (Dosing),0,60,10 );
ReefAngel.StandardLights( (WaveLeft),11,30,17,30 );
////// Place your custom code below here
// CheckPower(); // Monitor for power outages
// CheckSwitches(); // Monitor for float switches
// SetSun(); // Setup Sun rise/set lighting
SetMoon(); // Setup Moon rise/set lighting
SetTide(); // Set High/Low tide properties
SetRF(); // Set Vortech modes
// CheckATO(); // Calculate ATO reservoir evaporation
// RefillATO(); // Automatic ATO reservoir refill
// Vacation(); // Automation while on Vacation
// LogFeedings(); // Track a relay
// RunFeeder(); // Automatic Fish feeder
// RunSwabbie(); // Skimmer neck cleaner
// RunDosingPumps(); // Dose by volume or time
// LogDosingPumps(); // Keep track of dosing
// CalibrateDPumps(); // Calibrate Dosing pumps
// AutoWaterChange(); // Automated water change
// Reminders(); // Increment maintenance counters
// LockPorts(); // Clear overrides for critical ports
DelayedOnModes(Skimmer); // DelayedOn after mode change only
//Dosing
if (ReefAngel.Params.PH<800 && !dosing)
{
ReefAngel.Timer[1].Start();
ReefAngel.Timer[2].Start();
ReefAngel.Relay.On((Dosing));
dosing=true;
}
if (ReefAngel.Timer[1].IsTriggered())
{
ReefAngel.Relay.Off((Dosing));
}
if (ReefAngel.Timer[2].IsTriggered())
{
dosing=false;
}
if (ReefAngel.Params.PH>855 && dosing)
{
ReefAngel.Relay.Off((Dosing));
}
//ATO Res.
ReefAngel.WaterLevelATO( Box1_Port8,600,10,80 );
//Skimmer failsafe
if (ReefAngel.Relay.Status((Return)) != 1)
{
ReefAngel.Relay.Off((Skimmer));
}
////// Place your custom code above here
// This should always be the last line
ReefAngel.Portal( "aranax" , "");
ReefAngel.ShowInterface();
}
/* void CheckPower() {
static boolean powerOutage=false;
static WiFiAlert powerAlert;
// Power Outage - turn off everything
if (!ReefAngel.Relay.IsRelayPresent(EXP1_RELAY)) // Expansion Relay NOT present
{
powerOutage=true;
ReefAngel.Relay.Off(Skimmer);
//ReefAngel.Relay.Off(WhiteLEDs);
//ReefAngel.Relay.Off(BlueLEDs);
//ReefAngel.Relay.Off(Extension);
ReefAngel.Relay.Off(Heater);
//ReefAngel.Relay.Off(Refugium);
//ReefAngel.Relay.Off(Reactor);
ReefAngel.Relay.Off(Vortech1);
//ReefAngel.Relay.Off(Vortech2);
//ReefAngel.Relay.Off(VortechUPS);
powerAlert.Send("Power+outage!");
}
// Power Restored - Turn things back on
if (powerOutage && ReefAngel.Relay.IsRelayPresent(EXP1_RELAY))
{
LastStart=now();
powerOutage=false;
//ReefAngel.Relay.On(Reactor);
ReefAngel.Relay.On(Vortech1);
//ReefAngel.Relay.On(Vortech2);
//ReefAngel.Relay.On(VortechUPS);
powerAlert.Send("Power+restored.",true);
}
}
void CheckSwitches() {
static boolean returnOverride=true;
static WiFiAlert switchAlert, skimmerAlert, atoAlert;
skimmerAlert.SetDelay(3600);
atoAlert.SetDelay(3600);
if (ReefAngel.DisplayedMenu==FEEDING_MODE || ReefAngel.DisplayedMenu==WATERCHANGE_MODE)
returnOverride=true;
// Turn off return if sump overflowing or out of water in return
ReefAngel.ReverseATOHigh(); // swap switch behavior so we can reuse as ATO
if (!ReefAngel.HighATO.IsActive()) { // switch on by default
if (!returnOverride) {
switchAlert.Send("Sump+level+alarm!+Return+pump+disabled.");
ReefAngel.Relay.Override(Return,0);
returnOverride=true;
}
} else {
returnOverride=false;
}
// Turn off Skimmer if waste collector is full.
if (!ReefAngel.LowATO.IsActive()) { // switch is on by default
skimmerAlert.Send("Skimmate+container+full!+Skimmer+disabled.");
ReefAngel.Relay.Override(Skimmer,0);
if (InternalMemory.read(Mem_B_MaintSkimmer) > 0) // Reset last Skimmer counter
InternalMemory.write(Mem_B_MaintSkimmer,0);
}
// Turn off Skimmer if Return pump has been shutoff.
if (!ReefAngel.Relay.Status(Return)) {
ReefAngel.Relay.Override(Skimmer,0);
}
// Alert if ATO timeput flag
if (bitRead(ReefAngel.AlertFlags,ATOTimeOutFlag))
atoAlert.Send("ATO+timeout!+ATO+disabled.");
}
void SetSun() {
// Start acclimation routine
int acclRiseOffset=InternalMemory.read(Mem_B_AcclRiseOffset)*60;
int acclSetOffset=InternalMemory.read(Mem_B_AcclSetOffset)*60;
byte acclDay=InternalMemory.read(Mem_B_AcclDay);
ReefAngel.CustomVar[Var_AcclDay]=acclDay;
// See if we are acclimating corals and decrease the countdown each day
static boolean acclCounterReady=false;
if (now()%SECS_PER_DAY!=0) acclCounterReady=true;
if (now()%SECS_PER_DAY==0 && acclCounterReady && acclDay>0) {
acclDay--;
acclCounterReady=false;
InternalMemory.write(Mem_B_AcclDay,acclDay);
}
// End acclimation
sun.Init(InternalMemory.read_int(Mem_I_Latitude), InternalMemory.read_int(Mem_I_Longitude));
sun.SetOffset(-1,(acclDay*acclRiseOffset),-1,(-acclDay*acclSetOffset)); // Bahamas
sun.CheckAndUpdate(); // Calculate today's Sunrise / Sunset
} */
void SetMoon() {
// rfi
byte offset=InternalMemory.read(Mem_B_MoonSlope);
byte startD=InternalMemory.read(Mem_B_PWMSlopeStartD);
byte endD=InternalMemory.read(Mem_B_PWMSlopeEndD);
byte timeD=InternalMemory.read(Mem_B_PWMSlopeDurationD);
byte startA=InternalMemory.read(Mem_B_PWMSlopeStartA);
byte endA=InternalMemory.read(Mem_B_PWMSlopeEndA);
byte timeA=InternalMemory.read(Mem_B_PWMSlopeDurationA);
static byte mp=MoonPhase();
if (mp!=MoonPhase()) {
InternalMemory.write(Mem_B_PWMSlopeEndD,mp);
InternalMemory.write(Mem_B_PWMSlopeEndA,mp);
mp=MoonPhase();
}
moon_init(InternalMemory.read_int(Mem_I_Latitude), InternalMemory.read_int(Mem_I_Longitude));
ReefAngel.PWM.SetDaylight(PWMSlope(Moon.riseH,Moon.riseM,Moon.setH,Moon.setM, startD,endD,timeD,0));
ReefAngel.PWM.SetActinic(PWMSlope(Moon.riseH,Moon.riseM,Moon.setH,Moon.setM, startA,endA,timeA,0));
}
void SetTide() {
// rfi
byte nightSpeed=InternalMemory.read(Mem_B_NightSpeed);
byte tideMin=InternalMemory.read(Mem_B_TideMin);
byte tideMax=InternalMemory.read(Mem_B_TideMax);
// Set tide offsets
tide.SetOffset(tideMin, tideMax);
// Set tide speed. Slope in/out of Night Mode
tide.SetSpeed(PWMSlope(sun.GetRiseHour()-1,sun.GetRiseMinute(),
sun.GetSetHour(),sun.GetSetMinute(),nightSpeed+tideMin,vtSpeed,120,nightSpeed+tideMin));
// Show tide info on portal
ReefAngel.CustomVar[Var_Tide]=tide.CalcTide();
}
void SetRF() {
int ntmDelay=InternalMemory.read(Mem_B_NTMDelay)*60;
int ntmTime=InternalMemory.read(Mem_B_NTMTime)*60;
boolean nightRF=InternalMemory.read(Mem_B_NightRF);
boolean feedingRF=InternalMemory.read(Mem_B_FeedingRF);
static time_t t;
vtMode=InternalMemory.RFMode_read();
vtSpeed=InternalMemory.RFSpeed_read();
vtDuration=InternalMemory.RFDuration_read();
if ((now()-t > ntmDelay && now()-t < ntmTime+ntmDelay) && feedingRF) {
// Post feeding mode
vtMode=Smart_NTM;
vtSpeed=InternalMemory.read(Mem_B_NTMSpeed);
vtDuration=InternalMemory.read(Mem_B_NTMDuration);
} else if (!sun.IsDaytime() && nightRF) {
vtMode=Night;
vtSpeed=InternalMemory.read(Mem_B_NightSpeed);
vtDuration=InternalMemory.read(Mem_B_NightDuration);
} else {
if (vtMode!=Night && ReefAngel.RF.Mode==Night)
ReefAngel.RF.SetMode(Night_Stop,0,0);
}
if (ReefAngel.DisplayedMenu==FEEDING_MODE) {
t=now(); // Run post feeding mode when this counter stops
} else if (ReefAngel.DisplayedMenu==WATERCHANGE_MODE) {
ReefAngel.RF.SetMode(Constant,25,0);
} else {
if ((vtMode==Smart_NTM) || (vtMode==ShortPulse)) vtDuration=InternalMemory.read(Mem_B_NTMDuration);
(vtMode==Custom) ? RFCustom() : ReefAngel.RF.SetMode(vtMode,vtSpeed,vtDuration);
}
}
void RFCustom() {
static boolean changeMode;
byte rcSpeed, rcSpeedAS;
// Define new modes
const int BHazard=15;
const int Else=16;
const int Sine=17;
byte tideSpeed=tide.CalcTide();
byte tideMin=InternalMemory.read(Mem_B_TideMin);
byte tideMax=InternalMemory.read(Mem_B_TideMax);
byte tideMode=InternalMemory.read(Mem_B_TideMode);
float pumpOffset=(float) InternalMemory.read(Mem_B_PumpOffset)/100;
byte RandomModes[]={ ReefCrest, TidalSwell, Smart_NTM, Lagoon, ShortPulse, LongPulse, BHazard, Else, Sine };
if (now()%SECS_PER_DAY!=0) changeMode=true;
if ((now()%SECS_PER_DAY==0 && changeMode)) {
tideMode=random(100)%sizeof(RandomModes);
InternalMemory.write(Mem_B_TideMode,tideMode);
changeMode=false;
}
ReefAngel.CustomVar[Var_TideMode]=tideMode+1;
switch (RandomModes[tideMode]) {
case ReefCrest: {
rcSpeed=ReefCrestMode(tideSpeed,vtDuration*2,true);
rcSpeedAS=ReefCrestMode(tideSpeed,vtDuration*2,false);
break;
}
case Lagoon: {
rcSpeed=ReefCrestMode(tideSpeed,vtDuration,true);
rcSpeedAS=ReefCrestMode(tideSpeed,vtDuration,false);
break;
}
case TidalSwell: {
rcSpeed=TidalSwellMode(tideSpeed,true);
rcSpeedAS=TidalSwellMode(tideSpeed,false);
break;
}
case Smart_NTM: {
rcSpeed=NutrientTransportMode(0,tideSpeed,vtDuration*50,true);
rcSpeedAS=NutrientTransportMode(0,tideSpeed,vtDuration*50,false);
break;
}
case ShortPulse: {
rcSpeed=ShortPulseMode(0,tideSpeed,vtDuration*50,true);
rcSpeedAS=ShortPulseMode(0,tideSpeed,vtDuration*50,false);
break;
}
case LongPulse: {
rcSpeed=LongPulseMode(0,tideSpeed,vtDuration,true);
rcSpeedAS=LongPulseMode(0,tideSpeed,vtDuration,false);
break;
}
case BHazard: {
rcSpeed=millis()%1200>800?tideSpeed:0;
rcSpeedAS=millis()%1200<400?0:tideSpeed;
break;
}
case Else: {
rcSpeed=ElseMode(tideSpeed,vtDuration*2,true);
rcSpeedAS=ElseMode(tideSpeed,vtDuration*2,false);
break;
}
case Sine: {
rcSpeed=SineMode(tideSpeed-tideMin,tideSpeed+tideMin,vtDuration*100,true);
rcSpeedAS=SineMode(tideSpeed-tideMin,tideSpeed+tideMin,vtDuration*100,false);
break;
}
default: {
rcSpeed=tideSpeed;
rcSpeedAS=tideSpeed;
}
}
ReefAngel.RF.SetMode(Custom,rcSpeedAS*pumpOffset,tide.isOutgoing());
ReefAngel.RF.SetMode(Custom,rcSpeed,tide.isIncoming());
}
// Monitor ATO reservoir
/* void CheckATO() {
static time_t t;
static WiFiAlert atoLogAlert;
static boolean atoSaved;
byte prevLevelOld, prevLevel, currLevel;
byte numHours, rate, rateAlarm;
char msg[32];
atoLogAlert.SetDelay(SECS_PER_HOUR*6);
currLevel=ReefAngel.WaterLevel.GetLevel();
prevLevel=InternalMemory.read(Mem_B_LogATO);
prevLevelOld=InternalMemory.read(Mem_B_LogPrevATO);
numHours=(now()%(SECS_PER_HOUR*6))/SECS_PER_HOUR;
rate=(prevLevelOld-currLevel)*(24/(6+numHours));
rateAlarm=InternalMemory.read(Mem_B_RateAlarm);
ReefAngel.CustomVar[Var_LogATO]=rate;
if ((rate<rateAlarm && rateAlarm!=0) && !ReefAngel.Relay.Status(VO_Vacation)) {
if (!ReefAngel.Relay.Status(VO_RefillATO)) {
sprintf(msg,"ATO+rate+(%d)+is+too+low!",rate);
atoLogAlert.Send(msg);
}
}
if (now()%(SECS_PER_HOUR*6)==0) { // Save level and alert every 6 hours
if (!atoSaved) {
atoSaved=true;
InternalMemory.write(Mem_B_LogATO,currLevel);
InternalMemory.write(Mem_B_LogPrevATO,prevLevel);
}
} else {
atoSaved=false;
}
}
// ATO Refill mode. Top off ATO reservoir until it's at 100%
void RefillATO() {
static boolean refillActive=false;
static WiFiAlert refillAlert;
byte level, prevRate;
if (ReefAngel.Relay.Status(VO_EnableATO) || ReefAngel.Relay.Status(VO_Vacation)) {
ReefAngel.Relay.Override(VO_RefillATO,2);
}
level=ReefAngel.WaterLevel.GetLevel();
if (ReefAngel.Relay.Status(VO_RefillATO)) {
if (level<100) {
ReefAngel.Relay.On(ATOres);
refillActive=true;
} else {
ReefAngel.Relay.Override(VO_RefillATO,2);
refillAlert.Send("ATO+Reservoir+is+full.");
if (InternalMemory.read(Mem_B_MaintATO) > 0) // Reset last ATO counter
InternalMemory.write(Mem_B_MaintATO,0);
}
} else {
if (refillActive) {
prevRate=InternalMemory.read(Mem_B_LogPrevATO)-InternalMemory.read(Mem_B_LogATO);
InternalMemory.write(Mem_B_LogPrevATO, level+prevRate);
InternalMemory.write(Mem_B_LogATO, level+1);
ReefAngel.Relay.Off(ATORes);
refillActive=false;
}
}
}
void Vacation() {
static boolean onVacation=InternalMemory.read(Mem_B_Vacation);
ReefAngel.Relay.Set(VO_Vacation, onVacation); // Sets RelayData only
if (ReefAngel.Relay.Status(VO_Vacation)) { // Looks at actual status
onVacation=ReefAngel.Relay.Status(VO_Vacation);
InternalMemory.write(Mem_B_Vacation, onVacation);
ReefAngel.Relay.Override(VO_Vacation,2); // Back to auto mode
}
if (onVacation) {
ReefAngel.WaterLevelATO(ATORes);
if (now()%SECS_PER_DAY==19*SECS_PER_HOUR) {
ReefAngel.FeedingModeStart();
}
}
}
void LogFeedings() {
static byte feedings;
static boolean feedStatus;
if (ReefAngel.Relay.Status(Feeder)) {
feedStatus=true;
} else {
if (feedStatus) {
feedStatus=false;
feedings++;
}
}
if (ReefAngel.DisplayedMenu==FEEDING_MODE) {
if (InternalMemory.read(Mem_B_MaintFeeding) > 0) // Reset last time in Feeding Mode
InternalMemory.write(Mem_B_MaintFeeding,0);
}
ReefAngel.CustomVar[Var_Feedings]=feedings;
if (now()%SECS_PER_DAY==SECS_PER_DAY-1) feedings=0; // Clear feedings at end of day
}
void RunFeeder() {
int press=InternalMemory.read(Mem_B_AutoFeedPress);
int repeat=InternalMemory.read(Mem_B_AutoFeedRepeat)*SECS_PER_HOUR;
int offset=InternalMemory.read(Mem_B_AutoFeedOffset)*SECS_PER_HOUR;
boolean autoFeed=InternalMemory.read(Mem_B_AutoFeed);
static time_t t;
ReefAngel.Relay.Set(VO_AutoFeed, autoFeed);
if (ReefAngel.Relay.Status(VO_AutoFeed)!=autoFeed) {
autoFeed=ReefAngel.Relay.Status(VO_AutoFeed);
InternalMemory.write(Mem_B_AutoFeed, autoFeed);
ReefAngel.Relay.Override(VO_AutoFeed,2);
}
if (autoFeed) {
if (sun.IsDaytime() && (now()+offset)%repeat==0) {
t=now();
}
}
if (ReefAngel.Relay.isMaskOn(Feeder)) {
ReefAngel.Relay.Override(Feeder,2);
t=now()-now()%20; // One feeding has already happened.
}
// Press the button once every 20 seconds
if (now()-t < press*20) {
ReefAngel.Relay.Set(Feeder,now()%20==0);
} else {
ReefAngel.Relay.Off(Feeder);
}
}
/* void RunSwabbie() {
int repeat=InternalMemory.read(Mem_B_SwabbieRepeat)*60;
int runtime=InternalMemory.read(Mem_B_SwabbieTime)*60;
static time_t t;
// Manual mode
if (ReefAngel.Relay.isMaskOn(Swabbie)) {
ReefAngel.Relay.Override(Swabbie,2);
t=now();
}
if (now()-t < runtime) {
ReefAngel.Relay.On(Swabbie);
} else {
ReefAngel.DosingPumpRepeat(Swabbie,0,repeat,runtime);
}
}
// Definitions for dosing pumps
#define numDPumps 3
byte pump[numDPumps]={ DPump1, DPump2, Extension}; // Pump 3 is just for logging/calibration routine
byte varReport[numDPumps]={ Var_DPump1, Var_DPump2, Var_WCVol};
byte memDPTime[numDPumps]={ Mem_B_DP1Timer, Mem_B_DP2Timer, Mem_B_DP3Timer};
int memDPVolume[numDPumps]={ Mem_I_DP1Volume, Mem_I_DP2Volume, Mem_I_DP3Volume };
int memDPRepeat[numDPumps]={ Mem_I_DP1RepeatInterval, Mem_I_DP2RepeatInterval, Mem_I_DP3RepeatInterval };
int memCalTime[numDPumps]={ Mem_I_CalDP1Time, Mem_I_CalDP2Time, Mem_I_CalDP3Time };
int memCalVol[numDPumps]={ Mem_I_CalDP1Vol, Mem_I_CalDP2Vol, Mem_I_CalDP3Vol };
void RunDosingPumps() {
float rate;
byte dpTime;
int dpRepeat, calcTime, totalVolume;
const int numPumps = numDPumps-1; // -1 = Remove "Extension" from the equation.
static byte doseTime[numPumps]={
InternalMemory.read(memDPTime[0]),
InternalMemory.read(memDPTime[1])
};
for (int i=0;i < numPumps; i++) {
dpTime=InternalMemory.read(memDPTime[i]);
dpRepeat=InternalMemory.read_int(memDPRepeat[i]);
rate=(float)InternalMemory.read_int(memCalVol[i])/InternalMemory.read_int(memCalTime[i]);
calcTime=(InternalMemory.read_int(memDPVolume[i])/rate)/(1440/dpRepeat);
totalVolume=rate*(dpTime*(1440/dpRepeat));
if (dpTime!=doseTime[i]) { // Memory has changed.
InternalMemory.write_int(memDPVolume[i], totalVolume); // Update volume
doseTime[i]=dpTime;
} else if (dpTime!=calcTime) { // Calculated time has changed.
InternalMemory.write(memDPTime[i], calcTime); // Update time
doseTime[i]=calcTime;
}
// Make sure we're not calibrating
if (!ReefAngel.Relay.Status(VO_Calibrate))
ReefAngel.DosingPumpRepeat(pump[i], i*5, dpRepeat, doseTime[i]);
}
}
void LogDosingPumps() {
static time_t pumpTimer[numDPumps];
static boolean pumpStatus[numDPumps];
float rate;
for (int i=0;i< numDPumps;i++) {
if (ReefAngel.Relay.Status(pump[i])) {
if (!pumpStatus[i]) {
pumpTimer[i]=now()-pumpTimer[i]; // Pump was off, timer is now a time
pumpStatus[i]=true;
}
} else {
if (pumpStatus[i]) {
pumpTimer[i]=now()-pumpTimer[i]; // Pump was on, timer is now a timer
pumpStatus[i]=false;
rate=(float)InternalMemory.read_int(memCalVol[i])/InternalMemory.read_int(memCalTime[i]);
ReefAngel.CustomVar[varReport[i]]=pumpTimer[i]*rate;
}
}
if (now()%SECS_PER_DAY==SECS_PER_DAY-1 && i!=2) { // Don't overwrite WC log
pumpTimer[i]=0; // Clear timer at end of day
ReefAngel.CustomVar[varReport[i]]=0; // Clear portal variable
}
}
// Reset logging for WC fill pump at start of WC
static boolean wcStart;
if (ReefAngel.DisplayedMenu!=WATERCHANGE_MODE) wcStart=false;
if (ReefAngel.DisplayedMenu==WATERCHANGE_MODE && !wcStart) {
ReefAngel.CustomVar[varReport[2]]=0;
pumpTimer[2]=0;
wcStart=true;
}
}
void CalibrateDPumps() {
static time_t pumpTimer[numDPumps];
static boolean pumpStatus[numDPumps];
static boolean running=false;
if (ReefAngel.Relay.Status(VO_Calibrate)) {
running=true;
for (int i=0;i < numDPumps;i++) {
if (ReefAngel.Relay.Status(pump[i])) {
if (!pumpStatus[i]) {
pumpTimer[i]=now()-pumpTimer[i]; // Pump was off, timer is now a time
pumpStatus[i]=true;
}
} else {
if (pumpStatus[i]) {
pumpTimer[i]=now()-pumpTimer[i]; // Pump was on, timer is now a timer
pumpStatus[i]=false;
}
}
}
} else {
if (running) {
running=false;
for (int i=0;i < numDPumps;i++) {
if (pumpTimer[i]>0 && !ReefAngel.Relay.Status(VO_LockPorts)) {
InternalMemory.write_int(memCalTime[i], pumpTimer[i]);
}
ReefAngel.Relay.Override(pump[i],2); // Go back to auto mode
pumpStatus[i]=false;
pumpTimer[i]=0;
}
}
}
}
void AutoWaterChange() {
int runtime=InternalMemory.read_int(Mem_I_WCFillTime);
static WiFiAlert wcAlert;
static boolean started;
static time_t t;
if (ReefAngel.DisplayedMenu==WATERCHANGE_MODE) {
ReefAngel.Relay.On(Refugium);
if (ReefAngel.Relay.Status(VO_EnableATO)) {
ReefAngel.SingleATOHigh(Extension); // Refill fresh SW as needed
if (InternalMemory.read(Mem_B_MaintWC) > 0) // Reset last WC counter
InternalMemory.write(Mem_B_MaintWC,0);
if (ReefAngel.Relay.Status(VO_StartFill) && !started) {
ReefAngel.Relay.Override(Reactor,1); // Start draining
started=true;
t=now();
}
if ( (now()-t > runtime && started) || bitRead(ReefAngel.AlertFlags,ATOTimeOutFlag) ) {
ReefAngel.Relay.Override(Reactor,0); // Stop draining
ReefAngel.Relay.Override(VO_StartFill,2); // Reset Start switch
if (started) wcAlert.Send("Reactor+disabled.", true);
started=false;
}
} else {
// Done with ATO
ReefAngel.Relay.Off(Extension);
// Backup WC Vol
if (InternalMemory.read(Mem_B_MaintWCVol) != ReefAngel.CustomVar[Var_WCVol])
InternalMemory.write(Mem_B_MaintWCVol, ReefAngel.CustomVar[Var_WCVol]);
// Clear stale timeout
ReefAngel.ATOClear();
}
} else {
ReefAngel.Relay.Override(VO_EnableATO,2);
ReefAngel.Relay.Override(VO_StartFill,2);
}
}
// Disable masks for things that should not be turned on by mistake
void LockPorts() {
ReefAngel.AddPortOverrides();
if (ReefAngel.Relay.Status(VO_LockPorts)) {
ReefAngel.OverridePortsE[0] = Port7Bit | Port8Bit;
ReefAngel.OverridePortsE[1] = Port4Bit | Port5Bit | Port7Bit;
} else {
ReefAngel.OverridePortsE[0] = 0;
ReefAngel.OverridePortsE[1] = 0;
}
}
/*
void Reminders() {
static boolean counterReady;
byte counter[]= { Mem_B_MaintGAC, Mem_B_MaintGFO, Mem_B_MaintCal, Mem_B_MaintAlk,
Mem_B_MaintWC, Mem_B_MaintATO, Mem_B_MaintFeeding, Mem_B_MaintSkimmer, Mem_B_MaintSocks };
if (now()%SECS_PER_DAY!=0) counterReady=true;
if (now()%SECS_PER_DAY==0 && counterReady) {
for (int i=0;i<sizeof(counter);i++) {
InternalMemory.write(counter[i],InternalMemory.read(counter[i])+1);
}
counterReady=false;
}
} */
void NextRFMode() {
vtMode++;
if (vtMode > 12) {
vtMode=0;
vtSpeed=50; // Constant
} else if (vtMode == 1) {
vtSpeed=40; // Lagoon
} else if (vtMode == 2) {
vtSpeed=45; // Reef Crest
} else if (vtMode == 3) {
vtSpeed=55; vtDuration=10; // Short Pulse
} else if (vtMode == 4) {
vtSpeed=55; vtDuration=20; // Long Pulse
} else if (vtMode == 5) {
vtSpeed=InternalMemory.read(Mem_B_NTMSpeed);
vtDuration=InternalMemory.read(Mem_B_NTMDuration); // Smart_NTM
} else if (vtMode == 6) {
vtSpeed=50; vtDuration=10; // Smart_TSM
} else if (vtMode == 7) {
vtSpeed=InternalMemory.read(Mem_B_NightSpeed);
vtDuration=InternalMemory.read(Mem_B_NightDuration);
vtMode=9; // Night
} else if (vtMode == 10) {
vtSpeed=65; vtDuration=5; // Storm
} else if (vtMode == 11) {
vtSpeed=45; vtDuration=10; // Custom
}
if (vtMode!=InternalMemory.RFMode_read())
InternalMemory.RFMode_write(vtMode);
if (vtSpeed!=InternalMemory.RFSpeed_read())
InternalMemory.RFSpeed_write(vtSpeed);
if (vtDuration!=InternalMemory.RFDuration_read())
InternalMemory.RFDuration_write(vtDuration);
}
// Menu Code
void MenuEntry1() {
// Toggle refugium light between on/auto.
// ReefAngel.Relay.Override(Refugium, ReefAngel.Relay.Status(Refugium)+1);
ReefAngel.DisplayedMenu = RETURN_MAIN_MODE;
}
void MenuEntry2() {
ReefAngel.FeedingModeStart();
}
void MenuEntry3() {
ReefAngel.WaterChangeModeStart();
}
void MenuEntry4() {
NextRFMode();
ReefAngel.DisplayedMenu = RETURN_MAIN_MODE;
}
void MenuEntry5() {
ReefAngel.ATOClear();
ReefAngel.DisplayMenuEntry("Clear ATO Timeout");
}
void MenuEntry6() {
ReefAngel.OverheatClear();
ReefAngel.DisplayMenuEntry("Clear Overheat");
}
void MenuEntry7() {
ReefAngel.SetupCalibratePH();
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry8() {
ReefAngel.SetupCalibrateWaterLevel();
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
void MenuEntry9() {
ReefAngel.SetupDateTime();
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}
// Custom Main Screen
void DrawCustomMain() {
const int NumScreens=3;
static boolean drawGraph=true;
// Main Header
// ReefAngel.LCD.DrawText(DefaultFGColor, DefaultBGColor, 35, 2,"Lee's Reef");
ReefAngel.LCD.DrawDate(5,2);
ReefAngel.LCD.Clear(COLOR_BLACK, 1, 11, 128, 11);
// Param Header
DrawParams(5,14);
switch (ScreenID) {
case 0:
{
if (drawGraph) { ReefAngel.LCD.DrawGraph(5,40); drawGraph=false; }
break;
}
case 1: { DrawStatus(5,40); break; }
case 2: { DrawSunMoon(5,40); break; }
}
// Draw Relays
DrawRelays(12,94);
// Date+Time
// ReefAngel.LCD.DrawDate(5,122);
if (ReefAngel.Joystick.IsLeft()) {
ReefAngel.ClearScreen(DefaultBGColor);
ScreenID--; drawGraph=true;
}
if (ReefAngel.Joystick.IsRight()) {
ReefAngel.ClearScreen(DefaultBGColor);
ScreenID++; drawGraph=true;
}
if (ScreenID<0) ScreenID=NumScreens-1;
if (ScreenID>=NumScreens) ScreenID=0;
}
void DrawCustomGraph() {
if (ScreenID==0)
ReefAngel.LCD.DrawGraph(5, 40);
}
void DrawParams(int x, int y) {
char buf[16];
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,x+5,y,"Temp:");
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,x+80, y, "PH:");
// Temp and PH
y+=2;
ConvertNumToString(buf, ReefAngel.Params.Temp[T2_PROBE], 10);
ReefAngel.LCD.DrawText(T2TempColor, DefaultBGColor, x+45, y, buf);
y+=6;
ConvertNumToString(buf, ReefAngel.Params.Temp[T1_PROBE], 10);
ReefAngel.LCD.DrawLargeText(T1TempColor, DefaultBGColor, x+5, y, buf, Num8x16);
ConvertNumToString(buf, ReefAngel.Params.PH, 100);
ReefAngel.LCD.DrawLargeText(PHColor, DefaultBGColor, x+80, y, buf, Num8x16);
y+=5;
ConvertNumToString(buf, ReefAngel.Params.Temp[T3_PROBE], 10);
ReefAngel.LCD.DrawText(T3TempColor, DefaultBGColor, x+45, y, buf);
}
void DrawStatus(int x, int y) {
int t=x;
ReefAngel.LCD.DrawLargeText(COLOR_INDIGO,DefaultBGColor,15,y,"High",Font8x16);
ReefAngel.LCD.DrawLargeText(COLOR_INDIGO,DefaultBGColor,85,y,"Low",Font8x16);
if (ReefAngel.HighATO.IsActive()) {
ReefAngel.LCD.FillCircle(55,y+3,5,COLOR_GREEN);
} else {
ReefAngel.LCD.FillCircle(55,y+3,5,COLOR_RED);
}
if (ReefAngel.LowATO.IsActive()) {
ReefAngel.LCD.FillCircle(70,y+3,5,COLOR_GREEN);
} else {
ReefAngel.LCD.FillCircle(70,y+3,5,COLOR_RED);
}
y+=12;
// Display Water level
ReefAngel.LCD.DrawText(DefaultFGColor,DefaultBGColor,x,y,"AT0 Level:"); x+=65;
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.WaterLevel.GetLevel(),DPColor,x,y,1);
x+=5*(intlength(ReefAngel.WaterLevel.GetLevel())+1);
ReefAngel.LCD.DrawText(DPColor, DefaultBGColor, x, y, "%");
y+=12; x=t;
// Vortech Mode
ReefAngel.LCD.DrawText(0,255,x,y,"RF:"); x+=20;
ReefAngel.LCD.Clear(DefaultBGColor,x,y,t+(128-t),y+8);
if (vtMode == 0) ReefAngel.LCD.DrawLargeText(COLOR_GREEN,255,x,y,"Constant");
else if (vtMode == 1) ReefAngel.LCD.DrawLargeText(COLOR_GOLD,255,x,y,"Lagoon");
else if (vtMode == 2) ReefAngel.LCD.DrawLargeText(COLOR_GOLD,255,x,y,"Reef Crest");
else if (vtMode == 3) ReefAngel.LCD.DrawLargeText(COLOR_RED,255,x,y,"Short Pulse");
else if (vtMode == 4) ReefAngel.LCD.DrawLargeText(COLOR_RED,255,x,y,"Long Pulse");
else if (vtMode == 5) ReefAngel.LCD.DrawLargeText(COLOR_MAGENTA,255,x,y,"Smart NTM");
else if (vtMode == 6) ReefAngel.LCD.DrawLargeText(COLOR_MAGENTA,255,x,y,"Tidal Swell");
else if (vtMode == 9) ReefAngel.LCD.DrawLargeText(COLOR_WHITE,0,x,y,"Night");
else if (vtMode == 10) ReefAngel.LCD.DrawLargeText(COLOR_BLUE,0,x,y,"Storm");
else if (vtMode == 11) ReefAngel.LCD.DrawLargeText(COLOR_BLUE,255,x,y,"Custom");
y+=10; x=t;
ReefAngel.LCD.DrawText(0,255,x,y,"RF Speed:"); x+=60;
ReefAngel.LCD.Clear(DefaultBGColor,x,y,128,y+8);
ReefAngel.LCD.DrawText(COLOR_BLUE, DefaultBGColor,x,y,vtSpeed); x+=15;
ReefAngel.LCD.DrawText(COLOR_BLUE, DefaultBGColor,x,y,"/"); x+=10;
ReefAngel.LCD.DrawText(COLOR_BLUE, DefaultBGColor,x,y,vtDuration);
y+=10; x=t;
// Display Acclimation timer
if (ReefAngel.CustomVar[Var_AcclDay] > 0) {
ReefAngel.LCD.DrawText(DefaultFGColor,DefaultBGColor,x,y,"Acclimation Day:"); x+=100;
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.CustomVar[Var_AcclDay],DefaultFGColor,x,y,1);
} else {
ReefAngel.LCD.Clear(DefaultBGColor,x,y,128,y+8);
}
}
void DrawSunMoon(int x, int y) {
char buf[16];
int t=x;
y+=2;
/// Display Sunrise / Sunset
sprintf(buf, "%02d:%02d", sun.GetRiseHour(), sun.GetRiseMinute());
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,x,y,"Rise:"); x+=31;
ReefAngel.LCD.DrawText(COLOR_RED,DefaultBGColor,x,y,buf);
sprintf(buf, "%02d:%02d", sun.GetSetHour(), sun.GetSetMinute()); x+=36;
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,x,y,"Set:"); x+=25;
ReefAngel.LCD.DrawText(COLOR_RED,DefaultBGColor,x,y,buf);
y+=15; x=t;
/// Display Moonrise / Moonset
sprintf(buf, "%02d:%02d", Moon.riseH, Moon.riseM);
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,x,y,"MR:"); x+=21;
ReefAngel.LCD.DrawText(COLOR_RED,DefaultBGColor,x,y,buf);
sprintf(buf, "%02d:%02d", Moon.setH, Moon.setM); x+=36;
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,x,y,"MS:"); x+=21;
ReefAngel.LCD.DrawText(COLOR_RED,DefaultBGColor,x,y,buf); x+=36;
if (Moon.isUp) ReefAngel.LCD.DrawText(COLOR_RED,DefaultBGColor,x,y,"@");
else ReefAngel.LCD.DrawText(COLOR_RED,DefaultBGColor,x,y,"_");
y+=10; x=t;
// MoonPhase
ReefAngel.LCD.DrawText(0,255,x,y,"Moon:");
ReefAngel.LCD.Clear(DefaultBGColor,x+32,y,128,y+8);
ReefAngel.LCD.DrawText(COLOR_MAGENTA,255,x+32,y,MoonPhaseLabel());
y+=10; x=t;
// MoonLight %
ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,x,y,"MoonLights:"); x+=68;
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.PWM.GetDaylightValue(),DPColor,x,y,1);
x+=5*(intlength(ReefAngel.PWM.GetDaylightValue())+1);
ReefAngel.LCD.DrawText(DPColor, DefaultBGColor, x, y, "%");
}
void DrawRelays(int x, int y) {
// Draw Relays
byte TempRelay = ReefAngel.Relay.RelayData;
TempRelay &= ReefAngel.Relay.RelayMaskOff;
TempRelay |= ReefAngel.Relay.RelayMaskOn;
ReefAngel.LCD.DrawOutletBox(x, y, TempRelay);
y+=12;
TempRelay = ReefAngel.Relay.RelayDataE[0];
TempRelay &= ReefAngel.Relay.RelayMaskOffE[0];
TempRelay |= ReefAngel.Relay.RelayMaskOnE[0];
ReefAngel.LCD.DrawOutletBox(x, y, TempRelay);
y+=12;
TempRelay = ReefAngel.Relay.RelayDataE[1];
TempRelay &= ReefAngel.Relay.RelayMaskOffE[1];
TempRelay |= ReefAngel.Relay.RelayMaskOnE[1];
ReefAngel.LCD.DrawOutletBox(x, y, TempRelay);
}
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;
}
}
void DelayedOnModes(byte relay) {
static unsigned long startTime=now();
if (startTime==LastStart && ReefAngel.HighATO.IsActive()) {
ReefAngel.Relay.On(relay);
} else {
ReefAngel.Relay.DelayedOn(relay);
}
}
Re: Why does my RA go into feeding mode randomly
Not sure if this is related but...
1) I set my Return, Wavemaker Right and Wavemaker Left to Always On via the portal.
2) at 8:00 pm the RA unit seemed to reset/restart and all relays went back to their default "auto" state
The RA unit is plugged into a surge protector but there was no spike that occurred that would have reset the unit. Seems like the unit just reset itself on its own. Again, not sure if its related but I just noticed this happen. Please let me know if there is anything that you can uncover to help me/us troubleshoot this issue. Thanks.
Jeremiah
1) I set my Return, Wavemaker Right and Wavemaker Left to Always On via the portal.
2) at 8:00 pm the RA unit seemed to reset/restart and all relays went back to their default "auto" state
The RA unit is plugged into a surge protector but there was no spike that occurred that would have reset the unit. Seems like the unit just reset itself on its own. Again, not sure if its related but I just noticed this happen. Please let me know if there is anything that you can uncover to help me/us troubleshoot this issue. Thanks.
Jeremiah
Re: Why does my RA go into feeding mode randomly
Do you have the RF module to connect wirelessly to vortechs?
Re: Why does my RA go into feeding mode randomly
Yes. I had the same issue (random feeding mode and resets) when the RF module was connected or disconnected.
Re: Why does my RA go into feeding mode randomly
Hmm mine doesn't have any issues when the RF module is disconnected (so far). I wonder if you are suffering from the exactly same issue as us. When it goes into these random feeding modes for you, is the head unit really in feeding mode or are the relays just turning off?
Re: Why does my RA go into feeding mode randomly
really in feeding ie. the display says feeding mode. If I exit out of feeding mode, the pump turns back on.
Just curious, are you calling the pump by port number in code ie. "port4" or "box1_port4" or "Port4Bit"? Or are you calling via defined named ie. "(Pump)" or "(ReturnPump)"?
Just curious, are you calling the pump by port number in code ie. "port4" or "box1_port4" or "Port4Bit"? Or are you calling via defined named ie. "(Pump)" or "(ReturnPump)"?
Re: Why does my RA go into feeding mode randomly
UPDATE
All,
I got annoyed that this issue was still happening so I did the following:
1) Backed my "lee's revised" ino
2) Used my current laptop and restored the code on the RA to default via TOOLS-->Restore Preloaded Code
3) Verified that the RA was reset to default code.
4) Used a BRAND NEW computer from my work and installed ReefAngelInstaller_1.1.0
5) Followed all the setup instructions
5) Re-downloaded the 4 folders that need to be copied to library from Lee's thread
6) Uploaded my backed-up code (I emailed it to myself)
7) Within 15 minutes my unit went into Feeding Mode without input from me.
Basically, reverting to original code, and restoring from a new computer did nothing. Just like before, I have no idea why my RA goes into Feeding Mode randomly. Please help. Thanks.
Jeremiah
All,
I got annoyed that this issue was still happening so I did the following:
1) Backed my "lee's revised" ino
2) Used my current laptop and restored the code on the RA to default via TOOLS-->Restore Preloaded Code
3) Verified that the RA was reset to default code.
4) Used a BRAND NEW computer from my work and installed ReefAngelInstaller_1.1.0
5) Followed all the setup instructions
5) Re-downloaded the 4 folders that need to be copied to library from Lee's thread
6) Uploaded my backed-up code (I emailed it to myself)
7) Within 15 minutes my unit went into Feeding Mode without input from me.
Basically, reverting to original code, and restoring from a new computer did nothing. Just like before, I have no idea why my RA goes into Feeding Mode randomly. Please help. Thanks.
Jeremiah
Re: Why does my RA go into feeding mode randomly
Hey guys,
Is there any other testing or data that you need to help us solve this? I'm at a loss at this point. I'd really like to get my tank running optimally again so any help you can provide would be appreciated. thanks.
Jeremiah
Is there any other testing or data that you need to help us solve this? I'm at a loss at this point. I'd really like to get my tank running optimally again so any help you can provide would be appreciated. thanks.
Jeremiah
Re: Why does my RA go into feeding mode randomly
Has anyone tried downgrading the libraries. If its SW related it would help to know exactly which version introduced the issue.
Re: Why does my RA go into feeding mode randomly
Going from 110 to 109 didn't compile for me. I was getting this compile error:
Then I copied ReefAngel.cpp and ReefAngel.h from 110 to 109 and I got this error:
Code: Select all
The following features were automatically added:
Watchdog Timer
Version Menu
The following features were detected:
Dimming Signal
RF Expansion Module
Wifi Attachment
Custom Main Screen
Custom Variable
Extra Font - Medium Size (8x8 pixels)
Extra Font - Numbers Only - Large Font (8x16 pixels)
Date/Time Setup Menu
Relay Expansion Module
Custom Menu
Water Level Expansion Module
Moon Phase Label
Number of Relay Expansion Modules: 2
Number of Menu Options: 9
Lees_alteredv3_cleaned.cpp: In function 'void setup()':
Lees_alteredv3_cleaned:171: error: 'class ReefAngelClass' has no member named 'AddWaterLevelExpansion'
Code: Select all
The following features were automatically added:
Watchdog Timer
Version Menu
The following features were detected:
Dimming Signal
RF Expansion Module
Wifi Attachment
Custom Main Screen
Custom Variable
Extra Font - Medium Size (8x8 pixels)
Extra Font - Numbers Only - Large Font (8x16 pixels)
Date/Time Setup Menu
Relay Expansion Module
Custom Menu
Water Level Expansion Module
Moon Phase Label
Number of Relay Expansion Modules: 2
Number of Menu Options: 9
In file included from Lees_alteredv3_cleaned.cpp:21:
C:\Users\jmaza\Documents\Arduino\libraries\ReefAngel/ReefAngel.h:108: error: 'RA_Wifi' does not name a type
Lees_alteredv3_cleaned.cpp: In function 'void setup()':
Lees_alteredv3_cleaned:170: error: 'class ReefAngelClass' has no member named 'InitMenu'
Lees_alteredv3_cleaned.cpp: In function 'void loop()':
Lees_alteredv3_cleaned:255: error: 'class ReefAngelClass' has no member named 'ShowInterface'
Lees_alteredv3_cleaned.cpp: In function 'void MenuEntry5()':
Lees_alteredv3_cleaned:471: error: 'class ReefAngelClass' has no member named 'DisplayMenuEntry'
Lees_alteredv3_cleaned.cpp: In function 'void MenuEntry6()':
Lees_alteredv3_cleaned:475: error: 'class ReefAngelClass' has no member named 'DisplayMenuEntry'
Lees_alteredv3_cleaned.cpp: In function 'void MenuEntry8()':
Lees_alteredv3_cleaned:482: error: 'class ReefAngelClass' has no member named 'SetupCalibrateWaterLevel'
Lees_alteredv3_cleaned.cpp: In function 'void MenuEntry9()':
Lees_alteredv3_cleaned:486: error: 'class ReefAngelClass' has no member named 'SetupDateTime'
Lees_alteredv3_cleaned.cpp: In function 'void DrawCustomMain()':
Lees_alteredv3_cleaned:497: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:498: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:506: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:519: error: 'class ReefAngelClass' has no member named 'Joystick'
Lees_alteredv3_cleaned:523: error: 'class ReefAngelClass' has no member named 'Joystick'
Lees_alteredv3_cleaned.cpp: In function 'void DrawCustomGraph()':
Lees_alteredv3_cleaned:534: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned.cpp: In function 'void DrawParams(int, int)':
Lees_alteredv3_cleaned:540: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:541: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:545: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:548: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:550: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:553: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned.cpp: In function 'void DrawStatus(int, int)':
Lees_alteredv3_cleaned:559: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:560: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:563: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:565: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:569: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:571: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:576: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:577: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:579: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:583: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:584: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:585: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:586: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:587: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:588: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:589: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:590: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:591: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:592: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:593: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:594: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:597: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:598: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:599: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:600: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:601: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:606: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:607: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:609: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned.cpp: In function 'void DrawSunMoon(int, int)':
Lees_alteredv3_cleaned:620: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:621: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:623: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:624: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:629: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:630: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:632: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:633: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:634: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:635: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:639: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:640: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:641: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:645: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:646: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:648: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned.cpp: In function 'void DrawRelays(int, int)':
Lees_alteredv3_cleaned:656: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:662: error: 'class ReefAngelClass' has no member named 'LCD'
Lees_alteredv3_cleaned:668: error: 'class ReefAngelClass' has no member named 'LCD'
Re: Why does my RA go into feeding mode randomly
Think you need to try a clean install...
Re: Why does my RA go into feeding mode randomly
How do I do a clean install of libs 109? This install was semi-clean in that it was a new computer that I installed using libs 110 (most recent). I copied the appropriate files (moon, wifialert, etc.) and compiled successfully. I then downloaded libs 109 from a link in another post, unzipped files to my Arduino folder, renamed Library to Library_bak then renamed Library-109 (the name of unzipped libs) to Library. I relaunched Arduino, check libs version to confrim it said 109 then compiled and got these errors.
As a test I renamed everything back to "normal", relaunched Arduino, checked libs to confirm it said 110 and recompiled successfully.
As a test I renamed everything back to "normal", relaunched Arduino, checked libs to confirm it said 110 and recompiled successfully.
Re: Why does my RA go into feeding mode randomly
The wifialert package has been updated to be compatible with 1.1.0, i think using the current version with the old library screwed up the package. Can you try a hard coded wizard version with 1.0.9 and see if you still have an issue. If it's good i'd recommend using the same ino on 1.1.0 to reproduce...my code is a hog using lots of custom memory locations and also if your using my RF custom mode could be contributing... I also do some weird things that could contribute if memory is set wrong including triggering feed mode in the vacation() function...
Re: Why does my RA go into feeding mode randomly
Downgrading libs isn't going to be as turn key as I thought. What i did:
Fresh install
Renamed Library folder to Library_bak
Unzipped Libs 1.0.9 to Arduino folder and renamed to Library
Launched Arduino and confirmed the libs are 1.0.9
Ran Wizard and skipped to Generate Only (didn't upload)
Once code was on screen I hit Verify and got the compile error below:
I'm assuming the install assumes libs 1.1.0 and thus adds certain lines to the generated code as needed.
I'm going to run a few tests; like reverting back to my original ino, using clean 1.1.0 Wizard generated code and reverting back to default code via Tools --> Restore Preloaded code. I just wanted to get this latest test out there. Thanks.
Jeremiah
Fresh install
Renamed Library folder to Library_bak
Unzipped Libs 1.0.9 to Arduino folder and renamed to Library
Launched Arduino and confirmed the libs are 1.0.9
Ran Wizard and skipped to Generate Only (didn't upload)
Once code was on screen I hit Verify and got the compile error below:
Code: Select all
The following features were automatically added:
Watchdog Timer
Version Menu
The following features were detected:
RF Expansion Module
Wifi Attachment
Relay Expansion Module
2014 Main Screen
Extra Font - Medium Size (8x8 pixels)
Water Level Expansion Module
Number of Relay Expansion Modules: 1
Simple Menu
libsv9_test.cpp: In function 'void setup()':
libsv9_test:41: error: 'class ReefAngelClass' has no member named 'Use2014Screen'
libsv9_test:42: error: 'class ReefAngelClass' has no member named 'AddWaterLevelExpansion'
I'm going to run a few tests; like reverting back to my original ino, using clean 1.1.0 Wizard generated code and reverting back to default code via Tools --> Restore Preloaded code. I just wanted to get this latest test out there. Thanks.
Jeremiah
Re: Why does my RA go into feeding mode randomly
Roberto,
Do you have an archive of the 1.0.9 install somewhere?
Jeremiah, was 1.0.9 definitely the version you had that was working?
Do you have an archive of the 1.0.9 install somewhere?
Jeremiah, was 1.0.9 definitely the version you had that was working?
Re: Why does my RA go into feeding mode randomly
Thanks Roberto.
To the guys that are having this issue: I confirmed that my issue is the same, in that, if I disconnect my RF unit the random feeding mode stops. That said, have you tried swapping/switching ports on the expansion hub? I was testing each port on my expansion unit and found that the issue has gone away (for now) if I plug my RF unit into one of the SIDE ports (the side with only 2 available ports). I only have 3 modules (RF, Relay and Single ATO) and I had all three plugged into the "bottom" (in my setup) ports, so I used 3 of the 4 on one side. I switched the RF to ports mentioned above and I have gone ~20 hours without issue (longest stretch w/o issue).
@ Robert et al - any thoughts as to why changing the expansion slot would fix the issue or is it likely just coincidence?
Jeremiah
To the guys that are having this issue: I confirmed that my issue is the same, in that, if I disconnect my RF unit the random feeding mode stops. That said, have you tried swapping/switching ports on the expansion hub? I was testing each port on my expansion unit and found that the issue has gone away (for now) if I plug my RF unit into one of the SIDE ports (the side with only 2 available ports). I only have 3 modules (RF, Relay and Single ATO) and I had all three plugged into the "bottom" (in my setup) ports, so I used 3 of the 4 on one side. I switched the RF to ports mentioned above and I have gone ~20 hours without issue (longest stretch w/o issue).
@ Robert et al - any thoughts as to why changing the expansion slot would fix the issue or is it likely just coincidence?
Jeremiah
Re: Why does my RA go into feeding mode randomly
I tried switching the ports as well, though it was less frequent it still did happen. I remember a while back there being an issue with usb noise on the expansion hub causing the system to periodically shut down.
Re: Why does my RA go into feeding mode randomly
So for me all signs point to the RF module. Every time I unplug it I don't get any mysterious Feeding Modes. Can this be updated? Roberto I have the firmware that makes the RF module reset all the time. Probably flashed that around October.
Re: Why does my RA go into feeding mode randomly
Can you try the original one?
- Attachments
-
- update.zip
- (408.13 KiB) Downloaded 496 times
Roberto.
-
- Posts: 126
- Joined: Thu Sep 19, 2013 7:46 am
- Location: Saint Cloud, FL
Re: Why does my RA go into feeding mode randomly
Any ideas?
I just installed my unit and getting random feed mode
Fresh install
Rf module
I took everything off feed mode
Could it be that I have my vortech WES's plugged into relay box? Should these be plugged into wall?
I just installed my unit and getting random feed mode
Fresh install
Rf module
I took everything off feed mode
Could it be that I have my vortech WES's plugged into relay box? Should these be plugged into wall?
-
- Posts: 126
- Joined: Thu Sep 19, 2013 7:46 am
- Location: Saint Cloud, FL
Re: Why does my RA go into feeding mode randomly
Just to update:
I took the advice and plugged the USB side of the RF module into the side of the expansion module. Two days now and there is no random feed mode happening anymore. Both pumps are plugged into relay box and everything seems to be OK now? Solution who knows but it is working properly.
I took the advice and plugged the USB side of the RF module into the side of the expansion module. Two days now and there is no random feed mode happening anymore. Both pumps are plugged into relay box and everything seems to be OK now? Solution who knows but it is working properly.
Re: Why does my RA go into feeding mode randomly
Didn't update the RF unit yet, but tried other usb ports in the expansion hub. I even have the Vortech pumps turned off and I am still having the issue.
Re: Why does my RA go into feeding mode randomly
Haven't looked at this thread in a while. I'm trying one of the usb ports on the side (2 usb ports) of the expansion module. One thing I noticed is wiggling the connector on the RF module causes all of the relays to go beserk, if I wiggle the other end of the usb port (on the expansion hub) nothing happens. There is something very fishy with this RF module. It maybe a bad cable and I can see what happens when I replace it. But it is definitely the RF module/usb that causing this issue.
Re: Why does my RA go into feeding mode randomly
i would agree that is has to be something to do with the RF module, every time when the controller goes berserk first thing i will check is the RF module connection.
Any idea how to solve this?
Any idea how to solve this?
Re: Why does my RA go into feeding mode randomly
Has anyone ever figured this issue out? I still get random feeding modes happen throughout the day. I have just switched the feedmode ports to my unused ports, but it would be nice to work correctly.