Close

Life in the Slow Lane - or else Here Comes the Sun?

A project log for Does Anyone Really Know What Time It is?

If you havent noticed, the clock in the Windows Taskbar has gone missing. Will it ever return?

glgormanglgorman 07/02/2025 at 07:540 Comments

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.

Discussions