Thursday, 30 January 2014

First Working Draft Program R/A Only

I had some time last night to fiddle about with getting the "stepdegrees" variable to work within the Hour Angle calculations. I had tried a number of different methods but the first method that work is the one below.


A quick photo of the RA stepper motor and
CW / CCW buttons being tested.

Like I have said before, I really don't know much about this C++ malarkey, so I am sure someone will be poking holes in it, please feel free to improve on it if you wish - My end game is to have a downloadable Arduino library and build plan so others can make a cheap motorised telescope mount, any assistance would be welcomed.


/*-----( Import needed libraries )-----*/
#include <Stepper.h>
#include <Wire.h> 
#include <Button.h>

unsigned long start, finished, elapsed; // Unsigned long for Sidereal day calculation

/*-----( Declare Constants, Pin Numbers )-----*/
//---( Number of steps per revolution of INTERNAL motor in 4-step mode )---
#define STEPS_PER_MOTOR_REVOLUTION 32   

//---( Steps per OUTPUT SHAFT of gear reduction )---
#define STEPS_PER_OUTPUT_REVOLUTION 32 * 64  //2048  

/*-----( Declare objects )-----*/
// create an instance of the stepper class, specifying
// the number of steps of the motor and the pins it's
// attached to

//The pin connections need to be 4 pins connected
// to Motor Driver In1, In2, In3, In4  and then the pins entered
// here in the sequence 1-3-2-4 for proper sequencing

Stepper RA_stepper(STEPS_PER_MOTOR_REVOLUTION, 8, 10, 9, 11);

Stepper DEC_stepper(STEPS_PER_MOTOR_REVOLUTION, 12, 14, 13, 15);

Stepper FOC_stepper(STEPS_PER_MOTOR_REVOLUTION, 16, 18, 17, 19);

/*
Create Button Objects
 */
Button RAscCW = Button(A0,PULLUP); //create a Button object for the Right Ascension Clockwise switch @ pin A0
Button RAscCCW = Button(A1,PULLUP); //create a Button object for Right Ascension Anti-Clockwise switch @ pin A1

Button DECCW = Button(A2,PULLUP); //create a Button object for the Declination Clockwise switch @ pin A2
Button DECCCW = Button(A3,PULLUP); //create a Button object for the Declination Anti-Clockwise switch @ pin A3

Button HNudgeBut = Button(A4,PULLUP); //create a Button object for the Hour Plus Nudge switch @ pin A4
Button MNudgeBut = Button(A5,PULLUP); //create a Button object for the Minute Plus Nudge Anti-Clockwise switch @ pin A5

Button FOCUSin = Button(A6,PULLUP); //create a Button object for the Telescope Focus IN switch @ pin A6
Button FOCUSout = Button(A7,PULLUP); //create a Button object for the Telescope Focus OUT switch @ pin A7


int Stepcount = 0; // creates a zero value for the stepcounter

int Hnudge = 0; // Nudge Hour + 1
int Mnudge = 0; // Nudge Minute + 1


float D,LSTH,LSTM,LSTS,ms; // sidereal count millis

float ihr;  // create float for output of initial convertion

float stepdegrees; // output from stepper motor in degrees


void setup()   /*----( SETUP: RUNS ONCE )----*/
{
Serial.begin(9600); // will have LCD here on final version.
}
void loop()   /*----( LOOP: RUNS CONSTANTLY )----*/
{

          if(HNudgeBut.isPressed()) // Hour Nudge Button + 1
          {
            Hnudge++;
          } 
          if(MNudgeBut.isPressed()) // Hour Nudge Button + 1
          {
            Mnudge++;
          } 
          if(RAscCCW.isPressed()) // Right Ascension Clockwise Slew
          {
            RA_stepper.setSpeed(900);   // speed
            RA_stepper.step(-50);       // step value per cycle - too high == lack of sensitivity / too low == poor slew rate/stutter
            Stepcount -=50;                // stepcount must equal step value per cycle.
          }
          if(RAscCW.isPressed())
          {
            RA_stepper.setSpeed(900);   // speed
            RA_stepper.step(50);        // step value per cycle - too high == lack of sensitivity / too low == poor slew rate/stutter
            Stepcount +=50;                // stepcount must equal step value per cycle.
          }
          else
          {
            RA_stepper.setSpeed(300);  // Adjust to equal 0.2507 Degrees of Right Ascension per minute 
            RA_stepper.step(1);        // step value per cycle, 1 is OK for low speeds, may need to change once fitted to mount and tested
            Stepcount ++;                 // stepcount must equal step value per cycle.
          }
  
 int Hnudge; // Nudge Hour + 1
 int Mnudge; // Nudge Minute + 1
 float ihr;  // create float for output of initial convertion
 float stepdegrees; // output from stepper motor in degrees
 

 stepdegrees = ((Stepcount/5.68)/10)+37.954; // when the Arduino is "reset" @ polar alignment the count will start at pos; 37.954541 degrees *location of polaris*

 Hnudge = 0;                  // Sidereal clock set Hour nudge
 Mnudge = 0;                  // Sidereal clock set Minute nudge
 ihr = ((stepdegrees/15));   // divides total degrees into number of hours in an sidereal day (15 degrees per hour)

 float D,LSTH,LSTM,LSTS,ms;   // Local Sidereal time calculator, with nudge control for setting the clock.
 unsigned long over;
 elapsed=(((ihr*3600000)+(Hnudge*3600000)+(Mnudge*60000))+start); // elapsed is the ajustable hour angle in milliseconds = Right Ascension + Hour set + Minute Set + Elapsed Time 
 D=int(elapsed/86164091);                                         // = 23 hrs 56 mins 4 seconds = Sidereal day
 over=elapsed%86164091;                                           // +1 Sidereal day
 LSTH=int(elapsed/3600000);                                       // = 60 minutes
 over=elapsed%3600000;                                            // + 1 hour
 LSTM=int(over/60000);                                            // = 60 seconds
 over=over%60000;                                                 // + 1 Minute
 LSTS=int(over/1000);                                             // = 1000 ms
 ms=over%1000;  

 Serial.print("H = " );                       
 Serial.print(LSTH);      
 Serial.print("\t M= ");      
 Serial.print(LSTM); 
 Serial.print("\t S= ");      
 Serial.print(LSTS); 

}


/* --(end main loop )-- */

/* ( THE END ) */

So, the bulk of this has been covered in my post on calculating the Hour Angle, however this also incorporates the Right Ascension motor control, with a temporary output to a Serial.print so I can see if it is working without hooking up an LCD display.

I am using an additional library which you will need if you want to use or modify my work:

Alexander Brevig's excellent Button.h library; http://playground.arduino.cc/Code/Button makes writing button/switch etc. dependant functions really simple and clear, he also has some good additional latching features which I have recently used in other little projects I am working on.

So, as mentioned the additional code is for controlling the Right Ascension stepper motor, currently in 3 distinct ways - Following a comment on my Stargazer Lounge Thread for this project I am also looking at allowing variable speed on the slew function, but for now this is where I am:


Button RAscCW = Button(A0,PULLUP); //create a Button object for the Right Ascension Clockwise switch @ pin A0
Button RAscCCW = Button(A1,PULLUP); //create a Button object for Right Ascension Anti-Clockwise switch @ pin A1


This is creating Button functions with the names for clockwise and anti-clockwise Right Ascension Slew. It is called upon by;

 if(RAscCW.isPressed()) // Right Ascension Clockwise Slew

  {
    RA_stepper.setSpeed(900);   // speed
    RA_stepper.step(50);       // step value per cycle - too high == lack of sensitivity / too low == poor slew rate/stutter
    Stepcount +=50;                // stepcount must equal step value per cycle.
  }

Where if the clockwise Button is pressed the stepper motor will rotate clockwise at 900 steps per second (faster than previously cited, I have been fiddling). Although the rate is 900 steps per second it will only move 50 steps at a time as denoted by "RA_stepper.step (50), this means that if you let go of the button the motor will stop after 50 steps, if this is higher the motor will continue to move long after releasing the button.


if(RAscCCW.isPressed())
  {
    RA_stepper.setSpeed(900);   // speed
    RA_stepper.step(-50);        // step value per cycle - too high == lack of sensitivity / too low == poor slew rate/stutter
    Stepcount -=50;                // stepcount must equal step value per cycle.
  }

This is the next "if" function, basically the same slewing motion but anti-clockwise.



else
  {
    RA_stepper.setSpeed(300);  // Adjust to equal 0.2507 Degrees of Right Ascension per minute 
    RA_stepper.step(1);        // step value per cycle - too high == lack of sensitivity / too low == poor slew rate/stutter
    Stepcount ++;                 // stepcount must equal step value per cycle.
  }

Here we see an "else" statement, whereby if neither slew button is pressed the system will automatically track on the right ascension.

You may have noticed each of the above functions has "Stepcount xxxx" this an incrementing function which is equal to the number of steps made per function cycle. This is how the program knows the number of steps taken and therefore the position of the mount, more detail of that is explained in my first programming post. 


DIY Equatorial Tracking Mount Idea

This is a bit backward, as I should have posted this before the programming part, but hey ho!

This Christmas (2013), my most awesome wife surprised me with a Celestron Travelscope, a small refracting telescope mainly for lunar and planetary observations; which she may be starting to regret! I am now hooked on astronomy and want to see more and start photographing my views too.

The Travelscope is an excellent low powered wide field scope perfect for lunar viewing and some astrophotography.  But, the mount does let it down, something my wife had researched and warned me about.

So, I like a challenge and started looking at what mount options are out there - not knowing a single thing about any of them! 

I wanted to make the mount more sturdy, primarily and easier for AP. So, after some research it made sense to concentrate my ideas on the Equatorial Mount style as this it is much easier to track object during long exposures with an equatorial mountA little bit about mounts; I am just a beginner so don't rely on my explanations at all! If you want to know more about the two options Wikipedia actually have some pretty good information:



So you can see why I chose the Equatorial design - once set up you just need a 'simple' tracking motor to run at a fixed rate that equals the earth's rotation; 365ยบ/day. How on earth was I going to do this cheaply without effecting the quality (too much) and in a way that I could scale up simply as my new found hobby expanded? ? ? In my day job I have to overcome substantial engineering hurdles while simultaneously answering to my MD with regards to keeping costs to minimum; so I like to think I am pretty good at this - or perhaps I am just good at making people think I've spent less on development worj? Yeah, probably the latter....No, definitely the latter... anyway,  this is my money, so I'm going to be a tight fisted Scrooge!!

I had seen some "pipe" based mounts online which seemed to be in the sort of ball park I was thinking about:

Here and Here.

But I really wanted to make something I could scale simply and without access to a lathe or mill (anymore) I decided to look at PVCu plastics, I design with the them on a daily basis, so know the range of fittings well. The goo thing about PVC is that they come with a massive range of solvent weld reducing bushes, many of them coincide nicely with standard bearing housings:

Standard ABEC "609" bearings have an OD of 22mm and a 1/2" reducing bush has an ID of 21.70mm with a + only tolerance, they fit nicely! There are also larger sizes which fit too. My advice would be to get a standard bearing chart and a PVCu pipe OD chart (this is what the reducing bushes mate with and find the size you are after:

A metric bearing chart is here; http://www.bearingworks.com/bearing_sizes/index.php

A PVCu pipe diameter chart can be seen below, these are nominal as they are extrusions and generally the reducer will have a decent tolerance of up to 0-5 - 0.8mm:




So, I had established that I could use standard bearings and PVCu pipe to make the mount, but how was I going to do it and what parts should I use.

I have drawn up a quick 3D model showing my proposed idea proposed idea, they are very vague at the moment but indicative of my plan, I have chosen to use 1 1/4" fittings with 1/2" reducers running 22mm bearings (10mm bore):

The red shows the two main axis, motors are floating in mid air for the time being
counter weight not shown.
Showing the press-fit bearing idea in a bit more detail:







I will try an update this further soon, I have got the parts and have been dummy-ing it all up, I will do another page on the assembly process when I get to it.

PVCu pipe can be brought from lots of places, I have a commercial supply, but Pipestock is good in the UK for small quantities:


If you have any questions feel free to email me, or contact me on Stargazing lounge, where I have started a discussion about the idea:







Wednesday, 29 January 2014

Initial Arduino Programming for a Tracking Mount

I had been thinking about buying an Arduino for a very long time, but could never really work out what to make with one! I have never done any C++ programming before but I have had experience with CNC coding in the past when I was working in manufacturing engineering (predominantly 9 axis Fanuc and Mazatrol) so I understand the concepts in programming quite well, even if the applications are million miles apart.

I will say this early. I am NOT in any shape or form an expert in C++ language or even arduino in general I first looked at the language on Boxing day 2013 (5 weeks ago), what I have learned is pretty basic and done through experimenting and trawling the Arduino Website for hours on end - there is a lot of really useful info on there.

Also, there are definitely more accurate ways of calculating the following functions and probably simpler ways too, but this is what I decided to do and how I have decided to it is based on the following points:


  • It is accurate enough to last a whole evening (does it need to be any more accurate??)
  • It doesn't need a Real Time Clock / permanent power supply.
  • It doesn't need to be connected to a PC.
  • And, most importantly, I was able to write the program with my limited skills!!
As with all control designs, I started with a control philosophy. I tried lots of things before settling for (conceding) the following:

There will be 3 no. stepper motors controlling:

  1. Focusing (possibly, not urgent though)
  2. Right Ascension / Hour Angle (2 speeds, Slew and Tracking).
  3. Declination.
Declination and the Focusing are both quite simple in concept, so I will go into them once I have explained the Right Ascension. Basically Right Ascension  "is the angular distance measured eastward along the celestial equator from the vernal equinox to the hour circle of the point in question." 


There are some good explanations of Right Ascension on-line (Here and Here). BUT, the problem with Right Ascension is that the Earth's time is not as we now it; we all know we have leap year every 4 years, it doesn't affect us any more than an extra day once in a while so no-one really appreciates it - well for calculating a celestial co-ordinate it is a bloody pain in the ass!

  • Earth Day according to GMT/UTC is 24 hrs 00 mins 00 seconds with a 4 year synchronisation (and on occasion other smaller corrections).
  • Sidereal Day (actual time it takes for a full 360 degree rotation of Earth is 23 hours, 56 minutes, 4.0916 seconds.
So the Right Ascension of any given point in the sky changes by about 4 minutes a day, this shift is compensated and is called the Hour Angle;


LHA is the Localised Hour Angle for the Object you are trying to locate.
LST is your Local Sidereal Time.
xobject is the Right Ascension of the object you are trying to locate.

So, to the coding, in order to create a usable system for object locating we need to do a few things:
  1. Convert the polar alignment "start position" (polaris) Right Ascension into an angle (so that the stepper motor position can be used to create a "live" Right Ascension figure.
  2. Convert the Right Ascension angle into an hour angle by removing the the current sidereal time from it.
  3. Convert the final decimal into a readable "time stamp" so you can slew to a given Hour Angle and view the object you are slewing too!
This was not as simple as I had initially thought it to be, there were many ways I could have achieved this, they were either expensive (not really, but more than I wanted to spend), time consuming, not suited to my personal preference or just plain out of my range of knowledge, they included:

  • Using a RTC and coding it for LST - I didn't want the hassle.
  • Using serial time from the PC and coding a scaling factor on the Epoch for LST. - very complex for me and I didn't want to have to be connected to a laptop all the time.
  • GPS timing - too pricy for this project.

I decided on something relatively simple.

Sidereal time is complex to keep for long periods dues to the disparity between itself and UTC, however as long as you not pass 23 hours and 56 minutes it is for all intents and purposes, just UTC, shifted. People will be shouting at their keyboards. I don't care. I have spent many years in engineering and I have learnt many things, the most important thing is and always will KISS - Keep It Simple, Stupid. For my clients I call it "appropriate technology" it offends them less!

  • How long am I using the telescope for at a time? - A whole night, tops - less than 23 hours and 56 minutes.
  • Will it be accurate for that time period? Yes.

Right, so the idea is that we have the Right Ascension for polaris hardcoded into the Arduino (02h 31m 49.09s) as decimal degrees. when you polar align, you then press Hour, Minute and Second buttons to set the time to Sidereal time, this will in effect give you 23 hours and 56 minutes of accurate LHA tracking without having to actually calculate LST.

LST can be entered using a LST app or from This Sidereal Clock.

How does this translate into C++

Well this was my first attempt, it is basically a calculator, and didn't work very well, but it may help people understand the basics of right ascension and it's relationship with a real angle so I have included it with explanations.

First we need to create all the variables required to make the counting system work:

int H; // output of truncated float for Hours
int M; // output of truncated float for Minutes

int Hnudge; // Nudge Hour + 1
int Mnudge; // Nudge Minute + 1

int HAH; // Hour angle from Right Ascension minus Local Sidereal time
int HAM; // Hour angle from Right Ascension minus Local Sidereal time
float HAS; // Hour angle from Right Ascension minus Local Sidereal time

float ihr;  // create float for output of initial conversion
float imin; // create float for output of initial conversion
float S; // create float for output of Seconds, no conversion needed, decimals wanted.
float stepdegrees; // output from stepper motor in degrees

  1. int H will be used to create something called a truncated output, in this instance it gives us only the integer from a decimal time i.e. 2.51 hours would give only an hour integer of 2, which is correct - it will not round up, this is very important.
  2. int M is the same but for minutes.
  3. int Hnudge and Mnudge are variables for buttons whereby if the corresponding button is pressed the Xnudge values increases by 1 - not currently programmed.
  4. int HAH and HAM are final compensated time integers.
  5. float HAS is a float, this means it can handle decimals and will output a true reading rather than a truncated one like "int" this is used against the truncated figure to get the time in seconds.
  6. float ihr, imin and S are the initial float variables in the right ascension calculation, relating to the idea in point 5.
  7. float stepdegrees is the output from the stepper motor count in degrees i.e. where the telescope is pointing in a raw decimal degree figure.

Here is the code for the actual calculation, I'll try to explain it below with a worked example;


int Hnudge; // Nudge Hour + 1
int Mnudge; // Nudge Minute + 1
float ihr;  // create float for output of initial conversion
float imin; // create float for output of initial conversion
float RAS; // create float for output of Seconds, no conversion needed, decimals wanted.
float stepdegrees; // output from stepper motor in degrees

int RAH; // output of truncated float for Hours
int RAM; // output of truncated float for Minutes

stepdegrees = (Stepcount/5.68); // 5.68 degrees per step

Hnudge = 0;                  // Sidereal clock set Hour nudge
Mnudge = 0;                  // Sidereal clock set Minute nudge
ihr = ((stepdegrees/15));   // divides total degrees into number of hours in an 
sidereal day (15 degrees per hour)
RAH = ihr - 0.5;            // ensures that the output in hours is always rounded down to show correct value in "time form"

imin = ((ihr - RAH)*60);   // multiplies the remainder of stepdegrees minus rounded hours and multiplies by 60 to convert to minutes.
RAM = imin - 0.5;            // ensures that the output in minutes is always rounded down to show correct value in "time form"

RAS = (((imin - RAM)*60));   // multiplies the remainder of stepdegrees minutes minus rounded minutes and multiplies by 60 to convert to seconds, this is float so also includes 10ths.



This may look like complete gobbledegook, but it is basically fairly simple algebra whereby all the variables we started earlier are being used in a fixed way to create an output. I am really rubbish at explaining myself, I am told this daily, but I will try:

At the beginning of the code we have added a couple of additional variables RAH, RAM and RAS, as I mentioned earlier we are using an integer variable to create our readable output, in order to create the "truncated output" mentioned before we have to create an integer which will always give us the correct Hour, Minute or Second for a given decimal:

if, ihr = 2.516 hours then RAH = 2.516 - 0.5 = 2.016, which as an int = 2
if, ihr = 2.016 hours then RAH = 2.016 - 0.5 = 1.516, which as an int = 2

Edit: Thanks to Tom (TCWORLD) from the Stargazer's Lounge, this was creating an error and most likely the cause of my other problems further down; polaris is more than 30 minutes into an hour (>0.5) so, this code actually worked by accident while I was initially testing. Tom correctly points out that as the float to int cast is only truncating the results would be as follows for some given floats:


2.016 -> 2
2.980 -> 2
1.999 -> 1
1.516 -> 1

This would give anything with a right ascension of less than 30 minutes past the hour the incorrect hour.

This code was already redundant following my updates, but for anyone thinking they could use this elsewhere; it doe not work. Will - 31-01-2014, 13:21.

This is what is called truncating the output, it allows us to show any decimal pertaining to an hour as a single integer and the correct one regardless of rounding, to boot.

We then need to do the same for the Minutes to get a sensible reading:

the code states that; imin = (ihr - RAH)*60 this means that imin is equal to the remainder of the hour decimal minus the truncated result:

imin = 2.516 - 2 = 0.516 * 60 (to turn the figure into minutes) = 30.96 minutes

this needs to be truncated to give a minute integer

RAM = (imin - 0.5)   =  30.96 - 0.5   = 30.46 = int = 30.

RAS = (imin - RAM) * 60  =  30.96-30  = 0.96 * 60 = float = 57.60 seconds.

So that process has taken a decimal hour figure and created 2 sets of integers and a float, printed like so:

2.516 hours is equal to 2h : 30m : 57.60 s. 

I couldn't get this code any further than creating a fixed result it didn't integrate well once a clock counter (millis) was introduced. Learning curves, aye! - See edit above for why!!!




All was not lost though, I actually ended up with something much more simple using the unsigned long function and adding the decimal angle of the Right Ascension of polaris + the stepper position to the millis() count before the  unsigned long function to create the Hour Angle offset as follows:


 int Hnudge; // Nudge Hour + 1
 int Mnudge; // Nudge Minute + 1
 float ihr;  // create float for output of initial convertion
 float stepdegrees; // output from stepper motor in degrees
 

 stepdegrees = ((Stepcount/5.68)/10)+37.954; // temporary fixed angle for testing will be a "stepcount * no. degrees/step" where stepcount will have a button starting the count at 37.954541 degrees *location of polaris*

 Hnudge = 0;                  // Sidereal clock set Hour nudge
 Mnudge = 0;                  // Sidereal clock set Minute nudge
 ihr = ((stepdegrees/15));   // divides total degrees into number of hours in an sidereal day (15 degrees per hour)
 
 float D,LSTH,LSTM,LSTS,ms;   // Local Sidereal time calculator, with nudge control for setting the clock.
 unsigned long over;
 elapsed=(((ihr*3600000)+(Hnudge*3600000)+(Mnudge*60000))+start); // elapsed is the ajustable hour angle in milliseconds = Right Ascension + Hour set + Minute Set + Elapsed Time 
 D=int(elapsed/86164091);                                         // = 23 hrs 56 mins 4 seconds = Sidereal day
 over=elapsed%86164091;                                           // +1 Sidereal day
 LSTH=int(elapsed/3600000);                                       // = 60 minutes
 over=elapsed%3600000;                                            // + 1 hour
 LSTM=int(over/60000);                                            // = 60 seconds
 over=over%60000;                                                 // + 1 Minute
 LSTS=int(over/1000);                                             // = 1000 ms
 ms=over%1000;  

I'll try to explain how this is working on the back of the previous explanation of the right ascension calc above.

So in the background we have the microprocessor counting continuously in milliseconds, this count is being used to calculate all the timings in this program so everything interacting with it must be scaled to the same units:

Firstly we start with a step count from the stepper motor for argument sake 500. Each step has an angular value of 5.68 degrees and it is attached to a 10:1 drive so 500 steps is equal to:

(500/5.68)/10 =  8.803 degrees.

We then need to add the value of polaris to this, so that during polar alignment the system is "zeroed" to the celestial pole;

8.803 + 37.954. this has been designated as "stepdegrees" it will always equal the value of the step count in degrees plus polaris.

To convert this to a decimal hour we need to divide by how many degrees the earth rotates in 1 hour. this is 15 degrees;

ihr = stepdegrees/15   ==  46.757 / 15 = 3.1171 hours.

Then in order to add this value to the millisecond count we need to convert it to milliseconds

3.1171 * 3600000.

Then, we need to account for the Local Sidereal Time adjustment, as explained this is just an offset to keep the system simple. Each time the nudge buttons are pressed they increase the value by an increment of one so we need to scale each increment to the value they are supposed to represent in milliseconds, also:

+ (Hnudge * 3600000) + (Mnudge * 6000)

Plus the millisecond count;

+start

So, as the motor position changes so does the time relative to both the celestial co-ordinate AND Local Sidereal Time. Success.

Now to make the the time readable by a human and equal to the Hour Angle within something like stellarium:

unsigned long, over = a counting function which will roll over and count sets of numbers based on the value, this can be used quite simply to turn the complex mess above into a simple clock time:



 elapsed=(((ihr*3600000)+(Hnudge*3600000)+(Mnudge*60000))+start); // elapsed is the ajustable hour angle in milliseconds = Right Ascension + Hour set + Minute Set + Elapsed Time 
 D=int(elapsed/86164091);                                         // = 23 hrs 56 mins 4 seconds = Sidereal day
 over=elapsed%86164091;                                           // +1 Sidereal day


D is equal to how many times the "ihr" has gone over 86164091ms (a sidereal day)


 LSTH=int(elapsed/3600000);                                       // = 60 minutes
 over=elapsed%3600000;                                            // + 1 hour



LSTH is equal to how many times the "ihr" has gone over 3600000ms within 86164091ms (hours)


 LSTM=int(over/60000); // = 60 seconds  over=over%60000;                                                 // + 1 Minute


LSTM is equal to how many times the "ihr" has gone over 60000ms within 36000000ms (minutes)


 LSTS=int(over/1000);                                             // = 1000 ms
 ms=over%1000;  

LSTS is equal to how many times the "ihr" has gone over 1000ms within 60000ms (seconds)


I hope that has made some sense, I have since done some work on compiling this into a program with all the buttons and stepper motor controls. I will upload this in full once completed so anyone can hopefully replicate the whole build for cheap tracking telescope mount with joypad controlled driven "point to" capabilities!

If you have any questions, please feel free to email me.