-> There are a few things that could make the posting more useful:
-> An explanation of the calculations that is independent of a programming
-> language, so that someone who wants to do the calculations by hand, or in a
-> different programming language can do so easily.
-> You can obviously read and write BASIC, not everyone can... even
-> programmers.
-> I have been programming professionally for 23 years, and haven't looked at
-> a BASIC program that used line numbers and "Gosub" for almost 30. BASIC was
-> the first programming language I learned, followed by a multitude of others.
-> The first structured language I learned was Pascal. I haven't wanted to go
-> back to BASIC since.
-> There are a lot to choose frome these days that are available for free.
-> My personal favorite is Ada (I find it to be the most readable), other free
-> choices (in no particular order) are: Python, Pascal, C, C++, Java, C#,
-> FORTRAN, Javascript, Structured BASIC, Perl, Modula2, (there are many more).
-> The most popular ones these days seem to be C++ and Java.
-> With a good description fo the calculatiosn reverse-engineering isn't
-> required to reprogram in a different language.
-> Regards,
-> Steve
The version I posted a couple of days ago is a "dumbed down" one that
is intended to run on very small and/or old computers that have only
BASICs that use line numbers, GOSUBs, and the like. The "real" program
is in QBasic, which has no line numbers, and uses SUBs and FUNCTIONs,
etc.. I posted it here a week or so ago. However, since you apparently
didn't see it, I'll append it again below.
This QBasic program includes more explanatory comments than the
simplified one. Of course, as always, I had to decide on some
compromise between clarity and excessive verbosity, and like all
compromises it will not satisfy everyone. However, I have been told by
people who had not previously seen the program that they found it easy
to read and understand.
The calculation includes several distinct stages. First, the latitude
(declination) and longitude of the sun are calculated, from
astronomical theory. Then a sequence of alternations between polar
(azimuth and elevation) and Cartesian (X, Y, Z) co-ordinate systems is
done, with small changes at each step. The result is to change the
reference frame so that the sun's position is found relative to the
local vertical and compass alignment of the observer. Finally, the same
technique is used to bisect the angle between the directions of the sun
and of the required target so as to find the alignment of the mirror.
The purpose of the program is to form the basis for software that can
be used to operate a computer-controlled sun-tracker or heliostat. To
do that, it would have to be extended by the addition of code to allow
the computer to control motors that turn the tracker or mirror. Since I
have no way of knowing the details of this hardware, I could not write
this code.
If you want further explanation, please contact me again, either here
or via the snail-mail address that is included in the program.
dow
-----------------------------------------------------
' 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 Jan 13
' 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)
A = Ang(Y, X)
IF A < PY THEN AZ = A + PY ELSE AZ = A - 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
------------------------------------------------------