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