Jump to content

NLCbanner2024.jpg.2478be509670e60c2d6efd04834b8b47.jpg

Arduino controlled focussing


Gina

Recommended Posts

Here is the test sketch from the site where I got my stepper motor and UNL2003A driver (adjusted to my setup). This rotates the shaft one revolution one way then a revolution back again using half-stepping. It's working well :)


// This Arduino example demonstrates bidirectional operation of a
// 28BYJ-48, which is readily available on eBay, using a ULN2003
// interface board to drive the stepper. The 28BYJ-48 motor is a 4-
// phase, 8-beat motor, geared down by a factor of 68. One bipolar
// winding is on motor pins 1 & 3 and the other on motor pins 2 & 4.
// Refer to the manufacturer's documentation of Changzhou Fulling
// Motor Co., Ltd., among others. The step angle is 5.625/64 and the
// operating Frequency is 100pps. Current draw is 92mA.
////////////////////////////////////////////////
//declare variables for the motor pins
int motorPin1 = 2; // Blue - 28BYJ48 pin 1
int motorPin2 = 3; // Pink - 28BYJ48 pin 2
int motorPin3 = 4; // Yellow - 28BYJ48 pin 3
int motorPin4 = 5; // Orange - 28BYJ48 pin 4
// Red - 28BYJ48 pin 5 (VCC)
int motorSpeed = 1200; //variable to set stepper speed
int count = 0; // count of steps made
int countsperrev = 512; // number of steps per full revolution
int lookup[8] = {B01000, B01100, B00100, B00110, B00010, B00011, B00001, B01001};
//////////////////////////////////////////////////////////////////////////////
void setup() {
//declare the motor pins as outputs
pinMode(motorPin1, OUTPUT);
pinMode(motorPin2, OUTPUT);
pinMode(motorPin3, OUTPUT);
pinMode(motorPin4, OUTPUT);
Serial.begin(9600);
}
//////////////////////////////////////////////////////////////////////////////
void loop(){
if(count < countsperrev )
clockwise();
else if (count == countsperrev * 2)
count = 0;
else
anticlockwise();
count++;
}
//////////////////////////////////////////////////////////////////////////////
//set pins to ULN2003 high in sequence from 1 to 4
//delay "motorSpeed" between each pin setting (to determine speed)
void anticlockwise()
{
for(int i = 0; i < 8; i++)
{
setOutput(i);
delayMicroseconds(motorSpeed);
}
}
void clockwise()
{
for(int i = 7; i >= 0; i--)
{
setOutput(i);
delayMicroseconds(motorSpeed);
}
}
void setOutput(int out)
{
digitalWrite(motorPin1, bitRead(lookup[out], 0));
digitalWrite(motorPin2, bitRead(lookup[out], 1));
digitalWrite(motorPin3, bitRead(lookup[out], 2));
digitalWrite(motorPin4, bitRead(lookup[out], 3));
}
Link to comment
Share on other sites

  • Replies 180
  • Created
  • Last Reply

The clockwise/anticlockwise procedures turn the stepper by 8 half-steps whereas the other sketch turned by one phase - equivalent to 2 half-steps, so one focus count will be 5 operations of the clockwise/anticlockwise procedure. So it would make sense to add a loop of 5 counts to the clockwise/anticlockwise procedures - then calling these would produce onr focus count in one direction or the other.

I now have a sketch that works as wanted though I still have focuser selection to add (no problem). The push buttons switches I'm using are unreliable and I'm thinking of getting some better quality ones. I have a 100ms bounce allowance but I'm still getting a bounce on one of the buttons and another is reluctant to make contact. They're very cheap ones I got form Maplins some time ago. The stepper is much smoother with the half-step operation :)


// This Arduino example demonstrates bidirectional operation of a
// 28BYJ-48, which is readily available on eBay, using a ULN2003
// interface board to drive the stepper. The 28BYJ-48 motor is a 4-
// phase, 8-beat motor, geared down by a factor of 68. One bipolar
// winding is on motor pins 1 & 3 and the other on motor pins 2 & 4.
// Refer to the manufacturer's documentation of Changzhou Fulling
// Motor Co., Ltd., among others. The step angle is 5.625/64 and the
// operating Frequency is 100pps. Current draw is 92mA.
////////////////////////////////////////////////
//declare variables for the motor pins
int motorPin1 = 2; // Blue - 28BYJ48 pin 1
int motorPin2 = 3; // Pink - 28BYJ48 pin 2
int motorPin3 = 4; // Yellow - 28BYJ48 pin 3
int motorPin4 = 5; // Orange - 28BYJ48 pin 4
// Red - 28BYJ48 pin 5 (VCC)
int motorPin1a = 6; // Blue - 28BYJ48 pin 1
int motorPin2a = 7; // Pink - 28BYJ48 pin 2
int motorPin3a = 8; // Yellow - 28BYJ48 pin 3
int motorPin4a = 9; // Orange - 28BYJ48 pin 4
////////////////////////////
int motorSpeed = 1200; //variable to set stepper speed
int count = 0; // count of steps made
int countsperrev = 512; // number of steps per full revolution
int lookup[8] = {B01000, B01100, B00100, B00110, B00010, B00011, B00001, B01001};
//////////////////////////////////
int wfPin = 10; // Widefield focuser select switch
int controlPin = 0; // Input control line pin
boolean wf; // Widefield focuser true/false
int focusCount = 0; // focus count for WF
// int focusCount_b = 0; // focus count for scope
// int focusCountPrev_a = 0;
// int focusCountPrev_b = 0;
int val = 0; // value of control input voltage
int opCode = 0; // corresponding operation code
int stepSize = 5; // how many motor steps correspond to one focussing step
boolean busy = false; // used to provide single action buttons - wait for "up" before continuing
//////////////////////////////////////////////////////////////////////////////
void setup() {
//declare the motor pins as outputs
pinMode(motorPin1, OUTPUT);
pinMode(motorPin2, OUTPUT);
pinMode(motorPin3, OUTPUT);
pinMode(motorPin4, OUTPUT);
Serial.begin(9600);
}
//////////////////////////////////////////////////////////////////////////////
//set pins to ULN2003 high in sequence from 1 to 4
//delay "motorSpeed" between each pin setting (to determine speed)
void moveBackward()
{
for (int s = 0; s < stepSize; s++) {
for(int i = 0; i < 8; i++)
{
setOutput(i);
delayMicroseconds(motorSpeed);
}
}
focusCount--;
Serial.println(focusCount);
}
///////////////////////////
void moveForward()
{
for (int s = 0; s < stepSize; s++) {
for(int i = 7; i >= 0; i--)
{
setOutput(i);
delayMicroseconds(motorSpeed);
}
}
focusCount++;
Serial.println(focusCount);
}
////////////////////////
void setOutput(int out)
{
digitalWrite(motorPin1, bitRead(lookup[out], 0));
digitalWrite(motorPin2, bitRead(lookup[out], 1));
digitalWrite(motorPin3, bitRead(lookup[out], 2));
digitalWrite(motorPin4, bitRead(lookup[out], 3));
}
///////////////////////
void moveB10() {
if (busy == false) { // do it once then wait for button release
for (int i = 9; i >= 0; i--) {
moveBackward(); }
busy = true; }
}
////////////////////////////
void moveB1() {
if (busy == false) {
moveBackward();
busy = true; }
}
//////////////////////////
void moveF1() {
if (busy == false) {
moveForward();
busy = true; }
}
///////////////////////
void loop() {
wf = (digitalRead(wfPin) == LOW);
val = analogRead(controlPin);
// Break points 102, 307, 512, 717 and 922
if (val < 102) { // allow for small variations in control line voltage by separating into bands
opCode = 0;
} else if (val < 307) {
opCode = 1;
} else if (val < 512) {
opCode = 2;
} else if (val < 717) {
opCode = 3;
} else if (val < 922) {
opCode = 4;
} else {
opCode = 5;
}
//
switch(opCode) {
case 0 : busy = false; delay(100); break; // clear busy flag and wait for button state to settle (switch bounce)
case 1 : moveBackward(); break;
case 2 : moveB10(); break;
case 3 : moveB1(); break;
case 4 : moveF1(); break;
case 5 : moveForward(); break;
}
}
Link to comment
Share on other sites

From the loop:

void loop() {

wf = (digitalRead(wfPin) == LOW);

val = analogRead(controlPin);

// Break points 102, 307, 512, 717 and 922

if (val < 102) { // allow for small variations in control line voltage by separating into bands

opCode = 0;

} else if (val < 307) {

opCode = 1;

} else if (val < 512) {

opCode = 2;

} else if (val < 717) {

opCode = 3;

} else if (val < 922) {

opCode = 4;

} else {

opCode = 5;

}

//

... where did you get the break points? I take it you derived them from measured values given by the resistors? Just that it seems to me they're not round numbers - if they're each n points above the measured values then sorry for butting in :embarrassed: but if they're the exact measured values then they give little scope for upward variation in voltage.

Link to comment
Share on other sites

For the max analogue input voltage of 5v analogRead produces 1024. All input voltages below that are pro-rate eg, 2.5v gives 512. I wanted 5 buttons so divided the 5v into 5 giving 1,2,3,4,5 volts and 0v with all off. The break points chosen correspond to the half-way value between ie. 0.5, 1.5, 2.5, 3.5 and 4.5v. That's 0.1, 0.3, 0.5, 0.7, 0.9 times 1024. I used the calculator to get these in-between digital values.

Link to comment
Share on other sites

To select the required focus motor from the switch was simply a matter of changing the setOutput procedure as follows.


void setOutput(int out)
{
if (wf) {
digitalWrite(motorPin1, bitRead(lookup[out], 0));
digitalWrite(motorPin2, bitRead(lookup[out], 1));
digitalWrite(motorPin3, bitRead(lookup[out], 2));
digitalWrite(motorPin4, bitRead(lookup[out], 3));
} else {
digitalWrite(motorPin1a, bitRead(lookup[out], 0));
digitalWrite(motorPin2a, bitRead(lookup[out], 1));
digitalWrite(motorPin3a, bitRead(lookup[out], 2));
digitalWrite(motorPin4a, bitRead(lookup[out], 3));
}
}
Link to comment
Share on other sites

Sounds fine :) Though that switch has a strange permutation of connections.

After a bit more research on the switch it looks like they are mostly used for switching guitar pickups. The output is Gray code and can be decoded using only 3 digital inputs on the arduino.

Link to comment
Share on other sites

How's the backlash on these gearboxes, Gina? Looking at the internals I get the feeling that some gears are very small and would become a problem.

MNtJRtaHSOy8C5Bpd6PCcQ.jpg

Sorry, I missed this earlier :( The backlash is about one of my focus counts ie. one hundredth of a revolution or 3.6 degrees. Actually, I think it's slightly less so of the order of 3 degrees.
Link to comment
Share on other sites

I now have my focussing system installed and working :) Well mostly - one driver seems to have gone kaput - but the other is working fine. I have the working driver connected to the scope focussing stepper motor. The amount of movement produced by a focussing step seems about right :) The backlash in the stepper gearbox is about one focussing step so to change direction means just one extra step to cater for the backlash. I was out in the obsy tonight and tried focussing on a bright star. I selected the Ha filter being what I want to use for the next imaging session and used my 5 button control box to focus. I used about half a second exposure, looping in Artemis and set the FWHM box onto the star. It was at around 6 after a coarse focus. I then stepped each way to determine which way to go - it was backwards, and single steps were taking a while to get there so I used the back10 button until I got it around 2. Finally, single stepping got the FWHM around 1 and below. I was able to go back and forth quite easily with the small backlash.

Link to comment
Share on other sites

I know this hasn't anything to do what u guys are up to now :)

But i wonder how the original SGL code should be setup?

I have a problem with the Limit, in FrmControl, it sais the "LMT" is 30000 steps, but i have a total of about 170.000 steps to my draw tube.

And one revelution with the easudriver and a 200step motor, is that 1600 steps?

And what is "volatile long NoOfSteps = 1000; //required number of steps to make" referring to?

here is the code i am referring to:


// initialize the library with the numbers of the interface pins
int dirPin = 2; // Easy Driver Direction Output Pin
int stepperPin = 3; // EasyDriver Stepper Step Output Pin
int powerPin = 4; //Sets the output used to power the Driver board
unsigned long powerMillis = 0; // used to remember when EasyDriver power was enabled
int motorSteps =1600; //number if steps for the motor to turn 1 revolution
volatile long NoOfSteps = 1000; //required number of steps to make
volatile long Position = 0; //used to keep track of the current motorposition
volatile long MaxStep = 200000; //define maximum no. of steps, max travel
volatile int SPEED = 500;
volatile byte MotorType = 0; // Motortypes, default is 0, Stepper motor, 1=Servo, 2=DC motor
volatile int BoardType = 0; // Boardtypes, default is 0, EasyDriver, 1=L293 chip, 2=LadyAda AFmotor board
Link to comment
Share on other sites

Volatile tells the compiler that the value may change - so each time you read it will read from the location rather than the CPU cache or CPU register value.

It's used, usually, when you have hardware mapped into a variable location and you want to ensure the latest value is used.

Link to comment
Share on other sites

Got the widefield rig set up this morning and been checking the focus rate on the lens. It's far too slow so I'm going to take out two gears from the plastic gearbox to reduce it's ratio from 64:1 to 4:1. ATM holding down either of the fast forward/reverse buttons takes an age to change focus so I'm going to try reducing by 16x and see how that is. At least I can check this in daylight by focussing on a distant house on the far hill about a mile away.

Link to comment
Share on other sites

Widefield focussing motor/gearbox with 4:1 reduction gearing in the plastic gearbox.

post-13131-0-68376800-1363529936_thumb.j

If I find this is still too fine I can reduce by another 4:1 by putting the output shaft in place of the middle shaft and not use any plastic gears.

Link to comment
Share on other sites

This reduction ratio seems quite reasonable but I won't know for sure until I can get on a star. I found I needed extra tension in the belt driving the camera focussing sleeve than with the other lenses - it was slipping at first. That was why it was seeming taking forever to focus - it was never going to get there :D

Link to comment
Share on other sites

The widefield rig and focussing system had a working trial last night. I think the focussing is a little coarse - I think single stepping went either side of the correct focus. Ha and SII were reasonably focussed but I just couldn't get the OIII image to focus to better than around a HWFM value of around 4 with gert big round blobs for stars. I was imaging the Heart & Soul Nebulae which look very promising for NB imaging (I found I could just get them both in with my 105mm f2.8 lens on the 314L+).

So I need either to add more gearbox reduction or change the sketch to reduce the focus step size for this focuser. ATM only one stepper driver is working, so for the latter solution, I need to fix that. It wants fixing anyway :D

Link to comment
Share on other sites

I have the wifefield rig indoors. Checking the plastic gearbox I find it isn't possible to change the reduction ratio from 4:1 to 16:1 with the stepper motor so I'm using the software solution. I've chenged the number of stepper motor steps per focussing step from 5 to 2. Also, while examining the sketch I found a mistake that may be the cause of the second focussing stepper not working. I hadn't included the second set when setting the motorPins to OUTOUT in the setup procedure.

I've also improved the mounting rigidity slightly (though this really wants a new design) and fixed the belt slippage problem. Used another (smaller) belt inside out with a springy wedge to hold it tight around the focus sleeve. This then acts like a large timing pulley for the main belt to drive.

Next job is to put it all back and test it.

Link to comment
Share on other sites

I'm thinking that if I could clamp the filter wheel and use a jockey pulley to tension the focussing belt I might be able to make a more rigid mounting.

Link to comment
Share on other sites

This is going a bit off-topic but never mind :D Ideas for mounting the WF rig. First though was pair of brackets made out of ali strip but I haven't got any left ATM so would have to buy more. Then I thought of wood (I'm more at ease working wood than metal anyway) - see sketch 1. The piece to clamp the filter wheel to isn't wide enough really and I can't fine anything better. OTOH I have an ali plate of 200mm x 150mm x 3mm which I bought for the main mounting but was too small so not used and thought that would make a good back plate - see sketch 2 (front) and 3 (back).

post-13131-0-29258400-1363702092_thumb.j post-13131-0-34613300-1363702093_thumb.p post-13131-0-67142700-1363702094_thumb.p

Link to comment
Share on other sites

Volatile tells the compiler that the value may change - so each time you read it will read from the location rather than the CPU cache or CPU register value.

It's used, usually, when you have hardware mapped into a variable location and you want to ensure the latest value is used.

That is correct but the change has to occur without the knowledge of the s/w. Are you seriously telling me the the board type can spontaneously change without the s/w knowing about it. You either auto detect the board type or it is set by a s/w option there is no way it can change "spontaneously".

As far as I can tell non of those variable should be volatile.

Link to comment
Share on other sites

That is correct but the change has to occur without the knowledge of the s/w. Are you seriously telling me the the board type can spontaneously change without the s/w knowing about it. You either auto detect the board type or it is set by a s/w option there is no way it can change "spontaneously".

As far as I can tell non of those variable should be volatile.

True, it seems that none of those parameters are actually memory locations for hardware.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. By using this site, you agree to our Terms of Use.