diff options
Diffstat (limited to 'software/main/sun.c')
-rw-r--r-- | software/main/sun.c | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/software/main/sun.c b/software/main/sun.c new file mode 100644 index 0000000..44d9fa1 --- /dev/null +++ b/software/main/sun.c @@ -0,0 +1,100 @@ +#include <stdio.h> +#include <string.h> +#include <stdbool.h> +#include <math.h> +#include <time.h> + +#include "../include/sun.h" + +double deg_to_rad(double angle) { + return angle * (M_PI / 180); +} + +double rad_to_deg(double angle) { + return angle * (180 / M_PI); +} + +double sun_calculation(struct tm curr_time, double longitude, double latitude) { + // Calulate day of the year + int day_in_year = floor(275 * (curr_time.tm_mon + 1) / 9) - + ((floor(((curr_time.tm_mon + 1) + 9) / 12)) * + (1 + floor(((curr_time.tm_year + 1900) - 4 * floor((curr_time.tm_year + 1900) / 4) + 2) / 3))) + + curr_time.tm_mday - 30; + + // Longitude to hour, get approx time + double long_hour = longitude / 15; + double approx_time; + + if (curr_time.tm_hour < 12) + approx_time = day_in_year + ((6 - long_hour) / 24); + else + approx_time = day_in_year + ((18 - long_hour) / 24); + + // Sun's mean anomaly + double mean_anomaly = (0.9856 * approx_time) - 3.289; + + // Sun's true longitude + double true_longitude = mean_anomaly + (1.916 * sin(deg_to_rad(mean_anomaly)) + + (0.02 * sin(deg_to_rad(2 * mean_anomaly)) + 282.634)); + + // Keep longitude between [0, 360) + if (true_longitude >= 360) + true_longitude -= 360; + else if (true_longitude < 0) + true_longitude += 360; + + // Sun's right ascension + double right_ascension = rad_to_deg(atan(0.91764 * tan(deg_to_rad(true_longitude)))); + + // Keep Right Ascension between [0, 360) + if (right_ascension >= 360) + right_ascension -= 360; + else if (right_ascension < 0) + right_ascension += 360; + + // Quadrant calibration + int longitude_quadrant = (floor(true_longitude / 90)) * 90; + int right_ascension_quadrant = (floor(right_ascension / 90)) * 90; + + right_ascension += (longitude_quadrant - right_ascension_quadrant); + + right_ascension /= 15; // convert to hours + + // Calculate Sun's declination + double sin_declination = 0.39782 * sin(deg_to_rad(true_longitude)); + double cos_declination = cos(asin(sin_declination)); + + // Calculate Sun's local hour angle + double sun_hour; + + double cos_hour = (-0.01454 - (sin_declination * sin(deg_to_rad(latitude)))) / + (cos_declination * cos(deg_to_rad(latitude))); + + if (curr_time.tm_hour < 12) + sun_hour = 360 - rad_to_deg(acos(cos_hour)); + else + sun_hour = rad_to_deg(acos(cos_hour)); + + sun_hour /= 15; // convert to hours + + // Local time + double local_mean_time = sun_hour + right_ascension - (0.06571 * approx_time) - 6.622; + + // Adjust to UTC + double sun_UTC = local_mean_time - long_hour; + + // Keep Sun UTC between [0, 24) + if (sun_UTC >= 24) + sun_UTC -= 24; + else if (sun_UTC < 0) + sun_UTC += 24; + + double sun_time = sun_UTC + LOCAL_OFFSET; + + if (sun_time < 0) + return (24 + sun_time); + else if (sun_time > 24) + return (sun_time - 24); + else + return sun_time; +}
\ No newline at end of file |