|
|
View previous topic :: View next topic |
Author |
Message |
Jerry I
Joined: 14 Sep 2003 Posts: 96 Location: Toronto, Ontario, Canada
|
Structure Usage problems |
Posted: Tue Mar 24, 2020 10:24 pm |
|
|
Hi
Thank you in advance for any help.
This is some code I downloaded from http://www.psa.es/sdg/sunpos.htm which is supposed to calculate the sun position from anywhere in the world by passing some parameters.
I have always had problems using structures and I got it to compile to the point where I have commented the call to the function that causes the error.
The original code used DOUBLE variable, I have changed it to a float.
Compiler version I am using 4.134.
2 Files attached.
See code below.
Code: |
// This file is available in electronic form at http://www.psa.es/sdg/sunpos.htm
#define PIC_18F2620
#define BAUD1_SPEED 9600
#define BAUD2_SPEED 19200
#case
#include <18F2620.h>
#fuses h4, nowdt, noprotect, nolvp, put
#device *=16
#use delay(clock=40000000) /////////// Check Crystal Value ////////////
#use rs232(baud=9600,parity=N,xmit=PIN_C5,rcv=PIN_C4,bits=8, ERRORS, stream=HOSTPC)
#include "sunpos.h"
#include <math.h>
void sunpos(struct cTime udtTime, struct cLocation udtLocation, struct cSunCoordinates *udtSunCoordinates)
{
// Main variables
float dElapsedJulianDays;
float dDecimalHours;
float dEclipticLongitude;
float dEclipticObliquity;
float dRightAscension;
float dDeclination;
// Auxiliary variables
float dY;
float dX;
// Calculate difference in days between the current Julian Day
// and JD 2451545.0, which is noon 1 January 2000 Universal Time
{
float dJulianDate;
long int liAux1;
long int liAux2;
// Calculate time of the day in UT decimal hours
dDecimalHours = udtTime.dHours + (udtTime.dMinutes
+ udtTime.dSeconds / 60.0 ) / 60.0;
// Calculate current Julian Day
liAux1 =(udtTime.iMonth-14)/12;
liAux2=(1461*(udtTime.iYear + 4800 + liAux1))/4 + (367*(udtTime.iMonth
- 2-12*liAux1))/12- (3*((udtTime.iYear + 4900
+ liAux1)/100))/4+udtTime.iDay-32075;
dJulianDate=(float)(liAux2)-0.5+dDecimalHours/24.0;
// Calculate difference between current Julian Day and JD 2451545.0
dElapsedJulianDays = dJulianDate-2451545.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)
{
float dMeanLongitude;
float dMeanAnomaly;
float dOmega;
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)
{
float dSin_EclipticLongitude;
dSin_EclipticLongitude= sin( dEclipticLongitude );
dY = cos( dEclipticObliquity ) * dSin_EclipticLongitude;
dX = cos( dEclipticLongitude );
dRightAscension = atan2( dY,dX );
if( dRightAscension < 0.0 ) dRightAscension = dRightAscension + twopi;
dDeclination = asin( sin( dEclipticObliquity )*dSin_EclipticLongitude );
}
// Calculate local coordinates ( azimuth and zenith angle ) in degrees
{
float dGreenwichMeanSiderealTime;
float dLocalMeanSiderealTime;
float dLatitudeInRadians;
float dHourAngle;
float dCos_Latitude;
float dSin_Latitude;
float dCos_HourAngle;
float dParallax;
dGreenwichMeanSiderealTime = 6.6974243242 +
0.0657098283*dElapsedJulianDays
+ dDecimalHours;
dLocalMeanSiderealTime = (dGreenwichMeanSiderealTime*15
+ udtLocation.dLongitude)*rad;
dHourAngle = dLocalMeanSiderealTime - dRightAscension;
dLatitudeInRadians = udtLocation.dLatitude*rad;
dCos_Latitude = cos( dLatitudeInRadians );
dSin_Latitude = sin( dLatitudeInRadians );
dCos_HourAngle= cos( dHourAngle );
udtSunCoordinates->dZenithAngle = (acos( dCos_Latitude*dCos_HourAngle
*cos(dDeclination) + sin( dDeclination )*dSin_Latitude));
dY = -sin( dHourAngle );
dX = tan( dDeclination )*dCos_Latitude - dSin_Latitude*dCos_HourAngle;
udtSunCoordinates->dAzimuth = atan2( dY, dX );
if ( udtSunCoordinates->dAzimuth < 0.0 )
udtSunCoordinates->dAzimuth = udtSunCoordinates->dAzimuth + twopi;
udtSunCoordinates->dAzimuth = udtSunCoordinates->dAzimuth/rad;
// Parallax Correction
dParallax=(dEarthMeanRadius/dAstronomicalUnit)
*sin(udtSunCoordinates->dZenithAngle);
udtSunCoordinates->dZenithAngle=(udtSunCoordinates->dZenithAngle
+ dParallax)/rad;
}
}
main()
{
struct cTime udtTime;
struct cLocation udtLocation;
struct cSunCoordinates udtSunCoordinates;
udtSunCoordinates.dZenithAngle = 0;
udtSunCoordinates.dAzimuth = 0;
udtLocation.dLongitude = -79.4520;
udtLocation.dLatitude = 43.7072;
udtTime.iYear = 2020;
udtTime.iMonth = 3;
udtTime.iDay = 24;
udtTime.dHours = 12;
udtTime.dMinutes = 30;
udtTime.dSeconds = 00;
// COMMENTED ERROR BELOW
// sunpos(udtTime, udtLocation, udtSunCoordinates);
// ORIGINAL CODE UNMODIFIED
sunpos(cTime udtTime,cLocation udtLocation, cSunCoordinates *udtSunCoordinates)
fprintf (HOSTPC, "azim %3.1f zenref %3.1f \r\n", udtSunCoordinates.dAzimuth, udtSunCoordinates.dZenithAngle);
}
|
Code: |
// File Sunpos.h
// This file is available in electronic form at http://www.psa.es/sdg/sunpos.htm
#ifndef __SUNPOS_H
#define __SUNPOS_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
typedef struct cTime
{
int16 iYear;
int16 iMonth;
int16 iDay;
int16 dHours;
int16 dMinutes;
int16 dSeconds;
};
typedef struct cLocation
{
float dLongitude;
float dLatitude;
};
typedef struct cSunCoordinates
{
float dZenithAngle;
float dAzimuth;
};
void sunpos(struct cTime udtTime, struct cLocation udtLocation, struct cSunCoordinates *udtSunCoordinates);
#endif
|
Thanks again,
Jerry |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Wed Mar 25, 2020 2:14 am |
|
|
Two things:
First, wherever 'long' is used, replace this with signed int32. A 'long' on
most C's is an int32, and the default for most int's is signed. The maths
won't give the right result, unless an int32 is used.
Then the reason it fails is you are missing one key character.
Look at the declaration for sunpos:
void sunpos(struct cTime udtTime, struct cLocation udtLocation, struct cSunCoordinates *udtSunCoordinates)
Note the '*' on the coordinates.
You need to pass this the address of the variable:
sunpos(udtTime, udtLocation, &udtSunCoordinates);
Note the '&'.
With those two changes, it then merrily compiles and has a chance
of working. No idea if it will.... |
|
|
Jerry I
Joined: 14 Sep 2003 Posts: 96 Location: Toronto, Ontario, Canada
|
|
Posted: Wed Mar 25, 2020 4:17 pm |
|
|
Thanks Ttelmah,
Got it compiled found lots of calculation errors with complex equations.
Trying to make equations less complex.
Still working on it.
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Wed Mar 25, 2020 4:52 pm |
|
|
That's a lot of high powered math for an itty bitty PIC to run....
Be sure to print out intermediate results and be careful of brackets, use lots of them so the calculations are in the correct sequence. |
|
|
Jerry I
Joined: 14 Sep 2003 Posts: 96 Location: Toronto, Ontario, Canada
|
|
Posted: Wed Mar 25, 2020 4:59 pm |
|
|
Hi All,
I think I am going to give up. Math errors everywhere.
Tried simplifing calculations then got to Sin() and Cos() functions.
all answers appeared wrong based on calculator.
Strange I never had so many calculation errors using floats.
I tried??. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Mar 25, 2020 5:03 pm |
|
|
Radians vs. degrees ? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Wed Mar 25, 2020 5:15 pm |
|
|
yikes....
udtLocation.dLongitude = -79.4520;
udtLocation.dLatitude = 43.7072;
I saw these and figure you have to live near me !! I scroll up and see Toronto..... under your name.
small world.
wrong calculator ?
I know QB4.5 under Win98 runs accurate numbers.. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Thu Mar 26, 2020 1:48 am |
|
|
As PCM_Programmer says, degrees versus radians.
In C all angular calculations are done using radians not degrees. This is
common in proper mathematics. However most normal calculators will
use degrees.
Declare yourself some basic #defines:
Code: |
#define RADFACT (0.0174532925)
#define DEGTORAD(x) (x*RADFACT)
#define RADTODEG(x) (x/RADFACT)
|
Then when you have your angle and want the sin:
result = sin(DEGTORAD(angle));
You shouldn't need to convert the other way, but if you do, RADTODEG
does this.
I've written it to be 'optimised', so that the conversion from degrees to
radians is done as a single multiplication, since this is the conversion
you are most likely to need. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|