DIY Stepper Controller using Arduino

My first version of a stepper controller uses a 555 timer chip and a 74LS194 shift register. The tracking rate is controlled by the 555 timer chip through a resistor and a capacitor. By changing the resistance and capacitance values, the tracking rate also changes. A variable resistor is used to speed up and slow down the rotation of the stepper. Since the timing signals are controlled by analog components, the tracker suffers from issues related to the tracking rate. It usually requires ‘tracking rate adjustment’ (to match the movement of the sky) at the start of an imaging session. While it has served me for four years and used it to image some interesting targets, it is clear that an upgrade is needed.

Upon learning some basics about Arduino, I immediately saw the potential to use it as a controller for a stepper motor, the kind of motor used in devices that require precise motion control such as in many telescope mounts. I started looking at some excellent tutorials on the Internet and was able to build the simple stepper controller featured in this article.

The main advantage of using a microcontroller is that it makes it possible for the stepper controller to keep a far accurate tracking rate, unlike my previous controller that changes tracking rate with the slightest change in ambient temperature. Since it is digital, there is no need for a re-calibration at the start of every imaging session. Buttons can be placed to allow easy adjustment of the tracking speed such as to speed up or slow down the tracking rate momentarily, for easy adjustment. LEDs can be used as status indicators (e.g., current step rate).

After a few months, I have finally built a fairly simple yet reliable stepper controller that can be used to drive very small trackers, or even more advanced ones such as a telescope. And since it is built with an Arduino, it is possible to add some upgrades to it in the future.

arduino stepper
Controller for equatoral trackers such as a telescope mount with stepper motor

Removing the cover reveals the circuit board for the stepper driver. This circuit sits on top of the Arduino, much like a DIY shield (a circuit board that you can attach readily to an Arduino by stacking it on top of it, through the connecting pins.)

arduino_stepper (4)
Stepper controller with the DIY stepper driver circuit.

Dismantled, you can clearly see the Arduino board on the left (there are many versions of an Arduino board, in this particular project, I have used what is called an Arduino UNO). You can see the connecting pins that run vertically on the board’s left and right sides. The pins connect the Arduino to the Stepper Driver (center). The Stepper Driver is a board that holds L293D chip and some PC817 optical isolators. Some LED lights were left on the board which could come handy during troubleshooting. Also visible is some sort of a relay circuit and its connector (right), to allow a GPUSB (some kind of a module that allows a computer to talk to my telescope mount) to control the DIY Stepper Controller for autoguiding purposes (it’s a completely optional feature that I decided to include as it may come handy in the future). The use of a GPUSB, however, will be discussed in a separate article.

arduino_stepper (3)
Components of the stepper controller. Only the Arduino Uno and the Stepper driver will be discussed in this article. The Relay and the Connector (for GPUSB) to enable a computer to send guiding signals to the stepper controller (for autoguiding purposes) will be discussed in a separate article.

Here you can see the circuit board for the LED lights and the four push-button switches.

arduino_stepper (1)
The circuit for the LED lights and the push-buttons.

To build this DIY Stepper Controller, you will be needing some basic understanding of electronic circuits. The diagram below illustrates how the parts will be put together.

eteny_arduino_stepper_feb2016
To view a larger image, click here. Circuit diagram for the Stepper Motor Controller. An Arduino Uno is used to provide pulses for the L293D H-bridge through optional PC817 opto-isolators. The circuit can drive both bipolar and unipolar steppers (operated in bipolar mode).

The Arduino board requires what is called a ‘sketch’. A screenshot of the sketch used in this DIY stepper controller is shown in the following photo. As you may have noticed, it is composed of lines of text with a set of instructions in it. It is a ‘program’ that you upload to the Arduino board to let it know what to do. This program is uploaded by connecting the Arduino board to a computer through a USB connection, using the Arduino Software. Learn more about Arduino. Once you are familiar with some basics, you will be able to understand how to use the sketch below.

Eteny_ControllerforKenkoNESmount
To view a larger image, click here. Script for the Arduino stepper motor controller. For inquiries about the sketch, please send an email to eteny@nightskyinfocus.com.

If the sketch above seems too complicated, you can try uploading a simpler sketch that can be used to spin the motor (note that this sketch does not read the buttons, it only spins the motor).

Eteny_simplecodeforKenkoNESmount
To view a larger image, click here. Script for the Arduino stepper motor controller. For inquiries about the sketch, please send an email to eteny@nightskyinfocus.com.

Once you’ve finished building the DIY Stepper Controller circuit above and uploaded the sketch to the Arduino board, you should see some blinking lights indicating that your controller is up and running and ready to track the skies!

arduino_stepper_lights
Arduino stepper motor controller for a telescope mount.

This page is a work-in-progress. In future posts, I will describe an advanced application of the tracker such as enabling the Arduino stepper controller to receive commands from a computer through a serial connection, and perform automatic tracking error corrections (autoguiding) with a program running on a computer, such as PHD Guiding.

Visit this page for captured images and future upgrades on this project. Clear skies!

test_shot_autoguider_moodedDSLR
To view a larger image, click here. A 240-second test image to determine the tracker’s accuracy. The image was taken a focal length of 900 mm from a city with severe light pollution using a filter-modified Canon 450D DSLR. Tracking was guided using PHD2 Guiding software, a modified Logitech 4000 web camera, and a 400 mm focal length guide scope.

Here’s the code in plain text. I have not made any changes since I wrote it in February 2016.

// Eteny, http://www.nightskyinfocus.com, updated February 27, 2016, 9 pm
// Stepper Motor Controller with Autoguider function for the RA axis only

#include <Stepper.h> //Include the Stepper Library
const int stepperPin1 = 9; //Stepper pin
const int stepperPin2 = 10; //Stepper pin
const int stepperPin3 = 11; //Stepper pin
const int stepperPin4 = 12; //Stepper pin
Stepper motor(24, stepperPin1, stepperPin2, stepperPin3, stepperPin4); //Number of steps in one full rotation: 24 steps as indicated in my stepper (15 degrees per step), with 1:500 gear ratio) and the four pins used by the stepper (stepperPin1, stepperPin2, stepperPin3, stepperPin4)
int motorSpeed = 48; //Value (revolutions per minute) found through experimentation (Moon = 50 rpm, Stars = 48 rpm)
int command; //Variable to store the commands coming from the serial communication
int speakerPin = 6; //Tones are used as feedback
const int buttonApin = 2; //Green push button switch, speed up
const int buttonBpin = 3; //Red push button switch, slow down
const int buttonCpin = 4; //Orange push button switch, increase speed
const int buttonDpin = 5; //Yellow push button switch, decrease speed
const int redLEDpin = 7; //Red LED speed indicator
const int greenLEDpin = 8; //Green LED speed indicator
boolean meridianFlip = false; //Mode of operation: Meridian Flip ON (responses to the RA signals are not reversed) or Meridian Flip ON (responses to the RA signals are reversed)

void setup()
{
pinMode(stepperPin1, OUTPUT); //Stepper pin
pinMode(stepperPin2, OUTPUT); //Stepper pin
pinMode(stepperPin3, OUTPUT); //Stepper pin
pinMode(stepperPin4, OUTPUT); //Stepper pin //Stepper pin
pinMode(redLEDpin, OUTPUT); //Red LED pin
pinMode(greenLEDpin, OUTPUT); //Red LED pin
Serial.begin(57600); //Baud rate used by PHD2 Guiding
Serial.println(“INITIALIZED#”); //Arduino replies with ‘INITIALIZED#’ once serial communication is established
}

void loop()
{
spinMotor();
checktrackingMode();
readButtons();
readSerial();
ledSpeedIndicator();
}

void spinMotor()
{
motor.step(1); //Replace value with -1 if you wish to reverse the rotation of motor
motor.setSpeed(motorSpeed); //Spins motor at a predefined speed of 48 rpm
}

void speedUp()
{
motor.step(1); //Replace this value with -1 if you wish to reverse the rotation of motor
motor.setSpeed(motorSpeed*2); //Spins motor at a 2X the predefined speed
playHighTone(); //Plays audio feedback
Serial.println(“West/RA-#”); //Nudges the telescope towards the west
}

void slowDown()
{
motor.step(1); //Replace value with -1 if you wish to reverse the rotation of motor
motor.setSpeed(motorSpeed/2); //Spins the motor at 1/2X the predefined speed
playLowTone(); //Plays audio feedback
Serial.println(“East/RA+#”); //Nudges the telescope towards the east
}

void increaseSpeed()
{
motorSpeed = motorSpeed + 1; //Increases the motor’s rpm
if (motorSpeed >= 100){ //Limits the rpm to a maximum value obtained through experimentation
motorSpeed = 100; }
//Value found through experimentation
motor.setSpeed(motorSpeed);
playHighTone();
Serial.print(“RPM:”);
Serial.print(motorSpeed);
Serial.println(“#”);
delay(200);
}

void decreaseSpeed()
{
motorSpeed = motorSpeed – 1; //Reduces the motor’s rpm
if (motorSpeed <= 1){ //Limits the rpm to a minimum value
motorSpeed = 1; } //Lowest value set at 1 rpm
motor.setSpeed(motorSpeed);
playHighTone();
Serial.print(“RPM:”);
Serial.print(motorSpeed);
Serial.println(“#”);
delay(200);
}

void checktrackingMode()
{
if (digitalRead(buttonCpin) == HIGH && digitalRead(buttonDpin) == HIGH){ //Meridian flip mode is turned ON when the yellow and orange buttons are pressed simultaneously
meridianFlip = true;
motorSpeed = 48; //RPM reverts to the predefined value
playHighTone();
Serial.println(“Meridian Flip ON: RA signals in reversed mode#”);
delay(1000);
}
if (digitalRead(buttonApin) == HIGH && digitalRead(buttonBpin) == HIGH){ //Meridian flip mode is turned OFF when green and red buttons are pressed simultaneously
meridianFlip = false;
motorSpeed = 48; //RPM reverts to the predefined value
playHighTone();
Serial.println(“Meridian Flip OFF: RA signals in normal mode#”);
delay(1000);
}
}

void ledSpeedIndicator () //Common cathode (common GND) red and green LEDs
{
if (motorSpeed <= 48){ //Red indicates that the motor is operating at an RPM that is lower than the predefined value
digitalWrite(7, HIGH);
}
else {
digitalWrite(7, LOW);
}
if (motorSpeed >= 48){ //Green indicates that the motor is operating at an RPM that is higher than the predefined value
digitalWrite(8, HIGH);
}
else {
digitalWrite(8, LOW);
}
} //When operating exactly at the predefined value (48 rpm), the red and green LEDs light up together to produce an orange light

void readButtons ()
{
while (digitalRead(buttonApin) == HIGH && digitalRead(buttonBpin) == LOW && meridianFlip == false) { //Checks if green button has been pressed
speedUp();
}
while (digitalRead(buttonApin) == HIGH && digitalRead(buttonBpin) == LOW && meridianFlip == true) { //Checks if green button has been pressed
slowDown();
} //Arduino spins the motor at 2X speed
while (digitalRead(buttonApin) == LOW && digitalRead(buttonBpin) == HIGH && meridianFlip == false) { //Checks if red button has been pressed
slowDown();
}
while (digitalRead(buttonApin) == LOW && digitalRead(buttonBpin) == HIGH && meridianFlip == true) { //Checks if red button has been pressed
speedUp();
}
if (digitalRead(buttonCpin) == HIGH && digitalRead(buttonDpin) == LOW) { //Checks if orange button has been pressed
increaseSpeed();
}
if (digitalRead(buttonCpin) == LOW && digitalRead(buttonDpin) == HIGH) { //Checks if yellow button has been pressed
decreaseSpeed();
}
}

void readSerial()
{
if (Serial.available() > 0)
{
String command = Serial.readStringUntil(‘#’);
if(command == “CONNECT”){ //PHD2 sends “DISCONNECT” over the serial port
playHighTone();
Serial.println(“OK#”); //Arduino replies with ‘OK#’
}
else if (command == “DISCONNECT”){ //PHD2 sends “DISCONNECT” over the serial port
playLowTone();
Serial.println(“OK#”); //Arduino replies with ‘OK#’
}
else if(command == “RA0”){ //PHD2 sends “RA0” over the serial port
motorSpeed = 48; //Arduino spins the motor at the predefined speed
Serial.println(“OK#”); //Arduino replies with ‘OK#’
}
else if (command == “RA+” && meridianFlip==false){//PHD2 sends “RA+” over the serial port
motorSpeed = motorSpeed/2; //Arduino spins the motor at 1/2X speed
playLowTone();
Serial.println(“OK#”); //Arduino replies with ‘OK#’
}
else if (command == “RA+” && meridianFlip==true){ //PHD2 sends “RA+” over the serial port
motorSpeed = motorSpeed*2; //Arduino spins the motor at 2X speed
playHighTone();
Serial.println(“OK#”); //Arduino replies with ‘OK#’
}
else if (command == “RA-” && meridianFlip==false){ //PHD2 sends “RA-” over the serial port
motorSpeed = motorSpeed*2; //Arduino spins the motor at 2X speed
playHighTone();
Serial.println(“OK#”); //Arduino replies with ‘OK#’
}
else if (command == “RA-” && meridianFlip==true){ //PHD2 sends “RA-” over the serial port
motorSpeed = motorSpeed/2; //Arduino spins the motor at 1/2 speed
playLowTone();
Serial.println(“OK#”); //Arduino replies with ‘OK#’
}
}
}

void playHighTone()
{
tone(speakerPin, 7040, 20); //High frequency tone feedback
}

void playLowTone()
{
tone(speakerPin, 55, 50); //Low frequency tone feedback
}
// Eteny, http://www.nightskyinfocus.com

Related link:
Stepper Motor Controller (Analog)
Improvised Clock Drive Project

For featured photos, click here.
For tutorials on how to get started with astrophotography, click here.
For DIY astronomy projects useful for astrophotography, click here.
To subscribe to this site, click here.

© Anthony Urbano (Manila, Philippines)

Advertisements

13 thoughts on “DIY Stepper Controller using Arduino

    • The mount uses a 6-wire (unipolar) stepper motor, but operated in 4-wire (bipolar) mode, leaving two wires (the center taps) unconnected. Good luck!

  1. I was looking for more information about clock drives and I came across your page.

    I am very interested in building an Arduino based motor controller like yours and I wanted to ask you if your design is based on a specific clock drive or if it can be used with other clock drives or stopper motors with different specifications.

    Last year a built a barn door tracker using a 4 RPM motor (geared down to 1 RPM) and even though it worked well for wide field images of 25mm, it can’t handle more than that before star trails are evident and also it is a hassle to have to adjust the velocity at the beginning of each session.

    During Christmas, my wonderful wife got me an Ioptron Skytracker and I must say that I am not too impressed with it at all because it is not very accurate (even though is supposed to be using an Arduino system). This is the reason why I would like to build a my own tracker (based on the Ioptron Skytracker design as opposed to a barn door design) which would enable me to track without having to rewind. I would also be adding an auto guiding port to use with a stand alone auto guider since the idea is to build a very portable system. I have two little girls and I cannot justify spending so much money on a commercial mount, so I will be happy to build a tracker on my own in order to continue my passion with astrophotography.

    Now, I have no idea where to begin! I much appreciate your time and input.

    • Hi Sebastian,

      A microcontroller-based driver (such as an Arduino) should work with any stepper motor, drive train/gearbox, and most tracker configurations since the tracking rate can be easily specified. It should also work with well any well-built barn door tracker setup.

      I know someone (a local enthusiast) who seems to be getting good resullts with an Ioptron :) Are you certain you are properly polar-aligned, or the camera is properly balanced (i.e., the east side is slightly heavy)? Before you modify the tracker, we must be certain that you have narrowed the problem down to incorrect tracking rate (as this is the only thing that will render a tracker inaccurate).

      I would be happy to be of help.

      Eteny

      • Hi Eteny,

        Thank you very much for the prompt response and the willingness to help! =)

        What I am really interested in doing, is building a microcontroller based driver with an autoguiding system the way you did, although I would prefer a stand alone auto guider since want to keep things simple and without having to use a laptop.

        I have two options in mind, one is a tracker system based on the Ioptron Skytracker and the other is a friction drive system based on the Fornax10 light mount ii. Although the tracker would be nice since there is no need to rewind it.

        Let me know your thoughts and where you think I should start. I have experience building telescopes, etc, but I have no experience when it comes to electronics and Arduino coding at all. Having said that, part of the reason I want to do this is to learn about Arduino which seems to be a pretty amazing platform.

        Thank you!

      • When you say you want to build a tracker based on Ioptron or Fornax10, do you mean (1) building something similar (especially, fabricating your own gear system/gearbox mechanism) or (2) using already existing parts from those trackers and simply replace the circuit boards (since any commercially-available tracker is already equipped with rather decent gearbox). Anyway, let me know if you are modifying or building from scratch.

        There are key steps here: (1) you need to build a board that can make a motor spin at a constant speed, (2) look for a suitable gear system/drive configuration, (3) attach the motor to the gear system/drive, (4) spend some nights “adjusting” the motor’s speed, and (5) finally testing your tracker.

        Try to watch tutorials on stepper motors and Arduinos :)

  2. Hi Anthony,

    In response to your reply. First of all, sorry for the confusion…When I say that I would like to build a tracker based on the Ioptron or Fornax, I mean building a tracker using existing parts but not necessarily from those trackers.

    The other alternative is to replace the circuit board of my Ioptron Skytracker with an Arduino board that has been coded to yield less than 1 arc min of PE and also add a auto guide port. If this can be done, it would actually be even better since like you said, the Ioptron Skytracker already has a very decent gearbox system already.

    Thank you!
    Sebastian

    • I would advise against replacing the circuit board of Ioptron (or any other tracker for that matter) esp if it is not broken. I am sure their engineers have already programmed those boards to track as precisely as possible. Have you ruled out the possibility that you are simply not properly polar aligned? It is a very real possibility that your tracker is in perfect working order, and what causes the trailing has something to do with polar alignment.

      In achieving polar alignment, simply pointing at Polaris is not enough. Do you know how to perform the drift alignment method? If you want to build a tracker, first you should learn how to polar align. Otherwise, even the best and most accurate trackers in the world will be rendered useless.

      Anyway, assuming that you have achieved a proper polar alignment yet the tracker is still ‘not very accurate’, then perhaps you have reached the limit of the tracker’s capability, and replacing the circuit board will not do any good. You need to upgrade to a better (larger, more sturdy, better gear reduction, and more expensive) tracker by buying one or building one.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s