Apparently, there is now a "One Hertz Challenge". Not sure exactly how I am going to go about this. Maybe take a Parallax Propeller II module, which is capable of VGA as well as HDMI output, and make a version of the clock that I was talking about. Just in case I don't need trig calls. Just in case I don't need full OpenGL, but also just in case I would like to have a virtual clock face that accurately casts a shadow of the hands on the face of the clock, as if according to the position of the sun in the sky, that is according to the desired Longitude, Lattitude and maybe even current weather.
So, of course, if we are going to do this, we need to calculate the position of the sun in the sky, to a reasonable approximation, at least once per second, right? How hard can that be? Maybe not all that hard at all if we assume a circular orbit, ignore atmospheric effects, leap seconds, precession of the equinoxes, etc.
#include "stdafx.h"
#include <ATLComTime.h>
#include <math.h>
#include "../rubidium/defines.h" #include "../rubidium/drawstuff.h"
#define INCLINATION_OF_EARTH_ORBIT 23.439281
using namespace TENSORS;
class celestial_coordinates
{
public:
MATH_TYPE right_ascension;
MATH_TYPE declination;
};
solar_elements::solar_elements ()
{
COleDateTime _dt = COleDateTime::GetCurrentTime();
m_year = _dt.GetYear ();
m_month = _dt.GetMonth ();
m_day = _dt.GetDay ();
m_hour = _dt.GetHour ();
m_minute = _dt.GetMinute ();
m_second = _dt.GetSecond ();
m_longitude = 119.81;
m_latitude = 39.53;
m_time_zone = -8;
m_daylight_savings = 0; R = 3958.8*5280.0*FEET_TO_CM*1.0e-5;
m_ROTX = tensor::rotate_x (TO_RADIANS(INCLINATION_OF_EARTH_ORBIT));
}
void solar_elements::debug_test ()
{
ASSERT (julian_day (1,1,2000)==2451545);
ASSERT (julian_day (6,19,1987)==2446966);
ASSERT (julian_day (12,8,2009)==2455174);
int H,M;
for (H=0;H<24;H++)
for (M=0;M<60;M+=10)
{ m_hour = H;
m_minute = M;
compute_local_aspect();
// TRACE ("SOLAR time = %02d:%02d AZIMUTH = %f, EL = %f\n",H,M,m_az,m_el);
}
}
double solar_elements::julian_day (int M, MATH_TYPE D, int Y)
{
int mm = (M-14)/12;
int yy = (Y+4800+mm);
int JDN1 = (1461*yy)/4;
int JDN2 = (367*(M-2-12*mm))/12;
int JDN3 = (3*((yy+100)/100))/4;
MATH_TYPE JDN = JDN1+JDN2-JDN3+D-32075;
return JDN;
}
void solar_elements::compute_local_aspect()
{
MATH_TYPE solar_time, ra_base, ecliptic_aspect;
// estimate ecliptic aspect
m_gmt_seconds = 3600.0*(m_hour-m_daylight_savings-m_time_zone)+60.0*m_minute+m_second;
solar_time = m_gmt_seconds/3600.0 - m_longitude/15.0;
m_julian = julian_day (m_month,m_day,m_year) - julian_day (3,20,1900) + solar_time/24.0;
ra_base = fmodf(m_julian,365.242191)/(360.0/24.0);
ecliptic_aspect = ra_base*TWO_PI/24.0;
tensor SIDT = tensor::rotate_z ((solar_time-ra_base)*TWO_PI/24.0);
_vector ecliptic_aspect_vector = tensor::rotate_z (ecliptic_aspect)*_vector(1,0,0);
m_geocentric_solar_vector = m_ROTX*ecliptic_aspect_vector;
_vector siderial_solar_vector = SIDT*m_geocentric_solar_vector;
_vector local_xyz;
polar_orientation p;
p.m_theta = 0;
p.m_phi = TO_RADIANS(m_latitude);
local_xyz = p.get_xyz ();
tensor ROTL = tensor::rotator( _vector::normalize (local_xyz.cross(_vector(0,0,1)) ), p.m_phi-PI_OVER_TWO );
_vector local_solar_vector = ROTL*siderial_solar_vector;
polar_orientation q = polar_orientation::from_axis (local_solar_vector);
m_el = TO_DEGREES(q.m_phi);
m_az = fmodf(360+TO_DEGREES(q.m_theta),360);
}
To figure out how this works, you will need some kind of tensor library, which for now, I leave up to the user to provide.
glgorman
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.