Re: Dimmable LED Acclimation for corals
Posted: Wed Jan 01, 2014 3:25 pm
Thats the whole range of internal memory variables used by RA. Look for the pwm ones in the middle somewhere...
Community discussion about Reef Angel Controllers and reefing related subjects
https://forum.reefangel.com/
Code: Select all
//Defining different formulas for different channels
// This part would go in your global declarations.
#define Mem_B_AcclDay 100 // 30
#define Mem_B_AcclDuration 101 // 30
#define Mem_B_AcclStartingEndPercent 102 // 25
// The rest of this goes inside your loop() or custom function
// Let's make some variables to work with
byte acclDay = InternalMemory.read(Mem_B_AcclDay); // Let's get what's in memory
byte acclDuration = InternalMemory.read(Mem_B_AcclDuration); //Acclimation Duration
byte acclStartingEndPercent = InternalMemory.read(Mem_B_AcclStartingEndPercent); // Starting End% for Acclimation
byte startPercent = InternalMemory.read(Mem_B_PWMSlopeStart0); // Normal start% 13 //Using Mem_B_PWMSlopeStart0 for all 3 channels
byte endPercentBlue = InternalMemory.read(Mem_B_PWMSlopeEnd1); // Normal Blue end% 65 //Using Mem_B_PWMSlopeEnd1 for both Blue Channels 1,2
byte endPercentWhite = InternalMemory.read(Mem_B_PWMSlopeEnd0); // Normal White end% 75
float acclPercentPerDayBlue = (endPercentBlue-acclStartingEndPercent)/(acclDuration*100); // (65 - 25) / (30 * 100) = 0.013333 = 1.33% increase/day
float acclPercentPerDayWhite = (endPercentWhite-acclStartingEndPercent)/(acclDuration*100); // (75 - 25) / (30 * 100) = 0.016667 = 1.66% incrase/day
// This is how much we're going to alter the dimming
// This number could also be used to adjust the duration
// of the slope... the startPercent, the photoperiod..whatever you want
float acclFactorBlue=acclDay*acclPercentPerDayBlue; // 30 * 0.013333 = .4
float acclFactorWhite=acclDay*acclPercentPerDayWhite; // 30 * 0.016667 = .5
// Adjust the endPercent based on the acclFactor
endPercentBlue=endPercentBlue-(acclFactorBlue*100);
//Here are some samples
// Day 30 = 65 - (0.4 * 100) = 25%
// Day 15 = 65 - (0.199995 * 100) = 45%
// Day 5 = 65 - (0.066665 * 100)= 58%
endPercentWhite=endPercentWhite-(acclFactorWhite*100);
// Here's what some samples look like
// Day 30 = 75 - (0.5 * 100) = 25%
// Day 15 = 75 - (0.25 * 100) = 50%
// Day 5 = 75 - (0.083 * 100) = 67*
ReefAngel.PWM.SetChannel( 0, PWMSlope(13,0,20,30,startPercent,endPercentWhite,40,20) );
ReefAngel.PWM.SetChannel( 1, PWMSlope(12,0,21,30,startPercent,endPercentBlue,40,20) );
ReefAngel.PWM.SetChannel( 2, PWMSlope(12,0,21,30,startPercent,endPercentBlue,40,20) );
// At the end of the day, we need to decrement the acclimation counter.
static boolean acclCounterReady=false; // We need a boolean so we only do this once per day
if (now()%SECS_PER_DAY!=0) acclCounterReady=true; // If it's not midnight we'll get the boolean ready
if (now()%SECS_PER_DAY==0 && acclCounterReady && acclDay>0) { // It's midnight, our bool is true and acclDay is more than 0
acclDay--; // Reduce the counter
acclCounterReady=false; // Reset the boolean flag
InternalMemory.write(Mem_B_AcclDay,acclDay); // Update memory
}
Code: Select all
Mem_B_PWMSlopeStart0
Mem_B_PWMSlopeEnd0
Mem_B_PWMSlopeEnd1
Code: Select all
if ( InternalMemory.read(Mem_B_AcclDay)<=0 );
{
ReefAngel.PWM.SetChannel( 0, PWMSlope(13,0,20,30,13,55,40,20) ); // Minimum % for Dimming is 11%
ReefAngel.PWM.SetChannel( 1, PWMSlope(12,0,21,30,13,55,40,20) );
ReefAngel.PWM.SetChannel( 2, PWMSlope(12,0,21,30,13,55,40,20) ); // Start Hour, Start Minute, End Hour, End Minute, Start Percentage, End Percentage, Duration, Default Percentage used for lights on mode
}
Code: Select all
if (acclDay>0)
{
ReefAngel.PWM.SetChannel( 0, PWMSlope(13,0,20,30,startPercent,endPercentWhite,60,20) );
ReefAngel.PWM.SetChannel( 1, PWMSlope(12,0,21,30,startPercent,endPercentBlue,90,20) );
ReefAngel.PWM.SetChannel( 2, PWMSlope(12,0,21,30,startPercent,endPercentBlue,90,20) );
}
Code: Select all
if (acclDay=0)
{
ReefAngel.PWM.SetChannel( 0, PWMSlope(13,0,20,30,13,55,40,20) ); // Minimum % for Dimming is 11%
ReefAngel.PWM.SetChannel( 1, PWMSlope(12,0,21,30,13,55,40,20) );
ReefAngel.PWM.SetChannel( 2, PWMSlope(12,0,21,30,13,55,40,20) ); // Start Hour, Start Minute, End Hour, End Minute, Start Percentage, End Percentage, Duration, Default Percentage used for lights on mode
}
else if (acclDay>0)
{
ReefAngel.PWM.SetChannel( 0, PWMSlope(13,0,20,30,startPercent,endPercentWhite,60,20) );
ReefAngel.PWM.SetChannel( 1, PWMSlope(12,0,21,30,startPercent,endPercentBlue,90,20) );
ReefAngel.PWM.SetChannel( 2, PWMSlope(12,0,21,30,startPercent,endPercentBlue,90,20) );
}
Code: Select all
#include <ReefAngel_Features.h>
#include <Globals.h>
#include <RA_Wifi.h>
#include <Wire.h>
#include <OneWire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <InternalEEPROM.h>
#include <RA_NokiaLCD.h>
#include <RA_ATO.h>
#include <RA_Joystick.h>
#include <LED.h>
#include <RA_TempSensor.h>
#include <Relay.h>
#include <RA_PWM.h>
#include <Timer.h>
#include <Memory.h>
#include <InternalEEPROM.h>
#include <RA_Colors.h>
#include <RA_CustomColors.h>
#include <Salinity.h>
#include <RF.h>
#include <IO.h>
#include <ORP.h>
#include <AI.h>
#include <PH.h>
#include <WaterLevel.h>
#include <Humidity.h>
#include <DCPump.h>
#include <ReefAngel.h>
////// Place global variable code below here
// This part would go in your global declarations.
#define Mem_B_AcclDay 100 // 30
#define Mem_B_AcclDuration 101 // 30
#define Mem_B_AcclStartingEndPercent 102 // 25
////// Place global variable code above here
void setup()
{
// This must be the first line
ReefAngel.Init(); //Initialize controller
ReefAngel.AddStandardMenu(); // Add Standard Menu
ReefAngel.Use2014Screen(); // Let's use 2014 Screen
///// ReefAngel.AddPHExpansion(); // pH Expansion Module
// Ports toggled in Feeding Mode
ReefAngel.FeedingModePorts = Port3Bit | Port5Bit | Port7Bit;
// Ports toggled in Water Change Mode
ReefAngel.WaterChangePorts = Port2Bit | Port3Bit | Port4Bit | Port5Bit | Port8Bit;
// Ports toggled when Lights On / Off menu entry selected
ReefAngel.LightsOnPorts = Port2Bit | Port4Bit | Port8Bit;
// Ports turned off when Overheat temperature exceeded
ReefAngel.OverheatShutoffPorts = Port1Bit;
// Use T1 probe as temperature and overheat functions
ReefAngel.TempProbe = T1_PROBE;
ReefAngel.OverheatProbe = T1_PROBE;
// Set the Overheat temperature setting
InternalMemory.OverheatTemp_write( 820 );
// Ports that are always on
ReefAngel.Relay.On( Port3 );
ReefAngel.Relay.On( Port7 );
////// Place additional initialization code below here
//Custom Port Labels
ReefAngel.CustomLabels[0]="Heater";
ReefAngel.CustomLabels[1]="BlueLED";
ReefAngel.CustomLabels[2]="ReturnPump";
ReefAngel.CustomLabels[3]="WhiteLED";
ReefAngel.CustomLabels[4]="KalkATO";
ReefAngel.CustomLabels[5]="Moonlight";
ReefAngel.CustomLabels[6]="WP40";
ReefAngel.CustomLabels[7]="Refugium";
////// Place additional initialization code above here
}
void loop()
{
ReefAngel.StandardHeater( Port1,784,790 );
ReefAngel.StandardLights( Port2,12,0,21,30 );
ReefAngel.StandardLights( Port4,13,0,20,30 );
ReefAngel.SingleATO( true,Port5,1200,1 );
ReefAngel.StandardLights( Port8,20,30,13,0 );
/// Using custom code at the bottom ReefAngel.PWM.SetChannel( 0, PWMSlope(13,0,20,30,13,55,40,20) ); // Minimum % for Dimming is 11%
/// Using custom code at the bottom ReefAngel.PWM.SetChannel( 1, PWMSlope(12,0,21,30,13,55,40,20) );
/// Using custom code at the bottom ReefAngel.PWM.SetChannel( 2, PWMSlope(12,0,21,30,13,55,40,20) ); // Start Hour, Start Minute, End Hour, End Minute, Start Percentage, End Percentage, Duration, Default Percentage used for lights on mode
ReefAngel.PWM.SetActinic( ReefCrestMode (0, 0, false));
////// Place your custom code below here
if ( (hour()>=11) && (now()%SECS_PER_DAY<73800) ) // 11am - 8:30pm
{
ReefAngel.PWM.SetDaylight( ElseMode(60,20,true) ); // ReefCrest at 55% +/- 20% on sync mode
}
else if ( (now()%SECS_PER_DAY>73800) && (hour()<23) ) // 8:30pm - 11pm
{
ReefAngel.PWM.SetDaylight( NutrientTransportMode(0,70,400,true) ); // Nutrient Transport 0%minspeed - 70%maxspeed - 400ms
}
else if ( (hour()>=23 || hour()<11) ) // 11pm - 11am
{
ReefAngel.PWM.SetDaylight( ElseMode(30,10, true) ); // ReefCrest at 35% +/- 15% on sync mode
}
// The rest of this goes inside your loop() or custom function
// Let's make some variables to work with
byte acclDay = InternalMemory.read(Mem_B_AcclDay); // Let's get what's in memory
byte acclDuration = InternalMemory.read(Mem_B_AcclDuration); //Acclimation Duration 15
byte acclStartingEndPercent = InternalMemory.read(Mem_B_AcclStartingEndPercent); // Starting End% 55 for Acclimation
byte startPercent = InternalMemory.read(Mem_B_PWMSlopeStart0); // Normal start% 15 //Using Mem_B_PWMSlopeStart0 for all 3 channels
byte endPercentBlue = InternalMemory.read(Mem_B_PWMSlopeEnd1); // Normal Blue end% 65 //Using Mem_B_PWMSlopeEnd1 for both Blue Channels 1,2
byte endPercentWhite = InternalMemory.read(Mem_B_PWMSlopeEnd0); // Normal White end% 75
float acclPercentPerDayBlue = (endPercentBlue-acclStartingEndPercent)/(acclDuration*100); // (65 - 25) / (30 * 100) = 0.013333 = 1.33% increase/day
float acclPercentPerDayWhite = (endPercentWhite-acclStartingEndPercent)/(acclDuration*100); // (75 - 25) / (30 * 100) = 0.016667 = 1.66% incrase/day
// This is how much we're going to alter the dimming
// This number could also be used to adjust the duration
// of the slope... the startPercent, the photoperiod..whatever you want
float acclFactorBlue=acclDay*acclPercentPerDayBlue; // 30 * 0.013333 = .4
float acclFactorWhite=acclDay*acclPercentPerDayWhite; // 30 * 0.016667 = .5
// Adjust the endPercent based on the acclFactor
endPercentBlue=endPercentBlue-(acclFactorBlue*100);
//Here are some samples
// Day 30 = 65 - (0.4 * 100) = 25%
// Day 15 = 65 - (0.199995 * 100) = 45%
// Day 5 = 65 - (0.066665 * 100)= 58%
endPercentWhite=endPercentWhite-(acclFactorWhite*100);
// Here's what some samples look like
// Day 30 = 75 - (0.5 * 100) = 25%
// Day 15 = 75 - (0.25 * 100) = 50%
// Day 5 = 75 - (0.083 * 100) = 67*
ReefAngel.PWM.SetChannel( 0, PWMSlope(13,0,20,30,startPercent,endPercentWhite,60,20) );
ReefAngel.PWM.SetChannel( 1, PWMSlope(12,0,21,30,startPercent,endPercentBlue,90,20) );
ReefAngel.PWM.SetChannel( 2, PWMSlope(12,0,21,30,startPercent,endPercentBlue,90,20) );
// At the end of the day, we need to decrement the acclimation counter.
static boolean acclCounterReady=false; // We need a boolean so we only do this once per day
if (now()%SECS_PER_DAY!=0) acclCounterReady=true; // If it's not midnight we'll get the boolean ready
if (now()%SECS_PER_DAY==0 && acclCounterReady && acclDay>0) { // It's midnight, our bool is true and acclDay is more than 0
acclDay--; // Reduce the counter
acclCounterReady=false; // Reset the boolean flag
InternalMemory.write(Mem_B_AcclDay,acclDay); // Update memory
}
////// Place your custom code above here
// This should always be the last line
ReefAngel.Portal("ReEfnWrX","******");
ReefAngel.ShowInterface();
}
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(2000,3000); // Set the initial delay - default 500, 3000
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(2000,15000); // If so, come up with a new delay - default - 500, 5000
int ChangeUp = random(Offset); // Amount to go up or down
if (random(100)<50) // 50/50 chance of speed going up or going down
{
NewSpeed = MidPoint - ChangeUp;
AntiSpeed = MidPoint + ChangeUp;
}
else
{
NewSpeed = MidPoint + ChangeUp;
AntiSpeed = MidPoint - ChangeUp;
}
LastChange=millis(); // Reset the time of the last change
}
if (WaveSync)
{
return NewSpeed;
}
else
{
return AntiSpeed;
}
}
Code: Select all
#include <ReefAngel_Features.h>
#include <Globals.h>
#include <RA_Wifi.h>
#include <Wire.h>
#include <OneWire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <InternalEEPROM.h>
#include <RA_NokiaLCD.h>
#include <RA_ATO.h>
#include <RA_Joystick.h>
#include <LED.h>
#include <RA_TempSensor.h>
#include <Relay.h>
#include <RA_PWM.h>
#include <Timer.h>
#include <Memory.h>
#include <InternalEEPROM.h>
#include <RA_Colors.h>
#include <RA_CustomColors.h>
#include <Salinity.h>
#include <RF.h>
#include <IO.h>
#include <ORP.h>
#include <AI.h>
#include <PH.h>
#include <WaterLevel.h>
#include <Humidity.h>
#include <DCPump.h>
#include <ReefAngel.h>
////// Place global variable code below here
// This part would go in your global declarations.
#define Mem_B_AcclDay 100 // 30
#define Mem_B_AcclDuration 101 // 30
#define Mem_B_AcclStartingEndPercent 102 // 25
////// Place global variable code above here
void setup()
{
// This must be the first line
ReefAngel.Init(); //Initialize controller
ReefAngel.AddStandardMenu(); // Add Standard Menu
ReefAngel.Use2014Screen(); // Let's use 2014 Screen
///// ReefAngel.AddPHExpansion(); // pH Expansion Module
// Ports toggled in Feeding Mode
ReefAngel.FeedingModePorts = Port3Bit | Port5Bit | Port7Bit;
// Ports toggled in Water Change Mode
ReefAngel.WaterChangePorts = Port2Bit | Port3Bit | Port4Bit | Port5Bit | Port8Bit;
// Ports toggled when Lights On / Off menu entry selected
ReefAngel.LightsOnPorts = Port2Bit | Port4Bit | Port8Bit;
// Ports turned off when Overheat temperature exceeded
ReefAngel.OverheatShutoffPorts = Port1Bit;
// Use T1 probe as temperature and overheat functions
ReefAngel.TempProbe = T1_PROBE;
ReefAngel.OverheatProbe = T1_PROBE;
// Set the Overheat temperature setting
InternalMemory.OverheatTemp_write( 820 );
// Ports that are always on
ReefAngel.Relay.On( Port3 );
ReefAngel.Relay.On( Port7 );
////// Place additional initialization code below here
//Custom Port Labels
ReefAngel.CustomLabels[0]="Heater";
ReefAngel.CustomLabels[1]="BlueLED";
ReefAngel.CustomLabels[2]="ReturnPump";
ReefAngel.CustomLabels[3]="WhiteLED";
ReefAngel.CustomLabels[4]="KalkATO";
ReefAngel.CustomLabels[5]="Moonlight";
ReefAngel.CustomLabels[6]="WP40";
ReefAngel.CustomLabels[7]="Refugium";
////// Place additional initialization code above here
}
void loop()
{
ReefAngel.StandardHeater( Port1,784,790 );
ReefAngel.StandardLights( Port2,12,0,21,30 );
ReefAngel.StandardLights( Port4,13,0,20,30 );
ReefAngel.SingleATO( true,Port5,1200,1 );
ReefAngel.StandardLights( Port8,20,30,13,0 );
/// Using custom code at the bottom ReefAngel.PWM.SetChannel( 0, PWMSlope(13,0,20,30,13,55,40,20) ); // Minimum % for Dimming is 11%
/// Using custom code at the bottom ReefAngel.PWM.SetChannel( 1, PWMSlope(12,0,21,30,13,55,40,20) );
/// Using custom code at the bottom ReefAngel.PWM.SetChannel( 2, PWMSlope(12,0,21,30,13,55,40,20) ); // Start Hour, Start Minute, End Hour, End Minute, Start Percentage, End Percentage, Duration, Default Percentage used for lights on mode
ReefAngel.PWM.SetActinic( ReefCrestMode (0, 0, false));
////// Place your custom code below here
if ( (hour()>=11) && (now()%SECS_PER_DAY<73800) ) // 11am - 8:30pm
{
ReefAngel.PWM.SetDaylight( ElseMode(60,20,true) ); // ReefCrest at 55% +/- 20% on sync mode
}
else if ( (now()%SECS_PER_DAY>73800) && (hour()<23) ) // 8:30pm - 11pm
{
ReefAngel.PWM.SetDaylight( NutrientTransportMode(0,70,400,true) ); // Nutrient Transport 0%minspeed - 70%maxspeed - 400ms
}
else if ( (hour()>=23 || hour()<11) ) // 11pm - 11am
{
ReefAngel.PWM.SetDaylight( ElseMode(30,10, true) ); // ReefCrest at 35% +/- 15% on sync mode
}
// The rest of this goes inside your loop() or custom function
// Let's make some variables to work with
byte acclDay = InternalMemory.read(Mem_B_AcclDay); // Let's get what's in memory
byte acclDuration = InternalMemory.read(Mem_B_AcclDuration); //Acclimation Duration 15
byte acclStartingEndPercent = InternalMemory.read(Mem_B_AcclStartingEndPercent); // Starting End% 55 for Acclimation
byte startPercent = InternalMemory.read(Mem_B_PWMSlopeStart0); // Normal start% 15 //Using Mem_B_PWMSlopeStart0 for all 3 channels
byte endPercentBlue = InternalMemory.read(Mem_B_PWMSlopeEnd1); // Normal Blue end% 65 //Using Mem_B_PWMSlopeEnd1 for both Blue Channels 1,2
byte endPercentWhite = InternalMemory.read(Mem_B_PWMSlopeEnd0); // Normal White end% 75
float acclPercentPerDayBlue = (endPercentBlue-acclStartingEndPercent)/(acclDuration*100); // (65 - 25) / (30 * 100) = 0.013333 = 1.33% increase/day
float acclPercentPerDayWhite = (endPercentWhite-acclStartingEndPercent)/(acclDuration*100); // (75 - 25) / (30 * 100) = 0.016667 = 1.66% incrase/day
// This is how much we're going to alter the dimming
// This number could also be used to adjust the duration
// of the slope... the startPercent, the photoperiod..whatever you want
float acclFactorBlue=acclDay*acclPercentPerDayBlue; // 30 * 0.013333 = .4
float acclFactorWhite=acclDay*acclPercentPerDayWhite; // 30 * 0.016667 = .5
// Adjust the endPercent based on the acclFactor
endPercentBlue=endPercentBlue-(acclFactorBlue*100);
//Here are some samples
// Day 30 = 65 - (0.4 * 100) = 25%
// Day 15 = 65 - (0.199995 * 100) = 45%
// Day 5 = 65 - (0.066665 * 100)= 58%
endPercentWhite=endPercentWhite-(acclFactorWhite*100);
// Here's what some samples look like
// Day 30 = 75 - (0.5 * 100) = 25%
// Day 15 = 75 - (0.25 * 100) = 50%
// Day 5 = 75 - (0.083 * 100) = 67*
ReefAngel.PWM.SetChannel( 0, PWMSlope(13,0,20,30,startPercent,endPercentWhite,60,20) );
ReefAngel.PWM.SetChannel( 1, PWMSlope(12,0,21,30,startPercent,endPercentBlue,90,20) );
ReefAngel.PWM.SetChannel( 2, PWMSlope(12,0,21,30,startPercent,endPercentBlue,90,20) );
// At the end of the day, we need to decrement the acclimation counter.
static boolean acclCounterReady=false; // We need a boolean so we only do this once per day
if (now()%SECS_PER_DAY!=0) acclCounterReady=true; // If it's not midnight we'll get the boolean ready
if (now()%SECS_PER_DAY==0 && acclCounterReady && acclDay>0) { // It's midnight, our bool is true and acclDay is more than 0
acclDay--; // Reduce the counter
acclCounterReady=false; // Reset the boolean flag
InternalMemory.write(Mem_B_AcclDay,acclDay); // Update memory
}
////// Place your custom code above here
// This should always be the last line
ReefAngel.Portal("ReEfnWrX","******");
ReefAngel.ShowInterface();
}
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(2000,3000); // Set the initial delay - default 500, 3000
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(2000,15000); // If so, come up with a new delay - default - 500, 5000
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;
}
}
lnevo wrote:It may interfere with your wifi while doing it, but after you upload the code, you can open Serial Monitor and see what the variables are doing...
Usually you dont want to do that because floats take up 4-8 times as much mem as a byte...so if you do try and keep it to the variables that need it...ReEfnWrX wrote:So if I wanted to use decimals for the formulas to keep them exact, I should assign all the variables as floats and then my final product end% a byte?