This program uses the "PSA" solar positioning algorithm calculating the sun position, based on longitude, latitude, and time zone. Then Mbed chip controls the two digital servos to rotate the solar panel to the correct azimuth and zenith angle.

Dependencies:   4DGL-uLCD-SE AX12 NetServices mbed spxml

Fork of AX12-HelloWorld by Chris Styles

Committer:
conantina
Date:
Mon Apr 25 17:28:13 2016 +0000
Revision:
2:2a3493799f03
n

Who changed what in which revision?

UserRevisionLine numberNew contents of line
conantina 2:2a3493799f03 1 /*
conantina 2:2a3493799f03 2 Helios.cpp-
conantina 2:2a3493799f03 3 Copyright (c) 2011 Hannes Hassler. All rights reserved.
conantina 2:2a3493799f03 4
conantina 2:2a3493799f03 5 This library is free software; you can redistribute it and/or
conantina 2:2a3493799f03 6 modify it under the terms of the GNU Lesser General Public
conantina 2:2a3493799f03 7 License as published by the Free Software Foundation; either
conantina 2:2a3493799f03 8 version 2.1 of the License, or (at your option) any later version.
conantina 2:2a3493799f03 9
conantina 2:2a3493799f03 10 This library is distributed in the hope that it will be useful,
conantina 2:2a3493799f03 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
conantina 2:2a3493799f03 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
conantina 2:2a3493799f03 13 Lesser General Public License for more details.
conantina 2:2a3493799f03 14
conantina 2:2a3493799f03 15 You should have received a copy of the GNU Lesser General Public
conantina 2:2a3493799f03 16 License along with this library; if not, write to the Free Software
conantina 2:2a3493799f03 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
conantina 2:2a3493799f03 18
conantina 2:2a3493799f03 19 This library can be used for calculating the solar position on Arduino.
conantina 2:2a3493799f03 20
conantina 2:2a3493799f03 21 The algorithm is an adaption from
conantina 2:2a3493799f03 22 the "PSA" solar positioning algorithm, as documented in:
conantina 2:2a3493799f03 23
conantina 2:2a3493799f03 24 Blanco-Muriel et al.: Computing the Solar Vector. Solar Energy Vol 70 No 5 pp 431-441.
conantina 2:2a3493799f03 25 http://dx.doi.org/10.1016/S0038-092X(00)00156-0
conantina 2:2a3493799f03 26
conantina 2:2a3493799f03 27 According to the paper, "The algorithm allows .. the true solar vector
conantina 2:2a3493799f03 28 to be determined with an accuracy of 0.5
conantina 2:2a3493799f03 29 minutes of arc for the period 1999–2015.
conantina 2:2a3493799f03 30 The original code has been downloaded from
conantina 2:2a3493799f03 31 http://www.psa.es/sdg/sunpos.htm
conantina 2:2a3493799f03 32
conantina 2:2a3493799f03 33 Adaptions:
conantina 2:2a3493799f03 34 Modified calculation of number of Days since 1.Jan 2000 (dJulianDate-2451545.0)
conantina 2:2a3493799f03 35 Neccessary because of the limited double precision on Arduino
conantina 2:2a3493799f03 36 (double has the same precision as float on the current Arduino (2011))
conantina 2:2a3493799f03 37 It should be used only for dates between 1.1.2000 and 31.12.2100
conantina 2:2a3493799f03 38 (PSA itself has garantueed accuracy only until 2015)
conantina 2:2a3493799f03 39
conantina 2:2a3493799f03 40 */
conantina 2:2a3493799f03 41
conantina 2:2a3493799f03 42 #include "Helios.h"
conantina 2:2a3493799f03 43 #include <math.h>
conantina 2:2a3493799f03 44
conantina 2:2a3493799f03 45
conantina 2:2a3493799f03 46 Helios::Helios(){}
conantina 2:2a3493799f03 47
conantina 2:2a3493799f03 48
conantina 2:2a3493799f03 49 void Helios::calcSunPos(
conantina 2:2a3493799f03 50 int iYear,
conantina 2:2a3493799f03 51 int iMonth,
conantina 2:2a3493799f03 52 int iDay,
conantina 2:2a3493799f03 53 double dHours,
conantina 2:2a3493799f03 54 double dMinutes,
conantina 2:2a3493799f03 55 double dSeconds,
conantina 2:2a3493799f03 56 double dLongitude,
conantina 2:2a3493799f03 57 double dLatitude)
conantina 2:2a3493799f03 58 {
conantina 2:2a3493799f03 59
conantina 2:2a3493799f03 60
conantina 2:2a3493799f03 61 // Calculate difference in days between the current Julian Day
conantina 2:2a3493799f03 62 // and JD 2451545.0, which is noon 1 January 2000 Universal Time
conantina 2:2a3493799f03 63 {
conantina 2:2a3493799f03 64
conantina 2:2a3493799f03 65 //double dJulianDate;
conantina 2:2a3493799f03 66 //long int liAux1;
conantina 2:2a3493799f03 67 //long int liAux2;
conantina 2:2a3493799f03 68 // Calculate time of the day in UT decimal hours
conantina 2:2a3493799f03 69 dDecimalHours = dHours + (dMinutes
conantina 2:2a3493799f03 70 + dSeconds / 60.0 ) / 60.0;
conantina 2:2a3493799f03 71
conantina 2:2a3493799f03 72 // Calculate current Julian Day
conantina 2:2a3493799f03 73 /* original calculation; does not work
conantina 2:2a3493799f03 74 for Arduino, because double precision is the same
conantina 2:2a3493799f03 75 same as float.
conantina 2:2a3493799f03 76 liAux1 =(iMonth-14)/12;
conantina 2:2a3493799f03 77 liAux2=(1461*(iYear + 4800 + liAux1))/4 + (367*(iMonth
conantina 2:2a3493799f03 78 - 2-12*liAux1))/12- (3*((iYear + 4900
conantina 2:2a3493799f03 79 + liAux1)/100))/4+iDay-32075;
conantina 2:2a3493799f03 80 dJulianDate=(double)(liAux2)-0.5+dDecimalHours/24.0;
conantina 2:2a3493799f03 81 // Calculate difference between current Julian Day and JD 2451545.0
conantina 2:2a3493799f03 82 dElapsedJulianDays = dJulianDate-2451545.0;
conantina 2:2a3493799f03 83 */
conantina 2:2a3493799f03 84
conantina 2:2a3493799f03 85 long int iYfrom2000=iYear-2000;
conantina 2:2a3493799f03 86 long int iA=(14-(iMonth))/12;
conantina 2:2a3493799f03 87 long int iM=(iMonth)+12*iA-3;
conantina 2:2a3493799f03 88
conantina 2:2a3493799f03 89 long int liAux3=(153*iM+2)/5;
conantina 2:2a3493799f03 90 long int liAux4=365*(iYfrom2000-iA);
conantina 2:2a3493799f03 91 long int liAux5=(iYfrom2000-iA)/4;
conantina 2:2a3493799f03 92
conantina 2:2a3493799f03 93
conantina 2:2a3493799f03 94 dElapsedJulianDays=(double)(iDay+liAux3+liAux4+liAux5+59)+
conantina 2:2a3493799f03 95 -0.5+dDecimalHours/24.0;
conantina 2:2a3493799f03 96
conantina 2:2a3493799f03 97 }
conantina 2:2a3493799f03 98
conantina 2:2a3493799f03 99 // Calculate ecliptic coordinates (ecliptic longitude and obliquity of the
conantina 2:2a3493799f03 100 // ecliptic in radians but without limiting the angle to be less than 2*Pi
conantina 2:2a3493799f03 101 // (i.e., the result may be greater than 2*Pi)
conantina 2:2a3493799f03 102 {
conantina 2:2a3493799f03 103
conantina 2:2a3493799f03 104 /*double dMeanLongitude;
conantina 2:2a3493799f03 105 double dMeanAnomaly;
conantina 2:2a3493799f03 106 double dOmega;*/
conantina 2:2a3493799f03 107
conantina 2:2a3493799f03 108 dOmega=2.1429-0.0010394594*dElapsedJulianDays;
conantina 2:2a3493799f03 109 dMeanLongitude = 4.8950630+ 0.017202791698*dElapsedJulianDays; // Radians
conantina 2:2a3493799f03 110 dMeanAnomaly = 6.2400600+ 0.0172019699*dElapsedJulianDays;
conantina 2:2a3493799f03 111 dEclipticLongitude = dMeanLongitude + 0.03341607*sin( dMeanAnomaly )
conantina 2:2a3493799f03 112 + 0.00034894*sin( 2*dMeanAnomaly )-0.0001134
conantina 2:2a3493799f03 113 -0.0000203*sin(dOmega);
conantina 2:2a3493799f03 114 dEclipticObliquity = 0.4090928 - 6.2140e-9*dElapsedJulianDays
conantina 2:2a3493799f03 115 +0.0000396*cos(dOmega);
conantina 2:2a3493799f03 116 }
conantina 2:2a3493799f03 117
conantina 2:2a3493799f03 118 // Calculate celestial coordinates ( right ascension and declination ) in radians
conantina 2:2a3493799f03 119 // but without limiting the angle to be less than 2*Pi (i.e., the result may be
conantina 2:2a3493799f03 120 // greater than 2*Pi)
conantina 2:2a3493799f03 121 {
conantina 2:2a3493799f03 122
conantina 2:2a3493799f03 123 dSin_EclipticLongitude= sin( dEclipticLongitude );
conantina 2:2a3493799f03 124 double dY1 = cos( dEclipticObliquity ) * dSin_EclipticLongitude;
conantina 2:2a3493799f03 125 double dX1 = cos( dEclipticLongitude );
conantina 2:2a3493799f03 126 dRightAscension = atan2( dY1,dX1 );
conantina 2:2a3493799f03 127 if( dRightAscension < 0.0 ) dRightAscension = dRightAscension + twopi;
conantina 2:2a3493799f03 128 dDeclination = asin( sin( dEclipticObliquity )*dSin_EclipticLongitude );
conantina 2:2a3493799f03 129 }
conantina 2:2a3493799f03 130
conantina 2:2a3493799f03 131 // Calculate local coordinates ( azimuth and zenith angle ) in degrees
conantina 2:2a3493799f03 132 {
conantina 2:2a3493799f03 133
conantina 2:2a3493799f03 134 dGreenwichMeanSiderealTime = 6.6974243242 +
conantina 2:2a3493799f03 135 0.0657098283*dElapsedJulianDays
conantina 2:2a3493799f03 136 + dDecimalHours;
conantina 2:2a3493799f03 137
conantina 2:2a3493799f03 138 dLocalMeanSiderealTime = (dGreenwichMeanSiderealTime*15
conantina 2:2a3493799f03 139 + dLongitude)*rad;
conantina 2:2a3493799f03 140 dHourAngle = dLocalMeanSiderealTime - dRightAscension;
conantina 2:2a3493799f03 141 dLatitudeInRadians = dLatitude*rad;
conantina 2:2a3493799f03 142 dCos_Latitude = cos( dLatitudeInRadians );
conantina 2:2a3493799f03 143 dSin_Latitude = sin( dLatitudeInRadians );
conantina 2:2a3493799f03 144 dCos_HourAngle= cos( dHourAngle );
conantina 2:2a3493799f03 145 dZenithAngle = (acos( dCos_Latitude*dCos_HourAngle
conantina 2:2a3493799f03 146 *cos(dDeclination) + sin( dDeclination )*dSin_Latitude));
conantina 2:2a3493799f03 147 double dY = -sin( dHourAngle );
conantina 2:2a3493799f03 148 double dX = tan( dDeclination )*dCos_Latitude - dSin_Latitude*dCos_HourAngle;
conantina 2:2a3493799f03 149 dAzimuth=atan2( dY, dX );
conantina 2:2a3493799f03 150 if ( dAzimuth < 0.0 )
conantina 2:2a3493799f03 151 dAzimuth = dAzimuth + twopi;
conantina 2:2a3493799f03 152 dAzimuth = dAzimuth/rad;
conantina 2:2a3493799f03 153 // Parallax Correction
conantina 2:2a3493799f03 154 dParallax=(dEarthMeanRadius/dAstronomicalUnit)
conantina 2:2a3493799f03 155 *sin(dZenithAngle);
conantina 2:2a3493799f03 156 dZenithAngle=(dZenithAngle
conantina 2:2a3493799f03 157 + dParallax)/rad;
conantina 2:2a3493799f03 158 dElevation=90-dZenithAngle;
conantina 2:2a3493799f03 159 }
conantina 2:2a3493799f03 160 }