Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

SunAlign program in various languages

8 views
Skip to first unread message

David Williams

unread,
Oct 11, 2008, 5:52:09 PM10/11/08
to
A while ago, I posted here a program I had written in QBasic which
calculates the position of the sun in the sky, as seen from anywhere
anytime, and also the required orientation of a mirror if it is to
reflect sunlight in any desired direction. The program is called
SunAlign, and could form the basis of software to run a
computer-operated sun-tracker or heliostat. I also posted a version in
a very "generic" BASIC.

Two people have recently translated the program into other languages.
Bill Stewart put it into Perl, and Dmitri (sorry, I don't know his
surname) translated it into C.

All the versions are available for downloading. If you sign on to
www.iwilltry.org, search for "heliostat" and follow the thread started
by "gaiatechnician" you will find both BASIC versions and also a link
to Dmitri's C version. Bill's Perl version is on www.otherpower.com,
also locatable by searching for "heliostat".

I hope they are useful...

dow

P.S. I might as well re-post the QBasic version below, to remind
everyone of what I'm talking about.

-------------------------------------------------

' SunAlign.BAS (Version for QBasic and similar dialects)

' Calculates position of sun in sky, as azimuth (compass bearing
' measured clockwise from True North) and angle of elevation, as
' seen from any place on earth, on any date and any time.
' Also calculates alignment of a heliostat mirror.

' David Williams
' P.O. Box 48512
' 3605 Lakeshore Blvd. West
' Toronto, Ontario. M8W 4Y6
' Canada

' Initially dated 2007 Jul 07
' This version 2008 Sep 02

' All angles in radians except in i/o routines DegIn and DegOut

DECLARE SUB C2P (X, Y, Z, AZ, EL)
DECLARE SUB P2C (AZ, EL, X, Y, Z)
DECLARE FUNCTION Ang (X, Y)
DECLARE SUB DegIn (P$, X)
DECLARE SUB DegOut (P$, X)

CONST PY = 3.1415926536# ' "PI" not assignable in some BASICs
CONST DR = 180 / PY ' degree / radian factor
W = 2 * PY / 365 ' earth's mean orbital angular speed in radians/day
WR = PY / 12' earth's speed of rotation relative to sun (radians/hour)
C = -23.45 / DR ' reverse angle of earth's axial tilt in radians
ST = SIN(C) ' sine of reverse tilt
CT = COS(C) ' cosine of reverse tilt
E2 = 2 * .0167 ' twice earth's orbital eccentricity
SN = 10 * W ' 10 days from December solstice to New Year (Jan 1)
SP = 12 * W ' 12 days from December solstice to perihelion

CLS

Menu:

PRINT "1. Calculate sun's position"
PRINT "2. Calculate mirror orientation"
PRINT "3. Calculate both"
PRINT "4. Quit program"
PRINT
PRINT "Which? (1 - 4)";

DO
S% = VAL(INKEY$)
LOOP UNTIL S% >= 1 AND S% <= 4
PRINT S%

IF S% = 4 THEN END

' Note: For brevity, no error checks on user inputs

PRINT
PRINT "Use negative numbers for directions opposite to those shown."
PRINT
DegIn "Observer's latitude (degrees North)", LT
DegIn "Observer's longitude (degrees East)", LG
INPUT "Time Zone (+/- hours from GMT/UT)"; TZN
INPUT "Time (HH,MM) (24-hr format)"; HR, MIN
INPUT "Date (M#,D#)"; Mth%, Day%

PRINT

CL = PY / 2 - LT ' co-latitude

D = INT(30.6 * ((Mth% + 9) MOD 12) + 58.5 + Day%) MOD 365
' day of year (D = 0 on Jan 1)

A = W * D + SN ' orbit angle since solstice at mean speed
B = A + E2 * SIN(A - SP) ' angle with correction for eccentricity

C = (A - ATN(TAN(B) / CT)) / PY
SL = PY * (C - INT(C + .5))' solar longitude relative to mean position

C = ST * COS(B)
DC = ATN(C / SQR(1 - C * C)) ' solar declination (latitude)
' arcsine of C. ASN not directly available in QBasic

LD = (HR - TZN + MIN / 60) * WR + SL + LG ' longitude difference

CALL P2C(LD, DC, sX, sY, sZ) ' polar axis (perpend'r to azimuth plane)
CALL C2P(sY, sZ, sX, sAZ, sEL) ' horizontal axis
CALL P2C(sAZ + CL, sEL, sY, sZ, sX) ' rotate by co-latitude

IF sZ < 0 THEN
BEEP
PRINT "Sun Below Horizon"
PRINT
GOTO NewCalc
END IF

IF S% <> 2 THEN ' calculate and display sun's position

CALL C2P(sX, sY, sZ, sAZ, sEL) ' vertical axis

DegOut "Sun's azimuth: ", sAZ
DegOut "Sun's elevation: ", sEL

PRINT

END IF

IF S% > 1 THEN ' calculate and display mirror orientation

PRINT "For target direction of light reflected from mirror:"
DegIn "Azimuth of target direction (degrees)", tAZ
DegIn "Elevation of target direction (degrees)", tEL

PRINT

CALL P2C(tAZ, tEL, tX, tY, tZ) ' target vector X,Y,Z
CALL C2P(sX + tX, sY + tY, sZ + tZ, mAZ, mEL)
' angle bisection by vector addition

PRINT "Mirror aim direction (perpendicular to surface):"
DegOut "Azimuth: ", mAZ
DegOut "Elevation: ", mEL

PRINT

END IF

NewCalc:

PRINT
PRINT "New Calculation"
PRINT

GOTO Menu


FUNCTION Ang (X, Y)
' calculates angle from positive X axis to vector to (X,Y)

SELECT CASE SGN(X)
CASE 1: Ang = ATN(Y / X)
CASE -1: Ang = ATN(Y / X) + PY
CASE ELSE: Ang = SGN(Y) * PY / 2
END SELECT

END FUNCTION

SUB C2P (X, Y, Z, AZ, EL)
' Cartesian to Polar. Convert from X,Y,Z to AZ,EL

EL = Ang(SQR(X * X + Y * Y), Z)
AZ = Ang(Y, X)
IF AZ < 0 THEN AZ = AZ + 2 * PY

END SUB

SUB DegIn (P$, X)
' Input angle in degrees and convert to radians

PRINT P$;
INPUT N
X = N / DR

END SUB

SUB DegOut (P$, X)
' converts radians to degrees, rounds to nearest 0.1, and prints

S$ = LTRIM$(STR$(INT(10 * ABS(X * DR) + .5)))
IF S$ = "3600" THEN S$ = "0"
IF LEN(S$) = 1 THEN S$ = "0" + S$
IF X < 0 THEN IF VAL(S$) THEN S$ = "-" + S$
PRINT P$; LEFT$(S$, LEN(S$) - 1); "."; RIGHT$(S$, 1); " degrees"

END SUB

SUB P2C (AZ, EL, X, Y, Z)
' Polar to Cartesian. Convert from AZ,EL to X,Y,Z

Z = SIN(EL)
C = COS(EL)
X = C * SIN(AZ)
Y = C * COS(AZ)

END SUB

-------------------------------------------------------
0 new messages