Got my controller,

New members questions
User avatar
Posts: 5420
Joined: Fri Jul 20, 2012 9:42 am
PostPosted: Thu Aug 09, 2012 7:14 pm
Woohoo! Got my controller hooked up to the Mac (no issues communicating!!) got the wifi module configured thru serial (Wifi Utility didn't do anything...) Connected to controller and tested through web. Port forwarding configured and working! iOS app working... Just have to configure portal now...but first, have to load some code!!!

The git commenting Doxygen step will now take a short intermission...maybe back to it later tonight or this weekend. Let the fun begin!!!

Thanks Roberto, package came nicely packed and everything looks great!!
User avatar
Posts: 5420
Joined: Fri Jul 20, 2012 9:42 am
PostPosted: Thu Aug 09, 2012 10:59 pm
So here's what I got after my first night of coding... let me know what you think.

Next up is to customize the menu and main screens to show the MoonPhase and Vortech Mode. Anyone have any input on changing the vortech mode through a custom menu? I saw the thread detailing this, but wasn't sure how that code ever ended up working...

Also need to see about working with the Sunrise/Sunset stuff I wanted to work on. But at least the controller is currently usable and ready to be connected up. Will probably code a few more features before making the swap.

Feedback is more than 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 <ReefAngel.h>

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

byte vtechmode;
boolean bFeeding=false;
boolean isNight=false;

//*********************************************************************************************************************************
//Define Relay Ports
#define Return             1
#define Skimmer            2
#define WhiteLEDs          3
#define BlueLEDs           4
#define Vortech            5
#define Heater             6
#define Refugium           7
#define UPS                8
//*********************************************************************************************************************************

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


void setup()
{
    // This must be the first line
    ReefAngel.Init();  //Initialize controller
    // Ports toggled in Feeding Mode
    ReefAngel.FeedingModePorts = 0;
    // Ports toggled in Water Change Mode
    ReefAngel.WaterChangePorts = Port1Bit | Port2Bit;
    // Ports toggled when Lights On / Off menu entry selected
    ReefAngel.LightsOnPorts = Port4Bit | Port7Bit ;
    // Ports turned off when Overheat temperature exceeded
    ReefAngel.OverheatShutoffPorts = Port6Bit;
    // Use T1 probe as temperature and overheat functions
    ReefAngel.TempProbe = T1_PROBE;
    ReefAngel.OverheatProbe = T1_PROBE;
    // Set the Overheat temperature setting
    InternalMemory.OverheatTemp_write( 869 );


    // Ports that are always on
    ReefAngel.Relay.On( Return );
    ReefAngel.Relay.On( UPS );
   
    ////// Place additional initialization code below here
   

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

void loop()
{
    ReefAngel.Relay.DelayedOn( Vortech,5 );
    ReefAngel.Relay.DelayedOn( Skimmer,5 );
    ReefAngel.StandardLights( WhiteLEDs,12,0,20,0 );
    ReefAngel.StandardLights( BlueLEDs,11,0,23,0 );
    ReefAngel.StandardHeater( Heater,788,792 );
   
    ////// Place your custom code below here
   
    if (( hour() <= 11 ) || ( hour() >= 23 ))
    {
      isNight=true;
    } else {
      isNight=false;
    }
   
    if (ReefAngel.DisplayedMenu==FEEDING_MODE) bFeeding=true;
    if (ReefAngel.DisplayedMenu==DEFAULT_MENU && bFeeding )
    {
      bFeeding=false;
      ReefAngel.RF.UseMemory=false;
      ReefAngel.RF.SetMode(Smart_NTM,155,5);
      ReefAngel.Timer[4].SetInterval(1800); // Timer for 30min
      ReefAngel.Timer[4].Start();
      vtechmode = 5;
    }
   
    if (ReefAngel.DisplayedMenu==DEFAULT_MENU && ReefAngel.Timer[4].IsTriggered())
    {
      if (isNight)
      {
        ReefAngel.RF.UseMemory=false;
        ReefAngel.RF.SetMode(Night,15,0);
        vtechmode = 9;
      } else {
        ReefAngel.RF.UseMemory=true;
        vtechmode = InternalMemory.RFMode_read();
      }
    }
   
    if (isNight)
    {
      ReefAngel.PWM.SetDaylight( MoonPhase() );
      ReefAngel.PWM.SetActinic( MoonPhase() );
      ReefAngel.Relay.On( Refugium );
    } else {
      ReefAngel.PWM.SetDaylight( 0 );
      ReefAngel.PWM.SetActinic( 0 );
      ReefAngel.Relay.Off( Refugium );
    }   
   
    ////// Place your custom code above here

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


Posts: 12519
Joined: Fri Mar 18, 2011 6:47 pm
PostPosted: Fri Aug 10, 2012 8:06 am
Nice job!!! :)
The easiest way of changing modes using the custom menu is by cycling modes everytime you choose that menu, then go to memory mode as the last choice.
Roberto.
User avatar
Posts: 5420
Joined: Fri Jul 20, 2012 9:42 am
PostPosted: Sat Aug 11, 2012 8:28 pm
If I did that, how do I prevent my loop() from reverting it back to memory mode? Also how do I set the default memory mode?

Posts: 12519
Joined: Fri Mar 18, 2011 6:47 pm
PostPosted: Sat Aug 11, 2012 8:55 pm
To prevent it from going back to memory mode, just use this:
Code: Select all
ReefAngel.RF.UseMemory=false;

It will simply ignore whatever is in the memory setting.

To change the memory setting, there are several ways:
Java status app
Android app
Portal
Built-in webserver
Roberto.
User avatar
Posts: 5420
Joined: Fri Jul 20, 2012 9:42 am
PostPosted: Sun Aug 12, 2012 5:16 am
Nevermind, re-reading my code, I only go back to memory mode if the timer is trigged. But can I set the default memory mode in my setup()? and change later through the apps?

Posts: 12519
Joined: Fri Mar 18, 2011 6:47 pm
PostPosted: Sun Aug 12, 2012 7:10 am
Yes.
Code: Select all
  InternalMemory.RFMode_write(3);
  InternalMemory.RFSpeed_write(50);
  InternalMemory.RFDuration_write(10);
Roberto.
User avatar
Posts: 5420
Joined: Fri Jul 20, 2012 9:42 am
PostPosted: Sun Aug 12, 2012 9:20 pm
Ok, here is my current code...

I still haven't sync'd up my Vortech yet, but now that I have the laptop able to upload code, I can work on that. Also should have pH calibration fluid in the LFS by Wednesday... I still have to setup the Vortech control menu so I can play with it from the controller. (Do the mode buttons still work on the unit itself after it's sync'd?) The moonlights are hooked up and look sweet! They are really low, even on 100% which is perfect.. I just want a touch of light when everything is off so it's not so dark... Right now we're at 20% and it gives a nice glimmer. Too bad I can't get a good photo.

Anyway, does anyone have a good code to add the Vortech controls? I want to preserve most of the Simple_Menu and have to start playing around with that.

I've also added the Sunrise / Sunset, but my string writing seems a bit messed up. I think the calculations are good, but without seeing the results, it's hard to tell. It seemed about an hour off from the Utah given as the example, so I really need some time to troubleshoot. I've got the base code stripped of all weather and dimming functions, so it's pretty basic. If someone can take a look and give me another set of eyes would be great!

Anyway, here it is...sorry to be soo long winded..

Code: Select all
//By Matthew Hockin 2012. 
//SWFLTEK library functions, #includes, and #define were copied directly from the Epherma library
//Epherma (SWFLTEK.com) was written by Michael Rice- thanks Michael it works great.
//If you copy from this (its all open source) please
//acknowledge Michael for SWFLTEK library code (obviously labeled) or Matthew Hockin (for the rest).

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

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

//includes for SWFLTEK functions
#include <stdlib.h>
#include <math.h>

//defines for SWFLTEK functions
#define _sec_rad 206264.806247096370813 // arc-seconds per radian
#define _tilt 0.409092804222329 // axial tilt of earth at epoch, in radians
#define _tropical_year 31556925 // tropical year in seconds... rounding error accumulates to 26 seconds by the year 2136
#define _zenith 3.11250383272322 // 'zenith' of rising (setting) sun in radians (360 - 2 * 90.833 degrees)

//*******************GLOBAL VARIABLE DECLERATIONS FOR MHOCKIN Weather package*************************************
long latitude, longitude;
long elapsedTime;//used multiple places as elapsed since midnight
long newDay;
unsigned long rise;//time in seconds from the year 2000 (GMT) for sunrise
unsigned long set;//time in seconds from the year 2000 (GMT) for sunrise
int SunriseHour, SunriseMin, SunsetHour, SunsetMin;
byte dow=0;//day of week
//END HEADER FOR MHOCKIN Weather package //

#define NUMBERS_8x16
byte vtechmode;
boolean bFeeding=false;
boolean isNight=false;
double MoonAge(int,int,int);
int JulianDate(int,int,int);
byte MoonState();
byte ThisPhase;
byte DayAge;


//*********************************************************************************************************************************
//Define Relay Ports
#define Return             1
#define Skimmer            2
#define WhiteLEDs          3
#define BlueLEDs           4
#define Vortech            5
#define Heater             6
#define Refugium           7
#define UPS                8
//*********************************************************************************************************************************

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

void DrawCustomMain()
{
  char text[7];
  byte x = 5;
  byte y = 2;
  byte t;

  // Main Header
  ReefAngel.LCD.DrawText(DefaultFGColor, DefaultBGColor, 35, y,"Lee's Reef");
  ReefAngel.LCD.Clear(COLOR_BLACK, 1, y+9, 128, y+9);
 
  // Param Header
  y=y+20;
  ReefAngel.LCD.DrawText(T1TempColor,DefaultBGColor,x+5,y,"Temp:");
  ReefAngel.LCD.DrawText(PHColor,DefaultBGColor,x+60, y, "PH:");

  // Temp and PH
  y=y+10;
  ReefAngel.LCD.Clear(DefaultBGColor,x,y,x+(128-x),y+16);
  ConvertNumToString(text, ReefAngel.Params.Temp[T1_PROBE], 10);
  ReefAngel.LCD.DrawLargeText(T1TempColor, DefaultBGColor, x+5, y, text, Num8x16);
  ConvertNumToString(text, ReefAngel.Params.PH, 100);
  ReefAngel.LCD.DrawLargeText(PHColor, DefaultBGColor, x+60, y, text, Num8x16);
  pingSerial();
 
  y=y+20;
  /*
  /// Display Sunrise / Sunset (to be calculated later...)
  char riseTime[5];
  char setTime[5];
  char temp[]="  ";
 
  itoa(SunriseHour,temp,10);
  strcat(riseTime, temp);
  strcat(riseTime, ":");
  itoa(SunriseMin,temp,10);
  strcat(riseTime, temp);
 
  itoa(SunsetHour,temp,10);
  strcat(setTime, temp);
  strcat(setTime, ":");
  itoa(SunsetMin,temp,10);
  strcat(setTime, temp);
 
  ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,x,y,"Rise:");
  ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,x+32,y,riseTime);
  ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,x+70,y,"Set:");
  ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,x+98,y,setTime);
  */
  // MoonLight %
  y=y+10; 
  t = intlength(ReefAngel.PWM.GetDaylightValue()) + 1;  t *= 5;
  ReefAngel.LCD.DrawText(COLOR_BLACK,DefaultBGColor,x,y,"MoonLight:");
  ReefAngel.LCD.DrawSingleMonitor(ReefAngel.PWM.GetDaylightValue(), DPColor, x+63, y, 1);
  ReefAngel.LCD.DrawText(DPColor, DefaultBGColor, x+63+t, y, "%");
  pingSerial();
 
  // MoonPhase
  y=y+10;
  DayAge = MoonAge(day(), month(), year());
  MoonState(DayAge);
  char* ThisPhaseLabel[]={ "New","Waxing Crescent","First Quarter","Waxing Gibbous","Full","Waning Gibbous","Last Quarter","Waning Crescent" };
  ReefAngel.LCD.DrawText(0,255,x,y,"Moon:");
  ReefAngel.LCD.Clear(DefaultBGColor,x+32,y,x+(128-x),y+8);
  ReefAngel.LCD.DrawText(COLOR_CORNFLOWERBLUE,255,x+32,y,ThisPhaseLabel[ThisPhase]);
  pingSerial();
 
  // Vortech Mode
  y=y+10;
  ReefAngel.LCD.DrawText(0,255,x,y,"RF:");
  ReefAngel.LCD.Clear(DefaultBGColor,x+20,y,x+(128-x),y+8);
  if (vtechmode == 0) ReefAngel.LCD.DrawText(COLOR_LIMEGREEN,255,x+20,y,"Constant");
  else if(vtechmode == 1) ReefAngel.LCD.DrawText(COLOR_GOLD,255,x+20,y,"Lagoon");
  else if (vtechmode == 2) ReefAngel.LCD.DrawText(COLOR_GOLD,255,x+20,y,"Reef Crest");
  else if (vtechmode == 3) ReefAngel.LCD.DrawText(COLOR_CORNFLOWERBLUE,255,x+20,y,"Short Pulse");
  else if (vtechmode == 4) ReefAngel.LCD.DrawText(COLOR_PINK,255,x+20,y,"Long Pulse");
  else if (vtechmode == 5) ReefAngel.LCD.DrawText(COLOR_MAGENTA,255,x+20,y,"Nutrient");
  else if (vtechmode == 6) ReefAngel.LCD.DrawText(COLOR_MAGENTA,255,x+2,y,"Tidal Swell");
  else if (vtechmode == 9) ReefAngel.LCD.DrawText(COLOR_WHITE,0,x+20,y,"Night");
  pingSerial();
 
  // Relays
  byte TempRelay = ReefAngel.Relay.RelayData;
  TempRelay &= ReefAngel.Relay.RelayMaskOff;
  TempRelay |= ReefAngel.Relay.RelayMaskOn;
  ReefAngel.LCD.DrawOutletBox(12, 103, TempRelay);
  pingSerial();
 
  // Date+Time
  ReefAngel.LCD.DrawDate(6, 122);
  pingSerial();
}

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


void setup()
{
    // This must be the first line
    ReefAngel.Init();  //Initialize controller
    // Ports toggled in Feeding Mode
    ReefAngel.FeedingModePorts = 0;
    // Ports toggled in Water Change Mode
    ReefAngel.WaterChangePorts = Port1Bit | Port2Bit;
    // Ports toggled when Lights On / Off menu entry selected
    ReefAngel.LightsOnPorts = Port4Bit | Port7Bit ;
    // Ports turned off when Overheat temperature exceeded
    ReefAngel.OverheatShutoffPorts = Port6Bit;
    // 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( Return );
    ReefAngel.Relay.On( Vortech );
    ReefAngel.Relay.On( UPS );
   
    ////// Place additional initialization code below here
   

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

void loop()
{
    // Set Sunrise and Sunset from MHOCKIN Weather package functions.
    elapsedTime=(now()-newDay);  //Elapsed time is seconds from midnight of today- local processor time.
    if (dow!=day()){ //used to see that were in a new day and need to recalculate sunrise and sunset
      CalSun();
      dow=day();
    }

    ReefAngel.Relay.DelayedOn( Skimmer,5 );
    ReefAngel.StandardLights( WhiteLEDs,12,0,20,0 );
    ReefAngel.StandardLights( BlueLEDs,11,0,23,0 );
    ReefAngel.StandardHeater( Heater,788,792 );
   
    ////// Place your custom code below here
   
    if (( hour() <= 11 ) || ( hour() >= 23 )) isNight=true; else isNight=false;
   
    if (ReefAngel.DisplayedMenu==FEEDING_MODE) bFeeding=true;
    if (ReefAngel.DisplayedMenu==DEFAULT_MENU && bFeeding )
    {
      bFeeding=false;
      ReefAngel.RF.UseMemory=false;
      ReefAngel.RF.SetMode(Smart_NTM,155,5);
      ReefAngel.Timer[4].SetInterval(1800); // Timer for 30min
      ReefAngel.Timer[4].Start();
      vtechmode = 5;
    }
   
    if (ReefAngel.DisplayedMenu==DEFAULT_MENU && ReefAngel.Timer[4].IsTriggered())
    {
      if (isNight)
      {
        ReefAngel.RF.UseMemory=false;
        ReefAngel.RF.SetMode(Night,15,0);
        vtechmode = 9;
      } else {
        ReefAngel.RF.UseMemory=true;
        vtechmode = InternalMemory.RFMode_read();
      }
    }
   
    if (isNight)
    {
      ReefAngel.PWM.SetDaylight( MoonPhase() );
      ReefAngel.PWM.SetActinic( MoonPhase() );
      ReefAngel.Relay.On( Refugium );
    } else {
      ReefAngel.PWM.SetDaylight( 0 );
      ReefAngel.PWM.SetActinic( 0 );
      ReefAngel.Relay.Off( Refugium );
    }   
   
    ////// Place your custom code above here

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

int JulianDate(int d, int m, int y)
{
  int mm, yy;
  int k1, k2, k3;
  int j;

  yy = y - (int)((12 - m) / 10);
  mm = m + 9;
  if (mm >= 12)
  {
    mm = mm - 12;
  }
  k1 = (int)(365.25 * (yy + 4712));
  k2 = (int)(30.6001 * mm + 0.5);
  k3 = (int)((int)((yy / 100) + 49) * 0.75) - 38;
  // 'j' for dates in Julian calendar:
  j = k1 + k2 + d + 59;
  if (j > 2299160)
  {
    // For Gregorian calendar:
    j = j - k3; // 'j' is the Julian date at 12h UT (Universal Time)
  }
  return j;
}

double MoonAge(int d, int m, int y)
{
  int j = JulianDate(d, m, y);
  //Calculate the approximate phase of the moon
  int ip = (j + 4.867) / 29.53059;
  ip = ip - abs(ip);
  //After several trials I've seen to add the following lines,
  //which gave the result was not bad
  if(ip < 0.5)
    int ag = ip * 29.53059 + 29.53059 / 2;
  else
    int ag = ip * 29.53059 - 29.53059 / 2;
  // Moon's age in days
  byte ag = abs(ag) + 1;
  return ag;
}

byte MoonState(byte D)
{
  switch(D){
  case 1:
    0, 29;
    ThisPhase = 0;
  case 2:
    1, 2, 3, 4, 5, 6;
    ThisPhase = 1;
  case 3:
    7;
    ThisPhase = 2;
  case 4:
    8, 9, 10, 11, 12, 13;
    ThisPhase = 3;
  case 5:
    14;
    ThisPhase = 4;
  case 6:
    15, 16, 17, 18, 19, 20, 21;
    ThisPhase = 5;
  case 7:
    22;
    ThisPhase = 6;
  case 8:
    23, 24, 25, 26, 27, 28;
    ThisPhase = 7;
  default:
    return 0;
  }
}

//Start of sunrise, sunset and cloud calculations- runs on reset and once a day thereafter.
void CalSun(){
   //Serial.println("CalSun Run Now");

       latitude=dmsToSeconds(40,44,00);//United States of America- Salt Lake City, local time is -7 hours GMT
       longitude=dmsToSeconds(-111,47,00);
       //**********************ok now were done changing things IF YOU CHANGED the Top part of the GLOBAL variable decleration AND this... your FULLY configured and ready to load********************************************
   
    if (dow==0){//if the controller has resarted we need to find midnight
      long hours, minutes;//store current elapsed local hours as total seconds from midnight
      time_t t=now();//store current clock time to parse
      hours=hour(t);
      hours=(hours*3600);//current hour number 0-23 as seconds
      minutes=minute(t);
      minutes=(minutes*60);//minutes of current hour as seconds
      newDay=now();
      newDay-=(hours+minutes);//Convert current local unix epoch time to local unix epoch time of midnight
    }
    else if (dow!=0){//if we did not restart but the day is new then it is midnight and were good to go..
      newDay=now();
    }
     
    //#define SECS_YR_2000 (946684800) the time at the start of y2k (need to subtract from unix epoch time to bring to Y2K origin
    newDay-=946684800;//convert GMT unix Epoch to seconds elasped since 2000 for GMT midnight of today
   
    rise=newDay;//set value to send to SunRise as midnight GMT in seconds from Y2K
    set=newDay;//
    //Calculate rise time and set time using Epherma Library functions (see end of code)
    SunRise(&rise);//call to Epherma function
    SunSet(&set);//Call to Epherma functionunsigned long newDay;
 
   /*Serial.print("rise and set=  ");
   Serial.println(rise);
   Serial.println(set);
   Serial.print("newDay as seconds since 2000 to todays midnight=  ");
   Serial.println(newDay);*/
   rise=(rise-newDay);// set to elapsed seconds of day
   set=(set-newDay);
   /*Serial.print("rise and set as elapsed seconds of day=  ");
   Serial.println(rise);
   Serial.println(set);*/
   newDay+=946684800;//Convert newDay back to unix epoch GMT midnight today (used in loop to determine how far we are into the day)
   /*Serial.print("newDay as seconds since since 1970 to todays midnight=  ");
   Serial.println(newDay);
   Serial.print("elapsed is");
   long elapsed=now()-newDay;
   Serial.println(elapsed);*/
   SunriseHour=hour(rise);
   SunriseMin=minute(rise);
   SunsetHour=hour(set);
   SunsetMin=minute(set);
 }//END SunCalc FUNCTION

//********************** DO NOT MESS WITH THIS UNLESS YOU KNOW WHAT YOUR DOING****************************
//THE CODE BELOW THIS copied directly from the SWFLTEK Epherma library constructed by Michael Rice. 
//this code is being used freely with attribution to Micahel Rice in accord with his request
//  A big thank you for these library functions.  Its great!

// decimal degrees
long ddToSeconds(float dd){
   return dd * 3600.0;
}

//Degrees, minutes, seconds
long dmsToSeconds(int d, unsigned char m, unsigned char s){
long ret;

   ret = labs((long)d);
   ret = ret * 3600L + 60L * m + s;
   ret = (d<0L) ? -ret : ret;
   return ret;
}
/* ------------------------------------------------------------------------------------------------
   'Equation of Time'
   We use the 'short form equation, which has a theoretical accuracy of about 40 seconds.
   The returned value is in seconds.
*/
int equation_of_time(unsigned long dt){
double t;

   dt -= 192540UL; // refer to Jan 3 2000 05:29 (first periapsis)
   dt %= _tropical_year;
   t = dt;
   t /= _tropical_year;
   t *= 6.283185307179586;
   t = -459.27672 * sin(t) + 575.333472 * sin(2.0 * t + 3.588414);
   return t;
}


/* -----------------------------------------------------------------------------------------------
   'Solar Declination'
   Returns declination in radians
   Accurate to within 50 arc-seconds
*/

double SolarDeclination(unsigned long dt){
double y;

   dt %= _tropical_year;
   y = dt;
   y /= _tropical_year; // fractional year
   y *= 6.283185307179586;
   y=0.006918-0.399912*cos(y)+0.070257*sin(y)-0.006758*cos(y*2)+0.000907*sin(y*2)-0.002697*cos(y*3)+0.00148*sin(y*3);
   return y;
}

/* ------------------------------------------------------------------------------------------------
   Return the period between sunrise and sunset, in seconds.
   At high latitudes around the time of the solstices, this could be zero, or all day.
*/
unsigned long daylightseconds(unsigned long dt){
float l, d, e;
long n;

   d = -SolarDeclination(dt); // will be positive in Northern winter
   l = latitude / _sec_rad; // latitude in radians

   e += 60.0 * l * tan(l + d); // latitudinal error
   d = tan(l) * tan(d); //

   if(d>1.0) return 86400UL;
   if(d < -1.0) return 0UL;

   d = acos(d);
   d /= _zenith;

   n = 86400UL * d;
   n += e;
   return n;
}


/* ------------------------------------------------------------------------------------------------
   Modify the passed time stamp to the time of sunrise (or sunset if 'set' is non-zero).
   Returns 0 to signal 'normal' completion. If the position is in a polar circle, 1 will be
   returned if the sun is above the horizon all day, and -1 if the sun is below the horizon
   all day.

*/
char SunRiseSet(unsigned long * dt, char set){
unsigned long daylen;

   daylen = daylightseconds(*dt);
   if(daylen == 86400UL) return 1;   // there is no 'night' today (midnight sun)
   if(daylen == 0UL) return -1; // there is no 'day' today

   *dt /= 86400UL;
   *dt *= 86400UL;
   *dt += 43200UL; // set the time stamp to 12:00:00 GMT

   *dt -= daylen / 2; //        sunrise at the prime meridian
   if(set) *dt += daylen; //     sunset at the prime meridian

   *dt -= equation_of_time(*dt);

   //*dt -= longitude / 15.0; // rotate to our own meridian

   return 0;
}

// 'short' forms of SunRiseSet
char SunRise(unsigned long* when){
    return SunRiseSet(when, 0);
}
char SunSet(unsigned long* when){
    return SunRiseSet(when, 1);
}
User avatar
Posts: 5420
Joined: Fri Jul 20, 2012 9:42 am
PostPosted: Mon Aug 13, 2012 9:56 pm
Ok roberto, I've made some progress. I have the custom menu cycling through my vortech modes. The only issue I have at the moment is the logic I'm doing for my scheduling...

I wanted to be able to override night mode to go into feed mode, so I've got that working, but I'd also like to be able to change the pumps if I'm in night mode as well. I've put a wrapper around the menu code so that it wouldn't change the screen if I'm set to not use memory.

Can you just look at my scheduling code and let me know if there's a better way? I should probably just simplify it since I probably shouldn't change my vortech or feed after lights out... but I want FULL control :)

Thanks,
Lee

Code is already posted in the thread below, so don't want to duplicate.

viewtopic.php?p=12941#p12941

Posts: 12519
Joined: Fri Mar 18, 2011 6:47 pm
PostPosted: Mon Aug 13, 2012 10:05 pm
Looks awesome!!
I think the only thing you may have problems is to come out of night mode.
Let me know if this is the case.
Roberto.
Next

Return to For New Members

Who is online

Users browsing this forum: No registered users and 5 guests

cron