Relay expansion code

Expansion modules and attachments
Post Reply
bmhair03
Posts: 166
Joined: Sun Mar 20, 2011 1:22 pm

Relay expansion code

Post by bmhair03 »

How do I add the exp. relay code to my PDE. I just need all 8 to always be on for now. Thanks
// Autogenerated file by RAGen (v1.2.2.171), (04/02/2012 19:38)
// RA_040212_1938.ino
//
// This version designed for v0.9.0 or later

/* The following features are enabled for this File:
#define DisplayImages
#define DateTimeSetup
#define VersionMenu
#define DirectTempSensor
#define DisplayLEDPWM
#define wifi
#define SaveRelayState
#define WDT
#define SIMPLE_MENU
#define PWMEXPANSION
#define CUSTOM_MAIN
#define COLORS_PDE
#define ENABLE_ATO_LOGGING
#define ENABLE_EXCEED_FLAGS
#define FONT_8x8
#define NUMBERS_16x16
#define RelayExp
*/


#include <ReefAngel_Features.h>
#include <RA_Colors.h>
#include <RA_CustomColors.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 <ReefAngel.h>

////// Place global variable code below here


//*********************************************************************************************************************************
//Start of PWM Expansion Code Header

// This is just how we are going to reference the PWM expansion ports
// within the code.
// You can change the labels if you would like, just as long as they are
// changed all throughout the code too.
#define LEDPWM0 0
#define LEDPWM1 1
#define LEDPWM2 2
#define LEDPWM3 3
#define LEDPWM4 4
#define LEDPWM5 5

// Initial values to all 6 channels at startup. They will always be 0.
byte PWMChannel[]={
0,0,0,0,0,0};

//End of PWM Expansion Code Header


//*********************************************************************************************************************************

#include <avr/pgmspace.h>
prog_char menu0_label[] PROGMEM = "Feeding Mode";
prog_char menu1_label[] PROGMEM = "Water Change Mode";
prog_char menu2_label[] PROGMEM = "Force Cloud";
prog_char menu3_label[] PROGMEM = "ATO Clear";
prog_char menu4_label[] PROGMEM = "Overheat Clear";
prog_char menu5_label[] PROGMEM = "About Me";
prog_char menu6_label[] PROGMEM = "pH Calibration";
PROGMEM const char *menu_items[] = {
menu0_label, menu1_label, menu2_label, menu3_label, menu4_label,
menu5_label, menu6_label};

boolean ForceCloud=false;


////// Place global variable code above here

void DrawCustomMain()
{
byte x = 6;
byte y = 2;
byte t;
ReefAngel.LCD.DrawDate(6, 2);
ReefAngel.LCD.Clear(COLOR_BLACK, 1, 11, 132, 11);
pingSerial();
x = 12;
y += MENU_START_ROW+1;
ReefAngel.LCD.DrawText(COLOR_BLUE, COLOR_WHITE, x, y+6, "Display"" ""PH");
char text[7];
ConvertNumToString(text, ReefAngel.Params.PH, 100);
ReefAngel.LCD.Clear(DefaultBGColor, x+16, y+65, x+65, y+16);
ReefAngel.LCD.DrawLargeText(PHColor, DefaultBGColor, x+75, y+18, text, Font8x16);
pingSerial();

ConvertNumToString(text, ReefAngel.Params.Temp[T1_PROBE], 10);
y += MENU_START_ROW*2;
x = 10;
ReefAngel.LCD.Clear(DefaultBGColor,x,y,x+(16*4),y+16);
pingSerial();
ReefAngel.LCD.DrawHugeNumbers(T1TempColor, DefaultBGColor, x, y, text);
pingSerial();
x += (16*4) + 8;
ReefAngel.LCD.DrawText(T2TempColor,DefaultBGColor,8,y+21,"LED:");
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp[T2_PROBE], T2TempColor,
24, y+31, 10);
ReefAngel.LCD.DrawText(T3TempColor,DefaultBGColor,x+8,y+21,"SUMP:");
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp[T3_PROBE], T3TempColor,
x+24, y+31, 10);

x = 15;
y=MENU_START_ROW*7;
y += 4;
ConvertNumToString(text, PWMChannel[LEDPWM0], 1);
strcat(text," ");
ReefAngel.LCD.DrawText(DPColor, DefaultBGColor, x, y, "L0:");
ReefAngel.LCD.DrawText(DPColor, DefaultBGColor, x+18, y, text);
pingSerial();

x += 60;
ConvertNumToString(text, PWMChannel[LEDPWM1], 1);
strcat(text," ");
ReefAngel.LCD.DrawText(APColor, DefaultBGColor, x, y, "L1:");
ReefAngel.LCD.DrawText(APColor, DefaultBGColor, x+18, y, text);
pingSerial();

x -= 60;
y += MENU_START_ROW;
ConvertNumToString(text, PWMChannel[LEDPWM2], 1);
strcat(text," ");
ReefAngel.LCD.DrawText(DPColor, DefaultBGColor, x, y, "L2:");
ReefAngel.LCD.DrawText(DPColor, DefaultBGColor, x+18, y, text);
pingSerial();

x += 60;
ConvertNumToString(text, PWMChannel[LEDPWM3], 1);
strcat(text," ");
ReefAngel.LCD.DrawText(APColor, DefaultBGColor, x, y, "L3:");
ReefAngel.LCD.DrawText(APColor, DefaultBGColor, x+18, y, text);
pingSerial();

x -= 60;
y += MENU_START_ROW;
ConvertNumToString(text, PWMChannel[LEDPWM4], 1);
strcat(text," ");
ReefAngel.LCD.DrawText(DPColor, DefaultBGColor, x, y, "L4:");
ReefAngel.LCD.DrawText(DPColor, DefaultBGColor, x+18, y, text);
pingSerial();

x += 60;
ConvertNumToString(text, PWMChannel[LEDPWM5], 1);
strcat(text," ");
ReefAngel.LCD.DrawText(APColor, DefaultBGColor, x, y, "L5:");
ReefAngel.LCD.DrawText(APColor, DefaultBGColor, x+18, y, text);
pingSerial();


//y += 39*2;
// x = 13;
byte TempRelay = ReefAngel.Relay.RelayData;
TempRelay &= ReefAngel.Relay.RelayMaskOff;
TempRelay |= ReefAngel.Relay.RelayMaskOn;
ReefAngel.LCD.DrawOutletBox(12, 105, TempRelay);
// #ifdef RelayExp
// draw 1st expansion relay
// TempRelay = ReefAngel.Relay.RelayDataE[0];
// TempRelay &= ReefAngel.Relay.RelayMaskOffE[0];
// TempRelay |= ReefAngel.Relay.RelayMaskOnE[0];
// ReefAngel.LCD.DrawOutletBox(12, 105, TempRelay);
// #endif RelayExp


}

void DrawCustomGraph()
{
// ReefAngel.LCD.DrawGraph(5, 5);
}

void MenuEntry1()
{
ReefAngel.FeedingModeStart();
}
void MenuEntry2()
{
ReefAngel.WaterChangeModeStart();
}
void MenuEntry3()
{
ForceCloud=true;
ReefAngel.DisplayedMenu=RETURN_MAIN_MODE;
}
void MenuEntry4()
{
ReefAngel.ATOClear();
ReefAngel.DisplayMenuEntry("Clear ATO Timeout");
}
void MenuEntry5()
{
ReefAngel.OverheatClear();
ReefAngel.DisplayMenuEntry("Clear Overheat");
}
void MenuEntry6()
{
ReefAngel.DisplayVersion();
}

void MenuEntry7()
{
ReefAngel.SetupCalibratePH();
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}

void setup()
{
// This must be the first line
ReefAngel.Init(); //Initialize controller
ReefAngel.PHMax=690;
ReefAngel.PHMin=270;

// Ports toggled in Feeding Mode
ReefAngel.FeedingModePorts = Port6Bit | Port7Bit;
// Ports toggled in Water Change Mode
ReefAngel.WaterChangePorts = Port6Bit | Port7Bit;
// Ports turned off when Overheat temperature exceeded
ReefAngel.OverheatShutoffPorts = Port3Bit | Port4Bit;
// Ports toggled when Lights On / Off menu entry selected
ReefAngel.LightsOnPorts = Port3Bit | Port4Bit;

// Ports that are always on
ReefAngel.Relay.On(Port1);
ReefAngel.Relay.On(Port5);
ReefAngel.Relay.On(Port6);
// ReefAngel.Relay.On(Port9);
// ReefAngel.Relay.On(Port(10);
// ReefAngel.Relay.On(Port(11);
// ReefAngel.Relay.On(Port(12);
// ReefAngel.Relay.On(Port(13);
//ReefAngel.Relay.On(Port(14);
// ReefAngel.Relay.On(Port(15);
// ReefAngel.Relay.On(Port(16);
//ReefAngel.Relay.On(Port2);
////// Place additional initialization code below here
// InternalMemory.PHMax_write(570);
// InternalMemory.PHMin_write(240);

////// Place additional initialization code above here
}

void loop()
{
// Specific functions that use Internal Memory values
ReefAngel.StandardLights(Port2,11,00,20,00);
ReefAngel.SingleATOLow(Port8);
ReefAngel.StandardLights(Port3,11,00,19,50);
ReefAngel.StandardLights(Port4,11,00,20,00);
//ReefAngel.StandardFan(Port8);

//ReefAngel.PWM.SetActinic(PWMSlope(10,0,20,00,10,100,60,ReefAngel.PWM.GetActinicValue()));


//ReefAngel.PWM.SetDaylight(PWMSlope(10,30,19,30,10,65,60,ReefAngel.PWM.GetDaylightValue()));
// Calculate your regular sunrise/sunset PWM value
////// Place your custom code below here
// Calculate your regular sunrise/sunset PWM value
PWMChannel[LEDPWM0]=PWMSlope(11,0,20,0,13,90,60,PWMChannel[LEDPWM0]);
PWMChannel[LEDPWM1]=PWMSlope(11,0,19,50,13,75,50,PWMChannel[LEDPWM1]);
//PWMChannel[LEDPWM2]=MoonPhase();
if (hour()>=20 || hour()<1)
{
PWMChannel[LEDPWM2]=MoonPhase();
}
else
{
PWMChannel[LEDPWM2]=0;
}
PWMChannel[LEDPWM3]=PWMSlope(11,0,20,00,13,90,60,PWMChannel[LEDPWM3]);
PWMChannel[LEDPWM4]=PWMSlope(11,0,19,50,13,75,50,PWMChannel[LEDPWM4]);

CheckCloud();

//PWMChannel[LEDPWM5]=PWMSlope(11,0,20,00,0,50,40,PWMChannel[LEDPWM5]);
ReefAngel.PWM.SetChannel(LEDPWM0,PWMChannel[LEDPWM0]);
ReefAngel.PWM.SetChannel(LEDPWM1,PWMChannel[LEDPWM1]);
ReefAngel.PWM.SetChannel(LEDPWM2,PWMChannel[LEDPWM2]);
ReefAngel.PWM.SetChannel(LEDPWM3,PWMChannel[LEDPWM3]);
ReefAngel.PWM.SetChannel(LEDPWM4,PWMChannel[LEDPWM4]);
//PWMExpansion(LEDPWM5,int(2.55*PWMChannel[LEDPWM5]));
////// Place your custom code above here
// This sends all the data to the portal
// Do not add any custom code that changes any relay status after this line
// The only code after this line should be the ShowInterface function
ReefAngel.Portal("bmhair03", "nascar03");

// This should always be the last line
ReefAngel.ShowInterface();
}



//*********************************************************************************************************************************
// Random Cloud/Thunderstorm effects function
void CheckCloud()
{

// ------------------------------------------------------------
// Change the values below to customize your cloud/storm effect

// Frequency in days based on the day of the month - number 2 means every 2
// days, for example (day 2,4,6 etc)
// For testing purposes, you can use 1 and cause the cloud to occur
// everyday
#define Clouds_Every_X_Days 1

// Percentage chance of a cloud happening today
// For testing purposes, you can use 100 and cause the cloud to have 100%
// chance of happening
#define Cloud_Chance_per_Day 50

// Minimum number of minutes for cloud duration. Don't use max duration of
// less than 6
#define Min_Cloud_Duration 3

// Maximum number of minutes for the cloud duration. Don't use max duration
// of more than 255
#define Max_Cloud_Duration 10

// Minimum number of clouds that can happen per day
#define Min_Clouds_per_Day 1

// Maximum number of clouds that can happen per day
#define Max_Clouds_per_Day 5

// Only start the cloud effect after this setting
// In this example, start could after 12:00pm
#define Start_Cloud_After NumMins(12,00)

// Always end the cloud effect before this setting
// In this example, end could before 8:00pm
#define End_Cloud_Before NumMins(19,00)

// Percentage chance of a lightning happen for every cloud
// For testing purposes, you can use 100 and cause the lightning to have
// 100% chance of happening
#define Lightning_Change_per_Cloud 75

// Channels used by the actinic LEDs on the PWM Expansion module
// These channels will not be dimmed when the cloud effect is triggered
// Number is a binary form. B001100 means channel 2 and 3 are used for
// actinics
#define Actinic_Channels B001001

// Channels used by the daylight LEDs on the PWM Expansion module
// These channels will be used for the spike when lightning effect is
// triggered
// Number is a binary form. B000011 means channel 0 and 1 are used for
// daylights
#define Daylight_Channels B010010

// Note: Make sure to choose correct values that will work within your
// PWMSLope settings.
// For example, in our case, we could have a max of 5 clouds per day and
// they could last for 50 minutes.
// Which could mean 250 minutes of clouds. We need to make sure the
// PWMSlope can accomodate 250 minutes of effects or
// unforseen results could happen.
// Also, make sure that you can fit double those minutes between
// Start_Cloud_After and End_Cloud_Before.
// In our example, we have 510 minutes between Start_Cloud_After and
// End_Cloud_Before, so double the 250 minutes (or 500 minutes) can
// fit in that 510 minutes window.
// It's a tight fit, but it did.

//#define printdebug // Uncomment this for debug print on Serial Monitor
// window
#define forcecloudcalculation // Uncomment this to force the cloud
// calculation to happen in the boot process.


// Change the values above to customize your cloud/storm effect
// ------------------------------------------------------------
// Do not change anything below here

static byte cloudchance=255;
static byte cloudduration=0;
static int cloudstart=0;
static byte numclouds=0;
static byte lightningchance=0;
static byte cloudindex=0;
static byte lightningstatus=0;
static int LastNumMins=0;
// Every day at midnight, we check for chance of cloud happening today
if (hour()==0 && minute()==0 && second()==0) cloudchance=255;

#ifdef forcecloudcalculation
if (cloudchance==255)
#else
if (hour()==0 && minute()==0 && second()==1 && cloudchance==255)
#endif
{
//Pick a random number between 0 and 99
cloudchance=random(100);
// if picked number is greater than Cloud_Chance_per_Day, we will not have
// clouds today
if (cloudchance>Cloud_Chance_per_Day) cloudchance=0;
// Check if today is day for clouds.
if ((day()%Clouds_Every_X_Days)!=0) cloudchance=0;
// If we have cloud today
if (cloudchance)
{
// pick a random number for number of clouds between Min_Clouds_per_Day and
// Max_Clouds_per_Day
numclouds=random(Min_Clouds_per_Day,Max_Clouds_per_Day);
// pick the time that the first cloud will start
// the range is calculated between Start_Cloud_After and the even
// distribuition of clouds on this day.

cloudstart=random(Start_Cloud_After,Start_Cloud_After+((End_Cloud_Before-Start_Cloud_After)/(numclouds*2)));
// pick a random number for the cloud duration of first cloud.
cloudduration=random(Min_Cloud_Duration,Max_Cloud_Duration);
//Pick a random number between 0 and 99
lightningchance=random(100);
// if picked number is greater than Lightning_Change_per_Cloud, we will not
// have lightning today
if (lightningchance>Lightning_Change_per_Cloud) lightningchance=0;
}
}
// Now that we have all the parameters for the cloud, let's create the
// effect

if (ForceCloud)
{
ForceCloud=false;
cloudchance=1;
cloudduration=10;
lightningchance=1;
cloudstart=NumMins(hour(),minute())+1;
}
if (cloudchance)
{
//is it time for cloud yet?
if (NumMins(hour(),minute())>=cloudstart &&
NumMins(hour(),minute())<(cloudstart+cloudduration))
{
// let's go through all channels to pick which ones will be dimmed
for (int a=0;a<6;a++)
{
if (bitRead(Actinic_Channels,a)==0)
{
// this will slope down the channel from the current PWM to 0 within
// 3minutes.
// then it will stay at 0 for the duration of the cycle
// and finally slope up from 0 to PWM value within 3 minutes
// it is basically an inversed slope

PWMChannel[a]=ReversePWMSlope(cloudstart,cloudstart+cloudduration,PWMChannel[a],0,180);
}
}
if (lightningchance &&
(NumMins(hour(),minute())==(cloudstart+(cloudduration/2))) && second()<5)
{
for (int b=0;b<6;b++)
{
// if (bitRead(Daylight_Channels,b)==1)
// {
if (random(100)<20) lightningstatus=1;
else lightningstatus=0;
if (lightningstatus) PWMChannel=100;
else PWMChannel=0;
//delay(10);
// }
// else
// {
// PWMChannel=20;
// }
}
}
}
if (NumMins(hour(),minute())>(cloudstart+cloudduration))
{
cloudindex++;
if (cloudindex < numclouds)
{

cloudstart=random(Start_Cloud_After+(((End_Cloud_Before-Start_Cloud_After)/(numclouds*2))*cloudindex*2),(Start_Cloud_After+(((End_Cloud_Before-Start_Cloud_After)/(numclouds*2))*cloudindex*2))+((End_Cloud_Before-Start_Cloud_After)/(numclouds*2)));
// pick a random number for the cloud duration of first cloud.
cloudduration=random(Min_Cloud_Duration,Max_Cloud_Duration);
//Pick a random number between 0 and 99
lightningchance=random(100);
// if picked number is greater than Lightning_Change_per_Cloud, we will not
// have lightning today
if (lightningchance>Lightning_Change_per_Cloud) lightningchance=0;
}
}
}

if (LastNumMins!=NumMins(hour(),minute()))
{
LastNumMins=NumMins(hour(),minute());
ReefAngel.LCD.Clear(255,0,120,132,132);
ReefAngel.LCD.DrawText(0,255,5,120,"C");
ReefAngel.LCD.DrawText(0,255,11,120,"00:00");
ReefAngel.LCD.DrawText(0,255,45,120,"L");
ReefAngel.LCD.DrawText(0,255,51,120,"00:00");
if (cloudchance && (NumMins(hour(),minute())<cloudstart))
{
int x=0;
if ((cloudstart/60)>=10) x=11;
else x=17;
ReefAngel.LCD.DrawText(0,255,x,120,(cloudstart/60));
if ((cloudstart%60)>=10) x=29;
else x=35;
ReefAngel.LCD.DrawText(0,255,x,120,(cloudstart%60));
}
ReefAngel.LCD.DrawText(0,255,90,120,cloudduration);
if (lightningchance)
{
int x=0;
if (((cloudstart+(cloudduration/2))/60)>=10) x=51;
else x=57;
ReefAngel.LCD.DrawText(0,255,x,120,((cloudstart+(cloudduration/2))/60));
if (((cloudstart+(cloudduration/2))%60)>=10) x=69;
else x=75;
ReefAngel.LCD.DrawText(0,255,x,120,((cloudstart+(cloudduration/2))%60));
}
}
}

byte ReversePWMSlope(long cstart,long cend,byte PWMStart,byte PWMEnd, byte clength)
{
long n=elapsedSecsToday(now());
cstart*=60;
cend*=60;
if (n<cstart) return PWMStart;
if (n>=cstart && n<=(cstart+clength)) return
map(n,cstart,cstart+clength,PWMStart,PWMEnd);
if (n>(cstart+clength) && n<(cend-clength)) return PWMEnd;
if (n>=(cend-clength) && n<=cend) return
map(n,cend-clength,cend,PWMEnd,PWMStart);
if (n>cend) return PWMStart;
}
User avatar
Sacohen
Posts: 1833
Joined: Sun Apr 21, 2013 6:25 am
Location: Davie, FL

Re: Relay expansion code

Post by Sacohen »

The expansion relay code is designed to be uploaded as a test only.
It's not supposed to be left in the unit.

The easiest way to do what you want is to use the wizard and set all the ports on the expansion module to be always on, the copy the generated code into your code.

It should look like this...

Code: Select all

    // Ports that are always on
    ReefAngel.Relay.On( Box1_Port1 );
    ReefAngel.Relay.On( Box1_Port2 );
    ReefAngel.Relay.On( Box1_Port3 );
    ReefAngel.Relay.On( Box1_Port4 );
    ReefAngel.Relay.On( Box1_Port5 );
    ReefAngel.Relay.On( Box1_Port6 );
    ReefAngel.Relay.On( Box1_Port7 );
    ReefAngel.Relay.On( Box1_Port8 );
I see your problem now.
As you can see from the Wizard code the expansion is identified as Box 1 and then the ports 1-8, rather than 9-16 like you have them.
bmhair03
Posts: 166
Joined: Sun Mar 20, 2011 1:22 pm

Re: Relay expansion code

Post by bmhair03 »

Thanks ill give that a try.
bmhair03
Posts: 166
Joined: Sun Mar 20, 2011 1:22 pm

Re: Relay expansion code

Post by bmhair03 »

ok i made this one it compiled fine but after trying to upload it I get a no internal memory found error on the RA now i cant even upload old pde. Help!?

// Autogenerated file by RAGen (v1.2.2.171), (04/02/2012 19:38)
// RA_040212_1938.ino
//
// This version designed for v0.9.0 or later

/* The following features are enabled for this File:
#define DisplayImages
#define DateTimeSetup
#define VersionMenu
#define DirectTempSensor
#define DisplayLEDPWM
#define wifi
#define SaveRelayState
#define WDT
#define SIMPLE_MENU
#define PWMEXPANSION
#define CUSTOM_MAIN
#define COLORS_PDE
#define ENABLE_ATO_LOGGING
#define ENABLE_EXCEED_FLAGS
#define FONT_8x8
#define NUMBERS_16x16
#define RelayExp
*/


#include <ReefAngel_Features.h>
#include <RA_Colors.h>
#include <RA_CustomColors.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 <ReefAngel.h>

////// Place global variable code below here


//*********************************************************************************************************************************
//Start of PWM Expansion Code Header

// This is just how we are going to reference the PWM expansion ports
// within the code.
// You can change the labels if you would like, just as long as they are
// changed all throughout the code too.
#define LEDPWM0 0
#define LEDPWM1 1
#define LEDPWM2 2
#define LEDPWM3 3
#define LEDPWM4 4
#define LEDPWM5 5

// Initial values to all 6 channels at startup. They will always be 0.
byte PWMChannel[]={
0,0,0,0,0,0};

//End of PWM Expansion Code Header


//*********************************************************************************************************************************

#include <avr/pgmspace.h>
prog_char menu0_label[] PROGMEM = "Feeding Mode";
prog_char menu1_label[] PROGMEM = "Water Change Mode";
prog_char menu2_label[] PROGMEM = "Force Cloud";
prog_char menu3_label[] PROGMEM = "ATO Clear";
prog_char menu4_label[] PROGMEM = "Overheat Clear";
prog_char menu5_label[] PROGMEM = "About Me";
prog_char menu6_label[] PROGMEM = "pH Calibration";
PROGMEM const char *menu_items[] = {
menu0_label, menu1_label, menu2_label, menu3_label, menu4_label,
menu5_label, menu6_label};

boolean ForceCloud=false;


////// Place global variable code above here

void DrawCustomMain()
{
byte x = 6;
byte y = 2;
byte t;
ReefAngel.LCD.DrawDate(6, 2);
ReefAngel.LCD.Clear(COLOR_BLACK, 1, 11, 132, 11);
pingSerial();
x = 12;
y += MENU_START_ROW+1;
ReefAngel.LCD.DrawText(COLOR_BLUE, COLOR_WHITE, x, y+6, "Display"" ""PH");
char text[7];
ConvertNumToString(text, ReefAngel.Params.PH, 100);
ReefAngel.LCD.Clear(DefaultBGColor, x+16, y+65, x+65, y+16);
ReefAngel.LCD.DrawLargeText(PHColor, DefaultBGColor, x+75, y+18, text, Font8x16);
pingSerial();

ConvertNumToString(text, ReefAngel.Params.Temp[T1_PROBE], 10);
y += MENU_START_ROW*2;
x = 10;
ReefAngel.LCD.Clear(DefaultBGColor,x,y,x+(16*4),y+16);
pingSerial();
ReefAngel.LCD.DrawHugeNumbers(T1TempColor, DefaultBGColor, x, y, text);
pingSerial();
x += (16*4) + 8;
ReefAngel.LCD.DrawText(T2TempColor,DefaultBGColor,8,y+21,"LED:");
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp[T2_PROBE], T2TempColor,
24, y+31, 10);
ReefAngel.LCD.DrawText(T3TempColor,DefaultBGColor,x+8,y+21,"SUMP:");
ReefAngel.LCD.DrawSingleMonitor(ReefAngel.Params.Temp[T3_PROBE], T3TempColor,
x+24, y+31, 10);

x = 15;
y=MENU_START_ROW*7;
y += 4;
ConvertNumToString(text, PWMChannel[LEDPWM0], 1);
strcat(text," ");
ReefAngel.LCD.DrawText(DPColor, DefaultBGColor, x, y, "L0:");
ReefAngel.LCD.DrawText(DPColor, DefaultBGColor, x+18, y, text);
pingSerial();

x += 60;
ConvertNumToString(text, PWMChannel[LEDPWM1], 1);
strcat(text," ");
ReefAngel.LCD.DrawText(APColor, DefaultBGColor, x, y, "L1:");
ReefAngel.LCD.DrawText(APColor, DefaultBGColor, x+18, y, text);
pingSerial();

x -= 60;
y += MENU_START_ROW;
ConvertNumToString(text, PWMChannel[LEDPWM2], 1);
strcat(text," ");
ReefAngel.LCD.DrawText(DPColor, DefaultBGColor, x, y, "L2:");
ReefAngel.LCD.DrawText(DPColor, DefaultBGColor, x+18, y, text);
pingSerial();

x += 60;
ConvertNumToString(text, PWMChannel[LEDPWM3], 1);
strcat(text," ");
ReefAngel.LCD.DrawText(APColor, DefaultBGColor, x, y, "L3:");
ReefAngel.LCD.DrawText(APColor, DefaultBGColor, x+18, y, text);
pingSerial();

x -= 60;
y += MENU_START_ROW;
ConvertNumToString(text, PWMChannel[LEDPWM4], 1);
strcat(text," ");
ReefAngel.LCD.DrawText(DPColor, DefaultBGColor, x, y, "L4:");
ReefAngel.LCD.DrawText(DPColor, DefaultBGColor, x+18, y, text);
pingSerial();

x += 60;
ConvertNumToString(text, PWMChannel[LEDPWM5], 1);
strcat(text," ");
ReefAngel.LCD.DrawText(APColor, DefaultBGColor, x, y, "L5:");
ReefAngel.LCD.DrawText(APColor, DefaultBGColor, x+18, y, text);
pingSerial();


// y += 39*2;
// x = 13;
byte TempRelay = ReefAngel.Relay.RelayData;
TempRelay &= ReefAngel.Relay.RelayMaskOff;
TempRelay |= ReefAngel.Relay.RelayMaskOn;
ReefAngel.LCD.DrawOutletBox(12, 105, TempRelay);
// #ifdef RelayExp
// draw 1st expansion relay
// TempRelay = ReefAngel.Relay.RelayDataE[0];
// TempRelay &= ReefAngel.Relay.RelayMaskOffE[0];
// TempRelay |= ReefAngel.Relay.RelayMaskOnE[0];
// ReefAngel.LCD.DrawOutletBox(12, 105, TempRelay);
// #endif RelayExp


}

void DrawCustomGraph()
{
// ReefAngel.LCD.DrawGraph(5, 5);
}

void MenuEntry1()
{
ReefAngel.FeedingModeStart();
}
void MenuEntry2()
{
ReefAngel.WaterChangeModeStart();
}
void MenuEntry3()
{
ForceCloud=true;
ReefAngel.DisplayedMenu=RETURN_MAIN_MODE;
}
void MenuEntry4()
{
ReefAngel.ATOClear();
ReefAngel.DisplayMenuEntry("Clear ATO Timeout");
}
void MenuEntry5()
{
ReefAngel.OverheatClear();
ReefAngel.DisplayMenuEntry("Clear Overheat");
}
void MenuEntry6()
{
ReefAngel.DisplayVersion();
}

void MenuEntry7()
{
ReefAngel.SetupCalibratePH();
ReefAngel.DisplayedMenu = ALT_SCREEN_MODE;
}

void setup()
{
// This must be the first line
ReefAngel.Init(); //Initialize controller
ReefAngel.PHMax=690;
ReefAngel.PHMin=270;

// Ports toggled in Feeding Mode
ReefAngel.FeedingModePorts = Port6Bit | Port7Bit;
// Ports toggled in Water Change Mode
ReefAngel.WaterChangePorts = Port6Bit | Port7Bit;
// Ports turned off when Overheat temperature exceeded
ReefAngel.OverheatShutoffPorts = Port3Bit | Port4Bit;
// Ports toggled when Lights On / Off menu entry selected
ReefAngel.LightsOnPorts = Port3Bit | Port4Bit;

// Ports that are always on
ReefAngel.Relay.On(Port1);
ReefAngel.Relay.On(Port5);
ReefAngel.Relay.On(Port6);
ReefAngel.Relay.On(Box1_Port1);
ReefAngel.Relay.On(Box1_Port2);
ReefAngel.Relay.On(Box1_Port3);
ReefAngel.Relay.On(Box1_Port4);
ReefAngel.Relay.On(Box1_Port5);
ReefAngel.Relay.On(Box1_Port6);
ReefAngel.Relay.On(Box1_Port7);
ReefAngel.Relay.On(Box1_Port8);
//ReefAngel.Relay.On(Port2);
////// Place additional initialization code below here
// InternalMemory.PHMax_write(570);
// InternalMemory.PHMin_write(240);

////// Place additional initialization code above here
}

void loop()
{
// Specific functions that use Internal Memory values
ReefAngel.StandardLights(Port2,11,00,20,00);
ReefAngel.SingleATOLow(Port8);
ReefAngel.StandardLights(Port3,11,00,19,50);
ReefAngel.StandardLights(Port4,11,00,20,00);
//ReefAngel.StandardFan(Port8);

//ReefAngel.PWM.SetActinic(PWMSlope(10,0,20,00,10,100,60,ReefAngel.PWM.GetActinicValue()));


//ReefAngel.PWM.SetDaylight(PWMSlope(10,30,19,30,10,65,60,ReefAngel.PWM.GetDaylightValue()));
// Calculate your regular sunrise/sunset PWM value
////// Place your custom code below here
// Calculate your regular sunrise/sunset PWM value
PWMChannel[LEDPWM0]=PWMSlope(11,0,20,0,13,90,60,PWMChannel[LEDPWM0]);
PWMChannel[LEDPWM1]=PWMSlope(11,0,19,50,13,75,50,PWMChannel[LEDPWM1]);
//PWMChannel[LEDPWM2]=MoonPhase();
if (hour()>=20 || hour()<1)
{
PWMChannel[LEDPWM2]=MoonPhase();
}
else
{
PWMChannel[LEDPWM2]=0;
}
PWMChannel[LEDPWM3]=PWMSlope(11,0,20,00,13,90,60,PWMChannel[LEDPWM3]);
PWMChannel[LEDPWM4]=PWMSlope(11,0,19,50,13,75,50,PWMChannel[LEDPWM4]);

CheckCloud();

//PWMChannel[LEDPWM5]=PWMSlope(11,0,20,00,0,50,40,PWMChannel[LEDPWM5]);
ReefAngel.PWM.SetChannel(LEDPWM0,PWMChannel[LEDPWM0]);
ReefAngel.PWM.SetChannel(LEDPWM1,PWMChannel[LEDPWM1]);
ReefAngel.PWM.SetChannel(LEDPWM2,PWMChannel[LEDPWM2]);
ReefAngel.PWM.SetChannel(LEDPWM3,PWMChannel[LEDPWM3]);
ReefAngel.PWM.SetChannel(LEDPWM4,PWMChannel[LEDPWM4]);
//PWMExpansion(LEDPWM5,int(2.55*PWMChannel[LEDPWM5]));
////// Place your custom code above here
// This sends all the data to the portal
// Do not add any custom code that changes any relay status after this line
// The only code after this line should be the ShowInterface function
ReefAngel.Portal("bmhair03", "nascar03");

// This should always be the last line
ReefAngel.ShowInterface();
}



//*********************************************************************************************************************************
// Random Cloud/Thunderstorm effects function
void CheckCloud()
{

// ------------------------------------------------------------
// Change the values below to customize your cloud/storm effect

// Frequency in days based on the day of the month - number 2 means every 2
// days, for example (day 2,4,6 etc)
// For testing purposes, you can use 1 and cause the cloud to occur
// everyday
#define Clouds_Every_X_Days 1

// Percentage chance of a cloud happening today
// For testing purposes, you can use 100 and cause the cloud to have 100%
// chance of happening
#define Cloud_Chance_per_Day 50

// Minimum number of minutes for cloud duration. Don't use max duration of
// less than 6
#define Min_Cloud_Duration 3

// Maximum number of minutes for the cloud duration. Don't use max duration
// of more than 255
#define Max_Cloud_Duration 10

// Minimum number of clouds that can happen per day
#define Min_Clouds_per_Day 1

// Maximum number of clouds that can happen per day
#define Max_Clouds_per_Day 5

// Only start the cloud effect after this setting
// In this example, start could after 12:00pm
#define Start_Cloud_After NumMins(12,00)

// Always end the cloud effect before this setting
// In this example, end could before 8:00pm
#define End_Cloud_Before NumMins(19,00)

// Percentage chance of a lightning happen for every cloud
// For testing purposes, you can use 100 and cause the lightning to have
// 100% chance of happening
#define Lightning_Change_per_Cloud 75

// Channels used by the actinic LEDs on the PWM Expansion module
// These channels will not be dimmed when the cloud effect is triggered
// Number is a binary form. B001100 means channel 2 and 3 are used for
// actinics
#define Actinic_Channels B001001

// Channels used by the daylight LEDs on the PWM Expansion module
// These channels will be used for the spike when lightning effect is
// triggered
// Number is a binary form. B000011 means channel 0 and 1 are used for
// daylights
#define Daylight_Channels B010010

// Note: Make sure to choose correct values that will work within your
// PWMSLope settings.
// For example, in our case, we could have a max of 5 clouds per day and
// they could last for 50 minutes.
// Which could mean 250 minutes of clouds. We need to make sure the
// PWMSlope can accomodate 250 minutes of effects or
// unforseen results could happen.
// Also, make sure that you can fit double those minutes between
// Start_Cloud_After and End_Cloud_Before.
// In our example, we have 510 minutes between Start_Cloud_After and
// End_Cloud_Before, so double the 250 minutes (or 500 minutes) can
// fit in that 510 minutes window.
// It's a tight fit, but it did.

//#define printdebug // Uncomment this for debug print on Serial Monitor
// window
#define forcecloudcalculation // Uncomment this to force the cloud
// calculation to happen in the boot process.


// Change the values above to customize your cloud/storm effect
// ------------------------------------------------------------
// Do not change anything below here

static byte cloudchance=255;
static byte cloudduration=0;
static int cloudstart=0;
static byte numclouds=0;
static byte lightningchance=0;
static byte cloudindex=0;
static byte lightningstatus=0;
static int LastNumMins=0;
// Every day at midnight, we check for chance of cloud happening today
if (hour()==0 && minute()==0 && second()==0) cloudchance=255;

#ifdef forcecloudcalculation
if (cloudchance==255)
#else
if (hour()==0 && minute()==0 && second()==1 && cloudchance==255)
#endif
{
//Pick a random number between 0 and 99
cloudchance=random(100);
// if picked number is greater than Cloud_Chance_per_Day, we will not have
// clouds today
if (cloudchance>Cloud_Chance_per_Day) cloudchance=0;
// Check if today is day for clouds.
if ((day()%Clouds_Every_X_Days)!=0) cloudchance=0;
// If we have cloud today
if (cloudchance)
{
// pick a random number for number of clouds between Min_Clouds_per_Day and
// Max_Clouds_per_Day
numclouds=random(Min_Clouds_per_Day,Max_Clouds_per_Day);
// pick the time that the first cloud will start
// the range is calculated between Start_Cloud_After and the even
// distribuition of clouds on this day.

cloudstart=random(Start_Cloud_After,Start_Cloud_After+((End_Cloud_Before-Start_Cloud_After)/(numclouds*2)));
// pick a random number for the cloud duration of first cloud.
cloudduration=random(Min_Cloud_Duration,Max_Cloud_Duration);
//Pick a random number between 0 and 99
lightningchance=random(100);
// if picked number is greater than Lightning_Change_per_Cloud, we will not
// have lightning today
if (lightningchance>Lightning_Change_per_Cloud) lightningchance=0;
}
}
// Now that we have all the parameters for the cloud, let's create the
// effect

if (ForceCloud)
{
ForceCloud=false;
cloudchance=1;
cloudduration=10;
lightningchance=1;
cloudstart=NumMins(hour(),minute())+1;
}
if (cloudchance)
{
//is it time for cloud yet?
if (NumMins(hour(),minute())>=cloudstart &&
NumMins(hour(),minute())<(cloudstart+cloudduration))
{
// let's go through all channels to pick which ones will be dimmed
for (int a=0;a<6;a++)
{
if (bitRead(Actinic_Channels,a)==0)
{
// this will slope down the channel from the current PWM to 0 within
// 3minutes.
// then it will stay at 0 for the duration of the cycle
// and finally slope up from 0 to PWM value within 3 minutes
// it is basically an inversed slope

PWMChannel[a]=ReversePWMSlope(cloudstart,cloudstart+cloudduration,PWMChannel[a],0,180);
}
}
if (lightningchance &&
(NumMins(hour(),minute())==(cloudstart+(cloudduration/2))) && second()<5)
{
for (int b=0;b<6;b++)
{
// if (bitRead(Daylight_Channels,b)==1)
// {
if (random(100)<20) lightningstatus=1;
else lightningstatus=0;
if (lightningstatus) PWMChannel=100;
else PWMChannel=0;
//delay(10);
// }
// else
// {
// PWMChannel=20;
// }
}
}
}
if (NumMins(hour(),minute())>(cloudstart+cloudduration))
{
cloudindex++;
if (cloudindex < numclouds)
{

cloudstart=random(Start_Cloud_After+(((End_Cloud_Before-Start_Cloud_After)/(numclouds*2))*cloudindex*2),(Start_Cloud_After+(((End_Cloud_Before-Start_Cloud_After)/(numclouds*2))*cloudindex*2))+((End_Cloud_Before-Start_Cloud_After)/(numclouds*2)));
// pick a random number for the cloud duration of first cloud.
cloudduration=random(Min_Cloud_Duration,Max_Cloud_Duration);
//Pick a random number between 0 and 99
lightningchance=random(100);
// if picked number is greater than Lightning_Change_per_Cloud, we will not
// have lightning today
if (lightningchance>Lightning_Change_per_Cloud) lightningchance=0;
}
}
}

if (LastNumMins!=NumMins(hour(),minute()))
{
LastNumMins=NumMins(hour(),minute());
ReefAngel.LCD.Clear(255,0,120,132,132);
ReefAngel.LCD.DrawText(0,255,5,120,"C");
ReefAngel.LCD.DrawText(0,255,11,120,"00:00");
ReefAngel.LCD.DrawText(0,255,45,120,"L");
ReefAngel.LCD.DrawText(0,255,51,120,"00:00");
if (cloudchance && (NumMins(hour(),minute())<cloudstart))
{
int x=0;
if ((cloudstart/60)>=10) x=11;
else x=17;
ReefAngel.LCD.DrawText(0,255,x,120,(cloudstart/60));
if ((cloudstart%60)>=10) x=29;
else x=35;
ReefAngel.LCD.DrawText(0,255,x,120,(cloudstart%60));
}
ReefAngel.LCD.DrawText(0,255,90,120,cloudduration);
if (lightningchance)
{
int x=0;
if (((cloudstart+(cloudduration/2))/60)>=10) x=51;
else x=57;
ReefAngel.LCD.DrawText(0,255,x,120,((cloudstart+(cloudduration/2))/60));
if (((cloudstart+(cloudduration/2))%60)>=10) x=69;
else x=75;
ReefAngel.LCD.DrawText(0,255,x,120,((cloudstart+(cloudduration/2))%60));
}
}
}

byte ReversePWMSlope(long cstart,long cend,byte PWMStart,byte PWMEnd, byte clength)
{
long n=elapsedSecsToday(now());
cstart*=60;
cend*=60;
if (n<cstart) return PWMStart;
if (n>=cstart && n<=(cstart+clength)) return
map(n,cstart,cstart+clength,PWMStart,PWMEnd);
if (n>(cstart+clength) && n<(cend-clength)) return PWMEnd;
if (n>=(cend-clength) && n<=cend) return
map(n,cend-clength,cend,PWMEnd,PWMStart);
if (n>cend) return PWMStart;
}
bmhair03
Posts: 166
Joined: Sun Mar 20, 2011 1:22 pm

Re: Relay expansion code

Post by bmhair03 »

Cant program anything now!!!?? NO code will upload I tried the test codes also help No internal memory found does not sound good ?
bmhair03
Posts: 166
Joined: Sun Mar 20, 2011 1:22 pm

Re: Relay expansion code

Post by bmhair03 »

I now have 2 RA's that say no internal memory found after trying to upload code /?? one is a plus the other gen 1.\
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: Relay expansion code

Post by rimai »

Make sure you have 1.1.0 libs and upload the initalinternalmemory
Roberto.
bmhair03
Posts: 166
Joined: Sun Mar 20, 2011 1:22 pm

Re: Relay expansion code

Post by bmhair03 »

I guess its time to re read manual :). Thanks
Post Reply