Let's discuss how we can use just a real time clock (RTC) like the DS1307 modules which are available all over the internet to calculate and display local Sidereal Time.

I had real trouble calculating sidereal time on paper and by using excel and other methods and I spent a great deal of time trying to get the arduino to calculate it and failed miserably. I managed to get close by reverse engineering a javascript applet which applied the formula below:

Current Julian Day (JN) = floor(365.25*(y+4716)) + floor(30.6001*(m+1)) + d - 13 -1524.5 + UTC/24.0;

Where floor is a mathematical function which essentially means use the largest integer...

y = year

m = month

d = day

ut = universal co-ordinated time or UTC

The Javascript function I forked for the arduino is below:

function JulDay (d, m, y, u){ if (y<1900) y=y+1900 if (m<=2) {m=m+12; y=y-1} A = Math.floor(y/100); JD = Math.floor(365.25*(y+4716)) + Math.floor(30.6001*(m+1)) + d - 13 -1524.5 + u/24.0; return JD

}

Essentially what it does is:

Given the current date made up of YYYY/MM/DD and the current time in UTC calculate the current Julian Day Number with respect to the current time.

So the arduino function needs to perform as follows:

Get the current date and time.

Process the year - if the year is less than 1900 then add 1900 to the value for year

Process the month and year - if the month is January or February add 12 months to the value for month and subtract one off the value for year.

Calculate A - Divide the value for year by 100 and use the largest integer value found as the result.

Calculate the Julian Date using all of the above values found and print the result.

I then connected a tiny RTC real time clock module to the I2C pins on the arduino R3.

Here are the circuit connections for those that are interested.

RTC Arduino Uno R3

SCL ------> Pin A4

SDA ------> Pin A5

VCC ------> Pin 5V

GND ------> Pin 0V

RTC Module connected to Arduino Clone |

I then set the date and time on the RTC module using the time.H example included in the arduino example files and used the processing sketch to set the DS1307 using the serial connection and my PC's time.

I then wrote some arduino 'C' code which matches the functionality of the javascript function.

That wasn't too hard to implement:

void calcJulian()

{

int d1 = day();

int m1 = month();

int y1 = year();

int Hr1 = hour();

int Mn1 = minute();

int Sc1 = second();

float A1;

double JDN4;

if ( y1 <= 1900 )

{

y1 = y1 + 1900;

}

if (m1 <= 2)

{

m1 = m1 + 12;

y1 = y1 - 1;

}

A1 = floor(y1 / 100);

JDN4 = floor( 365.25* ( y1 + 4716 )) + floor( 30.6001 * ( m1 + 1 )) + d1 - 13 - 1524.5;

Serial.print("Julian Day Number: ");

Serial.print(JDN4,2);

Serial.println();

}

The only issue is that for some reason whenever I added the code required to include the current time parameter the results were incorrect.

I also tried several other methods which I also found were incorrect.

The extra code required to calculate the current JD number and not the JD number for the current date at 00:00:00 is:

Hr1 = day() / 24;

Mn1 = minute / 60;

Sc1 = second / 3600;

UT = Hr1 + Mn1 + Sc1;

JD = JDN4 + UT;

Calculating Sidereal Time

But in the spirit of not giving in to mere trifles of poor programming I looked about the internet to see if anyone else had attempted to calculate sidereal time. There were lots of people who have tried this and some have managed it! Most used a look up table for the Julian Year to achieve the result required. One stood out...

The best implementation...in my opinion is here:

The function of interest is here:

// ********************************************************************************** //

// GREENWICH & LOCAL SIDEREAL TIME CALCULATIONS

// ********************************************************************************** //

// based on "ASTR 310 - Observational Astronomy: Formula for Greenwich Sidereal Time (GST)"

// see http://www.astro.umd.edu/~jph/GST_eqn.pdf formulas

void doSiderealCalc() {

// UTC calculation

DateTime now = RTC.now(); // current time

DateTime utcTime (now.unixtime() - TZ*3600); // adjust to GMT

utc = (float)utcTime.hour() + (float)utcTime.minute()/60.0 + (float)utcTime.second()/3600.0; // decimal form

// calculate G (based on extrapolation)

int g = (utcTime.year() - 2000);

int leap = int((g+1.0)/4.0); // number of leap years since 2000

int nleap = g-leap; // number of non-leap years since 2000

double G = g2000 + (float)leap*lc + (float)nleap*nc; // number of days

// calculate nd

int nd = doNumDays(utcTime.year(), utcTime.month(), utcTime.day());

// calculate GST and Local Sidereal Time (LST)

GST = G + (dc*nd) + (tc*utc) + fudge; // Grenwich Sidereal Time

LST = GST + 24.0 + (float)(LONGITUDE/360*siderealday); // adjust for longitude (longitude portion of siderail day

while(LST>24.0) { LST -= 24.0; } // adjust to bring into 0-24 hours

dh = int( LST ); // translate into hours, ...

dm = int( (LST - (float)dh)*60.0 ); //... mins and ...

ds = int( (LST - (float)dh - (float)dm/60.0)*3600.0 ); //... seconds

}

// number of days of month (m) and date (d) since beginning of year (y)

int doNumDays(int y, int m, int d) {

int v=0;

byte leapyear = ((y-2000)%4 == 0)? 1 : 0;

switch(m) {

case 12: v += 30; // Dec

case 11: v += 31; // Nov

case 10: v += 30; // Oct

case 9: v += 31; // Sep

case 8: v += 31; // Aug

case 7: v += 30; // Jul

case 6: v += 31; // Jun

case 5: v += 30; // May

case 4: v += 31; // Apr

case 3: v += 28 + leapyear; // May (if year is leapyear, add extra day after February)

case 2: v += 31; break; // Feb

}

return v+d; // days from Jan 1 of given year

}

I may also implement the function correctly from here:

http://www.astro.umd.edu/~jph/GST_eqn.pdf

Helpfully the author has shared the entire code (arduino sketch) on their blog - Nice bloke! I have also shared my version of it here - I have updated the code to remove the LCD display section and updated the daylight savings function. The latitude and longitude are hard coded for Manchester, UK. These values will have to be changed to calculate sidereal time for your location and the whole thing relies on the real time clock being set to the accurate local time.

Sidereal Code - Working

I'm actually over the moon (heh great pun!) that someone managed this as I was beginning, after hours of trying and several attempts, to wonder if the lack of floating point precision with the arduino was going to be a factor....Thankfully it was not.

The next post will discuss using a GPS module to receive the current UTC time, update the RTC module and then calculate local sidereal time using the latitude and longitude and then display it on a 20x4 Display.

Helpfully the author has shared the entire code (arduino sketch) on their blog - Nice bloke! I have also shared my version of it here - I have updated the code to remove the LCD display section and updated the daylight savings function. The latitude and longitude are hard coded for Manchester, UK. These values will have to be changed to calculate sidereal time for your location and the whole thing relies on the real time clock being set to the accurate local time.

Sidereal Code - Working

If it is to be compiled then a copy of the RTClib.h library will be required from here:

I'm actually over the moon (heh great pun!) that someone managed this as I was beginning, after hours of trying and several attempts, to wonder if the lack of floating point precision with the arduino was going to be a factor....Thankfully it was not.

The next post will discuss using a GPS module to receive the current UTC time, update the RTC module and then calculate local sidereal time using the latitude and longitude and then display it on a 20x4 Display.

Take care - Langster!

## No comments :

## Post a Comment