Hi, I'm making a project that controls the position of the sun, with the lat, long, year, month, day, hour, minute, second current, using a gps and an rtc.
To do this project I am using a formula, already for Arduino, of the Institute for Earth Science Research and Education, which should give the correct values.
In the previous project, in which I did not use this formula, I tried to transform a pure formula, always from the previous entity, into a language understandable for Arduino, but I had a problem with the azimuth and elevation changing their decimals with a jump of 0.200, both positive and negative, every 30 seconds. (normally they change by 0.010 every 1-2 sec)
I'm pretty sure the lat and long didn't change in value, they were always the same, so the only thing that could cause this jump in values was the changing time, but it shouldn't.
Now I'm trying with this formula already written for the microcontroller, but I don't know why it gives me azimuth and elevation values that do not correspond in any way with what I see on the suncal.org site. That is, I would like values in degrees, but unfortunately I don't know in which "format" the azimuth and elevation values are calculated.
In this formula I put the values that my gps and my watch read.
#include <DS3231.h>
#include <SoftwareSerial.h>
#include <TinyGPS.h>
#include <timestamp32bits.h>
#include <Wire.h>
#define DEG_TO_RAD 0.01745329
#define PI 3.141592654
#define TWOPI 6.28318531
SoftwareSerial mySerial(4, -1); //è -1 perchè non utilizziamo quel pin del gps, non ci interess inviare istruzioni ma solo ricevere dati
TinyGPS gps;
// Init the DS3231 using the hardware interface
DS3231 rtc(SDA, SCL);
timestamp32bits stamp = timestamp32bits();
int int_year, int_month, int_day, int_hour, int_minute, int_second;
byte month, day, hour, minute, second;
int year, count, count2; int x;
float flat, flon;
bool GPS_acquired = false;
float T,JD_frac,L0,M,e,C,L_true,f,R,GrHrAngle,Obl,RA,Decl,HrAngle,elev,azimuth;
long JD_whole,JDx;
String splitString(String str, char sep, int index)
{
int found = 0;
int strIdx[] = { 0, -1 };
int maxIdx = str.length() - 1;
for (int i = 0; i <= maxIdx && found <= index; i++)
{
if (str.charAt(i) == sep || i == maxIdx)
{
found++;
strIdx[0] = strIdx[1] + 1;
strIdx[1] = (i == maxIdx) ? i + 1 : i;
}
}
return found > index ? str.substring(strIdx[0], strIdx[1]) : "";
}
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
// set the data rate for the SoftwareSerial port
mySerial.begin(9600);
//int hour=16,minute=43,second=0,month=8,day=31,year,zone=1;
//float Lon=8.457*DEG_TO_RAD, Lat=44.667*DEG_TO_RAD;
}
void loop() {
rtc.begin();
bool newdata=false;
int year;
byte month, day, hour, minute, second, hundredths;
if (mySerial.available())
{
char c = mySerial.read();
// (c);
if (gps.encode(c))
{
newdata = true;
}
}
if ((newdata) && (count <= 50)) // acquisisce i 50 dati dal gps
{
gps.f_get_position(&flat, &flon);
if (isnan(flat) || isnan(flon)) {
count = 0;
} else {
count = count + 1;
Serial.println("Lat: "+(String)flat);
Serial.println("Long: "+(String)flon);
}
}
if ((newdata) && (count > 50))
{
if ((count > 50) && (GPS_acquired == false)) {
gps.crack_datetime(&year, &month, &day, &hour, &minute, &second);
rtc.setTime(hour, minute, second);
rtc.setDate(day, month, year);
rtc.setSQWRate(0);
Serial.println("Dati GPS acquisiti");
delay(250);
}
GPS_acquired = true;
//FORMULA (NON TOCCARE) **********************************************************************************************************************************
String day = splitString(rtc.getDateStr(), '.', 0);
String month = splitString(rtc.getDateStr(), '.', 1);
String year = splitString(rtc.getDateStr(), '.', 2);
String hour = splitString(rtc.getTimeStr(), ':', 0);
String minute = splitString(rtc.getTimeStr(), ':', 1);
String second = splitString(rtc.getTimeStr(), ':', 2);
int_day = day.toInt(); int_month = month.toInt(); int_year = year.toInt(); int_hour = hour.toInt(); int_minute = minute.toInt(); int_second = second.toInt();
Serial.print("Longitude and latitude "); Serial.print(flon/DEG_TO_RAD,3);
Serial.print(" "); Serial.println(flat/DEG_TO_RAD,3);
Serial.println("year,month,day,local hour,minute,second,elevation,azimuth");
//year=2022;
// Changes may be required in for... loop to get complete
// daylight coverage in time zones farther west.
//for (hour=10; hour<=24; hour++) {
JD_whole=JulianDate(int_year,int_month,int_day);
JD_frac=(int_hour+int_minute/60.+int_second/3600.)/24.-.5;
T=JD_whole-2451545; T=(T+JD_frac)/36525.;
L0=DEG_TO_RAD*fmod(280.46645+36000.76983*T,360);
M=DEG_TO_RAD*fmod(357.5291+35999.0503*T,360);
e=0.016708617-0.000042037*T;
C=DEG_TO_RAD*((1.9146-0.004847*T)*sin(M)+(0.019993-0.000101*T)*sin(2*M)+0.00029*sin(3*M));
f=M+C;
Obl=DEG_TO_RAD*(23+26/60.+21.448/3600.-46.815/3600*T);
JDx=JD_whole-2451545;
GrHrAngle=280.46061837+(360*JDx)%360+.98564736629*JDx+360.98564736629*JD_frac;
GrHrAngle=fmod(GrHrAngle,360.);
L_true=fmod(C+L0,TWOPI);
R=1.000001018*(1-e*e)/(1+e*cos(f));
RA=atan2(sin(L_true)*cos(Obl),cos(L_true));
Decl=asin(sin(Obl)*sin(L_true));
HrAngle=DEG_TO_RAD*GrHrAngle+flon-RA;
elev=asin(sin(flat)*sin(Decl)+cos(flat)*(cos(Decl)*cos(HrAngle)));
// Azimuth measured eastward from north.
azimuth=PI+atan2(sin(HrAngle),cos(HrAngle)*sin(flat)-tan(Decl)*cos(flat));
Serial.print(int_year); Serial.print(","); Serial.print(int_month);
Serial.print(","); Serial.print(int_day); Serial.print(", ");
Serial.print(int_hour); Serial.print(",");
Serial.print(int_minute); Serial.print(","); Serial.print(int_second);
Serial.print(","); Serial.print(elev/DEG_TO_RAD,3);
Serial.print(","); Serial.print(azimuth/DEG_TO_RAD,3); Serial.println();
}
}
long JulianDate(int year, int month, int day) {
long JD_whole;
int A,B;
if (month<=2) {
year--; month+=12;
}
A=year/100; B=2-A+A/4;
JD_whole=(long)(365.25*(year+4716))+(int)(30.6001*(month+1))+day+B-1524;
return JD_whole;
}
I will attach the official PDF of the Institute for Earth Science Research and Education with the formula, and I will also put my code with the formula only implemented gps and rtc.
If anyone knew how to give me some information I would be very grateful.
Thanks again for your availability.
sketch_aug31a.ino (5.2 KB)
ArduinoUnoSolarCalculations.pdf (228.8 KB)
Libreries.zip (587.2 KB)