sidereal time clock

hippy

Ex-Staff (retired)
Welcome to the PICAXE forum.

The display part is relatively easy and there are equations and algorithms for calculating sidereal time. The issues will be how accurate you want the sidereal time to be and doing the calculations.
 

BESQUEUT

Senior Member
The display part is relatively easy and there are equations and algorithms for calculating sidereal time. The issues will be how accurate you want the sidereal time to be and doing the calculations.
1 day is 0,9972696 sideral day. If you start the clock with a known sidereal time, calculations will be doable (using DS1307 time change for example)

If you want to convert current time+latitude/longitude to sidereal time, it will be very tricky.
You will have to deal with numbers like 24.06570982441908 siderals hours for a day...
 
Last edited:

hippy

Ex-Staff (retired)
I am not familiar with astrophysics and astronomical time but if there is a means to incrementally determine sidereal time from elapsing 'real time' that will be possible on a PICAXE and relatively easy to do, even if there are a lot of decimal places.

For example, if you wanted sidereal seconds ('w0') to increment by 1.234567890123 every 'real second', you can do something like this -

Code:
w4 =             w4 + 123
w3 = w4 / 1000 + w3 + 890 : w4 = w4 // 1000
w2 = w3 / 1000 + w2 + 567 : w3 = w3 // 1000
w1 = w2 / 1000 + w1 + 234 : w2 = w2 // 1000
w0 = w1 / 1000 + w0 + 1   : w1 = w1 // 1000
 

BESQUEUT

Senior Member
I am not familiar with astrophysics and astronomical time but if there is a means to incrementally determine sidereal time from elapsing 'real time' that will be possible on a PICAXE and relatively easy to do, even if there are a lot of decimal places.

For example, if you wanted sidereal seconds ('w0') to increment by 1.234567890123 every 'real second', you can do something like this -

Code:
w4 =             w4 + 123
w3 = w4 / 1000 + w3 + 890 : w4 = w4 // 1000
w2 = w3 / 1000 + w2 + 567 : w3 = w3 // 1000
w1 = w2 / 1000 + w1 + 234 : w2 = w2 // 1000
w0 = w1 / 1000 + w0 + 1   : w1 = w1 // 1000
Starting from a known sidereal date, the second increment is 24.06570982441908/24=1,00273790935079 (every "real" second)

English Wiki is more precise : 1.002 737 909 350 795 Sidereal_time

To detect second change from a DS1307, I suggest some code like :
Code:
do
    HI2Cin $0,  (ss,nn,hh,dd,ddd,mm,yy) ' read time DS1307
    if ss<> Prev_ss then
        gosub IncSidereal
        Prev_ss=ss
    endif
loop

IncSidereal:              ' thanks to Hippy
    w5 = w4 + 795
    w4 = w5 / 1000 + w4 + 350 : w5 = w5 // 1000
    w3 = w4 / 1000 + w3 + 909 : w4 = w4 // 1000
    w2 = w3 / 1000 + w2 + 737 : w3 = w3 // 1000
    w1 = w2 / 1000 + w1 + 002 : w2 = w2 // 1000
    w0 = w1 / 1000 + w0 + 1   : w1 = w1 // 1000
return
You now have to
1) Convert the starting sidereal date to w0,w1,w2...
2) convert w0,w1,w2,... to YY/MM/DD HH:MM:SS...

But, since w0 can't be greater than 65535, that will work only 18 hours...
We need a 64 bit integer to store the second counter, that is 4294967296 s=136 years...
Code:
Year=   ' current sidereal year
Month= ' current sidereal year
Day =
Hour=
Min=
Sec=


do
    HI2Cin $0,  (ss,nn,hh,dd,ddd,mm,yy) ' read time DS1307
    if ss<> Prev_ss then
        gosub IncSidereal
        Prev_ss=ss
    endif
loop
IncSidereal:              ' thanks to Hippy
    w5 = w4 + 790
    w4 = w5 / 1000 + w4 + 350 : w5 = w5 // 1000
    w3 = w4 / 1000 + w3 + 909 : w4 = w4 // 1000
    w2 = w3 / 1000 + w2 + 737 : w3 = w3 // 1000
    w1 = w2 / 1000 + w1 + 002 : w2 = w2 // 1000
    prev_w0=w0
    w0 = w1 / 1000 + w0 + 1
    if w0<prev_w0 then            ' w0 overflow    
         inc w10                  ' w10*65536+w0 is the 64 bits integer
    endif

    w1 = w1 // 1000
return
But since converting from a 64 bits integer to YY/MM/DD HH:MM:SS... is not so easy,
it may be better to inc directly Hours, min and sec ...

Code:
Inc_Sec:
     inc Sec
     if Sec=60 then
           Sec=0
           inc Min
           if Min=60 then
                  Min=0
                  inc Hour
                  if Hour=24 then
                         Hour=0
                         inc Day
                  endif
           endif
     endif
return
Since (wX//1000) < 1000
wX<2000
So
wX/1000 =0 OR 1
Code:
[S]   prev_w0=w0
      w0 = w1 / 1000 + w0 + 1[/S]
     if w1>999 then
             gosub IncSec
     endif
     gosub IncSec

    w1 = w1 // 1000
 
Last edited:

hippy

Ex-Staff (retired)
That's a good link. Thanks. The image on that pages showing progression of the earth around the sun explains the basic principle which helped me, and the handy calculation which it claims is accurate to 0.1 second per century -

GMST = 18.697 374 558 + 24.065 709 824 419 08 * D

That can be transformed into a per second calculation quite easily and then as you suggested, just increment by that decimal fraction every second.

I'd also increment seconds, minutes and hours separately rather than try and handle as bigger variables. That keeps them in an easy to use format for display. It probably also makes it easier to debug.
 

hippy

Ex-Staff (retired)
@ SG12015 : I suspect the real question is; how is it going ? Have you managed to get anywhere in pursuing your intended project ?
 

premelec

Senior Member
Is sidereal time monotonic linear? If so couldn't one just adjust the crystal frequency in a clock chip to produce it?
 

BESQUEUT

Senior Member
Is sidereal time monotonic linear? If so couldn't one just adjust the crystal frequency in a clock chip to produce it?
If we exclude the Precession effects, it is monotonic linear.
But the "adjustment" must be 4mn a day ; not sure this is possible.
Quartz "pullability" is around 200ppm. We need 3000 ppm...
We have to make a 32768 Hz quartz run at 32 859.27577 Hz.
According to this datasheet figure 5-2, it does not seem to be possible.
If so, this is an excellent idea.
 
Last edited:

BillBWann

Member
Is it possible to use the Pic Axe as a sidereal clock and display the time on a OLED.
I attach a program that I wrote some time ago that converts standard eastern Australian time (150 degrees East) to Sidereal time at a particular longitude. I used the equation GMST = 18.697 374 558 + 24.065 709 824 419 08 * D to determine that the Sidereal time at longitude 150 at midnight on 1/1/15 was 6:39:41. The program then calculates the current number of hours since then and multiplies it by 0.00273790932 and adds this to 6:39:41. It then adds an adjustment to account for the actual longitude of the clock.

The program runs on a 08M2 and assumes a DS3231 RTC (or similar) and a 2 line serial LCD display on pin 4.

Assuming that the real time clock is correct, the calculated Sidereal time should be accurate to a couple of seconds.

The display shows both the standard time (and date) and the local Sidereal time. I see that SG12015 lives in Perth where the standard time is based on longitude 120 (2 hours behind standard time in the eastern states of Australia). Therefore in his case, he’d have to set his actual clock longitude (see lines 28 & 29 of the program) to a value 30 degrees greater than his actual longitude for the display to be correct. I didn’t realize it when I wrote the program but the program variable SiteLongDeg is in reality a correction factor between the standard time longitude and the clock longitude centred on 150 degrees. Therefore even though the program was written for eastern Australia, it should work everywhere as long as the variable SiteLongDeg=150+actual longitude-standard time longitude.

Also if you wanted the display to show daylight saving time rather than standard time, you could set your RTC to that time and then subtract 15 degrees from your calculated value for SiteLongDeg.

Actually, as I type this, I realize that it isn’t as simple as this because the program assumes when it calculates the elapsed time since 1/1/15 that the time is Eastern Standard Time (10 hours). This could cause an error of 100 seconds or so if used in UK so to correct for this, the value of SiteLongMin needs to be increased by (150-LT)* 0.164 where LT is the longitude corresponding to the time zone being used by the RTC (for daylight saving time, it would normally be 15 degrees greater than standard time longitude). Therefore if the program was used right at Greenwich without daylight saving, the longitude used in the program would need to be set as:-

SiteLongDeg=150 and SiteLongMin=25

while if daylight saving time was being displayed on the RTC, it would be:-

SiteLongDeg=135 and SiteLongMin=22

Apologies for the complication but I hadn’t considered other people using the program when I wrote it and the idea of rewriting it for more general use doesn’t appeal to me at the moment.

Code:
#picaxe 08m2
'#no_data

symbol Tmpb3=b11
symbol Tmpb1=b12
symbol Tmpb2=b13
symbol TempW1=W7
symbol TempW2=W8
symbol LSBpointer=b16
symbol MSBpointer=b17
symbol M1Low=W10
symbol M1High=W11
symbol M2Low=W12
symbol M2High=W13

symbol hours=b10
symbol mins=b9
symbol secs=b8
symbol year=b7
symbol month=b6
symbol day=b5
symbol oldsecs=b4
symbol Tmpb4=b3
symbol Tmpb5=b2
symbol Tmpb6=b1


symbol SiteLongDeg=149	'Degrees Longitude of location of clock (75 - 323 degrees East)
symbol SiteLongMin=5	'Minutes Longitude of location of clock (0-60)

setfreq m8

serout c.4,N2400_8,("?f")	'Clear Display

do
	do
		
		Hi2CSETUP i2cmaster,%11010000,i2cslow_8,i2cbyte	'To communicate with RTC
		readi2c 0,(secs,mins,hours,day,day,month,year)	'Get current time & date
		
		Tmpb1=secs&$0f
		secs=secs/16*10+Tmpb1
		Tmpb1=mins&$0f
		mins=mins/16*10+Tmpb1
		Tmpb1=hours&$0f
		hours=hours/16*10+Tmpb1
		Tmpb1=day&$0f
		day=day/16*10+Tmpb1
		Tmpb1=month&$0f
		month=month/16*10+Tmpb1
		Tmpb1=year&$0f
		year=year/16*10+Tmpb1
		
	loop until secs<>oldsecs
	oldsecs=secs
	
	bintoascii day,Tmpb1,Tmpb1,Tmpb2
	bintoascii month,Tmpb3,Tmpb3,Tmpb4
	bintoascii year,Tmpb5,Tmpb5,Tmpb6
	
	sertxd (Tmpb1,Tmpb2,"/",Tmpb3,Tmpb4,"/",Tmpb5,Tmpb6,",  ")
	serout c.4,N2400_8,("?y0?x09(",Tmpb1,Tmpb2,"/",Tmpb3,Tmpb4,"/",Tmpb5,Tmpb6,")")
	
	bintoascii hours,Tmpb1,Tmpb1,Tmpb2
	bintoascii mins,Tmpb3,Tmpb3,Tmpb4
	bintoascii secs,Tmpb5,Tmpb5,Tmpb6
	
	sertxd (Tmpb1,Tmpb2,":",Tmpb3,Tmpb4,":",Tmpb5,Tmpb6,cr,lf)
	serout c.4,N2400_8,("?x00",Tmpb1,Tmpb2,":",Tmpb3,Tmpb4,":",Tmpb5,Tmpb6)
	
	For bptr=28 to 35	'Zero Result
		@bptr=0
	next bptr
	
	call dayint	'Calculate the number of days since 1/1/15 & save in M1Low
	M1High=0
	M2Low=20864	'86400
	M2High=1
	call Mul32by32	'Convert days to seconds
	'call prt64
	
	M1Low=hours*3600	'Determine number of seconds to current time today
	M1High=hours**3600
	TempW1=mins*60+secs+M1Low
	if TempW1<M1Low then: inc M1High: endif
	M1Low=TempW1
	
	call AddM1	'Adds M1High:M1Low to 8 byte result
	'call prt64
	
	bptr=27	'High byte of M2
		for Tmpb1=31 to 28 step -1	'Move bottom 4 bytes of Rusult down to M2
		peek Tmpb1,Tmpb2
		@bptrdec=Tmpb2
	next Tmpb1
	
	For bptr=28 to 35	'Zero Result
		@bptr=0
	next bptr
	
	
	M1High=$B3	'0.00273790932
	M1Low=$6E7F
	call Mul32by32	'Multiply seconds since 1/1/15 by 0.00273790932
	
	bptr=28	'Move top 4 bytes of Result down over bottom 4 bytes - effectively divide by 2^32
	for Tmpb1=32 to 35
		peek Tmpb1,Tmpb2
		@bptrinc=Tmpb2
	next Tmpb1
	do: @Bptrinc=0:loop until bptr>35	'Zero the top 4 bytes
	
	M1Low=SiteLongDeg-75*240	'Site Longitude East can range from 75 to 322 degrees
	M1Low=SiteLongMin*4+M1Low	'Add in minutes of Longitude (4 seconds/minute)
	M1Low=M1Low+5981	'6:39:41 - 5:00:00 (75 degrees of longitude)
	M1High=0
	call AddM1	'Add in initial hours @ 1/1/2015 + Longitude offset
	
	M1Low=hours*3600	'Determine number of seconds to current time today
	M1High=hours**3600
	TempW1=mins*60+secs+M1Low
	if TempW1<M1Low then: inc M1High: endif
	M1Low=TempW1
	
	call AddM1	'Adds in the current time
	
	bptr=23	'High byte of M1
	for Tmpb1=31 to 28 step -1	'Move bottom 4 bytes of Rusult down to M1
		peek Tmpb1,Tmpb2
		@bptrdec=Tmpb2
	next Tmpb1
	
	lp:	'Reduce seconds to less than a day
	if M1High>0 then
		If M1High=1 and M1Low<$5180 then	'if <86400
		else
			M1Low=M1Low-$5180
			if M1Low>$AE7F Then: dec M1High: endif
			dec M1High
			goto lp
		endif
	endif
	
	Hours=0
	if M1Low>43200 or M1High>0 then
		M1Low=M1Low-43200
		if M1Low>$7fff then: dec M1High: endif
		Hours=hours+12
	endif
	secs=M1Low//60
	M1Low=M1Low/60
	mins=M1Low//60
	Hours=M1Low/60+hours
	
	bintoascii hours,Tmpb1,Tmpb1,Tmpb2
	bintoascii mins,Tmpb3,Tmpb3,Tmpb4
	bintoascii secs,Tmpb5,Tmpb5,Tmpb6
	
	sertxd (Tmpb1,Tmpb2,":",Tmpb3,Tmpb4,":",Tmpb5,Tmpb6,cr,lf,cr,lf)
	serout c.4,N2400_8,("?y1?x00",Tmpb1,Tmpb2,":",Tmpb3,Tmpb4,":",Tmpb5,Tmpb6," Sidereal")
	
	'call prt64
nap 4	'sleep for 288 msecs
loop
stop
end
'-------------------------------------------------------------

Mul32by32:
'Multiply the 32 bit munmers stored in M1 & M2 & store answer in b28 - b35. Needs to be cleared initially.

'bptr=28
For Tmpb1=20 to 23
	bptr=Tmpb1+8	'needs to progress along answer location
	For Tmpb2=24 to 27
		peek tmpb1,b16
		peek tmpb2,b17
		TempW1=b16*b17
		TempW2=@bptr+b14
		tmpb3=bptr
		do
			@bptrinc=b16
			TempW2=TempW2/256
			TempW2=b16+@bptr
		loop while b17>0
		@bptrinc=b16
		
		bptr=tmpb3+1
		TempW2=@bptr+b15
		tmpb3=bptr
		do
			@bptrinc=b16
			TempW2=TempW2/256
			TempW2=b16+@bptr
		loop while b17>0
		@bptrinc=b16
		bptr=tmpb3
	next tmpb2
next tmpb1
return
'-------------------------------------------------------------
Dayint:
'Calculates the number of days since 1/1/15 & saves result in M1Low

M1Low=year-15

If M1Low>0 then
	M1Low=0: dec year
	For Tmpb1=15 to year
		M1Low=M1Low+365
		Tmpb2=Tmpb1/4*4
		if Tmpb2=Tmpb1 then
			inc M1Low
		endif
	next Tmpb1
	inc year
endif

For Tmpb1=1 to month
	if Tmpb1=month then
		M1Low=M1Low+day
	else
		read Tmpb1,Tmpb2
		M1Low=M1Low+Tmpb2
		if Tmpb1=2 then
			Tmpb2=year/4*4
			if Tmpb1=Tmpb2 then
				inc M1Low
			endif
		endif
	endif
next Tmpb1
dec M1Low 'Starts from 1/1/15 not 0/1/15
'sertxd ("M1Low=",#M1Low,cr,lf)
return			
'-------------------------------------------------------------
AddM1:
'Adds the 4 byte word M1 to the 8 byte result(bytes 28 to 35)

For Tmpb3=20 to 23
	bptr=Tmpb3+8	'needs to progress along answer location
	peek tmpb3,Tmpb2
	do
		W6=@bptr+Tmpb2
		@bptrinc=Tmpb1
	loop while Tmpb2>0	'Tmpb2 is high byte of w6 - Tmp1 is low
	next Tmpb3
return

'-------------------------------------------------------------
Prt64:
'Print out the 64 bit number starting at bptr=28 in decimal but destroys it in the process (debug only)

bptr=36		'set bptr to bottom of the remainder stack

MSBpointer=35	'MSB of long 64 bit word
LSBpointer=35-8+1	'LSB of 64 bit word

do
	b15=0	'set initial remainder to zero
	for Tmpb2=MSBpointer to LSBpointer step-1	'step through each digit of the long word
		peek Tmpb2,b14	'get the digit
		Tmpb1=TempW1/10		'calculate the quotient
		poke Tmpb2,Tmpb1		'write quotient back into long word 
		b15=TempW1//10	'carry the remainder onto the next digit
	next Tmpb2
	@bptrinc=b15				'push remainder of long word/10 onto stack
	peek MSBpointer,Tmpb1		'get the MSB of the remaining long word
	if Tmpb1=0 then: MSBpointer=MSBpointer-1:endif	'move MSB pointer down if current digit is zero
loop until MSBpointer<LSBpointer	'Finish when the original long word is reduced to zero

dec bptr
do		'print out the result
	Tmpb1=@bptrdec
	if Tmpb1<10 then
		sertxd(#Tmpb1)
	else
		Tmpb1="A"-10+Tmpb1
		sertxd(Tmpb1)
		endif
loop until bptr<36
sertxd (cr,lf)

Return

'-------------------------------------------------------------
eeprom 0,(0,31,28,31,30,31,30,31,31,30,31,30,31)
 

BillBWann

Member
For anyone who plans to implement the sidereal clock described in #13, I’ve just written a small spreadsheet to calculate the values that need to be entered into the program at lines 28 & 29. The values of your longitude and the longitude of your standard time zone are entered into the first 3 columns and the calculated values for standard time and daylight saving time are shown in the next 4 columns.

The spreadsheet contains some examples of cities around the world.

Actually, I can't attach the spreadsheet as it says its an invalid file. It seems valid to me but has it got something to do with it possibly containing a macro or something? It doesn't but some of my other spreadsheets do. I tried changing the macro security to disabling all macros and resaving it but it didn't make any difference.

Any suggestions?
 

tmfkam

Senior Member
Perhaps renaming the file extension to .pdf would work?

Alternately, zip it and upload it as a compressed archive?

Good luck and I'm sure that anyone wanting to build a similar clock to yours will be extremely grateful for your generosity.
 

techElder

Well-known member
A spreadsheet is a "potentially" dangerous file ... just as is a PICAXE BASIC file. :)

Rather than rename it to "fool" the forum software, just zip it as tmfkam says above and let the user take the responsibility of checking it on their system.

PS. At least if you zip it, the user will get all your hard work in formatting the spreadsheet, too.
 

AlanJ

New Member
PIC based sidereal clock

This might of interest to this community. I built a GPS locked sidereal clock using a PIC16F628A processor. The code is all in assembler and makes extensive use of interrupts, so I don't think it will translate to PICAXE. However, I don't know much about the PICAXE architecture so this is idle conjecture. See http://www.cashin.net/sidereal/ for the details. Apart from the 5V supply the parts cost less than AU$25.
 

BillBWann

Member
I’m embarrassed to say that I found another silly error in the longitude converter spreadsheet – this time a typing error in the daylight saving degree calculation.

Hopefully third time lucky.
 

Attachments

Top