JerkyJunky's Starter Screen

Share you PDE file with our community
Post Reply
jerkyjunky
Posts: 12
Joined: Wed Nov 07, 2012 10:08 am

JerkyJunky's Starter Screen

Post by jerkyjunky »

Been a fun couple days programming in a new screen for my RA. Here is what I have so far:

http://i.imgur.com/9UVk9.jpg

The wavemaker stuff is filler until I get an actual unit, but the rest is legit. Here is the 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 <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 <ReefAngel.h>

////// Place global variable code below here
#define FONT_8x16

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


void setup()
{
    // This must be the first line
    ReefAngel.Init();  //Initialize controller
    ReefAngel.AddStandardMenu();  // Add Standard Menu

    // Ports toggled in Feeding Mode
    ReefAngel.FeedingModePorts = Port5Bit;
    // Ports toggled in Water Change Mode
    ReefAngel.WaterChangePorts = Port5Bit | Port8Bit;
    // Ports toggled when Lights On / Off menu entry selected
    ReefAngel.LightsOnPorts = 0;
    // Ports turned off when Overheat temperature exceeded
    ReefAngel.OverheatShutoffPorts = 0;
    // Use T1 probe as temperature and overheat functions
    ReefAngel.TempProbe = T1_PROBE;
    ReefAngel.OverheatProbe = T1_PROBE;
    // Set the Overheat temperature setting
    InternalMemory.OverheatTemp_write( 800 );


    // Ports that are always on
    ReefAngel.Relay.On( Port5 );
    ReefAngel.Relay.On( Port6 );
    ReefAngel.Relay.On( Port7 );
    ReefAngel.Relay.On( Port8 );

    ////// Place additional initialization code below here
    

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

void loop()
{
    ReefAngel.StandardLights( Port1,19,45,8,15 );
    ReefAngel.StandardLights( Port3,19,59,8,1 );
    ReefAngel.StandardLights( Port4,7,59,20,1 );
    ReefAngel.PWM.SetDaylight( PWMSlope(8,0,20,0,15,100,60,0) );
    ReefAngel.PWM.SetActinic( PWMSlope(20,0,8,0,15,100,60,0) );
    ////// Place your custom code below here
    

    ////// Place your custom code above here

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

void DrawCustomMain()
{
    byte offset = 3;
    byte waterLevel = ReefAngel.WaterLevel.GetLevel();
    byte dispLights = ReefAngel.PWM.GetDaylightValue();
    byte sumpLights = ReefAngel.PWM.GetActinicValue();
    byte TempRelay = ReefAngel.Relay.RelayData;
    byte atoPort = 3;
    TempRelay &= ReefAngel.Relay.RelayMaskOff;
    TempRelay |= ReefAngel.Relay.RelayMaskOn;
    char text[10];
    
    
    // Header = Title + Date and Time
    ReefAngel.LCD.DrawText(COLOR_GREEN, DefaultBGColor, 15, offset, "JerkyJunky's Reef");
    ReefAngel.LCD.DrawDate(6, offset + 10);
    ReefAngel.LCD.Clear(COLOR_GREEN, 1, offset + 20, 128, offset + 20);
    offset = 26;
    pingSerial();
    
    // Main Relay Box & Parameters
    ReefAngel.LCD.DrawCircleOutletBoxHorizontal(2, offset, TempRelay);
    ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 50, offset, "Temp:");
    ConvertNumToString(text, ReefAngel.Params.Temp[T1_PROBE], 10);
    ReefAngel.LCD.DrawLargeText(COLOR_PURPLE, 255, 49, offset + 9, text, Font8x16);
    ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 101, offset, "pH:");
    ConvertNumToString(text, ReefAngel.Params.PH, 100);
    ReefAngel.LCD.DrawLargeText(COLOR_ORANGE, 255, 93, offset + 9, text, Font8x16);
    ReefAngel.LCD.Clear(COLOR_GREEN, 1, offset + 23, 128, offset + 23);
    offset = offset + 27;
    pingSerial();

    // Lights
    if (dispLights > 0)
      ReefAngel.LCD.DrawText(COLOR_GREEN, DefaultBGColor, 10, offset, "Display");
    else
      ReefAngel.LCD.DrawText(COLOR_RED, DefaultBGColor, 10, offset, "Display");
    if (sumpLights > 0)
      ReefAngel.LCD.DrawText(COLOR_GREEN, DefaultBGColor, 72, offset, "Refugium");
    else
      ReefAngel.LCD.DrawText(COLOR_RED, DefaultBGColor, 72, offset, "Refugium");
    ConvertNumToString(text, dispLights, 1);
    strcat(text, "%");
    ReefAngel.LCD.DrawLargeText(COLOR_BLUE, DefaultBGColor, 15, offset + 9, text, Font8x16);
    ConvertNumToString(text, sumpLights, 1);
    strcat(text, "%");
    ReefAngel.LCD.DrawLargeText(COLOR_BLUE, DefaultBGColor, 95, offset + 9, text, Font8x16);
    ReefAngel.LCD.Clear(COLOR_GREEN, 1, offset + 24, 128, offset + 24);
    offset = offset + 27;
    pingSerial();
    

    // Water Level & ATO
    if (waterLevel >= 100)
    {
    ReefAngel.LCD.DrawText(COLOR_BLUE, DefaultBGColor, 5, offset, "Tank Level");
    ReefAngel.LCD.DrawLargeText(COLOR_BLUE, DefaultBGColor, 25, offset + 9, "Full", Font8x16);
    }
    else if (waterLevel >= 50)
    {
    ReefAngel.LCD.DrawText(COLOR_ORANGE, DefaultBGColor, 5, offset, "Tank Level");
    ConvertNumToString(text, waterLevel, 1);
    strcat(text, "%");
    ReefAngel.LCD.Clear(DefaultBGColor, 1, offset + 9, 128, offset + 18);
    ReefAngel.LCD.DrawLargeText(COLOR_ORANGE, DefaultBGColor, 25, offset + 9, text, Font8x16);
    }
    else
    {
    ReefAngel.LCD.DrawText(COLOR_RED, DefaultBGColor, 5, offset, "Tank Level");
    ConvertNumToString(text, waterLevel, 1);
    strcat(text, "%");
    ReefAngel.LCD.DrawLargeText(COLOR_RED, DefaultBGColor, 25, offset + 9, text, Font8x16);    
    }
    ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 70, offset + 2, "ATO:");
    if (ReefAngel.LowATO.IsActive())
    {
    	ReefAngel.LCD.DrawText(COLOR_GREEN, DefaultBGColor, 95, offset + 2, "Avail");
    }
    else
    {
    	ReefAngel.LCD.DrawText(COLOR_RED, DefaultBGColor, 95, offset + 2, "Empty");
    }
    ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 72, offset + 12, "Pump:");
    if ((TempRelay&(1<<(atoPort - 1)))==1<<(atoPort - 1))
    {
        ReefAngel.LCD.Clear(DefaultBGColor, 102, offset + 12, 128, offset + 21);        
    	ReefAngel.LCD.DrawText(COLOR_GREEN, DefaultBGColor, 102, offset + 12, "On");
    }
    else
    {
    	ReefAngel.LCD.DrawText(COLOR_RED, DefaultBGColor, 102, offset + 12, "Off");
    }
    ReefAngel.LCD.Clear(COLOR_GREEN, 1, offset + 24, 128, offset + 24);
    offset = offset + 27;
    pingSerial();

    // Wavemaker
    ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 8, offset, "Vortech Mode");
    ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 95, offset, "Speed");
    ReefAngel.LCD.DrawLargeText(COLOR_ORANGE, DefaultBGColor, 5, offset + 9, "Reef Crest", Font8x16);
    ReefAngel.LCD.DrawLargeText(COLOR_GREEN, DefaultBGColor, 98, offset + 9, "XX%", Font8x16);

}

void DrawCustomGraph()
{
}
Now to add in the cloud logic, the sunrise by location code, the ATO controls, and the heater settings. WHEW! Going to be a fun weekend. :D
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

JerkyJunky's Starter Screen

Post by lnevo »

Looks great!
jerkyjunky
Posts: 12
Joined: Wed Nov 07, 2012 10:08 am

Re: JerkyJunky's Starter Screen

Post by jerkyjunky »

Thanks! Still some errors that will pop up I already know of. I'm not clearing everything that needs to be so I'll get some artifacts I'm sure. Sucks the tank is still cycling and I can't play fully with the lights and cloud settings for a bit. Darn bacteria refusing to breed! :(
binder
Posts: 2871
Joined: Fri Mar 18, 2011 6:20 pm
Location: Illinois
Contact:

Re: JerkyJunky's Starter Screen

Post by binder »

nice and busy screen. it has all the stuff you need. Looking good!
jerkyjunky
Posts: 12
Joined: Wed Nov 07, 2012 10:08 am

Re: JerkyJunky's Starter Screen

Post by jerkyjunky »

Here is the next version of my display:

http://i.imgur.com/7zyND.jpg

As you can see, I have completed the Event Previewer area, and have it accurately (or so it seems) predicting the next lighting effect be it sunrise, sunset, dawn, dusk, cloud, or sunlight. It also should be saying the correct ETA as well. The bottom diag numbers are time of dawn tomorrow.

Here is the code I used to get it. I also have heavily modified cloud code. I've added in a min/max cloud fade chance. It also no longer used the ReversePWMSlope. Any feedback would be welcome! :-)

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 <ReefAngel.h>
#include <SunLocation.h>

////// Place global variable code below here
#define FONT_8x16
SunLocation sl;
time_t nextEvent = 0, timeSunRise, timeSunSet, nextCloud = 0;
String nextEventName;
boolean isCloudy = false;

//Cloud Defines:
	// Frequency in days based on the day of the month - number 2 means every 2 days, for example (day 2,4,6 etc)
#define Clouds_Every_X_Days 1 

  // Percentage chance of a cloud happening today
#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 7

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

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

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

	// Time in minutes for the fade of a cloud to take affect
#define Cloud_Fade_Duration 3

	// Minimum fade of cloud
#define Min_Cloud_Fade 20

	// Maximum fade of cloud
#define Max_Cloud_Fade 70

  // Only start the cloud effect after this setting
//#define Start_Cloud_After NumMins(10,30)

  // Always end the cloud effect before this setting
//#define End_Cloud_Before NumMins(17,30)

  // Percentage chance of a lightning happen for every cloud
#define Lightning_Chance_per_Cloud 0

byte cloudChance=0;
byte cloudDuration=0;
time_t cloudStart=0;
byte numClouds=0;
byte lightningChance=0;
byte cloudIndex=0;
byte lightningStatus=0;
byte cloudFade = 0;

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


void setup()
{
    // This must be the first line
    ReefAngel.Init();  //Initialize controller
    ReefAngel.AddStandardMenu();  // Add Standard Menu

    // Ports toggled in Feeding Mode
    ReefAngel.FeedingModePorts = Port5Bit;
    // Ports toggled in Water Change Mode
    ReefAngel.WaterChangePorts = Port5Bit | Port8Bit;
    // Ports toggled when Lights On / Off menu entry selected
    ReefAngel.LightsOnPorts = 0;
    // Ports turned off when Overheat temperature exceeded
    ReefAngel.OverheatShutoffPorts = 0;
    // Use T1 probe as temperature and overheat functions
    ReefAngel.TempProbe = T1_PROBE;
    ReefAngel.OverheatProbe = T1_PROBE;
    // Set the Overheat temperature setting
    InternalMemory.OverheatTemp_write( 800 );

    ReefAngel.Relay.On( Port2 );
    ReefAngel.Relay.On( Port5 );
    ReefAngel.Relay.On( Port6 );
    ReefAngel.Relay.On( Port7 );
    ReefAngel.Relay.On( Port8 );

    if (nextEvent == 0) {GetNextEvent();}

}


void loop()
{
	//Moonlights
    ReefAngel.StandardLights(Port1, hour(timeSunSet - 900), minute(timeSunSet - 900), hour(timeSunRise + 900), minute(timeSunRise + 900));
	//Sump Lights
    ReefAngel.StandardLights(Port3, hour(timeSunSet - 60), minute(timeSunSet - 60), hour(timeSunRise + 60), minute(timeSunRise + 60));
	//Display Lights
    ReefAngel.StandardLights(Port4, hour(timeSunRise - 60), minute(timeSunRise - 60), hour(timeSunSet + 60), minute(timeSunSet + 60));
    //Sun Pattern for Display
    ReefAngel.PWM.SetDaylight(PWMSlope(hour(timeSunRise), minute(timeSunRise), hour(timeSunSet), minute(timeSunSet), 15, 100, 30, 0));
    //Sun Pattern for Sump
    ReefAngel.PWM.SetActinic(PWMSlope(hour(timeSunSet), minute(timeSunSet), hour(timeSunRise), minute(timeSunRise), 15, 100, 30, 0));
    
    ////// Place your custom code below here
    if (now() >= nextEvent) { GetNextEvent(); }
    if (isCloudy)
    {
    	ReefAngel.PWM.SetDaylight(PWMSlope(hour(cloudStart), minute(cloudStart), hour(cloudStart + cloudDuration), minute(cloudStart + cloudDuration), 100, cloudFade, 3, 100));
    }
    ReefAngel.Portal("jerkyjunky");
    ////// Place your custom code above here

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


void GetNextEvent()
{
		if (nextEvent == 0)
		{
			sl.CalSun();
			timeSunRise = sl.GetSunRise();
			timeSunSet = sl.GetSunSet();
		}
		if (now() < timeSunRise - 1800)
		{
			nextEventName = "Dawn";
			nextEvent = timeSunRise - 1800;
		}
		else if (now() < timeSunRise)
		{
			sl.CalSun();
			cloudChance = 255;
			GetNextCloud();
			timeSunRise = sl.GetSunRise();
			timeSunSet = sl.GetSunSet();
			nextEventName = "Sunrise";
			nextEvent = timeSunRise;
		}
		else if (now() >= timeSunSet + 1800)
		{
			nextEventName = "Dawn";
                        sl.GetTomorrowSunRise(&timeSunRise);
			nextEvent = timeSunRise - 1800;
		}
		else if (now() >= timeSunSet)
		{		
			nextEventName = "Dusk";
			nextEvent = timeSunSet + 1800;
		}
		else
		{
			if ((now() > nextCloud) && (nextCloud > 0))
			{
				nextEventName = "Cloud";
				nextEvent = nextCloud;
			}
			else if ((now() >= nextCloud) && (nextCloud > 0))
			{
				isCloudy = true;
				cloudFade = random(Min_Cloud_Fade, Max_Cloud_Fade);
				nextEventName = "Sun";
				nextEvent = nextCloud + cloudDuration;
			}
			else if (isCloudy)
			{
				isCloudy = false;
				cloudIndex++;
				GetNextCloud();
				if (nextCloud > 0)
				{
					nextEvent = nextCloud;
					nextEventName = "Cloud";
				}
				else
				{
					nextEventName = "Sunset";
					nextEvent = timeSunSet;
				}
			}
			else
			{
				nextEventName = "Sunset";
				nextEvent = timeSunSet;
			}
		}
}


void GetNextCloud()
{
		//Init - Ran by GetNextEvent() at Dawn once per day by setting cloudChance to 255
		if (cloudChance == 255)
		{
			//is today cloudy?
			cloudChance = random(100);
			if ((cloudChance > Cloud_Chance_per_Day) || ((day() % Clouds_Every_X_Days) != 0))
			{
				cloudChance = 0;
			}
			else
			{
				time_t t = now();
				numClouds = random(Min_Clouds_per_Day, Max_Clouds_per_Day);
				cloudStart = t - ((hour(t) * 3600) + (minute(t) * 60) + second(t));
				cloudStart += (random(timeSunRise, timeSunRise + ((timeSunSet - timeSunRise) / (numClouds * 2)))) * 60;
				cloudDuration = (random(Min_Cloud_Duration, Max_Cloud_Duration)) * 60;
				lightningChance = random(100);
				if (lightningChance > Lightning_Chance_per_Cloud) lightningChance = 0;
			}
		}
		else
		{
			if (cloudIndex < numClouds)
			{
				time_t t = now();
				cloudStart = t - ((hour(t) * 3600) + (minute(t) * 60) + second(t));
				cloudStart += (random(timeSunRise + (((timeSunSet - timeSunRise) / (numClouds * 2)) * cloudIndex * 2), (timeSunRise + (((timeSunSet - timeSunRise) / (numClouds * 2)) * cloudIndex * 2)) + ((timeSunSet - timeSunRise) / (numClouds * 2)))) * 60;
				cloudDuration = (random(Min_Cloud_Duration, Max_Cloud_Duration)) * 60;
				lightningChance = random(100);
				if (lightningChance > Lightning_Chance_per_Cloud) lightningChance = 0;
			}
			else
			{
				cloudStart = 0;
				cloudDuration = 0;
				cloudIndex = 0;
			}
		}
}


void DrawCustomMain()
{
    byte offset = 3;
    byte waterLevel = ReefAngel.WaterLevel.GetLevel();
    byte dispLights = ReefAngel.PWM.GetDaylightValue();
    byte sumpLights = ReefAngel.PWM.GetActinicValue();
    byte TempRelay = ReefAngel.Relay.RelayData;
    byte atoPort = 3;
    TempRelay &= ReefAngel.Relay.RelayMaskOff;
    TempRelay |= ReefAngel.Relay.RelayMaskOn;
    char text[10];
    
    
    // Header = Title + Date and Time
    ReefAngel.LCD.DrawText(COLOR_GREEN, DefaultBGColor, 15, offset, "JerkyJunky's Reef");
    ReefAngel.LCD.DrawDate(6, offset + 10);
    ReefAngel.LCD.Clear(COLOR_GREEN, 1, offset + 20, 128, offset + 20);
    offset = 26;
    pingSerial();
    
    // Main Relay Box & Parameters
    ReefAngel.LCD.Clear(DefaultBGColor, 1, offset, 45, offset + 21);
    ReefAngel.LCD.DrawCircleOutletBoxHorizontal(2, offset, TempRelay);
    ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 50, offset, "Temp:");
    ConvertNumToString(text, ReefAngel.Params.Temp[T1_PROBE], 10);
    ReefAngel.LCD.DrawLargeText(COLOR_PURPLE, 255, 49, offset + 9, text, Font8x16);
    ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 101, offset, "pH:");
    ConvertNumToString(text, ReefAngel.Params.PH, 100);
    ReefAngel.LCD.DrawLargeText(COLOR_ORANGE, 255, 93, offset + 9, text, Font8x16);
    offset = offset + 23;
    pingSerial();


    // Water Level & ATO
    ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 5, offset, "Tank Level");
    if (waterLevel >= 100)
    {
    ReefAngel.LCD.DrawLargeText(COLOR_BLUE, DefaultBGColor, 19, offset + 9, "Full", Font8x16);
    }
    else if (waterLevel >= 50)
    {
    ConvertNumToString(text, waterLevel, 1);
    strcat(text, "%");
    ReefAngel.LCD.Clear(DefaultBGColor, 1, offset + 9, 60, offset + 22);
    ReefAngel.LCD.DrawLargeText(COLOR_ORANGE, DefaultBGColor, 23, offset + 9, text, Font8x16);
    }
    else
    {
    ConvertNumToString(text, waterLevel, 1);
    strcat(text, "%");
    ReefAngel.LCD.Clear(DefaultBGColor, 1, offset + 9, 60, offset + 22);
    ReefAngel.LCD.DrawLargeText(COLOR_RED, DefaultBGColor, 23, offset + 9, text, Font8x16);    
    }
    ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 70, offset + 2, "ATO:");
    if (ReefAngel.LowATO.IsActive())
    {
    	ReefAngel.LCD.DrawText(COLOR_GREEN, DefaultBGColor, 95, offset + 2, "Avail");
    }
    else
    {
    	ReefAngel.LCD.DrawText(COLOR_RED, DefaultBGColor, 95, offset + 2, "Empty");
    }
    ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 72, offset + 12, "Pump:");
    if ((TempRelay&(1<<(atoPort - 1)))==1<<(atoPort - 1))
    {
        ReefAngel.LCD.Clear(DefaultBGColor, 102, offset + 12, 128, offset + 21);        
    	ReefAngel.LCD.DrawText(COLOR_GREEN, DefaultBGColor, 102, offset + 12, "On");
    }
    else
    {
    	ReefAngel.LCD.DrawText(COLOR_RED, DefaultBGColor, 102, offset + 12, "Off");
    }
    ReefAngel.LCD.Clear(COLOR_GREEN, 1, offset + 24, 128, offset + 24);
    offset = offset + 27;
    pingSerial();
    
    
    // Lights
    if (dispLights > 0)
      ReefAngel.LCD.DrawText(COLOR_GREEN, DefaultBGColor, 10, offset, "Display");
    else
      ReefAngel.LCD.DrawText(COLOR_RED, DefaultBGColor, 10, offset, "Display");
    if (sumpLights > 0)
      ReefAngel.LCD.DrawText(COLOR_GREEN, DefaultBGColor, 72, offset, "Refugium");
    else
      ReefAngel.LCD.DrawText(COLOR_RED, DefaultBGColor, 72, offset, "Refugium");
    ReefAngel.LCD.Clear(DefaultBGColor, 1, offset + 9, 128, offset + 22);
    ConvertNumToString(text, dispLights, 1);
    strcat(text, "%");
    if (strlen(text) == 5)
      ReefAngel.LCD.DrawLargeText(COLOR_BLUE, DefaultBGColor, 10, offset + 9, text, Font8x16);
    else if (strlen(text) == 4)
      ReefAngel.LCD.DrawLargeText(COLOR_BLUE, DefaultBGColor, 14, offset + 9, text, Font8x16);
    else if (strlen(text) == 3)
      ReefAngel.LCD.DrawLargeText(COLOR_BLUE, DefaultBGColor, 18, offset + 9, text, Font8x16);
    else
      ReefAngel.LCD.DrawLargeText(COLOR_BLUE, DefaultBGColor, 22, offset + 9, text, Font8x16);
    ConvertNumToString(text, sumpLights, 1);
    strcat(text, "%");
    if (strlen(text) == 5)
      ReefAngel.LCD.DrawLargeText(COLOR_BLUE, DefaultBGColor, 80, offset + 9, text, Font8x16);
    else if (strlen(text) == 4)
      ReefAngel.LCD.DrawLargeText(COLOR_BLUE, DefaultBGColor, 84, offset + 9, text, Font8x16);
    else if (strlen(text) == 3)
      ReefAngel.LCD.DrawLargeText(COLOR_BLUE, DefaultBGColor, 88, offset + 9, text, Font8x16);
    else
      ReefAngel.LCD.DrawLargeText(COLOR_BLUE, DefaultBGColor, 92, offset + 9, text, Font8x16);
    offset = offset + 25;
    pingSerial();
    
    ReefAngel.LCD.Clear(DefaultBGColor, 1, offset, 128, offset + 17);
    ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 2, offset, "Next Event:");
    nextEventName.toCharArray(text, 10);
    ReefAngel.LCD.DrawText(COLOR_BLUE, DefaultBGColor, 70, offset, text);
    ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 2, offset + 9, "Time Until:");
    if (nextEvent > now())
    {
      ConvertNumToString(text, hour(nextEvent - now()), 1);
      strcat(text, ":");
      ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 75, offset + 9, text);
      ConvertNumToString(text, minute(nextEvent - now()), 1);
      ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 95, offset + 9, text);
    }
    else
    {
      ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 75, offset + 9, "NOW!");
    }
    pingSerial();
    
    ConvertNumToString(text, hour(timeSunSet) , 1);
    ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 2, offset + 18, text);
    ConvertNumToString(text, minute(timeSunSet) , 1);
    ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 70, offset + 18, text);

}

void DrawCustomGraph()
{
}
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: JerkyJunky's Starter Screen

Post by rimai »

Pretty cool :)
Roberto.
psyrob
Posts: 247
Joined: Thu Sep 01, 2011 8:44 pm

Re: JerkyJunky's Starter Screen

Post by psyrob »

Like it! I especially like how you tucked the relay circles up in the corner...
Image
jerkyjunky
Posts: 12
Joined: Wed Nov 07, 2012 10:08 am

Re: JerkyJunky's Starter Screen

Post by jerkyjunky »

Thanks! The code for it should be in the other how do I area if you wanted just that how to bit. :-)

I've edited a bit more and fixed some issues with the clouds not processing correctly. Also added in the ATO bit. I have a bucket on the side of my stand with RODI water in it and a pump. The pump has a float switch on it so I know if I'm about to suck air or not (LowATO). There is also an emergency float in the sump to act as a redundant check to the water sensor kit (HighATO). Other than that cleaned it up a bit and added better comments here and there.

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 <ReefAngel.h>
#include <SunLocation.h>

////// Place global variable code below here
#define FONT_8x16
SunLocation sl;
time_t nextEvent = 0, timeSunRise, timeSunSet, nextCloud = 0;
String nextEventName;
boolean isCloudy = false;
boolean isATOAvail = false;
byte atoPort = 0;;

//Cloud Defines:
  // Frequency in days based on the day of the month - number 2 means every 2 days, for example (day 2,4,6 etc)
#define Clouds_Every_X_Days 1 

  // Percentage chance of a cloud happening today
#define Cloud_Chance_per_Day 25

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

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

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

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

  // Time in minutes for the fade of a cloud to take affect
#define Cloud_Fade_Duration 3

  // Minimum fade of cloud
#define Min_Cloud_Fade 20

  // Maximum fade of cloud
#define Max_Cloud_Fade 70

byte cloudChance=0;
byte cloudDuration=0;
byte numClouds=0;
byte cloudIndex=0;
byte cloudFade = 0;

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


void setup()
{
	//This must be the first line
	ReefAngel.Init();  //Initialize controller
	ReefAngel.AddStandardMenu();  // Add Standard Menu

	//Ports toggled in Feeding Mode
	ReefAngel.FeedingModePorts = Port7Bit;
	//Ports toggled in Water Change Mode
	ReefAngel.WaterChangePorts = Port8Bit;
	//Ports toggled when Lights On / Off menu entry selected
	ReefAngel.LightsOnPorts = 0;
	//Ports turned off when Overheat temperature exceeded
	ReefAngel.OverheatShutoffPorts = 0;
	//Use T1 probe as temperature and overheat functions
	ReefAngel.TempProbe = T1_PROBE;
	ReefAngel.OverheatProbe = T1_PROBE;
	//Set the Overheat temperature setting
	InternalMemory.OverheatTemp_write(800);
	//Set the port ATO is on numerically
	atoPort = 6;

	//Enable LED driver board fan
	ReefAngel.Relay.On( Port2 );
	//Enable heater port - Currently not used
	ReefAngel.Relay.On( Port5 );
	//Enable skimmer
	ReefAngel.Relay.On( Port7 );
	//Enable return pump
	ReefAngel.Relay.On( Port8 );

	//Get an event at startup
	if (nextEvent == 0) {GetNextEvent();}

}


void loop()
{
	//Moonlights
	ReefAngel.StandardLights(Port1, hour(timeSunSet - 90), minute(timeSunSet - 90), hour(timeSunRise + 90), minute(timeSunRise + 90));
	
	//Sump Lights
	ReefAngel.StandardLights(Port3, hour(timeSunSet - 60), minute(timeSunSet - 60), hour(timeSunRise + 60), minute(timeSunRise + 60));
	
	//Display Lights
	ReefAngel.StandardLights(Port4, hour(timeSunRise - 1860), minute(timeSunRise - 1860), hour(timeSunSet + 1860), minute(timeSunSet + 1860));
	
	//Sun Pattern for Sump
	ReefAngel.PWM.SetActinic(PWMSlope(hour(timeSunSet), minute(timeSunSet), hour(timeSunRise), minute(timeSunRise), 15, 100, 30, 0));
	
	//Sun Pattern for Display
	if (isCloudy)
	{
		ReefAngel.PWM.SetDaylight(PWMSlope(hour(nextCloud), minute(nextCloud), hour(nextCloud + cloudDuration), minute(nextCloud + cloudDuration), 100, cloudFade, 3, 100));
	}
	else
	{
		ReefAngel.PWM.SetDaylight(PWMSlope(hour(timeSunRise - 1800), minute(timeSunRise - 1800), hour(timeSunSet + 1800), minute(timeSunSet + 1800), 15, 100, 30, 0));
	}
	
	//ATO code
	//check emergency float switch detector in sump for overfilling
	if (ReefAngel.HighATO.IsActive())
	{
		ReefAngel.Relay.Off(Port6);
	}
	//else check status of top off bucket
	//check if bucket level is too low to pump from or if water in sump is getting too high
	else if ((ReefAngel.LowATO.IsActive() == false) || (ReefAngel.WaterLevel.GetLevel() > 90))
	{
		ReefAngel.Relay.Off(Port6);
	}
	//check if pump should be enabled
	else if ((ReefAngel.LowATO.IsActive()) && (ReefAngel.WaterLevel.GetLevel() <= 80))
	{
		ReefAngel.Relay.On(Port6);
	}

	//Event logic
	//if we just past the current event, go get another
	if (now() >= nextEvent) { GetNextEvent(); }
	
	// This should always be the last line
	ReefAngel.ShowInterface();
}


void GetNextEvent()
{
	//check if called from setup and if so establish current day's params
	if (nextEvent == 0)
	{
		sl.CalSun();
		timeSunRise = sl.GetSunRise();
		timeSunSet = sl.GetSunSet();
	}
	//WHEN IS IT?!?!?
	//Before the sun starts peeking over the horizon?
	if (now() < timeSunRise - 1800)
	{
		nextEventName = "Dawn";
		nextEvent = timeSunRise - 1800;
	}
	//Is the sun rising?
	//Use this time to figure out if today will be cloudy since we can kind of see the sky now
	else if (now() < timeSunRise)
	{
		sl.CalSun();
		cloudChance = 255;
		GetNextCloud();
		timeSunRise = sl.GetSunRise();
		timeSunSet = sl.GetSunSet();
		nextEventName = "Sunrise";
		nextEvent = timeSunRise;
	}
	//Is it after the sun has fully set?
	else if (now() >= timeSunSet + 1800)
	{
		nextEventName = "Dawn";
		sl.GetTomorrowSunRise(&timeSunRise);
		nextEvent = timeSunRise - 1800;
	}
	//Is the sun starting to descend?
	else if (now() >= timeSunSet)
	{		
		nextEventName = "Dusk";
		nextEvent = timeSunSet + 1800;
	}
	//Sun is up.  What now?  Clouds perhaps?
	else
	{
		//If clouds today, are we before a cloud?
		if ((now() < nextCloud) && (nextCloud > 0))
		{
			nextEventName = "Cloud";
			nextEvent = nextCloud;
		}
		//We have just entered a cloud zone
		else if ((now() >= nextCloud) && (nextCloud > 0))
		{
			isCloudy = true;
			cloudFade = random(Min_Cloud_Fade, Max_Cloud_Fade);
			nextEventName = "Sun";
			nextEvent = nextCloud + cloudDuration;
		}
		//We are leaving a cloud zone, but are there more?  Find out. 
		else if (isCloudy)
		{
			isCloudy = false;
			cloudIndex++;
			GetNextCloud();
			if (nextCloud > 0)
			{
				nextEvent = nextCloud;
				nextEventName = "Cloud";
			}
			else
			{
				nextEventName = "Sunset";
				nextEvent = timeSunSet;
			}
		}
		//Nope, no clouds today.  Get ready for sunset.
		else
		{
			nextEventName = "Sunset";
			nextEvent = timeSunSet;
		}
	}
}


void GetNextCloud()
{
		//Init - Ran by GetNextEvent() at Dawn once per day by setting cloudChance to 255
		if (cloudChance == 255)
		{
			//Is today cloudy?
			cloudChance = random(100);
			if (cloudChance <= Cloud_Chance_per_Day)
			{
				time_t t = now();
				int minSunRise = 0, minSunSet = 0;
				minSunRise = (hour(timeSunRise) * 60) + minute(timeSunRise);
				minSunSet = (hour(timeSunSet) * 60) + minute(timeSunSet);
				numClouds = random(Min_Clouds_per_Day, Max_Clouds_per_Day);
				nextCloud = t - ((hour(t) * 3600) + (minute(t) * 60) + second(t));
				nextCloud += (random(minSunRise, minSunRise + ((minSunSet - minSunRise) / (numClouds * 2)))) * 60;
				cloudDuration = (random(Min_Cloud_Duration, Max_Cloud_Duration)) * 60;
			}
		}
		//We must have picked a cloudy day, but are there more?
		else
		{
			if (cloudIndex < numClouds)
			{
				time_t t = now();
				int minSunRise = 0, minSunSet = 0;
				minSunRise = (hour(timeSunRise) * 60) + minute(timeSunRise);
				minSunSet = (hour(timeSunSet) * 60) + minute(timeSunSet);
				nextCloud = t - ((hour(t) * 3600) + (minute(t) * 60) + second(t));
				nextCloud += (random(minSunRise + (((minSunSet - minSunRise) / (numClouds * 2)) * cloudIndex * 2), (minSunRise + (((minSunSet - minSunRise) / (numClouds * 2)) * cloudIndex * 2)) + ((minSunSet - minSunRise) / (numClouds * 2)))) * 60;
				cloudDuration = (random(Min_Cloud_Duration, Max_Cloud_Duration)) * 60;
			}
			//Nope, out of clouds for today
			else
			{
				nextCloud = 0;
				cloudDuration = 0;
				cloudIndex = 0;
			}
		}
}


void DrawCustomMain()
{
    byte offset = 3;																					//Display offset vertically
    byte waterLevel = ReefAngel.WaterLevel.GetLevel();				//Percentage of water height based off sensor (aprox 3-5 inches off top of sump height)
    byte dispLights = ReefAngel.PWM.GetDaylightValue();				//Percentage of lights on display
    byte sumpLights = ReefAngel.PWM.GetActinicValue();				//Percentage of lights on sump
    byte TempRelay = ReefAngel.Relay.RelayData;								//--------------------
    TempRelay &= ReefAngel.Relay.RelayMaskOff;								//Setup for relay info
    TempRelay |= ReefAngel.Relay.RelayMaskOn;									//--------------------
    char text[10];
    
    
    //Header Section - Title + Date and Time
    ReefAngel.LCD.DrawText(COLOR_GREEN, DefaultBGColor, 15, offset, "JerkyJunky's Reef");
    ReefAngel.LCD.DrawDate(6, offset + 10);
    ReefAngel.LCD.Clear(COLOR_GREEN, 1, offset + 20, 128, offset + 20);
    offset = 26;
    pingSerial();
    
    //Main Relay Box & Main Parameters
    ReefAngel.LCD.Clear(DefaultBGColor, 1, offset, 45, offset + 21);
    ReefAngel.LCD.DrawCircleOutletBoxHorizontal(2, offset, TempRelay);
    ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 50, offset, "Temp:");
    ConvertNumToString(text, ReefAngel.Params.Temp[T1_PROBE], 10);
    ReefAngel.LCD.DrawLargeText(COLOR_PURPLE, 255, 49, offset + 9, text, Font8x16);
    ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 101, offset, "pH:");
    ConvertNumToString(text, ReefAngel.Params.PH, 100);
    ReefAngel.LCD.DrawLargeText(COLOR_ORANGE, 255, 93, offset + 9, text, Font8x16);
    offset = offset + 23;
    pingSerial();


    //Water Level
    ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 5, offset, "Tank Level");
    ConvertNumToString(text, waterLevel, 1);
    strcat(text, "%");
    if (waterLevel >= 100)
    {
	    ReefAngel.LCD.DrawLargeText(COLOR_BLUE, DefaultBGColor, 19, offset + 9, "Full", Font8x16);
    }
    else if (waterLevel >= 90)
    {
			ReefAngel.LCD.Clear(DefaultBGColor, 1, offset + 9, 60, offset + 22);
	    ReefAngel.LCD.DrawLargeText(COLOR_BLUE, DefaultBGColor, 23, offset + 9, text, Font8x16);
    }
    else if ((waterLevel < 90) && (waterlevel >=80))
    {
			ReefAngel.LCD.Clear(DefaultBGColor, 1, offset + 9, 60, offset + 22);
			ReefAngel.LCD.DrawLargeText(COLOR_ORANGE, DefaultBGColor, 23, offset + 9, text, Font8x16);    
    }
    else
    {
			ReefAngel.LCD.Clear(DefaultBGColor, 1, offset + 9, 60, offset + 22);
			ReefAngel.LCD.DrawLargeText(COLOR_RED, DefaultBGColor, 23, offset + 9, text, Font8x16);
    }
    
    //ATO - Avail?
    ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 70, offset + 2, "ATO:");
    if (ReefAngel.LowATO.IsActive())
    	ReefAngel.LCD.DrawText(COLOR_GREEN, DefaultBGColor, 95, offset + 2, "Avail");
    else
    	ReefAngel.LCD.DrawText(COLOR_RED, DefaultBGColor, 95, offset + 2, "Empty");
    
    //ATO - Pump?
    ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 72, offset + 12, "Pump:");
    if ((TempRelay&(1<<(atoPort - 1)))==1<<(atoPort - 1))
    {
			ReefAngel.LCD.Clear(DefaultBGColor, 102, offset + 12, 128, offset + 21);        
   		ReefAngel.LCD.DrawText(COLOR_GREEN, DefaultBGColor, 102, offset + 12, "On");
    }
    else
    	ReefAngel.LCD.DrawText(COLOR_RED, DefaultBGColor, 102, offset + 12, "Off");
    ReefAngel.LCD.Clear(COLOR_GREEN, 1, offset + 24, 128, offset + 24);
    offset = offset + 27;
    pingSerial();
    
    
    //Lights
    if (dispLights > 0)
      ReefAngel.LCD.DrawText(COLOR_GREEN, DefaultBGColor, 10, offset, "Display");
    else
      ReefAngel.LCD.DrawText(COLOR_RED, DefaultBGColor, 10, offset, "Display");
    
    if (sumpLights > 0)
      ReefAngel.LCD.DrawText(COLOR_GREEN, DefaultBGColor, 72, offset, "Refugium");
    else
      ReefAngel.LCD.DrawText(COLOR_RED, DefaultBGColor, 72, offset, "Refugium");
    
    ReefAngel.LCD.Clear(DefaultBGColor, 1, offset + 9, 128, offset + 22);
    
    ConvertNumToString(text, dispLights, 1);
    strcat(text, "%");
    
    if (strlen(text) == 5)
      ReefAngel.LCD.DrawLargeText(COLOR_BLUE, DefaultBGColor, 10, offset + 9, text, Font8x16);
    else if (strlen(text) == 4)
      ReefAngel.LCD.DrawLargeText(COLOR_BLUE, DefaultBGColor, 14, offset + 9, text, Font8x16);
    else if (strlen(text) == 3)
      ReefAngel.LCD.DrawLargeText(COLOR_BLUE, DefaultBGColor, 18, offset + 9, text, Font8x16);
    else
      ReefAngel.LCD.DrawLargeText(COLOR_BLUE, DefaultBGColor, 22, offset + 9, text, Font8x16);
    
    ConvertNumToString(text, sumpLights, 1);
    strcat(text, "%");
    
    if (strlen(text) == 5)
      ReefAngel.LCD.DrawLargeText(COLOR_BLUE, DefaultBGColor, 80, offset + 9, text, Font8x16);
    else if (strlen(text) == 4)
      ReefAngel.LCD.DrawLargeText(COLOR_BLUE, DefaultBGColor, 84, offset + 9, text, Font8x16);
    else if (strlen(text) == 3)
      ReefAngel.LCD.DrawLargeText(COLOR_BLUE, DefaultBGColor, 88, offset + 9, text, Font8x16);
    else
      ReefAngel.LCD.DrawLargeText(COLOR_BLUE, DefaultBGColor, 92, offset + 9, text, Font8x16);
    
    offset = offset + 25;
    pingSerial();
    
    //Events Viewer
    ReefAngel.LCD.Clear(DefaultBGColor, 1, offset, 128, offset + 17);
    ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 2, offset, "Next Event:");
    nextEventName.toCharArray(text, 10);
    ReefAngel.LCD.DrawText(COLOR_BLUE, DefaultBGColor, 70, offset, text);
    ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 2, offset + 9, "Time Until:");
    if (nextEvent > now())
    {
      ConvertNumToString(text, hour(nextEvent - now()), 1);
      strcat(text, ":");
      ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 75, offset + 9, text);
      ConvertNumToString(text, minute(nextEvent - now()), 1);
      ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 95, offset + 9, text);
    }
    else
    {
      ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 75, offset + 9, "NOW!");
    }
    pingSerial();
    
    //Diag
    ConvertNumToString(text, hour(nextCloud) , 1);
    ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 2, offset + 18, text);
    ConvertNumToString(text, cloudChance , 1);
    ReefAngel.LCD.DrawText(COLOR_BLACK, DefaultBGColor, 70, offset + 18, text);

}

void DrawCustomGraph()
{
}

alexwbush
Posts: 327
Joined: Tue Mar 22, 2011 12:45 am
Location: San Diego, CA

Re: JerkyJunky's Starter Screen

Post by alexwbush »

where is the ReefAngel.LCD.DrawCircleOutletBoxHorizontal() function?
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: JerkyJunky's Starter Screen

Post by rimai »

It's not there yet :(
Maybe in the next libraries release
Roberto.
psyrob
Posts: 247
Joined: Thu Sep 01, 2011 8:44 pm

Re: JerkyJunky's Starter Screen

Post by psyrob »

So how does jerkyjunky get the horizontal box on his screen? Did he add the function to the libraries himself, in NokiaLCD?
Image
User avatar
lnevo
Posts: 5430
Joined: Fri Jul 20, 2012 9:42 am

JerkyJunky's Starter Screen

Post by lnevo »

Probably. Its not in his PDE. I know he wasn't shy editing SunLocation for some things he needed.
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: JerkyJunky's Starter Screen

Post by rimai »

It's in the queue of things to be updated and released in next libraries updates.
https://github.com/reefangel/Libraries/issues/56
Roberto.
Post Reply