Go Down

Topic: Time change and Tracking  (Read 1 time) previous topic - next topic

walraven92

Thanks for your reply! Can you give me an example code to do that? I will really appreciate it

jremington

Quote
Can you give me an example code to do that?
You still need to post your working code.

walraven92

Here you go. This is so far I get it to work.


Code: [Select]


#include <DS3231.h>
//Sun Position Calculation by Mowcius (mowcius.co.uk)
//Provides sun position (relative) from static variables

#include "Wire.h"

#define DS3231_I2C_ADDRESS 0x68
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return( (val/16*10) + (val%16) );
}
#include <math.h>
#define pi    3.14159265358979323846
#define twopi (2*pi)
#define rad   (pi/180)
#define EarthMeanRadius     6371.01 // In km
#define AstronomicalUnit    149597890 // In km

float Longitude = 73.55; //enter longitude here   
float Latitude = 40.44; //enter latitude here
//--------

//Program Variables
 float ZenithAngle;
 float Azimuth;
  float RightAscension;
 float Declination;
  float Parallax;
  float ElevationAngle;

 float ElapsedJulianDays;
 float DecimalHours;
 float EclipticLongitude;
 float EclipticObliquity;
//--------



void setup()
{
  Wire.begin();
  Serial.begin(9600);
  // set the initial time here:
 // DS3231 seconds, minutes, hours, day, date, month, year;
  setDS3231time(00,00,24,6,25,12,15);

}

bool IsDST(int dayOfMonth, int month, int dayOfWeek)
{
  if (month < 3 || month > 11)
  {
    return false;
  }
  if (month > 3 && month < 11)
  {
    return true;
  }
  int previousSunday = dayOfMonth - (dayOfWeek - 1); // Spark Sunday = 1
  //In march, we are DST if our previous sunday was on or after the 8th.
  if (month == 3)
  {
    return previousSunday >= 8;
  }
  //In November we must be before the first sunday to be dst.
  //That means the previous sunday must be before the 1st.
  return previousSunday <= 0;
}

//void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte
//dayOfMonth, byte month, byte year, float Minutes)

void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte
dayOfMonth, byte month, byte year)

{
  // sets time and date data to DS3231
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set next input to start at the seconds register
  Wire.write(decToBcd(second)); // set seconds
  Wire.write(decToBcd(minute)); // set minutes
  Wire.write(decToBcd(hour)); // set hours
  Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
  Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
  Wire.write(decToBcd(month)); // set month
  Wire.write(decToBcd(year)); // set year (0 to 99)
  Wire.endTransmission();
 // setYear(byte Year);
}


void readDS3231time(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
int *year)


{
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set DS3231 register pointer to 00h
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = 2000+bcdToDec(Wire.read());
}
void displayTime(int second, int minute, int hour, int dayOfWeek, int dayOfMonth, int month, int year)
{
  char buf[26];
  snprintf(buf,sizeof(buf),"%02d.%02d.%04d  %02d:%02d:%02d  ", dayOfMonth, month, year, hour, minute, second);
  Serial.print(buf);
}


void sunPos(int Minutes, int Hours, int Day, int Month, int Year){

//Hours = Hours - 5;
 // 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 JulianDate;
 long int liAux1;
 long int liAux2;
 // Calculate time of the day in UT decimal hours
 DecimalHours = Hours + (Minutes / 60.0);
 // Calculate current Julian Day
 liAux1 =(Month-14)/12;
 liAux2=(1461*(Year + 4800 + liAux1))/4 + (367*(Month
 - 2-12*liAux1))/12- (3*((Year + 4900
 + liAux1)/100))/4+Day-32075;
 JulianDate=(float)(liAux2)-0.5+DecimalHours/24.0;
 // Calculate difference between current Julian Day and JD 2451545.0
 ElapsedJulianDays = JulianDate-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 MeanLongitude;
 float MeanAnomaly;
 float Omega;
 Omega=2.1429-0.0010394594*ElapsedJulianDays;
 MeanLongitude = 4.8950630+ 0.017202791698*ElapsedJulianDays; // Radians
 MeanAnomaly = 6.2400600+ 0.0172019699*ElapsedJulianDays;
 EclipticLongitude = MeanLongitude + 0.03341607*sin( MeanAnomaly )
 + 0.00034894*sin( 2*MeanAnomaly )-0.0001134
 -0.0000203*sin(Omega);
 EclipticObliquity = 0.4090928 - 6.2140e-9*ElapsedJulianDays
 +0.0000396*cos(Omega);

 // 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 Sin_EclipticLongitude;
 Sin_EclipticLongitude= sin( EclipticLongitude );
 dY = cos( EclipticObliquity ) * Sin_EclipticLongitude;
 dX = cos( EclipticLongitude );
 RightAscension = atan2( dY,dX );
 if( RightAscension < 0.0 ) RightAscension = RightAscension + twopi;
 Declination = asin( sin( EclipticObliquity )*Sin_EclipticLongitude );

 // Calculate local coordinates ( azimuth and zenith angle ) in degrees

 float GreenwichMeanSiderealTime;
 float LocalMeanSiderealTime;
 float LatitudeInRadians;
 float HourAngle;
 float Cos_Latitude;
 float Sin_Latitude;
 float Cos_HourAngle;
 GreenwichMeanSiderealTime = 6.6974243242 +
 0.0657098283*ElapsedJulianDays
 + DecimalHours;
 LocalMeanSiderealTime = (GreenwichMeanSiderealTime*15
 + Longitude)*rad;
 HourAngle = LocalMeanSiderealTime - RightAscension;
 LatitudeInRadians = Latitude*rad;
 Cos_Latitude = cos( LatitudeInRadians );
 Sin_Latitude = sin( LatitudeInRadians );
 Cos_HourAngle= cos( HourAngle );
 ZenithAngle = (acos( Cos_Latitude*Cos_HourAngle
 *cos(Declination) + sin( Declination )*Sin_Latitude));
 dY = -sin( HourAngle );
 dX = tan( Declination )*Cos_Latitude - Sin_Latitude*Cos_HourAngle;
 Azimuth = atan2( dY, dX );
 if ( Azimuth < 0.0 )
  Azimuth = Azimuth + twopi;
 Azimuth = Azimuth/rad;
 // Parallax Correction
 Parallax=(EarthMeanRadius/AstronomicalUnit)
 *sin(ZenithAngle);
 ZenithAngle=(ZenithAngle //Zenith angle is from the top of the visible sky (thanks breaksbassbleeps)
 + Parallax)/rad;
    ElevationAngle = (90-ZenithAngle); //Retrieve useful elevation angle from Zenith angle
}

void loop()

{
  int year;
  byte month,dayOfWeek,dayOfMonth,hour,minute,second;
  readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  displayTime(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
  sunPos(minute, hour, dayOfMonth, month, year); //Run sun position calculations
  Serial.print("Elevation Angle:  ");
  Serial.print(ElevationAngle, 3); //Print Elevation (Vertical) with no decimal places as accuracy is not really great enough
  Serial.print("\tAzimuth:  ");
  Serial.print(Azimuth, 3); //Print Azimuth (Horizontal) with no decimal places
  Serial.print("\tHour:");
  Serial.print(hour);
  if(ElevationAngle < 0) Serial.println("  The sun has set. Get some sleep!");
  else Serial.println();
  delay(1000); // every second

 
}



aarg

How will you handle daylight savings time?
  ... with a transistor and a large sum of money to spend ...
Please don't PM me with technical questions. Post them in the forum.

jremington

Code: [Select]
setDS3231time(00,00,24,6,25,12,15);Why are you setting the RTC to 24 o'clock?

walraven92

I did not know what am  I doing so I was trying different options

I do not know.  :( .. I have posted the code with the progress that I made so far. It does not have the day light saving time.

I also need to control the motor based on time and elevation. Is there any piece of code available that can allow me to check time.

For example if it is 12 noon then actuate the motor so that it can move the solar panel to face the sun perpendicularly. I am using single horizontal axis tracker with solar panel starting facing East. So, at noon the solar panel is at zero degree facing the Sun in summer. Ho can Check for time. I meant can I use if then statement ??

I have an accelerometer feed backing the tilt information.

jremington

Until you understand how to set and read the clock, it is early to be worrying about later applications. You appear to have jumped into a project that is way over your head, given your present skills.

If I wanted to set the RTC to my current local time (Friday 25-Dec-2015, 9:04 AM) in 24 hour mode, I would use the following call:

Code: [Select]
setDS3231time(00,04,09,5,25,12,15);

To convert between UTC and local time, there are many options. Using the gmtime and timegm functions is one:

http://stackoverflow.com/questions/761791/converting-between-local-times-and-gmt-utc-in-c-c

walraven92

Yes, you are right. This project is way over my head. I do not deserve to do this project. But I am learning. All I can do is try. I will appreciate your help.

My local time right now is 12:16 pm.

I used the function call

  setDS3231time(00,16,12,6,25,12,15);

The program should give me following outputs

25.12.2015   which is correct. I am getting this output

Elevation Angle : -3.44      This is wrong

Azimuth: 241.877   This is Wrong

12:16:16   might be correct


The sun has set. Get some Sleep!   This is wrong


The correct answer should be


25.12.2015   

Elevation Angle : 25.99     

Azimuth: 181.1   

12:16:16   


I think I am getting is incorrect result because of some time difference problem.







jremington

#23
Dec 25, 2015, 06:30 pm Last Edit: Dec 25, 2015, 06:35 pm by jremington
Sink or swim!

Yes, obviously you need to correct for the time difference. The sunpos program requires UTC time and date, which you get from your local time by ADDING 5 hours and correcting for possible date changes.

Check whether the program is working correctly by entering a daylight UTC time and longitude=latitude=0 degrees. See what the NOAA calculator says for that time and location. 


walraven92

This is what I did. I subtracted 5 from the hours in the sunPos() function. Now it works fine. But how will handle the situation when UTC <5. Should I not subtract 5 from hours?

void sunPos(int Minutes, int Hours, int Day, int Month, int Year){

Hours = Hours - 5;


I also tried to do the 8 AM in the following way

setDS3231time(00,16,08,6,25,12,15);

But it gave me following error

error: invalid digit "8" in octal constant
invalid digit "8" in octal constant

Do you know how can I fix this error?


Can you also advise on moving the motor thing. If elevation is 90 then panel should be at zero. I guess how am I map the Sun's elevation values to move the motor.

jremington

Quote
But how will handle the situation when UTC <5. Should I not subtract 5 from hours?
That has already been explained, at least twice. Stop and think it through.

walraven92

ok, How about mapping the elevation values to actuate the motor

aarg

#27
Dec 25, 2015, 07:16 pm Last Edit: Dec 25, 2015, 07:18 pm by aarg
Setting the RTC does not have to be done in your sketch. There is a time setting example sketch in the library. All you have to do is load and run it once. Once the RTC has the time, any program can access it without knowing how to set it.
  ... with a transistor and a large sum of money to spend ...
Please don't PM me with technical questions. Post them in the forum.

walraven92

How can I take care of the condition when UTC <5 plus daylight saving time ?

Okay I will try to run that piece of code and let you know soon.

aarg

How can I take care of the condition when UTC <5 plus daylight saving time ?

Okay I will try to run that piece of code and let you know soon.
I've read so many threads asking for help to build time code from the bottom up. It's certainly praiseworthy, but time has a lot of "gotchas" that fill those threads with repetitive questions, "okay I got that, but what about this?...". Different people often the ask exactly the same questions. "How do I create an alarm?" "What about DST?" "How do I handle the different number of days in a month" and so on.

Even if you want to write your own code instead of using libraries, wouldn't it be a good idea to have a look at them, the source code? Because all the answers are in there.
  ... with a transistor and a large sum of money to spend ...
Please don't PM me with technical questions. Post them in the forum.

Go Up