Ok. With that being said, you will probably need to continue doing the relay toggling. Here's some code for you to test out. I have it toggling the relay port and put a comment in about removing the line if you didn't need to toggle the port. Also, I have the outlets turn on at the specified times in the arrays and the lights start to slope up/down appropriately. The slope values / percentages are based off of the internal memory values BUT could be changed and handled in the code if you wanted to (it would be pretty simple actually).
Just so you know, I just copied the code for the PWM slope function and tweaked it so it could be controlled manually outside of the libraries.
Anyways, here's the code. I know it compiles against the libraries version 1.1.3. I just tested the compile but I have not uploaded it to a controller to test out everything fully. The only thing that I changed was the code for the lights. So, you will want to verify that the times used for the lights are what you want.
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>
////// Place global variable code below here
void SeasonalDaylight ()
{
static int daylightArray[][4] = {
{13,0,22,0}, // default in case of error in month=0 (May)
{15,0,22,0}, //January (winter)
{14,30,22,0}, //February (winter)
{14,0,22,0}, //March (early spring)
{13,30,22,0}, //April (spring)
{13,0,22,0}, //May (spring)
{12,30,22,0}, //June (early summer)
{12,0,22,0}, //July (summer)
{12,30,22,0}, //August (summer)
{13,0,22,0}, //September (early fall)
{13,30,22,0}, //October (fall)
{14,0,22,0}, //November (fall)
{14,30,22,0} //December (early winter)
};
// Port 2 is power supply for Day lights
ReefAngel.PWM.SetDaylightRaw(PWMSlopeHighRes(
daylightArray[month()][0],
daylightArray[month()][1],
daylightArray[month()][2],
daylightArray[month()][3],
InternalMemory.PWMSlopeStartD_read(),
InternalMemory.PWMSlopeEndD_read(),
InternalMemory.PWMSlopeDurationD_read(),
ReefAngel.PWM.GetDaylightValueRaw()
));
/*
TODO comment out the next line if the power supply for the lights is not needed
and the lights are plugged into a power strip. Otherwise, if the lights
are plugged into the relay, you will need to toggle the port to turn
the lights off
*/
ReefAngel.StandardLights(Port2, daylightArray[month()][0], daylightArray[month()][1],
daylightArray[month()][2], daylightArray[month()][3]);
}//end SeasonalDaylight
void SeasonalActiniclight ()
{
static int actinicArray[][4] = {
{12,30,22,30}, // default in case of error in month=0 (May)
{14,30,22,30}, //January (winter)
{14,0,22,30}, //February (winter)
{13,30,22,30}, //March (early spring)
{13,0,22,30}, //April (spring)
{12,30,22,30}, //May (spring)
{12,0,22,30}, //June (early summer)
{11,30,22,30}, //July (summer)
{12,0,22,30}, //August (summer)
{12,30,22,30}, //September (early fall)
{13,0,22,30}, //October (fall)
{13,30,22,30}, //November (fall)
{14,0,22,30} //December (early winter)
};
// Port 1 is power supply for Actinic Lights
ReefAngel.PWM.SetActinicRaw(PWMSlopeHighRes(
actinicArray[month()][0],
actinicArray[month()][1],
actinicArray[month()][2],
actinicArray[month()][3],
InternalMemory.PWMSlopeStartA_read(),
InternalMemory.PWMSlopeEndA_read(),
InternalMemory.PWMSlopeDurationA_read(),
ReefAngel.PWM.GetActinicValueRaw()
));
/*
TODO comment out the next line if the power supply for the lights is not needed
and the lights are plugged into a power strip. Otherwise, if the lights
are plugged into the relay, you will need to toggle the port to turn
the lights off
*/
ReefAngel.StandardLights(Port1, actinicArray[month()][0], actinicArray[month()][1],
actinicArray[month()][2], actinicArray[month()][3]);
}//end SeasonalActinics
////// Place global variable code above here
void setup()
{
// This must be the first line
InternalMemory.LCDID_write(0); //this line was added when i got a replacement RA+ board
ReefAngel.Init(); //Initialize controller
ReefAngel.Use2014Screen(); // Let's use 2014 Screen
// Ports toggled in Feeding Mode
ReefAngel.FeedingModePorts = Port5Bit | Port6Bit;
// Ports toggled in Water Change Mode
ReefAngel.WaterChangePorts = Port3Bit | Port4Bit | Port5Bit | Port6Bit;
// Ports toggled when Lights On / Off menu entry selected
ReefAngel.LightsOnPorts = Port1Bit | Port2Bit;
// Ports turned off when Overheat temperature exceeded
ReefAngel.OverheatShutoffPorts = Port1Bit | Port2Bit | Port3Bit | Port5Bit | Port6Bit;
// Use T1 probe as temperature and overheat functions
ReefAngel.TempProbe = T1_PROBE;
ReefAngel.OverheatProbe = T1_PROBE;
// Feeeding and Water Change mode speed
ReefAngel.DCPump.FeedingSpeed=0;
ReefAngel.DCPump.WaterChangeSpeed=0;
// Ports that are always on
ReefAngel.Relay.On( Port4 );
////// Place additional initialization code below here
////// Place additional initialization code above here
}
void loop()
{
//ReefAngel.ActinicLights( Port1 );
//ReefAngel.DayLights( Port2 );
// Light code
SeasonalDaylight();
SeasonalActiniclight();
ReefAngel.StandardHeater( Port3 );
ReefAngel.Relay.DelayedOn(Port5 );
ReefAngel.DosingPumpRepeat1( Port7 );
ReefAngel.DosingPumpRepeat2( Port8 );
//ReefAngel.PWM.DaylightPWMSlope();
//ReefAngel.PWM.ActinicPWMSlope();
ReefAngel.DCPump.LowATOChannel = Sync; // WP40
ReefAngel.DCPump.HighATOChannel = AntiSync; // SW-8
ReefAngel.DCPump.AntiSyncOffset = 125;
////// Place your custom code below here
// Wavemaker
if ( ((hour() >= 2) && (hour() < 8)) || ((hour() >= 15) && (hour() < 19)) ) // off from 2am-8am & 3pm-7pm
{
ReefAngel.Relay.Off(Port6);
}
else
{
ReefAngel.WavemakerRandom( Port6, 30, 150 ); // random between 30 and 150 seconds
}
// DC pumps....................................
static int rmode;
static boolean changeMode=true;
// These are the modes we can cycle through. You can add more and even repeat...
byte modes[] = { ReefCrest, Lagoon, TidalSwell, ShortPulse, Sine, Else, Gyre, NutrientTransport };
if (now()%1800==0 || changeMode==true) // Change every 30 mins (1800seconds) or controller reboot
{
rmode=random(100)%sizeof(modes); // Change the mode by picking from our array
changeMode=false;
}
// Set timer when in feeding mode
static unsigned long feeding;
if (ReefAngel.DisplayedMenu==FEEDING_MODE) feeding=now();
// Continue NutrientTranspot Mode for 30 minutes after feeding
if (now()-feeding<1800)
{
ReefAngel.DCPump.UseMemory=false;
ReefAngel.DCPump.Duration=InternalMemory.DCPumpDuration_read();
ReefAngel.DCPump.Mode=ReefCrest;
ReefAngel.DCPump.Speed=75;
}
// Night/Quiet mode
else if (hour()>=2 && hour()<8 ) // 2am to 8am
{
ReefAngel.DCPump.UseMemory=false;
ReefAngel.DCPump.SetMode( Gyre,40,10 );
}
else if (hour()>=15 && hour()<19) // 3pm and 7pm
{
ReefAngel.DCPump.UseMemory=false;
ReefAngel.DCPump.SetMode( ShortPulse,40,30 );
}
//Storm mode
else if (hour()>=1 && hour()<2) // 1am and 2am
{
ReefAngel.DCPump.UseMemory=false;
ReefAngel.DCPump.SetMode( Else,70,15 );
}
else if (hour()>=11 && hour()<12) // 11am and 12pm
{
ReefAngel.DCPump.UseMemory=false;
ReefAngel.DCPump.SetMode( ReefCrest,80,15 );
}
// Custom Mode and nothing else going on
else if (InternalMemory.DCPumpMode_read()==11)
{
ReefAngel.DCPump.UseMemory=false;
ReefAngel.DCPump.Duration=InternalMemory.DCPumpDuration_read();
ReefAngel.DCPump.Mode=modes[rmode]; // Put the mode to the random mode :)
ReefAngel.DCPump.Speed=InternalMemory.DCPumpSpeed_read(); // Set speed from portal
} else {
ReefAngel.DCPump.UseMemory=true; // Will reset all values from memory
}
////// Place your custom code above here
// This should always be the last line
ReefAngel.Portal( "" );
ReefAngel.DDNS( "" ); // Your DDNS is
ReefAngel.ShowInterface();
}
Hopefully everything makes sense to you. If you need to alter any of the times, you should be able to figure it out from the code (arrays). This code also allows for both the Actinic and Daylight channels to be controlled independently. We could simplify things if they always used the same schedule OR if they were always 30 minutes (or whatever time offset) apart.
Let me know if you have any further questions or comments.