Introduction: Lo-Fi Telescope Pointer

About: I'm an electronic engineer, I love stargazing and making self-made stuff for astrophotography. I'm also interested in CNC and 3D printing. In free time I play bass guitar in a local band.

Recently I got interested in astrophotography, so I decided it was time to buy an entry level telescope to use my Canon EOS 600D. This instructable is about an Arduino-controlled DC motor for the telescope equatorial mount with a VB.NET interface including a NCP (North Celestial Pole) finder grid.

Step 1: Implementing NCP Finder Interface in VB.NET

I saw this awesome idea on YouTube (on this channel where a guy was building an NCP finder with a common webcam. On the same channel, but in another tutorial, he was showing how to collimate a newtonian scope with a program called "Mire de collimation". From these two smart ideas I tried to create one single tool in VisualBasic to find the NCP with my reflex live view mode on PC.

First I used Stellarium to set my DSLR sensor preview (on reflex website you can find all the parameters to fill the input mask in Stellarium). Then I took few screenshots and I edited them with Photoshop adding a circle around Polaris, a sort of cross in the NCP position and deleting the background: it's important to obtain a transparent image.

Step 2: The Telescope

First of all you'll need an equatorial mount. I've got this one from Celestron Astromaster 130 EQ-MD telescope, it comes with a DC motor for apparent sky movement compensation. You probably noticed that one does not simply to regulate the correct speed with the potentiometer, so your photos exposure can't be as long as you want. This telescope is a cheap model so at this time I'm gonna make a more accurate speed regulation with Arduino PWM.

In this step I've just soldered the motor terminals and I applied some glue to reinforce the junction.

Step 3: Make the Arduino Shield

List of materials I used:

  • Arduino UNO R3
  • Prototype board
  • L293DNE half-h driver
  • LM7806 voltage regulator
  • (1x) .33 uF capacitor
  • (1x) .10 uF capacitor
  • (2x) 27 kOhm resistor
  • (1x) 10 kOhm resistor
  • Generic transistor
  • SIL male connectors
  • Some wires
  • pin IC socket (optional but suggested)
  • Bluetooth serial module (optional)


The L293DNE from Texas Instruments it's a quadruple half-h driver (it can handle up to 2 DC motors). It provides separately the voltage to the load and it's also possible to control the direction of the current flow on output pins, so you're able to change rotating direction.

In the "original" setup DC motor is powered by a 9 V battery and a regulation circuit keeps the voltage down to 5.6 V at maximum speed, so I supposed my DC was a 6 V motor. Unfortunately the USB 5 V isn't enough, so we have to power the motor separately. I choose the LM7806 to give 6 V from a common 9 V battery.

In this first prototype shield I didn't reach perfection: I corrected some connection errors and I realized component placing isn't optimized yet; however in the future I'd like to add a temperature sensor and draw the entire board with Fritzing to use SMD components. I hope to post a second instructable where I can show a better job...

Step 4: Add the VB.NET Serial Communication

Basically it's a simple serial interface, it's not difficult to realize and there are a lot of tutorials about this. However I want to share my own version with some explanations.

This function shows you all the available COM ports and displays them in a ComboBox. You can't use ButtonConnect until there are no available COM ports.

Sub refreshCOM()
  For Each sp As String In My.Computer.Ports.SerialPortNames
  If ComboBox_COM.Items.Count = 0 Then
    ComboBox_COM.Text = ComboBox_COM.Items.Item(0).ToString
  End If
  If ComboBox_COM.Text = "" Then
    ButtonConnect.Enabled = False
    ButtonConnect.Enabled = True
  End If
End Sub

Serial port setup with DTR disabling to keep Arduino waiting until PC correctly opens the port.

Private Sub MainForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  SerialPort1.DataBits = 8
  SerialPort1.Parity = Parity.None
  SerialPort1.StopBits = StopBits.One
  SerialPort1.Handshake = Handshake.None
  SerialPort1.Encoding = System.Text.Encoding.Default
  SerialPort1.DtrEnable = False
End Sub

Finally we can try to connect with the serial port and, if nothing goes wrong, we can enable the DTR. I've got some problems during Bluetooth communication: it seems that Arduino doesn't wait for the DTR enabling... I think it's due to a missing connection between my BT board and Linvor transceiver.

Private Sub ButtonConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonConnect.Click
  SerialPort1.PortName = ComboBox_COM.Text.ToString
  SerialPort1.BaudRate = ComboBox_BAUD.Text
  Catch ex As Exception
    MsgBox("Error during shield connection.")
  End Try
  If SerialPort1.IsOpen Then
    Label2.Enabled = True
    MaskedTextBox1.Enabled = True
    ButtonSetSpeed.Enabled = True
    SerialPort1.DtrEnable = True
    Label2.Enabled = False
    MaskedTextBox1.Enabled = False
    ButtonSetSpeed.Enabled = False
  End If
End Sub

This is serial port reading method, the the program will also refresh GUI values in the StatusStrip and will gives the raw strings in a dedicated TextBox (for outdoor quick debugging).

Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    Dim line As String = SerialPort1.ReadLine
    TextBox1.Invoke(New ReadSerialDelegate(AddressOf ReadSerial), line.ToString)
  Catch ex As Exception
  End Try
End Sub

Delegate Sub ReadSerialDelegate(ByVal s As String)

Public Sub ReadSerial(ByVal s As String)
  TextBox1.Text += s + vbNewLine
  TextBox1.SelectionStart = TextBox1.Text.Length - 1
  If s.Contains("charge") Then
    Label_Battery.Text = s.Substring(s.Length - 4, 3)
  ElseIf s.Contains("speed") Then
    Label_Speed.Text = s.Substring(s.Length - 4, 3)
  End If
End Sub

Writing method is really simple, I won't spend words with it.

Private Sub ButtonSetSpeed_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonSetSpeed.Click
    Label_Speed.Text = MaskedTextBox1.Text
  Catch ex As Exception
    MsgBox(vbInformation, "Unable to write at " + SerialPort1.PortName)
  End Try
End Sub

So now we have a bare bones code to handle entire serial communication.

Step 5: Write .INO Code

Arduino must receive the speed command and send the current battery level.

Change R1 and R2 with your resistors values, I used a multimeter to find the exact values of mine. Battery voltage is calculated with 9 V supply regulated by a LM7806, so we have about 3 V of "margin" before voltage reaches the threshold of 6 V and the output of LM7806 starts to decrease.

const float R1 = 26600.0;
const float R2 = 26600.0;
const float VBATT = 3;
const int refreshRate = 10000;
int south = 1;
int batteryTimeout = 0;

In Arduino pinout configuration make sure that the batteryPin is an analog type.

int batteryPin = 0;
int enableCheckPin = 7;
int enableMotorPin = 3;
int in1Pin = 2;
int in2Pin = 4;

On setup, Arduino will wait until DTR is enabled.

void setup()
  pinMode(batteryPin, INPUT);
  pinMode(tempPin, INPUT);
  pinMode(enableCheckPin, OUTPUT);
  pinMode(in1Pin, OUTPUT);
  pinMode(in2Pin, OUTPUT);
  pinMode(enableMotorPin, OUTPUT);
  while (!Serial);

Here there is a basic voltmeter for the battery level measure, if charge is higher than 100% it means the battery is disconnected (I added an additional 5% for noise error prevention). In my case the measure is taken every 10000 ms (10 s), but obviously you can change it. Otherwise the DC speed can be changed in "real-time" mode.

void loop()
  if (batteryTimeout == 0) {
    batteryTimeout = refreshRate;
    digitalWrite(enableCheckPin, HIGH);
    float Vout = (analogRead(batteryPin) * 5.0) / 1024.0;
    digitalWrite(enableCheckPin, LOW);
    float Vin = Vout / (R2 / (R1 + R2));
    int charge = (Vin * 100) / VBATT;
    Serial.print("Current charge: 0");
    if (charge > 105) {
      Serial.println(" - ");
    } else {
  digitalWrite(in1Pin, !south);
  digitalWrite(in2Pin, south);
  if (Serial.available()) {
    int speed = Serial.parseInt();
    if (speed >= 0 && speed <= 255)
      analogWrite(enableMotorPin, speed);
      Serial.print("New speed set: 00");

This code need to be optimized, it's just a basic sketch to begin outdoor tests.

Step 6: Testing

On a dark night I tested entire stuff:

  • Check on Stellarium an object to observe and try to memorize its position.
  • Find a dark and flat area from where you can see both Polaris and the object you choose.
  • Place the equatorial mount, install the DSLR on it and make sure the system is parallel to gravity force direction.
  • Connect DSLR to PC, open VB.NET NCP Finder and the DSLR remote software to correctly find NCP.
  • HINT: you may use a Bahtinov mask to set focus on Polaris...

Now you can power the DC motor and take some photos to calibrate speed before your night observation.

After some tests, I've found MANY bugs in this first setup:

  • First of all power consumption (currently I'm going re-write the .INO code adding avr/sleep.h and avr/power.h).
  • The NCP finder mask isn't correct because Polaris changes its position during a year! I must design a 365-valid mask.
  • The voltage divider circuit doesn't work as well as I want: there's about 3 V fall on the BJT, don't know why it doesn't just work as a pass-transistor... I need to study electronic theory first!

I'm working on a second (improved) version of this Lo-Fi pointer, I'll post some news...

Hope this instructable will inspire you!