
Super Compact Electronic Focuser
#1
Posted 20 June 2014 - 08:20 PM
The focuser consists of a small geared stepper motor, part# 28BYJ-48 5V. I was able to buy 3 of these on eBay for $6 total! Although they're faily slow, the fastest speed is about 12RPM, they have quite a bit of torque. They also have very high resolution, 4096 step per revolution. Driving the fine foucus of my Moonlite yields a insanely fine resolution of 0.4um/step.
There is a small single sided PCB that has a ULN2003 and a few passive components. The entire unit runs off power from the USB, much like a small camera.
The coupling to the fine focus shaft has a knurled screw that acts as the clutch. Loosening the screw allow manual control of the course focus.
- PrestonE, Pinbout and iwannabswiss like this
#2
Posted 20 June 2014 - 08:25 PM
Here's the acrylic housing I made. The whole unit is not much larger than a focus knob.
- calypsob likes this
#3
Posted 20 June 2014 - 08:31 PM
#4
Posted 20 June 2014 - 09:07 PM
obin

#5
Posted 21 June 2014 - 01:55 AM
This goes on the list of things to build. Very cool project! Do you plan to show this off at a star party any time soon?
#6
Posted 21 June 2014 - 08:35 AM
#7
Posted 22 June 2014 - 08:13 AM
i have tons of those cheap ebay motors lying around. Didn't realize they were beefy enough for these types of applications.
#8
Posted 22 June 2014 - 08:47 AM
Can you post up the details on the hardware portion of your kit? I like the mounting bracket and focus drive interface. Can we have PN# and sources?
John
#9
Posted 22 June 2014 - 10:41 AM
I'd post the code here, but I'm not sure how it could be done. I don't think there is a file section.
George
#10
Posted 22 June 2014 - 10:45 AM
George
#11
Posted 22 June 2014 - 02:58 PM
#12
Posted 22 June 2014 - 07:57 PM
-------------------------------------------------------------
// Moonlite-compatible stepper controller
// Written by George Carlson June 2014.
// This version uses the Tiny 2.0 a uController mased on the Atmel ATMEGA32U4.
// hardware for the remote hand control is not supported.
//
// Many thanks to orly.andico@gmail.com, for the original command parser, others for bits on code picked up here and there on the net
//
// Since the MoonLite focuser only works with positive integers, I center (zero) my system at 30000. The range is from
// 0 to 65535, so 30000 is a good round number for the center.
// If the Current Position, or New Position is set to 0, this code will set the values at 30000. The reason for this
// is the system is designed to be set at center, manually focused, then focused in a +/- fashion by the controller.
#define RUNLED 11 /* Amber LED lights whenever motor is active, 11 for the Teensy */
#define HOME 30000
#define MAXCOMMAND 8
char inChar;
char cmd[MAXCOMMAND];
char param[MAXCOMMAND];
char line[MAXCOMMAND];
char tempString[6];
unsigned int hashCmd;
long pos;
int isRunning = 0;
int speed = 2;
int eoc = 0;
int idx = 0;
long millisLastMove = 0;
int Current = HOME;
int Target = HOME;
int DistanceToGo = 0;
int minSpeed = 2;
int maxSpeed = 20;
int testPin = 12;
// Temperature measurement
int temperatureChannel = 0;
unsigned int wADC;
double temperature;
int tempTemp;
#define SCALE 0.488 /* ADC>centigrade scale for my particular Teensy */
#define OFFSET 100 /* 2 * 50 offset for TPM-36 */
// Remote hand controller NOT USED ON TEENSY VERSION (but could be)
int handController = 1;
unsigned int rADC;
int speedTable[16] = {2,2,4,8,10,20,0,0,0,0,20,10,8,4,2,2};
int goTable[16] = {-1,-1,-1,-1,-1,-1,0,0,0,0,1,1,1,1,1,1};
// Motor connections
int motorPin1 = 18; // Blue - 28BYJ48 pin 1
int motorPin2 = 19; // Pink - 28BYJ48 pin 2
int motorPin3 = 17; // Yellow - 28BYJ48 pin 3
int motorPin4 = 16; // Orange - 28BYJ48 pin 4
// Red - 28BYJ48 pin 5 (VCC)
// lookup table for motor phase control
int StepTable[8] = {0b01001, 0b00001, 0b00011, 0b00010, 0b00110, 0b00100, 0b01100, 0b01000};
int phase = 0;
void forwardstep() {
Current++;
if(++phase >7)
phase = 0;
setOutput(phase);
for(int i=0; i < speed>>1; i++){
delay(1);
}
}
void backwardstep()
{
Current--;
if(--phase <0)
phase = 7;
setOutput(phase);
for(int i=0; i < speed>>1; i++){
delay(1);
}
}
void setOutput(int out)
{
digitalWrite(motorPin1, bitRead(StepTable[out], 0));
digitalWrite(motorPin2, bitRead(StepTable[out], 1));
digitalWrite(motorPin3, bitRead(StepTable[out], 2));
digitalWrite(motorPin4, bitRead(StepTable[out], 3));
}
int GetTemp(void)
{
wADC = analogRead(temperatureChannel);
if(wADC < 20)
wADC = 0; /* no temperture sensor attached (avoid noise)*/
temperature = ((wADC * SCALE)-OFFSET);
// The returned temperature is in degrees Celcius * 2 for benifit on MoonLite drivers
return (temperature);
}
void readHandController()
{
// digitalWrite(testPin,LOW);
// rADC = analogRead(handController); /* read twice, keep second reading */
rADC = analogRead(handController);
analogReference(INTERNAL);
if(rADC > 20)
// if hand controller is connected
{
rADC = rADC>>6;
if(goTable[rADC])
{
speed = speedTable[rADC];
Target = Target + goTable[rADC];
isRunning = 1;
digitalWrite(RUNLED,HIGH);
}
}
// digitalWrite(testPin,HIGH);
}
long hexstr2long(char *line) {
long ret = 0;
ret = strtol(line, NULL, 16);
return (ret);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
// start of program
void setup()
{
Serial.begin(9600);
//setup the motor pins as outputs
pinMode(motorPin1, OUTPUT);
pinMode(motorPin2, OUTPUT);
pinMode(motorPin3, OUTPUT);
pinMode(motorPin4, OUTPUT);
pinMode(RUNLED,OUTPUT); /* yellow LED */
pinMode(testPin, OUTPUT);
analogReference(INTERNAL2V56);
memset(line, 0, MAXCOMMAND);
millisLastMove = millis();
}
// Forever Loop
void loop(){
// readHandController(); Not used in Teensy Version
DistanceToGo = Target - Current; /* compute remaining distance to go */
if (!Serial.available()){
// run the stepper if there's no pending command and if there are pending movements
if (isRunning) {
if(DistanceToGo > 0)
forwardstep();
if(DistanceToGo < 0)
backwardstep();
millisLastMove = millis(); /* reset idle timer */
}
else { /* Check to see if idle time is up */
if ((millis() - millisLastMove) > 5000) {
// if so, turn off motor
digitalWrite(motorPin1, 0);
digitalWrite(motorPin2, 0);
digitalWrite(motorPin3, 0);
digitalWrite(motorPin4, 0);
}
}
if (DistanceToGo == 0) {
// if motion is complete
digitalWrite(RUNLED,LOW);
isRunning = 0;
}
}
else {
// read the command until the terminating # character
while (Serial.available() && !eoc) {
inChar = Serial.read();
if (inChar != '#' && inChar != ':') {
line[idx++] = inChar;
if (idx >= MAXCOMMAND)
idx = MAXCOMMAND - 1;
}
else {
if (inChar == '#')
eoc = 1;
}
}
} // end if (!Serial.available())
// process the command we got
if (eoc) {
digitalWrite(testPin,LOW);
memset(cmd, 0, MAXCOMMAND);
memset(param, 0, MAXCOMMAND);
int len = strlen(line);
if (len >= 2)
strncpy(cmd, line, 2);
if (len > 2)
strncpy(param, line + 2, len - 2);
memset(line, 0, MAXCOMMAND);
eoc = 0;
idx = 0;
// the stand-alone program sends :C# :GB# on startup
// :C# is to start a temperature conversion, doesn't require any response (we don't use it)
hashCmd = (byte(cmd[0]) | (byte(cmd[1])<<8)); /* combine the two command charaters into an unsigned int */
switch (hashCmd) {
// GP command Get current position
case ('P'<<8 | 'G'):
pos = Current;
sprintf(tempString, "%04X", pos);
Serial.print(tempString);
Serial.print("#");
break;
case ('T'<<8 | 'G'):
// GT command Get Temperature
tempTemp = GetTemp();
sprintf(tempString, "%04X",tempTemp);
Serial.print(tempString);
Serial.print("#");
break;
case ('I'<<8 | 'G'):
// GI command 01 if motor running, 00 if not
if (DistanceToGo != 0)
Serial.print("01#");
else
Serial.print("00#");
break;
case ('B'<<8 | 'G'):
// GB command Get current backlight value, always 00
Serial.print("00#");
break;
case ('H'<<8 | 'P'):
// PH command Find motor home
Current = HOME;
isRunning = 1;
digitalWrite(RUNLED,HIGH);
break;
case ('V'<<8 | 'G'):
// GV command Get software version, always 10
Serial.print("10#");
break;
case ('N'<<8 | 'G'):
// GN command Get new (target) position
pos = Target;
sprintf(tempString, "%04X", pos);
Serial.print(tempString);
Serial.print("#");
break;
case ('C'<<8 | 'G'):
// GC command Get temerature coefficient, always 2
Serial.print("02#");
break;
case ('D'<<8 | 'G'):
// GD command Get motor speed
sprintf(tempString, "%02X", speed);
Serial.print(tempString);
Serial.print("#");
break;
case ('D'<<8 | 'S'):
// SD command Set motor speed
speed = hexstr2long(param);
if(speed < minSpeed)
speed = minSpeed;
if(speed > maxSpeed)
speed = maxSpeed;
break;
case ('H'<<8 | 'G'):
// GH command Get half step mode, always 00
Serial.print("00#");
break;
case ('P'<<8 | 'S'):
// SP command Set current position
pos = hexstr2long(param);
if(pos == 0)
pos = HOME;
Current = pos;
break;
case ('N'<<8 | 'S'):
// SN command Set new position
pos = hexstr2long(param);
if(pos == 0)
pos = HOME;
Target = pos;
break;
case ('G'<<8 | 'F'):
// FG command Start motor command
isRunning = 1;
digitalWrite(RUNLED,HIGH);
break;
case ('Q'<<8 | 'F'):
// FQ command Stop motor command
isRunning = 0;
digitalWrite(RUNLED,LOW);
break;
}
digitalWrite(testPin,HIGH);
} // end process command
} // end forever loop
-----------------------------------------------------------
That's all folks,
George
#13
Posted 22 June 2014 - 08:39 PM

George,
I am not a member, but have been intending on joining... if they will have me!

I would love to see it in person. I will bring my 6339. If I do cobble one together, I can think of one or three other forum members with the same scope who would probably be interested... Have you guys through about adding a "manual hand controller"? I think you have a ton of unused IO's on that micro controller. That is something that would be a huge help when using this under normal viewing.
John
#14
Posted 22 June 2014 - 11:15 PM
Have you guys through about adding a "manual hand controller"? I think you have a ton of unused IO's on that micro controller. That is something that would be a huge help when using this under normal viewing.
John
The first two versions were manual. See 2nd version
Then I saw Orly's posting on the Indi site. I've written a lot of embedded code over the years, but only test programs and such on PC's. So I am not the one to write an ASCOM driver. Using an existing driver by emulating the MoonLite focuser was a big break.
The manual focuser uses a slide pot with a center detent. Sliding the lever forward moves the motor forward. The further you move the lever, the faster the motor goes. Pulling the lever backwards does the same in reverse. This only requires a single ADC input. The hand controller in the photo uses an 8 pin Tiny25 processor.
#15
Posted 23 June 2014 - 12:12 AM
You can use your existing Forward Step and Backward Step functions in the class initializer for AccelStepper, and avoid having to deal with maintaining the position yourself. AccelStepper would also take care of ramping speed up and down for long slews.
#16
Posted 23 June 2014 - 12:23 AM
#17
Posted 23 June 2014 - 01:05 AM
The first two versions were manual. See 2nd version
You guys are very cool. I really like the CNC enclosures and nice PCB work. Are you etching or using your CNC to cut them?
I am planning to attend on Friday, I am really looking forward to it.
Clear skies,
John
#18
Posted 23 June 2014 - 08:35 AM
The circuit board was mechanically etched on a CNC router of my design. I built the machine for high precision work but also with the 27x48" work area I can do fairly large items. Below is a photo of the machine I built. The circuit board is machined while mounted on a vacuum platen. This keeps the material very flat.
- tim53 and allardster like this
#19
Posted 23 June 2014 - 10:35 AM
I really like your table, and use of the tool box. Very cool setup.
I had a HF X2 mill that I converted to CNC with a flood enclosure and started building a tool changer... but it had to stay in Canada when I left...

Envy!! Very nice machine.
John
#20
Posted 23 June 2014 - 12:09 PM
This is a photo of the driver board with the SMT parts installed. The isolation tracks with cut with the CNC router and then the board will tin plated (electroless Tin).
George
#21
Posted 28 June 2014 - 12:53 AM
Well, sorry I missed you if you attended the NH Astro Club. The website said General Meetings Friday 27th 11:30pm - Sat 28th 2am.... I have checked it several times over this last week because I took off work to come back from Austin to attend tonight. But as it turns out, the website had a glitch sometime last week and the normal General Meeting times were not updated.

I am going to go clean some glass and read forums

Clear skies,
John
#22
Posted 05 September 2014 - 09:01 PM
I like this design and am going to try to add a (optional) stand alone hand control for observing. My idea is to use a small project enclosure. Maybe a switch for coarse or fine and a rotary encoder for direction. If anyone has any input on the code to add I'd greatly appreciate the help. Just a point in the right direction would be helpful.
#23
Posted 22 February 2017 - 02:35 PM
Hi,
I am trying an arduino focuser project very similar to your project described on your blog. I had the same concept to use an existing protocol and ASCOM driver rather than writing a custom ASCOM driver.
I have the Arduino working with the Serial monitor using the Moonlight protocol. It also works well with my old EasyFocus ASCOM driver I have been using for years.
So, I wanted to make sure it works with the current Moonlight ASCOM driver. Hmmm, this is a problem and I hope you have a hint as to what I need to do:)
When the Chooser selects the driver, and the Properties page is selected, it first pops up a screen wanting to know which of the installed Moonlight focusers I want to use. I don't have any moonlights, so the list of focusers is blank. I can't move on to the properties page to set COM port, etc.
I don't know how this list gets populated - I assume I need some dummy entry indicating I have a focuser? How do I set this?
Thanks for any help,
Robert Brewington
BrewSky Observatory
#24
Posted 13 April 2017 - 07:07 AM
where can i get this hardware, any sellers ?
#25
Posted 09 November 2017 - 09:16 PM
where can i get this hardware, any sellers ?
There is the myFocuserPro2 project which is documented with part lists and suppliers.
https://sourceforge....focuserpro2diy/
Rating: 5 - 3 votes - Free - Windows - Communication
5 days ago - Download Arduino ASCOM Focuser Pro2 DIY for free. Version 2 of the myFocuser Project. Version 2, myFocuserPro2 for telescopes controlled ...