Jump to content

- - - - -

Stepper Focuser

Voice your opinion about this subject in our forums

Stepper Focuser

by John E. Pearson


This project was undertaken to provide a remote control mechanism to focus the telescope. At high magnifications, you cannot touch the telescope without causing the image to jitter thereby making a sharp focus difficult to achieve. The original intent was to have a shaft encoder on both the control knob and the motor for a complete closed loop servo. It was quickly discovered that the Arduino processor could not handle the feedback monitoring of both encoders. It was then decided to use an encoder for input and a stepper motor for output. As long as the motor has sufficient torque and speed, the feeling of a closed loop is achieved.

The device consists of a control box containing an Arduino Uno R3 micro-controller, a motor shield to power the stepper, and a prototype interface shield for the switch debounce circuits, Figures 1&2. A second assembly is the remote control pendant which houses CW and CCW slew push buttons and the 24 point rotary shaft encoder, Figure 3. The third assembly is a mounting plate for the stepper motor, Figures 4&5. This plate attaches to the telescope using the three screws of the focus knob retaining ring. The plate is designed to fit both the 6SE and 8SE scopes. With a little ingenuity it could also be adapted to the 4/5SE series. Another plate has already been fabricated for an AT80EDTA refractor. Additional adaptations require only another motor and mounting plate. Figure 6 shows some of the major components before assembly.


The device has the following features.

1. Servo feel

Although a full closed loop servo is not implemented, the stepper motor provides the feeling that this is the case. In effect, when you turn the knob on the remote in either direction at any speed, the stepper, and hence the focus knob responds in a direct fashion. This will be true as long as the stepper has sufficient torque to overcome the friction of the focuser internal mechanism. The focus knob rotation on a 6SE is almost effortless and the stepper has far more torque than needed. A motor was selected to have 200 steps per revolution. This gives adequate angular resolution for fine focusing. There is a step down ratio of 8.33:1 electronically(200/24). The timing belt pulleys are of equal size so there is no mechanical reduction.

2. Programmability

Using an Arduino controller allows the designer to program the desired motion, change design for different adaptations, or add features and fixes as discovered by the author and other users. The controller is programmed via a Windows or Linux computer using a modified C++ language. The compiled program is loaded into the Arduino via a USB cable. It also allows the designer to tap into a wealth of knowledge and software libraries already created by others. There are also two very active forums available to exchange help and ideas.

3. Extra program features

The original design was to have just the encoder and two slew buttons. It was shortly discovered that the encoder knob also had a push button built into the mechanism. It was quickly decided to do something with this extra button. The extra features included in original design are the ability to change the slew speed to 1/4, 1/2, and 1 revolution per second(RPS). Also present is the ability to change the encoder step ratio to 1, 2, and 4 motor steps per encoder step. These features are triggered by pushing the encoder button then pushing one of the slew buttons. The CW button changes the slew speed and the CCW button changes the step ratio. A second push of the encoder button aborts the operation in case that button was pushed by mistake. The default setting is 1/2 RPS and a step ratio of 1:1.

4. Long cable possible

During the project, it was considered to add computer remote control to the device via a serial cable. That idea was abandoned for two reasons. First, there were not enough digital pins left for the serial link. The motor shield and button interface consumed all but one pin. Second, you would need a long cable going out to the telescope from the computer. However, a long cable can just as well be an extension of the remote pendant. This maintains the servo feel when manually operating the pendant.

5. Power consumption

One consideration was power consumption. Since most telescopes operate from a battery supply, the current consumption should be kept as low as possible. The  device and stepping motor operates from the mounts 12VDC supply. Steppers normally have current flowing through the windings even when stationary. This motor draws 0.35 Amperes in each of it's two windings. Fortunately, the AF-Motor library functions used in the software provide a command to release the winding drivers thereby shutting off current to the motor. The motor is still maintained in position by a magnetic locking effect common to steppers. In effect, when motion is complete, the motor is shut off and battery power is reduced considerably. When fast slewing, the current is 485 milliamps and when resting, it is only 145 milliamps. You can also turn off power to the stepper unit when focusing is complete.

Construction Hints

1. Arduino

A. Tape over USB socket

There is a possible short circuit condition when the motor shield is press down onto the Arduino. This happens because some circuitry on the underside of the shield will rest on top of the USB connector housing. It is advised to put Scotch tape on the housing top and also on the underside of the shield where they would come in contact.

B. Mounting holes

The Arduino board has four mounting holes. The one near the USB socket has very little clearance between it and the end of a header. To use this hole, you will need to file the side off of a nut and washer.

Because there is circuitry on the underside of the board, it is advised to use 1/4" insulating spacers when mounting the board into the enclosure. Number 4-40 hardware was used to mount the board.

2. Motor Shield

A. Two capacitors flat

It should be noted in the motor shield photo that the two blue capacitors along the bottom edge are lying on their side, Figure 7. This is necessary because they are too tall to allow the proto shield to be added to the top. The one in the bottom-center will need insulating sleeves over the wires to keep them from shorting out if accidentally pushed together. The three black capacitors along the top can stand upright as shown in the construction guide.

B. Sockets for all three chips

The motor shield kit comes with sockets for the two H-Bridge chips because these are easily destroyed with too much motor current. It was decided that all three chips would use sockets for ease of replacement.

C. Male/female headers so Proto shield can be stacked

The kit comes with male headers for the underside of the board. They are normally placed on the outer rows so they can plug into the Arduino board. However, because the proto shield needs to be stacked on top, a set of male/female headers was used in the outer row. This allows all three boards to be stacked.

D. Missing servo headers

The circuitry around the upper-left corner supports two R/C servos. These headers are  not needed. This is the circuitry that can potentially short out to the USB socket housing underneath.

E. External motor power

Near the bottom-left is a two pin screw terminal for external motor power and a jumper block just to it's right. Position the jumper so that it is on one pin only and connect the 12VDC lines to the terminal strip noting the polarity and wire colors. Red is always positive and black is always ground.

F. Trim reset switch pins or solder flush

You will want to install the reset push button at the lower-left corner to assist in trouble shooting with this board. When soldering this switch, try to make the pins flush with the underside. If not, cut off the protruding portion. These protrusions will hit the power socket on the Arduino and prevent the motor shield from fully seating. There will still be a little bit of tilt between the lower two boards.

3. Proto Shield

A. Male headers on outer row

You can buy the complete proto shield kit or get just the bare board and the few necessary parts, Figure 8. It will cost slightly less to use the later choice. Note that the two outer rows will need only the male headers on the underside.

B. Reset switch

The other two reset switches, below this board, will be covered up by the proto shield. For this reason, you will need to mount a reset switch in the lower-left position.

C. Two pin male header in place of power indicator LED

Near the upper-left corner is space for an LED and current limit resistor. Install a 680 ohm resistor in the appropriate holes and a two pin male header in place of the LED. Mount an LED on the enclosure near the power switch and run two wires to a two pin female header then plug it into the board. Note the red wire connecting the +5V trace to the hole near the LED header. Be sure to observe the correct polarity for LED's.

D. Components

The switch debounce circuits occupy the center area of the board. They are necessary because any mechanical switch is noisy and does not make a clean connect and disconnect. The schematic calls for 4K7 resistors. They were not available at the time of construction so 4K3 resistors were used. the capacitors are disc ceramic and are positioned along side the resistors. The best way to build this circuit is to copy it from the photo.

4. Remote Control Box

A. Push button switches

A die cast aluminum box was used for the remote pendant, Figure 3. You can use anything that fits your hand comfortably. The rotary encoder is mounted in the middle and a slew push button on each side. The photo shows the box reversed but would be used with the lid side down. The push buttons are available from Adafruit and numerous Chinese vendors on eBay. However, they use cheap plastic and are prone to melting if too much heat is used to attach the wires. You could use a different type of switch if available. To prevent damage to these switches, a forceps was clamped to the lead adjacent to the body to keep some of the heat from melting the plastic. It was still difficult to accomplish.

5. Main Control Box

A. Arduino mounting

When mounting the Arduino stack, position it to the right end of the box, Figure 1. This will allow space for a right-angled USB plug to enter the socket for programming. Also note the wires from the power LED running to the header near the top-center.

B. Molex socket hole dimensions

The motor and remote sockets used Molex connectors because they were available in the authors parts bucket. The down side is that you will need to make two rectangular holes in the box. The up side is that no soldering is required as they are crimp pins. They can also be removed with the appropriate tool for trouble shooting. The holes sizes are 0.505" x 0.552" for the 2x3 motor socket and 0.563" x 0.795" for the 3x4 remote socket. The best way to make these holes is to mark them on the box surface on the inside, drill a large hole in the center, and use a nibbler tool to square them up. You can of course use a different kind of plug and socket combination.

6. Timing Pulleys

A. Motor pulley

Both of the timing pulleys comes with a 3mm bore. The motor has a 5mm shaft size with a flat. The motor pulley has to be drilled out to the appropriate size. This was accomplished on a drill press with much frustration. It is recommended to take it to someone with a lathe to maintain proper centering and alignment. The set screw is a #4-40 size. Be prepared to see a mixture of English and metric fasteners on this and other scope projects.

B. Scope pulley

The scope pulley is even more frustrating. Figure 9. The shaft/tube size under the rubber focus knob on the SE scopes is 13mm. However, the hub on the pulley is 1/2" OD. To solve this problem, an aluminum shaft collar was used with a 1/2" hole. It will be necessary to open this hole to 13mm with an adjustable reamer to slip fit the focus tube. After this is accomplished, the collar needs to be epoxied onto the flat side of the pulley after careful centering. When complete, it will be attached with it's 1/4"-20 set screw.

7. Mounting plate

The drawing for the mounting plate calls for 1/8" hard aluminum stock, Figures 10&11. This could be 6061-T6 or 7075-T6. The choice is yours. However, it was found that 0.093 stock worked just as well. The piece available was a little wider than needed but was left as is. The extra space was used to mount the connector from the motor. The motor wires appear to be quite fragile so this connector takes the strain off of the wires. The schematic shows this arrangement with an interconnecting cable. Also notice on the plate drawing that all hole locations are dimensioned from the bottom and right edge. This allows you to use a dial caliper as a scratching tool to mark the lines. The crossover can be snap punched for later drilling. Also, the spacing between the motor and focus shaft is based on a calculated distance. Your timing belt may be shorter or longer. In this case, the motor center hole and two mounting screw holes can be enlarged to allow for belt adjustment. You can also extend the two screw holes with a small rat tail file. You may need flat washers under the two 3mm screw heads if the holes are too large. The mounting plate is attached to the scope using the three retaining ring holes. It is recommended to use spacers between the plate and scope surface so that the plate remains parallel to the ring. You will need three M3-0.5x12mm cheese head Philips screws. You can use #4 flat washers instead of metrics as they are much cheaper. All fasteners in this project are stainless steel and a combination of English and metric. The UK will want to go totally metric. These two drawings were made using the free DraftSight program. It is available for both Windows and Linux.


The schematic for this project is show in Figure 12. It was drawn using the KiCAD program. This free program is available for both Windows and Linux.

Arduino Source Code

The source code is show in text format in Figure 13. A source file in INO format is also available. This file is used by the Arduino compiler. You will need it to load the program or modify the code.

Parts List

1. Arduino Uno R3 controller, Adafruit ID: 50

2. Adafruit Motor Shield, Adafruit ID:81

3. Adafruit Proto Shield(bare board), Adafruit ID: 55

4. Adafruit Stepper Motor, 200 step, Adafruit ID: 324

5. Timing Pulleys, 2 ea., S3M 30 Tooth, Robot Shop: RB-Ftr-28

6. Timing Belt, 85 Tooth, 3mm Pitch, Robot Shop: RB-Ftr-36

7. Aluminum Shaft Collar, 1/2" ID, Cadence Supply, CSC-050-A (Note 1)

8. Resistor, 680R, 1/4W, 1ea.

9. Resistors, 4K7, 1/4W, 5 ea.

10. Capacitors, 100n, 50V, 5 ea.

11. Panel mount LED, red

12. Rotary shaft encoder, Adafruit ID: 377

13. Box for remote control

14. Box for electronic unit, Hammond 1411L

15. USB cable, straight A to right-angle B,  http://www.ebay.com/itm/290637007832?ssPageName=STRK:MEWNX:IT&_trksid=p3984.m1439.l2649 (Note 2)

16. Panel Mount 2.1mm DC barrel jack, Adafruit ID: 610

17. Power switch, SPST, on-off, your choice

18. Push button switch, N.O., momentary, 2ea., your choice

19. Tactile push button switch for reset, Adafruit ID: 367

Note 1. Adjustable reamer for shaft collar, 15/32" to 17/32", or 13mm. Victor Machinery Exchange, RMBL-A.

Note 2. The USB cable is needed to program the Arduino. The right-angle B is needed because of limited clearance at that end of the Hammond box. If you use a larger box then you won't likely need the extra cable. However, the Hammond 1411L seems ideal for this project.

File List

Main document - StepperFocuser1.00.rtf

Source code text -  StepperFocuserSourceCode9_ino.txt

Source code - SteppingMotorFocuser9_ino.ino

Mounting plate layout - MountingPlate86-1b.gif

Mounting plate hole locations - MountingPlate86-3.gif

Schematic diagram - FocuserSchematic86.gif

Enclosure angled view - EnclosureAngleView86-0304.jpg

Enclosure top view - EnclosureTopView86-0303.jpg

Final assembly left side view - FinalAssemblyLeft86-0312.jpg

Final assembly right side view - FinalAssemblyRight86-0313.jpg

Focuser components view - FocuserComponents86-0286.jpg

Scope pulley view - FocuserPulley86-0301.jpg

Motor shield view - MotorShield86-0295.jpg

Prototype shield view - ProtoShield86-0302.jpg

Remote control pendant - RemoteControlBox86-0291.jpg

Change log - ChangeLog.txt


A complete ZIP package is available at the following link. Look near the bottom of the web page for a download.


A demo video is available at YouTube. It shows the focuser in action and includes an audio narration.



Figure 1 - Control Box Top View

Figure 2 - Control Box Diagonal View

Figure 3 - Remote Control Pendent

Figure 4 - Mounting Plate Right Side

Figure 5 -  Mounting Plate Left Side

Figure 6 - Major Components

Figure 7 - Motor Shield

Figure 8 - Proto Shield

Figure 9 - Scope Pulley

Figure 10 - Mounting Plate Layout

Figure 11 - Mounting Plate Dimensions

Figure 12 - System Schematic

Figure 13 - Source Code

// Stepping motor focuser project, 06/05/2012, John E. Pearson, Arctic_Eddie


// Define constants

const int APin    = 5;    // Pin number for phase A switch

const int BPin    = 6;    // Pin number for phase B switch

const int CWPin   = 9;    // Pin number for CW switch

const int CCWPin  = 10;   // Pin number for CCW switch

const int EPin    = 2;    // Pin number for encoder push button

const int StepMax = 4;    // Max motor steps per encoder step

const int SlewMax = 60;  // Max slew speed

// Define global variables

int phaseA = HIGH; // Initial state of A input

int Speed = 30;   // Default slew speed in RPM

int StepRatio = 1; // Motor steps per encoder steps

//Define stepping motor object

AF_Stepper focusMotor(200, 1); // A 200 step motor on motor port 1

void setup ()


    // Set up slew inputs and connect internal 27K pullup resistors

    pinMode(CWPin, INPUT);

    digitalWrite(CWPin, HIGH);

    pinMode(CCWPin, INPUT);

    digitalWrite(CCWPin, HIGH);


    // Setup encoder inputs and connect internal 27K pullup resistors

    pinMode(APin, INPUT);

    digitalWrite(APin, HIGH);

    pinMode(BPin, INPUT);

    digitalWrite(BPin, HIGH);


    // Setup encoder push button for speed control, step ratio, and connect internal 27K pullup resistor

    pinMode(EPin, INPUT);

    digitalWrite(EPin, HIGH);

    // Set up motor speed when stepping

    focusMotor.setSpeed(Speed); // Set to initial value


    // Get initial state of phase A

    phaseA = digitalRead(APin);


void changeSlewSpeed()


    Speed = Speed * 2; // Double the speed

    if (Speed > SlewMax)


        Speed = 15; // Cycle back to lowest


    focusMotor.setSpeed(Speed);  // Update speed value to 30, 60, or 12090( 0.5, 1.0, 2.0 RPS )


void changeStepperRatio()


    StepRatio = StepRatio * 2; // Double the motor steps per encoder step( 1, 2, or 4 )

    if (StepRatio > StepMax)


        StepRatio = 1; // Cycle back to one stepper pulse per encoder pulse



void stepCW()


    // Output a signal to make stepper go CW

    focusMotor.step(StepRatio, FORWARD, INTERLEAVE);


void stepCCW()


    // Output a signal to make stepper go CCW

    focusMotor.step(StepRatio, BACKWARD, INTERLEAVE);


void loop()


    // All inputs are high due to pullups, low is active **************


    // Check for right slew, step until button released

    while (digitalRead(CWPin) == LOW) // Switch grounded means run CW


        stepCW(); // focusMotor.step(StepRatio, FORWARD, INTERLEAVE);


    focusMotor.release(); // Kill power to motor windings

    // Check for left slew, step until button released

    while (digitalRead(CCWPin) == LOW) // Switch grounded means run CCW


        stepCCW(); // focusMotor.step(StepRatio, BACKWARD, INTERLEAVE);


    focusMotor.release(); // Kill power to motor windings

    // Check encoder push button for slew speed or stepper ratio change

    if (digitalRead(EPin) == LOW)


        // Wait for encoder button to be released

        delay(1000); // Wait one sec for button release

        // Wait for one of the slew buttons to be pushed or the encoder button a second time

        while ((digitalRead(CWPin) == HIGH) && (digitalRead(CCWPin) == HIGH) && (digitalRead(EPin) == HIGH))



        // Find out which button was pushed

        if (digitalRead(CWPin) == LOW)




        else if (digitalRead(CCWPin) == LOW)




        else if (digitalRead(EPin) == LOW)


            // Do nothing, abort with second push


        else{} // Something strange happened so ignore


        // Wait for all buttons to be released

        while ((digitalRead(EPin) == LOW) || (digitalRead(CWPin) == LOW) || (digitalRead(CCWPin) == LOW))



        delay(1000); // Wait one sec for button release




    // Check for encoder change

    if (digitalRead(APin) != phaseA) // Phase A changed


        // Evaluate phase B to determine direction of step

        if (digitalRead(APin) != digitalRead(BPin))




        else // Both A and B are the same





    // Now release motor current

    focusMotor.release(); // Kill power to motor windings

    // Save new phase A

    phaseA = digitalRead(APin);



Cloudy Nights LLC
Cloudy Nights Sponsor: Astronomics