I tried re-introducing custom labels into my code, and ran into the reboot loop again. Here's the offending section:
which, when commented out, stops the reboot loop.
Code: Select all
#include <ReefAngel_Features.h>
#include <Globals.h>
#include <RA_Wifi.h>
#include <Wire.h>
#include <OneWire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <InternalEEPROM.h>
#include <RA_NokiaLCD.h>
#include <RA_ATO.h>
#include <RA_Joystick.h>
#include <LED.h>
#include <RA_TempSensor.h>
#include <Relay.h>
#include <RA_PWM.h>
#include <Timer.h>
#include <Memory.h>
#include <InternalEEPROM.h>
#include <RA_Colors.h>
#include <RA_CustomColors.h>
#include <Salinity.h>
#include <RF.h>
#include <IO.h>
#include <ORP.h>
#include <AI.h>
#include <PH.h>
#include <WaterLevel.h>
#include <Humidity.h>
#include <DCPump.h>
#include <PAR.h>
#include <ReefAngel.h>
#include <Moon.h>
////// Place global variable code below here
#define Heater_300W Port1
#define Heater_100W Port2
#define Skimmer Port3
#define Neck_Wipe Port4
#define Air_Pump Port5
#define Filter_Pump Port6
#define Refuge_Light Port7
#define Ozone_Gen Port8
#define FlowWolf Box1_Port1
#define Closed_Loop Box1_Port2
#define Kalk_Stirrer Box1_Port3
#define ATO_Pump Box1_Port4
#define Return_Pump_L Box1_Port5
#define Return_Pump_R Box1_Port6
#define Heater_200W Box1_Port7
#define Refugium_Pump Box1_Port8
#define Neutral_White_Center 0
#define Warm_White_Center 1
#define Royal_Blue_Center 2
#define Cool_Blue_Center 3
#define Cyan_Center 4
#define Red_Center 5
#define Indigo_Center 6
#define Violet_Center 7
int MoonBlueLevel=0;
int SunBlueLevel=0;
int SunIndigoLevel=0;
int MoonIndigoLevel=0;
////// Place global variable code above here
void setup()
{
ReefAngel.Init();
ReefAngel.AddStandardMenu();
ReefAngel.Use2014Screen();
ReefAngel.AddSalinityExpansion();
ReefAngel.AddORPExpansion();
ReefAngel.AddWaterLevelExpansion();
ReefAngel.Add16ChPWM();
/*
ReefAngel.CustomLabels[0]="300W Heat";
ReefAngel.CustomLabels[1]="100W Heat";
ReefAngel.CustomLabels[2]="Skimmer";
ReefAngel.CustomLabels[3]="Neck Wipe";
ReefAngel.CustomLabels[4]="Air Pump";
ReefAngel.CustomLabels[5]="Filters";
ReefAngel.CustomLabels[6]="Refuge Lt";
ReefAngel.CustomLabels[7]="Ozone";
ReefAngel.CustomLabels[8]="Diverter";
ReefAngel.CustomLabels[9]="Circ Pump";
ReefAngel.CustomLabels[10]="Kalk Stir";
ReefAngel.CustomLabels[11]="ATO Pump";
ReefAngel.CustomLabels[12]="Return L";
ReefAngel.CustomLabels[13]="Return R";
ReefAngel.CustomLabels[14]="200W Heat";
ReefAngel.CustomLabels[15]="Refuge Circ";
*/
ReefAngel.FeedingModePorts = 0;
ReefAngel.FeedingModePortsE[0] = Port5Bit | Port6Bit;
ReefAngel.WaterChangePorts = Port3Bit; // Skimmer
ReefAngel.WaterChangePortsE[0] = Port4Bit | Port8Bit; // ATO Pump and Refugium Circulation
ReefAngel.LightsOnPorts = 0;
ReefAngel.LightsOnPortsE[0] = 0;
ReefAngel.OverheatShutoffPorts = Port1Bit | Port2Bit;
ReefAngel.OverheatShutoffPortsE[0] = Port7Bit;
ReefAngel.TempProbe = T1_PROBE;
ReefAngel.OverheatProbe = T1_PROBE;
ReefAngel.DCPump.FeedingSpeed = 0;
ReefAngel.DCPump.WaterChangeSpeed = 0;
ReefAngel.Relay.On( Air_Pump );
ReefAngel.Relay.On( Filter_Pump );
ReefAngel.Relay.On( FlowWolf );
ReefAngel.Relay.On( Closed_Loop );
ReefAngel.Relay.On( Return_Pump_L );
ReefAngel.Relay.On( Return_Pump_R );
ReefAngel.Relay.On( Refugium_Pump );
}
void loop()
{
if ( ReefAngel.Params.Temp[T1_PROBE] < 775 ) ReefAngel.Relay.On( Heater_300W );
if ( ReefAngel.Params.Temp[T1_PROBE] > 780 ) ReefAngel.Relay.Off( Heater_300W );
if ( ReefAngel.Params.Temp[T2_PROBE] < 775 ) ReefAngel.Relay.On( Heater_100W );
if ( ReefAngel.Params.Temp[T2_PROBE] > 780 ) ReefAngel.Relay.Off( Heater_100W );
if ( ReefAngel.Params.Temp[T3_PROBE] < 775 ) ReefAngel.Relay.On( Heater_200W );
if ( ReefAngel.Params.Temp[T3_PROBE] > 780 ) ReefAngel.Relay.Off( Heater_200W );
ReefAngel.DCPump.UseMemory = false;
ReefAngel.DCPump.Threshold = 80;
ReefAngel.DCPump.SetMode( Sine, 100, 240 );
ReefAngel.DCPump.DaylightChannel = Sync;
ReefAngel.DCPump.ActinicChannel = AntiSync;
moon_init(44,-116); // approximate lat,lon for Boise, ID
SunBlueLevel = PWMSmoothRampHighestRes( 7, 45, 22, 00, 0, 2047, 100, 0 );
MoonBlueLevel = PWMSmoothRampHighestRes( Moon.riseH, Moon.riseM, Moon.setH, Moon.setM, 0, (int)(MoonPhase()/15), 45, 0);
SunIndigoLevel = PWMSmoothRampHighestRes( 7, 35, 22, 10, 0, 620, 100, 0 ) ; // 10 minute longer
MoonIndigoLevel = PWMSmoothRampHighestRes( Moon.riseH, Moon.riseM, Moon.setH, Moon.setM, 0, (int)(MoonPhase()/30), 45, 0);
ReefAngel.PWM.Set16ChannelRaw( Neutral_White_Center, PWMSmoothRampHighestRes( 7, 45, 22, 00, 0, 1532, 100, 0 ) );
ReefAngel.PWM.Set16ChannelRaw( Warm_White_Center, PWMSmoothRampHighestRes( 7, 45, 22, 00, 0, 1532, 100, 0 ) );
ReefAngel.PWM.Set16ChannelRaw( Royal_Blue_Center, max (SunBlueLevel, MoonBlueLevel) );
ReefAngel.PWM.Set16ChannelRaw( Cool_Blue_Center, PWMSmoothRampHighestRes( 7, 45, 22, 00, 0, 1280, 100, 0 ) );
ReefAngel.PWM.Set16ChannelRaw( Cyan_Center, PWMSmoothRampHighestRes( 7, 45, 22, 00, 0, 960, 100, 0 ) );
ReefAngel.PWM.Set16ChannelRaw( Red_Center, PWMSmoothRampHighestRes( 7, 35, 22, 10, 0, 960, 100, 0 ) ); // 10 minute longer
ReefAngel.PWM.Set16ChannelRaw( Indigo_Center, max (SunIndigoLevel, MoonIndigoLevel) );
ReefAngel.PWM.Set16ChannelRaw( Violet_Center, PWMSmoothRampHighestRes( 7, 40, 22, 05, 0, 320, 100, 0 ) ); // 05 minute longer
for (int i=0; i<8; i++)
{
ReefAngel.CustomVar[i] = (int)(ReefAngel.PWM.Get16ChannelValueRaw(i)/40.95);
}
ReefAngel.Relay.Set( Refuge_Light, !((hour() >= 10) && (hour() < 19)));
pinMode(lowATOPin,OUTPUT);
if ( (hour() >= 8) && (hour() < 22) )
{
if ( now()%3600<10 ) analogWrite(lowATOPin,0);
else if ( now()%3600 >= 10 && now()%3600<20 ) analogWrite(lowATOPin,255);
else analogWrite(lowATOPin,128);
}
else analogWrite(lowATOPin,96);
ReefAngel.Relay.DelayedOn( Skimmer, 1 );
if ( ReefAngel.WaterLevel.GetLevel() > 55 ) ReefAngel.Relay.Off( Skimmer );
if ( ReefAngel.DisplayedMenu==FEEDING_MODE ) ReefAngel.Relay.Off( Skimmer );
if ( !ReefAngel.HighATO.IsActive() ) ReefAngel.Relay.Override( Skimmer, 0 );
ReefAngel.DosingPumpRepeat( Neck_Wipe, 0, 240, 30 );
ReefAngel.DosingPumpRepeat( Kalk_Stirrer, 0, 240, 30 );
if ( (hour() >= 8) && (hour() < 22) )
{
ReefAngel.WaterLevelATO( ATO_Pump, 1200, 38, 40 ); // On at 38% and off at 40% with 1200 second (20 minute) timeout.
}
if ( (hour() == 7 ) )
{
ReefAngel.WaterLevelATO( ATO_Pump, 3601, 38, 40 ); // On at 38% and off at 40% with 3601 second (>60 minute) timeout. Long timeout permits top-up after ATO pump overnight pause.
}
if ( hour() == 22 )
{
ReefAngel.WaterLevelATO( ATO_Pump, 3599, 42, 45 ); // On at 41% and off at 43% with 3699 second (<60 minute) timeout. Long timeout and higher values ensure top-up before ATO pump overnight pause.
}
else ReefAngel.Relay.Off( ATO_Pump );
if ( ReefAngel.Params.ORP>450 || ReefAngel.Params.ORP==0 ) ReefAngel.Relay.Off( Ozone_Gen );
if ( ReefAngel.Params.ORP<400 && ReefAngel.Params.ORP>0 ) ReefAngel.Relay.On( Ozone_Gen );
ReefAngel.Portal( "joshlawless" );
ReefAngel.DDNS( "reef" );
ReefAngel.ShowInterface();
}
int PWMSmoothRampHighestRes(byte startHour, byte startMinute, byte endHour, byte endMinute, int startPWMint, int endPWMint, byte slopeLength, int oldValue)
{
LightsOverride=true;
int current_hour = hour();
long current_millis = millis();
long start = NumMins(startHour, startMinute)*600L;
long end = NumMins(endHour, endMinute)*600L;
long slopeLengthTenthSecs = slopeLength*600L;
if (start > end) // Start is greater than End so it is over midnight
{
if (current_hour < endHour) start -= 1440L*600L; // past midnight
if (current_hour >= startHour) end += 1440L*600L; // before midnight
}
long current = NumMins(current_hour, minute())*600L + second()*10L + (current_millis%1000 - current_millis%100)/100L;
if (slopeLengthTenthSecs > ((end-start)/2) ) slopeLengthTenthSecs = (end-start)/2; // don't allow a slope length greater than half the total period
if (current <= start || current >= end)
return oldValue; // it's before the start or after the end, return the default
else
{ // do the slope calculation
int pwmDelta = endPWMint - startPWMint;
float smoothPhase;
if ((current > (start + slopeLengthTenthSecs)) && (current < (end - slopeLengthTenthSecs)))
return endPWMint; // if it's in the middle of the slope, return the high level
else if ((current - start) < slopeLengthTenthSecs)
{ // it's in the beginning slope up
smoothPhase = (((float)(current-start)/(float)slopeLengthTenthSecs)*180.0) + 180.0;
}
else if ((end - current) < slopeLengthTenthSecs)
{ // it's in the end slope down
smoothPhase = (((float)(end-current)/(float)slopeLengthTenthSecs)*180.0) + 180.0;
}
return startPWMint + (int)(pwmDelta*((1.0+(cos(radians(smoothPhase))))/2.0));
}
}