Arduino-based Motor Focuser Controller

Everybody it seems has written their own Arduino-based motor focuser controller, of which the most popular is probably the SGL Observatory Automation version. There also is ArduinoFocus, which ambitiously reverse-engineered the Robofocus protocol; the sirJolo ASCOM focuser; and the E.J. Holmes Arduino focuser.  A common characteristic of all these projects is that they provide their own ASCOM driver.  I only tried the SGL version; sadly the ASCOM driver is in an almost-unusable state for me (basically it doesn't work - Sequence Generator Pro can't drive the focuser in an inward direction, which is pretty bad). So I decided to implement my own Arduino focuser, but make it compatible with an existing protocol.  This would allow me to use one of the commercial focuser drivers and avoid the problem of building my own ASCOM driver.

After some thought I decided to implement the Moonlite (otherwise known as the Lacey or EasyFocus) protocol. Since both a stand-alone and ASCOM driver are supported - and the stand-alone program echoes all the serial commands - it would be easier to debug the protocol.

On the hardware side, I wanted a design that can be readily-assembled, i.e. no soldering required. To achieve this, I used the Adafruit Motor Shield (AFMotor), version 1.2 - this version is now discontinued by Lady Ada, but China-made clones can be purchased for $5.00 shipped on ebay. This shield uses the L293D H-bridge controller, which is only capable of 600mA. This means that driven steppers must necessarily be small, and with fairly high resistance (in other words hybrid steppers cannot be driven).

Because my focuser is a Feathertouch, it uses a Starizona Microtouch MSM20 motor, which is a 300-step per revolution motor (with 48ppr and an internal 6.25:1 gearbox) giving 6.5 microns per step.  One benefit of the Microtouch motor is that unlike the Robofocus (which uses a DB-9 connector), the Microtouch uses a 6P6C (RJ-12) connector. It is very easy to purchase an RJ12 patch cable from any number of sources.  Then cut the RJ12 in the middle and bring out the correct wires.

During prolonged movements (i.e. a homing command), the L293D chip on the motor shield gets fairly hot; more so because I implemented full stepping with double-coil excitation to increase the torque (note therefore that my focuser does not implement half-stepping).  To alleviate overheating, it is a good idea to attach a heat sink to the L293D, I used an Aavid Thermalloy part number 580200B00000G which clips on top and under the L293D. You must make sure to buy an Adafruit Motor Shield (or clone) where the L293D is socketed, otherwise it would be impossible to attach this particular heat sink. Although the motor shield has two L293D's only one is used and therefore only one heat sink is necessary.

A final modification is required: most ASCOM drivers, when connecting the the focuser, immediately send a query or interrogate string. The problem with the Arduino is that when software connects to its serial port, the DTR line is pulled low, which resets the Arduino (this is a feature, necessary to implement programming the Atmega chip). It takes about 2 seconds for the Arduino to reset.  This becomes an issue because the ASCOM driver times out when it doesn't receive a response quickly enough.

The work-around is to prevent the Arduino from resetting when DTR is pulled low.  There are several ways of doing this, but on the Arduino Uno the easiest way is to connect a capacitor between RESET and GND. When the Arduino powers on, the capacitor is a short circuit, and the Arduino is stuck in a reset state. However once the capacitor charges up, RESET is now high, and if the capacitor is large enough, DTR pulling low (and pulling RESET low) will no longer work, because the capacitor provides enough voltage that DTR cannot pull RESET low anymore.  Alternatively you can omit the capacitor; the focuser can still be driven by the Moonlite stand-alone program, but not by the ASCOM focuser driver.

The side effect of the capacitor is that you cannot program the Arduino anymore! (more information in the last link above). In my case, I soldered the capacitor to the RESET and GND lines on the motor shield. Hence, you must detach the shield from the Arduino in order to upload the Moonlite focuser program; after the sketch has been uploaded into the Arduino, power everything down and re-attach the motor shield (with its capacitor).

So the total Bill of Materials consists of the following (aside from the Microtouch motor):
  • Arduino Uno or similar
  • RJ12 6P6C cable
  • Adafruit Motor Shield version 1.2 or clone
  • Aavid Thermalloy heat sink
  • capacitor, any value from 10uF to 100uF will work
Assembly is extremely simple: solder the capacitor to the motor shield; cut the RJ-12 cable, strip the four colored wires that are not black or white; tin these wires, and screw them into the left (M1/M2) motor connection block on the Adafruit motor shield.  Then upload the Moonlite sketch into the Arduino, unplug the USB, attach the motor shield to the Arduino, and you're all set.

In my tests, the Arduino plus shield can rack the Feathertouch focuser in and out under USB power alone (no need for a 12V power source on the barrel plug or on the auxiliary power connector on the motor shield). Results might vary depending on the torque required from the focuser.

Source code with some fixes for :GI# and compatibility with INDI; tested and working with both the stand-alone Moonlite focuser program, and the ASCOM 64-bit Windows driver loaded from inside Sequence Generator Pro. Note that this program does not implement speed changes (the AccelStepper library implements ramping, which makes speed changes un-necessary).

Selecting the Moonlite DRO Focuser Driver, and selecting the Arduino focuser. This program also does not implement temperature compensation, it just returns a hard-wired temperature. Also note that the speed setting, full step / half-step settings and temperature compensation commands are also ignored. I have not tested what happens if half-stepping is set or if temperature compensation is enabled.

Exercising the focuser through Sequence Generator Pro's Focus Control window.


waheex said...

highly impressive!

I have just got the motor shield and a stepper motor off ebay. It all works a treat. I hope to use it with a 200mm lens to get finer focusing. I have been doing this by hand but it's a bit of a nightmare. I'll post up some images on Stargazers Lounge and mention this great project as well. thanks

Matt Campagna said...

Thanks! I am doing a similar project and your source code will save me A TON of effor - you're awesome!

Craig Jameson said...


Thanks to your page I have the focuser working perfectly! The only thing I am trying to do is add the temperature but I cant get it to read it correctly....

It always reads 42.5c which is about twice the actual temperature and it does not seem to change either.

int temperature = sensors.getTempCByIndex(0);
Serial.print(temperature, HEX);

From the Spec , halfway down this page:

Command Response Description

GT XXXX Get the Current Temperature, Signed Hexadecimal