Sun position calculator - i'm looking for good code to calculate values

Hello,

I tried few codes of sun position calculator for arduino but each gives me wrong values which not match to values from this webpage:

http://www.esrl.noaa.gov/gmd/grad/solcalc/azel.html

is anybody who can show me the code which calculate good values ?

Greetings !
darrrrek

Have a look for a guy called AMPS-N - he's got a load of posts here on that subject.

I do hope this query has nothing to do with aiming a solar panel at the sun.

...R

Hi, I'm keeping an eye on this post. lol.
[soapbox] [/soapbox]
yep still works..

Tom :slight_smile:

One common mistake when using code to estimate angles and such is that the computer generally does it's trig calculations in radians and us humans think about angles in degrees. Maybe this mistake is not common to the rest of the programming world but for me unfortunately that mistake has been common for me in the last 30 or so years.

This one is the shortest, single precision floating point (yet accurate) algorithm I've been able to find. And yes, it does tell you where to point your solar panel. The date and time have to be UTC, but I added the time zone to help with printing out the local time.

It is not yet incorporated into Arduino-speak! I agree with the above comment that most codes you find should work. If they don't, you are either not using them correctly or did not adapt them properly to the peculiarities of the Arduino environment.

/*
	a simplified, yet accurate sun position calculator
	based on Blanco-Muriel et al.'s SPA algorithm
	closely matches altitude, azimuth values returned by NOAA calculator
	This variation was converted from Javascript
*/
    #include <math.h>
    #include <stdio.h>

   float UTHours=20., UTMinutes=0., UTSeconds=0.;
   float Lat=44., Lon=-123., TZ = -8;
   int year=2014,month=6,day=14;  //UTC date

// accuracy tests... double precision algorithm said to be accurate to 0.5 arcmin (.0083 deg) until 2015
// 2003/1/1 Lat,Lon = (0,0) @12:00 UTC: if double precision get alt=66.9713, az=177.9905, zenith=23.0287
//                       for above NOAA says                        66.98       177.99
// 2023/1/1 (0,0) @12:00 UTC: get 66.9847, 177.9738 NOAA says 66.99 177.97
// local test Eugene OR:
//   float UTHours=20., UTMinutes=0., UTSeconds=0.; //(local  hours - TZ)
//   float Lat=44.052, Lon=-123.087; // (44 3' 7" -123 5' 13") @12:00 local time no DST => 20:00 UT get alt = 68.97 az = 172.14 NOAA sez 68.98 172.12
//   int year=2014,month=6,day=12;  //UTC date

   void get_sun_pos(float latitude, float longitude, float *altitude, float *azimuth){

	float zenith;
	float pi =3.14159265358979323;
	float twopi=(2*pi);
	float rad=(pi/180);
	float EarthMeanRadius=6371.01;	// In km
	float AstronomicalUnit=149597890.;	// In km
	float DecimalHours = UTHours + (UTMinutes + UTSeconds / 60.0 ) / 60.0;
	long liAux1 =(month-14)/12;
	long liAux2=(1461*(year + 4800 + liAux1))/4 + (367*(month - 2-12*liAux1))/12- (3*(year + 4900 + liAux1)/100)/4+day-32075;
	float JulianDate=(liAux2)-0.5+ DecimalHours/24.0;
	float ElapsedJulianDays = JulianDate-2451545.0;
	float Omega=2.1429-0.0010394594*ElapsedJulianDays;
	float MeanLongitude = 4.8950630+ 0.017202791698*ElapsedJulianDays; // Radians
	float MeanAnomaly = 6.2400600+ 0.0172019699*ElapsedJulianDays;
	float EclipticLongitude = MeanLongitude + 0.03341607*sin( MeanAnomaly ) + 0.00034894*sin( 2*MeanAnomaly )-0.0001134 -0.0000203*sin(Omega);
	float EclipticObliquity = 0.4090928 - 6.2140e-9*ElapsedJulianDays +0.0000396*cos(Omega);
	float Sin_EclipticLongitude= sin( EclipticLongitude );
	float Y = cos( EclipticObliquity ) * Sin_EclipticLongitude;
	float X = cos( EclipticLongitude );
	float RightAscension = atan2( Y, X );
	if ( RightAscension < 0.0 ) RightAscension = RightAscension + twopi;
	float Declination = asin( sin( EclipticObliquity )* Sin_EclipticLongitude );
	float GreenwichMeanSiderealTime = 6.6974243242 + 0.0657098283*ElapsedJulianDays + DecimalHours;
	float LocalMeanSiderealTime = (GreenwichMeanSiderealTime*15 + longitude)*rad;
	float HourAngle = LocalMeanSiderealTime - RightAscension;
	float LatitudeInRadians = latitude*rad;
	float Cos_Latitude = cos( LatitudeInRadians );
	float Sin_Latitude = sin( LatitudeInRadians );
	float Cos_HourAngle= cos( HourAngle );
	float UTSunCoordinatesZenithAngle = (acos( Cos_Latitude*Cos_HourAngle*cos(Declination) + sin( Declination )*Sin_Latitude));
	Y = -sin( HourAngle );
	X = tan( Declination )*Cos_Latitude - Sin_Latitude*Cos_HourAngle;
	float UTSunCoordinatesAzimuth = atan2( Y, X );
	if ( UTSunCoordinatesAzimuth < 0.0 )
		UTSunCoordinatesAzimuth = UTSunCoordinatesAzimuth + twopi;
	UTSunCoordinatesAzimuth = UTSunCoordinatesAzimuth/rad;
	float Parallax=(EarthMeanRadius/AstronomicalUnit)*sin(UTSunCoordinatesZenithAngle);
	UTSunCoordinatesZenithAngle=(UTSunCoordinatesZenithAngle + Parallax)/rad;
	*azimuth=UTSunCoordinatesAzimuth;
	zenith=UTSunCoordinatesZenithAngle;
	*altitude=90.-UTSunCoordinatesZenithAngle;
}

int main()
{
    float alt, az;
    get_sun_pos(Lat, Lon, &alt, &az);
    printf("At Lat = %7.2f, Lon = %7.2f \r\n",Lat,Lon);
    printf("UTC Date: %02i/%02i/%4i local time: %2i:%02i \r\n",month,day,year,(int)(UTHours+TZ),(int)UTMinutes);
    printf("Sun altitude = %7.2f, azimuth = %7.2f",alt,az);

    return 0;
}
1 Like

Robin2:
I do hope this query has nothing to do with aiming a solar panel at the sun.

...R

If it is, then that was a good link !

I read the OP twice, went back and forth on if he is looking for a way to calculate his location abased on the sun, or if wanted to use the information of the location.

the cerebral meltdown site has a rather extensive program for tracking with links and references on calculations.
he goes through how to calculate and using that how to create movements.

cerebral meltdown also offers explanations of tracking as well as orientation and calculations of such.
this is not a 'instructables' version !

I've been using the code from Plataforma Solar de Almería - PSA Algorithm Files. It agrees with the NOAA calculator to better than a tenth of a degree.

Pete

Robin2:
I do hope this query has nothing to do with aiming a solar panel at the sun.

He apparently doesn't want to confirm or deny. He may be an astronomer. Standard works on these matters are by Peter Duffet-Smith and Jan Meeus and they should be as easily translatable to Arduino as they are to Commodore 64. I bet somebody has already done it and they are well-known through the astro mafia. Google is likely to find libraries based on them.