Sun position calculation library. Adaptation of Hannes Hassler's Helios class.

Dependents:   sunTracker weather_station_proj weather_station_project weather_station_proj_v1_2

Files at this revision

API Documentation at this revision

Comitter:
acracan
Date:
Sun Jun 24 12:10:33 2018 +0000
Commit message:
Adaptation of Hannes Hassler's Helios class

Changed in this revision

Helios.cpp Show annotated file Show diff for this revision Revisions of this file
Helios.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r ad31da30ae64 Helios.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Helios.cpp	Sun Jun 24 12:10:33 2018 +0000
@@ -0,0 +1,182 @@
+/*
+  Helios.cpp-
+  Copyright (c) 2011 Hannes Hassler.  All rights reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+  This library can be used for calculating the solar position on Arduino.
+
+  The algorithm is an adaption from
+  the "PSA" solar positioning algorithm, as documented in:
+
+  Blanco-Muriel et al.: Computing the Solar Vector. Solar Energy Vol 70 No 5 pp 431-441.
+  http://dx.doi.org/10.1016/S0038-092X(00)00156-0
+
+  According to the paper, "The algorithm allows .. the true solar vector
+  to be determined with an accuracy of 0.5
+  minutes of arc for the period 1999–2015.
+  The original code has been downloaded from
+  http://www.psa.es/sdg/sunpos.htm
+
+  Adaptions:
+  Modified calculation of number of Days since 1.Jan 2000 (dJulianDate-2451545.0)
+  Neccessary because of the limited double precision on Arduino
+  (double has the same precision as float on the current Arduino (2011))
+  It should be used only for dates between 1.1.2000 and 31.12.2100
+  (PSA itself has garantueed accuracy only until 2015)
+
+*/
+
+#include "Helios.h"
+#include <math.h>
+#include <mbed.h>
+
+
+Helios::Helios(double latitude, double longitude, int tzOffset)
+{
+    setLocalLatitude(latitude);
+    setLocalLongitude(longitude);
+    setLocalTimeZoneOffset(tzOffset);
+}
+
+
+void Helios::updatePosition()
+{
+    // rtc time
+    time_t rtcTime;
+    struct tm *rtcTimeInfo;
+    
+    double dElapsedJulianDays;
+    double dDecimalHours;
+    double dEclipticLongitude;
+    double dEclipticObliquity;
+    double dRightAscension;
+    double dDeclination;
+
+    double dSin_EclipticLongitude;
+    double dMeanLongitude;
+    double dMeanAnomaly;
+    double dOmega;
+
+    double dGreenwichMeanSiderealTime;
+    double dLocalMeanSiderealTime;
+    
+    double dHourAngle;
+    double dCos_HourAngle;
+    double dParallax;
+    double dZenithAngle;
+    
+    // get current time from RTC
+    time(&rtcTime);
+    rtcTimeInfo = localtime(&rtcTime);
+
+    // Calculate difference in days between the current Julian Day
+    // and JD 2451545.0, which is noon 1 January 2000 Universal Time
+
+    // Calculate time of the day in UT decimal hours
+    dDecimalHours = (rtcTimeInfo->tm_hour - iTzOffset) + (rtcTimeInfo->tm_min
+                    + rtcTimeInfo->tm_sec / 60.0 ) / 60.0;
+
+    // Calculate current Julian Day
+    long int iYfrom2000=rtcTimeInfo->tm_year-100;
+    long int iA=(14-(rtcTimeInfo->tm_mon+1))/12;
+    long int iM=(rtcTimeInfo->tm_mon+1)+12*iA-3;
+    
+    long int liAux3=(153*iM+2)/5;
+    long int liAux4=365*(iYfrom2000-iA);
+    long int liAux5=(iYfrom2000-iA)/4;
+    
+    
+    dElapsedJulianDays=(double)(rtcTimeInfo->tm_mday+liAux3+liAux4+liAux5+59)+
+                        -0.5+dDecimalHours/24.0;
+
+
+    // Calculate ecliptic coordinates (ecliptic longitude and obliquity of the
+    // ecliptic in radians but without limiting the angle to be less than 2*Pi
+    // (i.e., the result may be greater than 2*Pi)
+    dOmega=2.1429-0.0010394594*dElapsedJulianDays;
+    dMeanLongitude = 4.8950630+ 0.017202791698*dElapsedJulianDays; // Radians
+    dMeanAnomaly = 6.2400600+ 0.0172019699*dElapsedJulianDays;
+    dEclipticLongitude = dMeanLongitude + 0.03341607*sin( dMeanAnomaly )
+                         + 0.00034894*sin( 2*dMeanAnomaly )-0.0001134
+                         -0.0000203*sin(dOmega);
+    dEclipticObliquity = 0.4090928 - 6.2140e-9*dElapsedJulianDays
+                         +0.0000396*cos(dOmega);
+
+    // Calculate celestial coordinates ( right ascension and declination ) in radians
+    // but without limiting the angle to be less than 2*Pi (i.e., the result may be
+    // greater than 2*Pi)
+    dSin_EclipticLongitude= sin( dEclipticLongitude );
+    double dY1 = cos( dEclipticObliquity ) * dSin_EclipticLongitude;
+    double dX1 = cos( dEclipticLongitude );
+    dRightAscension = atan2( dY1,dX1 );
+    if( dRightAscension < 0.0 ) dRightAscension = dRightAscension + twopi;
+    dDeclination = asin( sin( dEclipticObliquity )*dSin_EclipticLongitude );
+
+    // Calculate local coordinates ( azimuth and zenith angle ) in degrees
+    dGreenwichMeanSiderealTime = 6.6974243242 +
+                                 0.0657098283*dElapsedJulianDays
+                                 + dDecimalHours;
+
+    dLocalMeanSiderealTime = (dGreenwichMeanSiderealTime*15
+                              + dLongitude)*rad;
+    dHourAngle = dLocalMeanSiderealTime - dRightAscension;
+
+    dCos_HourAngle= cos( dHourAngle );
+    dZenithAngle = (acos( dCos_Latitude*dCos_HourAngle
+                          *cos(dDeclination) + sin( dDeclination )*dSin_Latitude));
+    double dY = -sin( dHourAngle );
+    double dX = tan( dDeclination )*dCos_Latitude - dSin_Latitude*dCos_HourAngle;
+    dAzimuth=atan2( dY, dX );
+    if ( dAzimuth < 0.0 )
+        dAzimuth = dAzimuth + twopi;
+    dAzimuth = dAzimuth/rad;
+    // Parallax Correction
+    dParallax=(dEarthMeanRadius/dAstronomicalUnit)
+              *sin(dZenithAngle);
+    dZenithAngle=(dZenithAngle
+                  + dParallax)/rad;
+    dElevation=90-dZenithAngle;
+}
+
+void Helios::setLocalLatitude(double latitude)
+{
+    double dLatitudeInRadians;
+
+    dLatitude = latitude;
+    dLatitudeInRadians = dLatitude*rad;
+    dCos_Latitude = cos( dLatitudeInRadians );
+    dSin_Latitude = sin( dLatitudeInRadians );
+}
+
+void Helios::setLocalLongitude(double longitude)
+{
+    dLongitude = longitude;
+}
+
+void Helios::setLocalTimeZoneOffset(int tzOffset)
+{
+    iTzOffset = tzOffset;
+}
+
+double Helios::azimuth()
+{
+    return dAzimuth;
+}
+
+double Helios::elevation()
+{
+    return dElevation;
+}
\ No newline at end of file
diff -r 000000000000 -r ad31da30ae64 Helios.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Helios.h	Sun Jun 24 12:10:33 2018 +0000
@@ -0,0 +1,54 @@
+/*
+  Helios.h - Library for calculating the solar
+  position.
+  Copyright (c) 2011 Hannes Hassler.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+#ifndef Helios_h
+#define Helios_h
+
+
+#include <math.h>
+
+// Declaration of some constants
+#define pi    3.14159265358979323846
+#define twopi (2*pi)
+#define rad   (pi/180)
+#define dEarthMeanRadius     6371.01    // In km
+#define dAstronomicalUnit    149597890  // In km
+
+
+class Helios
+{
+public:
+    Helios(double latitude=47.15845, double longitude=27.60144, int tzOffset=0);
+    void updatePosition();
+    void setLocalLatitude(double latitude);
+    void setLocalLongitude(double longitude);
+    void setLocalTimeZoneOffset(int tzOffset);
+    double azimuth();
+    double elevation();
+private:
+    int iTzOffset;
+    double dLongitude;
+    double dLatitude;
+    double dCos_Latitude;
+    double dSin_Latitude;
+
+    double dAzimuth;
+    double dElevation;
+};
+#endif
\ No newline at end of file