2

Author Topic: Solar Tracker algorithm  (Read 1983 times)

0 Members and 1 Guest are viewing this topic.

Offline scottfromscottTopic starter

  • Beginner
  • *
  • Posts: 6
  • Helpful? 0
  • Me at my Acer Aspire One Net book
Solar Tracker algorithm
« on: August 14, 2010, 11:19:47 PM »
The following function uses an elegant, and fairly short algorithm for approximating the sun's position and could be used for a PV panel solar tracker . It is accurate to within about 1 degree of the NOAA sun position calculator's values for altitude and azimuth.
Code: [Select]
#include <stdio.h>
#include <math.h>

void get_sun_pos(float lat, float lon, char dt_type, float mo, float da, float hour, float minute, float *alt, float *az){
   /*
      calculate the Sun's altitude and azimuth
inputs: 'lat'itude, 'lon'gitude, dt_type('u'|'l'), 'mo'nth, 'da'y, hour, minute
dt_type contains 'u'tc date/time, or 'l'ocal date/time flag indicating whether mo, da, hour and minute are utc or local
   outputs: 'alt'itude, 'az'imuth
code based upon Prof. Richard B. Goldstein's sun position calculator at http://www.providence.edu/mcs/rbg/java/sungraph.htm
Appears to give fairly accurate results for the next 10 years or so
*/

float ti, local_hour;

if (dt_type == 'l') local_hour = hour;
else /* dt_type == 'u' */
{
/* calculate local date/time from utc date/time */
float time_offset = round(lon / 15); //longitude -> hours
local_hour = hour + time_offset;

//adjust hour, day, month as needed (ignore years and seconds)... 
if (local_hour < 0){
local_hour += 24;
da--;
if (da < 1){
mo--;
if (mo < 1) mo = 12;
da = (mo==4||mo==6||mo==9||mo==11)?30:(mo==1||mo==3||mo==5||mo==7||mo==10)?31:28;
}
}
else if (local_hour > 23){
local_hour -= 24;
da++;
if (da > (mo==4||mo==6||mo==9||mo==11)?30:(mo==1||mo==3||mo==5||mo==7||mo==10)?31:28){
mo++;
if (mo > 12) mo = 1;
da = 1;
}
}

}

//total hours and minutes and adjust for +/- offset from noon...
   ti = (local_hour + minute / 60) - 12;
 
    float pi180=M_PI/180;
    float adjtime;
    float za[] = {-0.5,30.5,58.5,89.5,119.5,150.5,180.5,211.5,242.5,272.5,303.5,333.5}; // days from jan at noon
    float zi;
    float zzi;
    float cth; // cosine of latitude
    float sth; // sine of latitude
    float cph;
    float sph;
    float cti;
    float sti;
    float x;
    float y;
    float loc;
    float phi;
    float sin_tau, cos_tau;

    loc = round(lon / 15) * 15; //
    adjtime = (lon - loc) / 40; // offset
    zi = za[(int)mo - 1];       //
    zzi = 360 * (zi + 0.5 + da - 82) / 365; //
    cos_tau = cos(zzi * pi180);
    sin_tau = sin(zzi * pi180);
    phi = acos(cos_tau * cos_tau + sin_tau * sin_tau * cos(23.45 * pi180)); // formula for sun declination (varies +/- 23.45 deg. over a year)
    phi = round(1000 * phi / pi180) / 1000; //
    if (sin_tau < 0){phi = -phi;}// sign +/- depends on the time of year   
    ti = ti * 15; // hours +/- offset from noon to degrees from Prime Meridian
    cth = cos(lat * pi180);
    sth = sin(lat * pi180);
    cph = cos(phi * pi180);
    sph = sin(phi * pi180);
    cti = cos(ti * pi180);

    //altitude = sin-1(sin theta * sin phi + cos theta * cos phi * cos tau)

    *alt = sth * sph + cth * cph * cti;
    *alt = asin(*alt) / pi180;
    *alt = round(1000 * *alt) / 1000;

    //azimuth = tan-1(-x'/y')=tan-1(cos phi sin tau/(cos theta sin phi - sin theta cos phi cos tau))

    sti = sin(ti * pi180);
    x = -cph * sti;
    y = cth * sph - sth * cph * cti;
    *az = 90 - atan2(y, x) / pi180;
    if(*az < 0) *az = *az + 360;
    *az = round(1000 * *az) / 1000;
}

int main()
{
float alt, az;
//           lat,lon,dt_type,mo, da,hour,minute, alt, az
get_sun_pos(-30, -90,  'u',   8, 14,  15,    30, &alt, &az);
printf("alt: %f  az:%f\n",alt,az);
}

 


Get Your Ad Here