Introduction: Star Track - Arduino Powered Star Pointer and Tracker
Star track is an Arduino based, GoTo-mount inspired star tracking system. It can point and track any object in the sky(Celestial coordinates are given as input) with 2 Arduinos, a gyro,RTC module,two low-cost stepper motors and a 3D printed structure.
In the first step, I'm going to introduce you to the basics of Positional Astronomy. Next, I'll explain the idea behind this project. I'll give you the Tinkercad links for the 3d printed parts. So you can edit them to your preferences. Also, I'll include a troubleshooting guide based on the problems I encountered during this build. This way you don't have to build the same thing. Maybe you can find a better algorithm to track the stars. Or you can develop the structure and use bigger motors to drive a telescope? Your imagination (and resources of course :')) is the limit. Let me know about your build!
EDIT:
This instructables was featured on,
IMPORTANT!:
This project includes laser pointers thus needs safety measures before use. In many countries, it is illegal to point lasers to an Aircraft and to use them near airports. For more information please check: http://www.laserpointersafety.com/
IMPORTANT NOTE:
You can use a cheap red dot sight instead of the laser. This will avoid all the issues with the laser (eye safety, legal issues, airplanes).( thanks for the feedback of Marty on Hackaday)
Step 1: A Little Bit of Positional Astronomy
In order to track the stars, you have to know the basics of the Celestial Coordinate System. Celestial coordinates define positions of objects in the sky. It's based on the observations of ancient astronomers. They believed that the earth was motionless and at the center of the universe. The sky, they thought , was a moving sphere surrounding Earth, a celestial sphere.[1] In its modern sense, as used in astronomy and navigation, the celestial sphere is an imaginary rotating sphere of undefined radius. All objects in the sky can be thought of as lying upon the sphere.[2] Unlike planets, since the distance between stars and Earth is gigantic, we can simplify the positions of the stars by projecting them on an imaginary sphere.
There are differents ways to specify a objects location on the celestial sphere, These differ in their choice of fundamental plane, which divides the celestial sphere into two equal hemispheres along a great circle.
Each coordinate system is named for its choice of fundamental plane:
Equatorial System
I chose the Equatorial system for this project. Because the altitude and azimuth of a star are constantly changing, it is not possible to use the horizontal coordinate system in a catalogue of positions. And since this project will track the objects in the sky based on the coordinates given. we need a coordinate system for cataloguing purposes. One based on the celestial equator and the celestial poles and defined in a similar manner to latitude and longitude on the surface of the Earth. In this system, known as the equatorial coordinate system, the position of an object is defined by the declination and right ascension. And the coordinates of an object in the sky do not change relative to your position.[3]
Equatorial Coordinates on Celestial sphere
Like Earth, the celestial sphere also has an equator, north pole and a south pole called celestial equator, celestial north pole, and celestial south pole. These are just projections of Earths equator,north pole and a south pole on the celestial sphere.
Like coordinates on earth (longitude and latitude), two coordinates define a point on the celestial sphere, Declination, and Right Ascension.
Declination
The coordinate indicating where an object is between the celestial poles is declination. Measured from the celestial equator it ranges from 0° to 90° at the north celestial pole and to -90° at the south celestial pole.[4]
Right Ascension
The second coordinate Right Ascension(RA). It is like (but not the same as) longitude. It locates where a star is along the celestial equator. It has a zero reference point like green which, called the Vernal Equinox Point (we will get into locating that later).[4] Unlike Declination, Right Ascension changes with time(rotation of the earth) And the coordinate of Right Ascension is not in degrees but in hours minutes and seconds. The celestial sphere will make a full rotation in 24h sidereal time (ie if a stars coordinates are 20 dec, 5h RA. After 2 hours the coordinates will be 20dec,7hRA.) Since 360/24=15 1 hour of RA is 15 degrees.
Sidereal Time
Sidereal time is different than solar time. A sidereal day is about 4 minutes less than a solar day. Because of the Earths orbit around the sun. I'm not going into details on how to calculate Sidereal time. I will include some links below if you are interested. You can use a Sidereal calculator. Local Sidereal Time (LST) indicates the Right Ascension on the sky that is currently crossing the Local Meridian. So, if a star has a Right Ascension of 05h 32m 24s, it will be on your meridian at LST=05:32:24.[5] In other words, if you face the north at 0h Local Sidereal Time. the Vernal Equinox Point(0h Ra) will be right above you. to understand it more clearly open this animation
http://astro.unl.edu/classaction/animations/coords...
select your location and hit start animation, You will see a line rotating. when that line is above the stick figure it is 0h Local sidereal time.
Here is a demonstration of Equatorial Coordinates on Celestial sphere by UNL Astronomy.
Celestial-Equatorial (RA/Dec) Demonstrator
How to Locate the North Celestial Pole
Now we know the coordinate system of the celestial sphere. But how do we locate a reference point to use our coordinate system? The North Celestial Pole will only change with your latitude. And can be located easily by the north star. Here is an interactive demonstration, you can change the latitude and hit the switch so you can see where the celestial sphere is located.
Celestial and Horizon Systems Comparison
Also here you can animate the movement of an object on the celestial sphere:
Note:
I did not get into details since this is something like an introduction to positional astronomy. If you want to learn more I will include the links that were really helpful for me. There are also problems that you can solve to practice what you have learned. This way you will be able to calculate the coordinates of a star with a given latitude and time.
Further Reading:
History - http://csep10.phys.utk.edu/astr161/lect/retrograde...
RA and DEC - http://www.physics.csbsju.edu/astro/sky/sky.11.htm...
Celestial Sphere - http://www.astronomyforbeginners.com/astronomy/cel...
Coordinate Systems - https://dept.astro.lsa.umich.edu/ugactivities/Labs...
Celestial Coordinates - http://sbo.colorado.edu/SBO_OLD_SITE/sbo/astroinfo...
Finding Astronomical Objects - https://www.saddleback.edu/faculty/mhaeri/document.. .
Local Side Real Clock converter - http://www.jgiesen.de/astro/astroJS/siderealClock/
How to Calculate Sidereal time - http://aa.usno.navy.mil/faq/docs/GAST.php
References:
[1]http://www.skyandtelescope.com/astronomy-resources...
[2]http://www.newworldencyclopedia.org/entry/Celestia...
[3]http://www.jtwastronomy.com/tutorials/celestial_co...
Step 2: The Idea
Many computerized telescopes have a type of telescope mount and related software which can automatically point a telescope to astronomical objects that the user selects. Called GoTo mounts. Like a standard equatorial mount, equatorial GoTo mounts can track the night sky by driving the right-ascension axis[1]
Since laser pointers are a perfect way to point stars, I thought a laser pointer with a GoTo mount would be a perfect tool for locating stars and to track them.
First I had to design a 2-axis mount.
- 360-degree rotating axis for RA
- A up-down axis for DEC
After aligning the RA axis with the North Celestial Pole, an Arduino connected with an RTC should be able to calculate and track RA with sidereal time. And you can adjust the 2 axes to the user input from a computer via serial.
But first I had to find a way to precisely point the mount to given degrees. The main idea was to use step motors and give them a specific step to take. But after a few tests I found out that the pointing was not accurate(a few degrees).
Instead, I used a gyroscope placed on the laser pointer to track the degrees on the two axes, this way I was able to send a command to the step motor to start and stop the movement if necessary.
Step 3: Tools & Parts
I used two Arduino's in this project(due to the lack of digital pins).One to control the motors, the other to process the gyro data and send commands to the other Arduino(Master-slave) I had an Uno and nano lying around so I used them. You can use other Arduino's as well.
Here are the main parts I used in this project:
5v Stepper Motor(x2) - 3.68$
Arduino Uno r3 clone - 5.80$
Arduino nano clone- 2.18$
3-Axis Gyro - 2.03$
RTC - 1.07$
______________________________________
Total - 14,76$
Also,
- Lots of jumper cables
- 30x47x11mm thrust ball bearing(again you can use a bearing you like but have to change the dimension on the parts.)
- (10x) M3 bolts and nuts
- (4x) 623 2RS bearings (I had these bearings at the moment. You can use any bearing, but you have to adjust the pieces from tinkercad to your dimensions.
- X-acto knife
- Superglue
- A laser pointer(recommended)
Step 4: Designing the Parts
The first part to design is the base. I thought of a delta type base plate so I can attach 3 legs and adjust them. Here is the Base plate You can edit it on tinkercad as you like. I will also include all .stl files in a zip folder.
The Base
Base Screw
Tripod Mount (Attached to the base)
Pitch(DEC) Mount
Gyro Mount
The Base Gear
Note: I'm giving these tinkercad links so you can change the parts to your preferences. All the other files including these are in the Parts.zip folder.
The Gears
Now for the most important part, designing the gears. I tried to create the gears in Autodesk Inventor but later I found a gear generator tool that generates gears to a .stl file. This was a life-saver for me.
http://joostn.github.io/OpenJsCad/
I printed the parts with a prusa i3 3d printer.
Step 5: Assembly-Base Structure
Step 6: Assembly - Electronics
Step 7: Code
How Does it Work?
There are two Arduino's working in order. Arduino Uno being master and nano being the slave.
Master module
The master(Uno) module has two inputs,
- Gyro data
- RTC(Real Time Clock) data
and 6 outputs,
- cw(base motor clockwise)
- ccw(base motor counter clockwise)
- stahp(base motor stop)
- cw2(DEC motor clockwise)
- ccw2(DEC motor counter clockwise)
- stahp2(DEC motor stop)
The RTC is set to UTC time, a function calculates local sidereal time in degrees and rotates the mount to 0h RA position. The loop constantly checks if the gyro data is equal to the user input & sidereal time data. The default is 0,0. If there is a change and the equality breaks the master module send a command to the slave module.
- If the user value is higher than the gyro value a signal is sent through cw the motor turns clockwise.
- If the user value is less than the gyro value a signal is sent through ccw the motor turns counter clockwise
- If the user value is equal to the gyro value a signal is sent through stahp and the motor stops
same for cw2,ccw2,stahp2.
This way the mount will turn to the user-specified coordinates. And update with sidereal time thus it will track the sky.
Note: I could use serial communication between the two Arduino's but since the analog pins are used by the inputs I had to use digital pins.
I uploaded the code to github so I can update it from one place:
https://github.com/gocivici/Star-Track
Master module code:
/*
This is the source code for the master-module of Star Track.
Required Libraries:
https://virtuabotix-virtuabotixllc.netdna-ssl.com...
https://github.com/jrowberg/i2cdevlib/zipball/mas...
Created 20 July 2016 by Görkem Bozkurt
*/
#include <virtuabotixRTC.h>
#include <Wire.h>
#include <MPU6050.h>
MPU6050 mpu;
//define RTC.
virtuabotixRTC myRTC(A0, A1, A2);
double M,Y,D,MN,H,S;
double A,B;
double location =32.88;//your longtitude
double LST_degrees;//variable to store local side real time(LST) in degrees.
double LST_hours;//variable to store local side real time(LST) in decimal hours.
unsigned long timer = 0;
float timeStep = 0.01;
// Pitch and Yaw values
double pitch = 0;
double yaw = 0;
double val = 0;//variable to store the user input DEC
double val2 = 0;//variable to store the user input RA
double temp = val2;//temporary value to store val2
const int stahp=7,stahp2=10;
const int cw=8,cw2=11;
const int ccw=6,ccw2=9;
void setup() {
//set date-time according to (seconds, minutes, hours, day of the week, day of the month, month, year)
myRTC.setDS1302Time(00, 38, 23, 5, 27, 7, 2016);
Serial.begin(115200);
pinMode(stahp,OUTPUT);
pinMode(cw,OUTPUT);
pinMode(ccw,OUTPUT);
pinMode(stahp2,OUTPUT);
pinMode(cw2,OUTPUT);
pinMode(ccw2,OUTPUT);
delay(5000);//wait before starting
while(!mpu.begin(MPU6050_SCALE_2000DPS, MPU6050_RANGE_2G))
{
}
mpu.calibrateGyro();
mpu.setThreshold(3);
}//--(end setup )---
void loop()
{
//this will update the RA degrees with sidereal time 1degree at a time
//this way the object or star on the sky is tracked.
if( floor(LST_degrees)==LST_degrees ){
if (LST_degrees>180){
val2 = temp+(360-LST_degrees);
}else{
val2 = temp-LST_degrees;
}
}
myRTC.updateTime();
LST_time();
recvdata();
pitch_check();
yaw_check();
timer = millis();
Vector norm = mpu.readNormalizeGyro();
//I've put the sensor with a 90 degree angle on the setup due to
//cable connection problems. Because of that the data values from the mpu6050 chip are
//different in this case:
//roll data(X-axis) is pitch.
//pitch data(Y-axis) is yaw.
yaw = yaw + norm.YAxis * timeStep;
pitch = pitch + norm.XAxis * timeStep;
Serial.print(" Yaw = ");
Serial.print(yaw);
Serial.print(" Pitch = ");
Serial.print(pitch);
Serial.print(" LST_d = ");
Serial.print(LST_degrees);
Serial.print(" LST_h = ");
Serial.println(LST_hours);//local sidereal time in decimal hours.
delay((timeStep*1000) - (millis() - timer));//timer for the gyro.
}
void recvdata(){
//This function receives data from serial as (0.00,0.00)
//splits it to strings by the comma ","
//than converts them to doubles
if (Serial.available() > 0){
String a= Serial.readString();
String value1, value2;
// For loop which will separate the String in parts
// and assign them the the variables we declare
for (int i = 0; i < a.length(); i++) {
if (a.substring(i, i+1) == ",") {
value2 = a.substring(0, i);
value1= a.substring(i+1);
break;
}
}
val=90-value1.toFloat();
val2=value2.toFloat();
temp = val2;
}
}
void pitch_check(){
//check if pitch is high, low or equal to the user input
//send commands to slave-module to start and stop motors
if(floor(pitch*100)/100==floor(val*100)/100){
digitalWrite(stahp,HIGH);
}else{
digitalWrite(stahp,LOW);
}
if(floor(pitch*100)<floor(val*100)){
digitalWrite(cw,HIGH);
}else{
digitalWrite(cw,LOW);
}
if(floor(pitch*100)>floor(val*100)){
digitalWrite(ccw,HIGH);
}else{
digitalWrite(ccw,LOW);
}
}
void yaw_check(){
//check if yaw is high, low or equal to the user input
//send commands to slave-module to start and stop motors
if(floor(yaw*100)==floor(val2*100)){
digitalWrite(stahp2,HIGH);
}else{
digitalWrite(stahp2,LOW);
}
if(floor(yaw*100)<floor(val2*100)){
digitalWrite(cw2,HIGH);
}else{
digitalWrite(cw2,LOW);
}
if(floor(yaw*100)>floor(val2*100)){
digitalWrite(ccw2,HIGH);
}else{
digitalWrite(ccw2,LOW);
}
}
void LST_time(){
//Calculates local sidereal time based on this calculation,
//http://www.stargazing.net/kepler/altaz.html
M = (double) myRTC.month;
Y = (double) myRTC.year;
D = (double) myRTC.dayofmonth;
MN = (double) myRTC.minutes;
H = (double) myRTC.hours;
S = (double) myRTC.seconds;
A = (double)(Y-2000)*365.242199;
B = (double)(M-1)*30.4368499;
double JDN2000=A+B+(D-1)+myRTC.hours/24;
double decimal_time = H+(MN/60)+(S/3600) ;
double LST = 100.46 + 0.985647 * JDN2000 + location + 15*decimal_time;
LST_degrees = (LST-(floor(LST/360)*360));
LST_hours = LST_degrees/15;
}
Slave Module:
/*
this is the source code for the slave module of Star Track
Required Libraries:
http://www.airspayce.com/mikem/arduino/AccelStepper/AccelStepper-1.51.zip
Created 20 July 2016 by Görkem Bozkurt
*/
#include <AccelStepper.h>
#define HALFSTEP 8
#include <Wire.h>
// Motor pin definitions
#define motorPin1 2 // IN1 on the ULN2003 driver 1
#define motorPin2 3 // IN2 on the ULN2003 driver 1
#define motorPin3 4 // IN3 on the ULN2003 driver 1
#define motorPin4 5 // IN4 on the ULN2003 driver 1
#define motorPin5 A0 // IN1 on the ULN2003 driver 1
#define motorPin6 A1 // IN2 on the ULN2003 driver 1
#define motorPin7 A2 // IN3 on the ULN2003 driver 1
#define motorPin8 A3 // IN4 on the ULN2003 driver 1
// Initialize with pin sequence IN1-IN3-IN2-IN4 for using the AccelStepper with 28BYJ-48
AccelStepper stepper1(HALFSTEP, motorPin1, motorPin3, motorPin2, motorPin4);
AccelStepper stepper2(HALFSTEP, motorPin5, motorPin7, motorPin6, motorPin8);
int stahp = 7,stahp2=10;
int cw = 6,cw2 = 11;
int ccw = 8,ccw2=9;
boolean stopped = false;
boolean stopped2 = false;
void setup() {
stepper1.setMaxSpeed(1000.0);
stepper2.setMaxSpeed(1000.0);
pinMode(stahp2,INPUT);
pinMode(cw2,INPUT);
pinMode(ccw2,INPUT);
pinMode(stahp,INPUT);
pinMode(cw,INPUT);
pinMode(ccw,INPUT);
}//--(end setup )---
void loop()
{
motor_pitch();
motor_roll();
if(stopped==false){
stepper1.run();
}
if(stopped2==false){
stepper2.run();
}
}
void motor_roll(){
if(digitalRead(stahp)==HIGH){
stopped = true;
}else{ if(digitalRead(cw)==HIGH){
stepper1.setSpeed(100);
stopped = false;
}
if(digitalRead(ccw)==HIGH){
stepper1.setSpeed(-100);
stopped = false;
}
}
}
void motor_pitch(){
if(digitalRead(stahp2)==HIGH){
stopped2 = true;
}else{ if(digitalRead(cw2)==HIGH){
stepper2.setSpeed(100);
stopped2 = false;
}
if(digitalRead(ccw2)==HIGH){
stepper2.setSpeed(-100);
stopped2 = false;
}
}
}
The slave module has 6 inputs from the master module with the same names. And drives the motors.
Slave Module code:
Step 8: First Test
We assembled the base and connected the electronics, now for the first test(indoor),
-Upload the master and slave codes to the Arduino's.
master ==> uno
slave ==> nano
-Connect the Arduino Uno to the computer and open the serial monitor .You will see 4 values printed to the serial monitor,
Yaw ==> RA value in degrees
Pitch ==> DEC value in degrees
LST_d ==> Local Sidereal Time in degrees
LST_h ==> Local Sidereal Time in decimal hours
When you first plug in the Arduino it will wait for 5 seconds. Then it will update the RA(yaw) value to your local sidereal time. After it is done it will continue to update the RA value 1 degree at a time.
Let's input 0,0 to the serial monitor.
When you try to move the mount, it will adjust itself to yaw=0, pitch=0.
Now let's try an input like 5.00,5.00(5 degrees DEC,5 degrees RA). The motors should position the mount at 5,5. degrees. If you encounter any problems check the next step.
Step 9: Troubleshooting
-The steppers are just vibrating
Check the connections of your stepper to the Arduino, different steppers have different pin outputs.
-The steppers start to wiggle when they arrive at the specified position
If your stepper speed is too fast it will struggle to stop at the position specified. Edit the speed of the stepper on the slave module(slave.ino) to something like 50-75.
-RA is not updating
Check the coin-cell battery on the RTC or the connections between the Arduino.
-RA-DEC values do not update(stuck at 0).
The gyro is the main cause of his problem (in my case it was). this is why I put 5 seconds of delay, in the beginning, this way there was no problem. If yıu find another way please let me know.
If you encounter any problem during the build let me know(Even if you solved the problem). So I can put it here.
Step 10: Final Assembly & Tracking
After assembling mount it to a tripod and go outside. The tripod will be a major tool because you will use it to align the setup with the north celestial pole.
After going outside away from city lights, adjust the Laser to an upright position by turning the motor with your hand.
Adjust the base gear so the RTC module is faced north.
Adjust the tripod angle while the laser is on and at an upright position, it should point the north star. If you can not see the north star you can use a phone app like sky map.
Plug in your Arduino to the setup. And wait while the RA degrees update.
Now you are all set. The laser pointer is now pointing 90 DEC,0 RA on the celestial sphere.
Tracking a star
There are huge star databases you can use. I will include the links below but for now, I will use Wikipedia for the coordinates of the star Arcturus. the coordinates of Arcturus are 14h 15m 39.7s , 19° 10′ 56″ first we have to convert this data to degrees, so our setup can process it.I used https://www.swift.psu.edu/secure/toop/convert.htm
the result is: RA: 213.9167 DEC: 19.1822
You can put this values into the serial monitor like this 213.9167,19.1822
and the setup will start to point and track that object/star.
Databases:
Step 11: What's Next
There are lots of things to improve on this project. My main goals for a later version are,
- Star database integrated into an android app. You will be able to choose a star. The data will be sent through Bluetooth to the Arduino as RA degrees, DEC degrees.
- Laser on/off switch with a servo. After the user input, the laser will be turned on for 3-5 seconds to point the star(currently you have to press it manually)
- more powerful motors and a bigger mount for a DSLR camera (maybe?)
- Bigger gear ratios for precise locations.
- Getting time and location data from a GPS module(currently, those are entered manually)
I hope you enjoyed this project as I did and learned something from it. If you find a mistake in the code or wrong information of any kind please let me know. All questions are welcome!
You can also contact me at: gocivici@gmail.com