Galil Mirror Controllers
By Russell Owen
Contents
Introduction
This manual describes motion controllers used to control various
mirrors and other devices at Apache Point Observatory. The manual
describes the basic software and wiring common to all devices. It
also describes most or all of the controlled devices, including
software and wiring additions. (At the time of this writing, the SDSS
engineering camera is not described.)
Each motion controller consists of a Galil DMC-15x0 motion
controller, added software described in this manual, and a mixture of
stepper motor and servo motor drivers. The stepper motor drivers must
include an "on full step" output if you wish to power down the motors
after a move (as we do in most cases, to reduce generated heat). One
such driver is the Intelligent Motion Systems IMS-483.
These motion controllers take as input the length of each
actuator, in microsteps. There is no attempt to deal with "natural"
units, such as μm, nor with a "natural" frame of reference, such
as piston, tilt and translation of a mirror. This decision was made
because the Galil motor controller's built-in programming language is
primitive and the number representation has very limited
precision.
There are also documentation from Galil which describe the built
in command set, wiring and electrical specifications. The newer Galil
documentation is divided into two manuals, one for commands, the
other for everything else. The older documentation combines
everything in one fat manual. The built in Galil command set is not
used for normal motion, because the added software provides higher-level
commands. But the built in language is worth knowing about,
as it can be very handy for engineering.
Commands
The following commands are intended to be used interactively. The
behavior of these commands may be altered by device-specific
modifications (described elsewhere in this manual):
Engineering Commands:
There are additional commands in the Galil that are only not documented here,
as they are intended for internal use. For a complete list, see the
source code (preferably the text files, as the code in the Galil
has the comments stripped away to save memory).
Axis Variables A, B, C, D...
Motion commands require a position or other parameter for each
axis. To execute these commands, first set variables A, B, C, D... to
the desired position or other value (see the command for details),
then execute the command. To leave an axis unchanged, leave the
variable alone. If you set a variable and want to clear it, set it to
MAXINT. To clear all variables at once, simply execute any non-motion
command, such as STATUS.
XQ #COMPVAR
Computes variables needed for operation, based on user-specified
constants. As such, it should be executed whenever you change any
user-specified constant. It is
also executed automatically at power up.
It is a grave mistake to change any user-specified constants
without then executing COMPVAR. At best your changes will be ignored,
but you might put the Galil into an inconsistent state resulting in
very strange behavior.
Warning: If you change any constants dealing with range of
motion, you should also home the system after
running COMPVAR.
XQ #HOME
Homes all axes using the algorithm described below.
Before calling, set axis variables A, B,
C... to any value other than MAXINT (the default) for the axes
you wish homed. Homing is prohibited if any axis is moving. An
axis must be homed before it can be moved using MOVE
or MOVEREL.
If the controller has been homed at least once since last power
up, the position error (change from last home position) is reported.
This error may be due to lost steps or an actual change in the home
position due to inaccuracy in the home switch or positioning
mechanism.
Caveats:
- Don't forget to specify the axes you want homed!
- The homing sequence can be important. Details for homing each
mirror at Apache Point Observatory are given in the TCC
Operator's Manual section Homing
Mirrors. More generally:
- In a system with axial and transverse actuators it is
usually best to home the transverse actuators first, then
center the transverse position, then home the axial
actuators.
- Depending on the design of the support system, there may be
crosstalk between axes, so that homing one axis without homing
related axes (e.g. all axials at the same time) could produce
incorrect results.
- Homing can take quite a long time, depending on the speed of
the actuators and the distance from home. To assist in automatic
homing, maximum times are returned for the longer operations, such
as initially running into the reverse limit. These times allow the
controlling computer to set reasonable time limits for the
operation to complete.
- Home is near the negative limit switch, so the first motion
after homing may take quite awhile.
- Homing sometimes fails for the SDSS M2 actuator system. This
is because the M2 axial actuators are not strictly monotonic at
the home switch. The only known solution is to repeatedly home
failed axes until homing succeeds. At present all, all other
systems should home correctly the first time and failure may
indicate a problem.
XQ #MOVE
Moves to the given absolute position, in microsteps. Before
calling, set axis variables A, B, C...
to the desired position. Example, moving only axes B and C (all
spaces are optional):
B = -5623
C = 25
XQ #MOVE
This command prints the duration of the move for each axis, the
target position and, when finished, the actual end position. The
command does not return until motion finishes and is verified to have
completed successfully.
If correction is enabled, then at the end of the move the encoders are read and a corrective move is made of all eligible actuators.
- To enable or disable correction for all axes, set NCORR to 0 or 1.
- To disable correction for a particular axis, set MAXCORRx to 0.
- If the error is too large (as set by MAXCORRx), an error is reported and no correction is made.
- An actuator is eligible for correction if it has an auxiliary encoder.
- See also ENCTIME and ENCRESx.
If MOFF = 1 then the motion will be rounded to
the nearest full step, and the motors powered down WTIME
seconds after the move completes. If MOFF = 0
then the motion will be to the nearest microstep and the motor
current will be left on (motor current may automatically be reduced
after a short time by the motor drivers, but the Galil motion
controller has nothing to do with such current reduction).
XQ #MOVEREL
Like MOVE except the specified position is an
offset, relative to the target position. The default offset is
zero.
XQ #SHOWPAR
Displays constant (but settable) parameters. If the system
includes additional device-specific enhancements then additional
lines showing device-specific parameters may be appended.
Sample output for a 4-axis system with no device-specific
enhancements. A leading colon has been removed:
XQ#SHOWPAR
02.01, 4 software version, NAXES number of axes
0, 1, 00 DOAUX aux status? MOFF motors off when idle? NCORR # corrections
00.10, 00.00, 30.00 WTIME, ENCTIME, LSTIME
-000500000, -000500000, -000500000, -000500000 -RNGx/2 reverse limits
000500000, 000500000, 000500000, 000500000 RNGx/2 forward limits
000050000, 000050000, 000050000, 000050000 SPDx speed
000005000, 000005000, 000005000, 000005000 HMSPDx homing speed
000500000, 000500000, 000500000, 000500000 ACCx acceleration
000000000, 000000000, 000000000, 000000000 MINCORRx min correction
000000000, 000000000, 000000000, 000000000 MAXCORRx max correction
000000050, 000000050, 000000050, 000000050 ST_FSx microsteps/full step
000005000, 000005000, 000005000, 000005000 MARGx dist betw hard & soft rev lim
000000000, 000000000, 000000000, 000000000 INDSEP index encoder pulse separation
0000.0000, 0000.0000, 0000.0000, 0000.0000 ENCRESx encoder resolution (microsteps/tick)
OK
XQ #STATUS
Displays the current status of the controller, including whether
axes have been homed, the commanded position, current
position and a status word for each
axis. If an axis has not been homed, the position information for
that axis is invalid and will be displayed as all 9s. If the system
includes additional device-specific hardware that has to be managed
for motion to begin and end (e.g. brakes or clamps) then additional
lines of status showing the status of that hardware will be
appended.
The meaning of current position
depends on whether the axis is a stepper or servo motor, and whether
or not it has an auxiliary (optional) encoder:
| No Aux. Encoder | Aux. Encoder |
Stepper Motor | commanded position | aux. encoder position |
Servo Motor | motor encoder pos. | aux. encoder position |
Sample output for a 3-axis system with no device-specific
enhancements. A few leading colons have been removed:
XQ#STATUS
-001497400, -000767250, -001199000 commanded position
-001497400, -000767250, -001199000 actual position
00065537, 00065540, 00065540 status word
OK
XQ #STOP
Halts the axes and (if MOFF = 1) powers down the motors. Warning: may not halt the motors on a full step.
Engineering Commands
Engineering commands are not intended for use by the TCC. They are more likely to change over time than commands used by the TCC. They may not return OK when finished.
XQ #GOFS
Moves slowly forward to the next full step (as reported by the stepper motor drivers). Before calling, set axis variables A, B, C... to any non-MAXINT value for the axes you wish to move. Axes with servo motors are not moved; no warning is given.
XQ #GOIND
Moves forward at speed HMSPDx to the next index pulse. Before calling, set axis variables A, B, C... to any non-MAXINT value for the axes you wish to move. Axes without an index pulse encoder (INSEPx=0) are not moved; no warning is given.
XQ #GORLIM
Runs into the reverse limit switch at full speed. Before calling, set axis variables A, B, C... to any non-MAXINT value for the axes you wish to move.
Warnings:
- Motion is limited to roughly 1.25 times the full range RNGx,
to detect a stalled actuator. If the actuator starts well forward
of its normal range (as can happen if the software range is
significantly smaller than the range between limit switches) the
actuator may not make it all the way to the limit switch the first
time. If this happens, inspect the actuator to make sure it is
moving safely and reissue the command.
- The actuators being moved may not all end up with their limit
switches compressed. This can happen for various reasons including
the limit switches not being right on the actuators (so motion in
one actuator affects another) or in the case of the SDSS M2
actuators, slightly irregular motion at the limit switches.
Device-Specific Modifications
Galil motion controllers may be modified to support special needs
for specific devices. Local modifications consist of several
parts:
The following subroutines must be replaced. This can be done by
starting your file with DL #LCMPVAR and including all of the other
subroutines listed, ending with a backslash on its own line. See
existing local modification files for examples of how this is done.
In addition to the required routines below, you may add any
subroutines you wish, preferably beginning with the letter L to avoid
confusion with built-in routines.
#LCMPVAR
Additions to #COMPVAR, which computes variables at power up and
reset. You must define #LVERS to the current version of your local
modifications. This is also a good place to define any constants or
initialize any variables needed by your local modifications. All
constant or variable names should begin with "L".
#LGO (was #LMINIT in version 1.5)
Actions to perform just before each motion begins (just before the
motors are turned on if MOFF=1). Test for A, B, C... <> MAXINT
to see which axes are about to move. Test _PRA <> 0,
_PRB<>0... to see if the specified axis is actually being
commanded to go anywhere new. The value of _PRx is either the amount
of the commanded move or in some cases (such as finding the reverse
limit switches) an upper limit. It is important that this code be
"restartable"; if #LMINIT is interrupted (e.g. due to a power
failure) then a subsequent call to #LMINIT should finish the
initialization sequence.
If initialization takes significant time then you should be smart
and only initialize if it has not already been done. If you fail to
do this you will not only waste time but you will also make the
reported time for a #MOVE or #MOVEREL incorrect (because the time
estimate only takes into account one initialization, whereas the move
calls #LGO twice).
#LSTATUS
Additions to #STATUS, the status display. Display the state of any
interesting hardware you've added.
#LSHWPAR
Additions to #SHOWPAR, the show parameters display. Display the
value of any interesting constants you've added.
#LMSTIME
Add the time needed to perform the actions in #LMSTOP for each
axis to RESx, in seconds. This allows an accurate reporting of the
motion end time. Test for A, B, C... <> MAXINT to see which
axes are about to move, and don't increase RESx unless the axis is
going to be moved (or, more precisely, extra time is required to stop
that axis for whatever reason).
#LMSTOP
Actions to perform after a move completes (just before the motors
are turned off, if MOFF = 1). It is important that this code be
"restartable"; if #LMSTOP is interrupted (e.g. due to a power
failure) then a subsequent call to #LMSTOP should finish the
end-of-motion sequence.
#LMVTIME (was #LMITIME in version 1.5)
Add the time needed to perform the actions in #LGO for each axis
to RESx, in seconds. This allows an accurate reporting of the total
motion time. Test for A, B, C... <> MAXINT to see which axes
are about to move, and don't increase RESx unless the axis is going
to be moved (or, more precisely, extra time is required to initialize
that axis for whatever reason). If LGO is smart about only
initializing when not already initialized then you should also make
#LMVTIME smart in the same way.
#END
This is a placeholder for the end of code. Test routines are
appended from this label, overwriting anything that follows. Hence
nothing should follow!
Internals
Basics
The controller represents numbers using 6 bytes of integer
followed by 2 bytes of fraction, for a range of:
-2147483647.9999 to 2147483647.9999
The Galil keeps track of positions in microsteps, or in the case of servo motors, in motor shaft encoder ticks. I use the term "microstep" for both cases. For stepper motors, the number of microsteps in a full step is determined by the stepper motor driver, and the corresponding value must be set in ST_FSx. A full step is defined as a magnetic detent on the stepper motor; it is also where the motor will go if only one coil is energized. For servo motors there is no concept akin to a "full step" and ST_FSx should be set to 1.
I had some trouble determining if a typical 200 step motor had 200 magnetic detents. Most motor manufacturers said yes, but a few claimed that 200 step motors had only 50 magnetic detents. I then tested several different stepper motors (including one 400 step motor) and found that all "n" step motors I tested had "n" magnetic detents.
Each axis may have an optional "auxiliary" encoder. For stepper motors, this is any encoder (since stepper motors are often run with no encoder). For servo motors, this is in addition to the required motor shaft encoder and is used in a situation where there may be slippage between the motor and the actuated part.
This controller can be made to turn off motors on a full step by setting MOFF = 1, in which case motions will always be rounded to the nearest full step. This is useful for reducing overall power dissipation and noise, while leaving a stepper motor with some (not very much) holding torque. If heat is less of an issue and you need stronger holding torque or higher resolution, you may prefer to keep the motor energized all the time. Most stepper motor drivers (including the IMS-483) will automatically reduce
current to the motor after a certain period of inactivity.
The following assumptions were made in coding the Galil motion controller:
- All axes are either left on after a move or else moves are
made to the nearest full step and all motors then powered off.
This property can only be set for the entire controller (all
axes), it cannot be set individually for each axis. This would be
difficult to change.
- The reverse limit switch is also the home switch for each
axis, so you cannot use the forward limit switch for homing. This
is an unpleasant limitation, but one that is very difficult to
code around.
- The range of motion is set by RNGx. The
forward and reverse soft limits are set at +/-RNGx / 2 rounded to
the nearest full step. Hence zero is always the center of travel.
If you set RNGx too large, you will find yourself running into the
positive limit switch (or hard limit if there is no switch) before
you reach the software limit. Setting RNGx too small needlessly
constrains motion and may also cause HOME to fail on the first
attempt (see Homing Algorithm), in
which case executing HOME again should do the trick.
- Motion of the actuators is strictly monotonic; motion in a
given direction at the motor should always produce motion in a
given direction at the actuator. If this is not true near the home
switch, homing may fail. This is, unfortunately, a common problem
with the SDSS Secondary axial actuators.
Homing Algorithm
Axes are homed as follows:
- Run into the reverse hard limit at full speed (using GORLIM)
and come to a controlled stop (hence no counts are lost; this is
always how stops are made when hitting limits). Soft limits are
set to 25% above the full range specified by RNGx;
if the travel between limit switches is greater than this, homing
may fail the first time, and need to be repeated.
- If any reverse limit switches are not depressed (i.e. the
switch was contacted, but continuing motion in some other axis
then disengaged the switch), try GORLIM
again. At this point all reverse limit switches must be engaged or
the process halts with an error message.
- Move forward slowly until the reverse limit disengages. The
reverse limit switch is ganged to the home switch input and the
FE
command is used to find the transition in the home
switch. A time limit determined by LSTIME
prevents FE
from running forever. (This is actually
implemented as a motion limit, but the limit is computed from
LSTIME).
- Move forward a distance MARGx to move out
of physical contact with the reverse limit switch.
- For each axis with an index pulse encoder, move forward slowly
to the next index pulse, using GOIND.
- If the motors are to be powered off after a move (MOFF
= 1), move forward very slowly until on a full step and then power
off the motors, using GOFS.
- This position is then defined to be the reverse soft limit.
The position is set to as -RNGx / 2 rounded to
the nearest full step. Hence if the motor is now on a full step, 0
will also be on a full step. (This is only relevant if the motors
are to be powered off after each move, but is always done in any
case.)
- If the unit has already been homed since last time it was
powered on, the new value for the reverse software limit is
compared to the old value and reported as a position error.
- Finally, the forward soft limit is set to the negative of the
reverse limit. Note that no checking is done to see if the forward
limit switch is outside this range, or if such a switch even
exists. It is the user's responsibility to set RNGx
correctly.
Coding Standards
The Galil's programming language is very primitive. All variables
are global, all math is fixed point, subroutines do not accept
arguments, parameters must be dealt with one at a time for each axis
(there are arrays, but Galil does not use them to set or return
information about the axes) there is no formal looping and there are
no string variables (a numeric variable can be used to hold 6 bytes
of string data). To make the job more tolerable, I developed the
following standards:
- In variable names "ST" is used for steps (microsteps), FS is
full steps, RV is revolutions and ENC is encoder ticks. (MS is
milliseconds, as usual).
- Subroutines that need statement labels (to which to jump) use
the following convention, where <n> is a unique number
(generally I count up by 2) and <name> is the name of the
subroutine truncated so that the complete label name is no more
than 7 letters long.
- #E<n><name> (E for error) to jump to an error
handler
- #G<n><name> to perform a normal jump (G for
good)
- #x<name> when a series of jumps is used for handling
a set of axes, where x is axis letter A-F
- Subroutines return results in variables RESx (x is axis letter
A-F) and possibly ISBAD (0 if OK, 1 if error). The one exception
is #DP... subroutines, which act on the desired position variables
DESPOSx.
- Assertion subroutines return RESx = 1 if the assertion failed
for axis x.
- If a set of numbers are to be computed, one per axis, I insist
that the computation for each axis fit on one line. This makes
errors in the pattern show up very clearly. Sometimes this
requires multiple sets of statements (e.g. breaking the problem
down) and results in less efficient code. Nonetheless, my
experience has shown that the gain in readability is well worth
the cost. With more complex-but-efficient code it is much, much
harder to spot errors in a specific axis. It's hard enough as it
is; the lack of ability to deal with data for axes as arrays is
very frustrating.
- I always work in microsteps, to reduce round-off errors
associated with the fixed-point arithmetic. Most user-set
constants are specified in revolutions, but none of them has a
critical effect on accurate positioning.
- Temporary variables are either called TEMP or begin with the
name of the subroutine.
- Background processes are not allowed to set RESx, ISBAD or any
other variable that might be used by some other subroutine. Hence
they cannot call most subroutines.
- Background processes associated with movement (turning off the
motors is presently the only such process) must be executed in
thread 3.
Constants and Parameters
Various constants (actually variables that are set once and saved)
are used to control aspects of motion such as velocity and range of
motion. There are some computed constants whose values depend on
these user-set constants, so whenever you change a user-specified
constant, be sure to run XQ #COMPVAR
to update all
computed constants.
The safest way to change constants is to edit the file "M1
Constants" or "M2 Constants" and upload the entire file to the Galil
(e.g. via copy/paste in any terminal emulator). This assures that
computed constants are correctly updated and that the values are
saved (using BV
).
In addition to these constants, the Galil has a few built-in
"parameters" that must also be specified for proper option. The
distinction between constants and parameters is purely internal to
the Galil; parameters are saved differently (using BN
)
and some of them are write-only (which is very frustrating).
Fortunately, there are only a few parameters and they should never
need to be changed once they are set correctly and saved.
In addition to setting these constants and parameters, there are
jumpers in the Galil that must be set appropriately to drive stepper
motors (one jumper per axis). Galil motor controllers come from the
factory configured to drive servo motors, not steppers.
User-Specified Constants
User-specified constants are actually variables that the software
does not touch (except in a few special cases noted below). Variables
may be set manually, but the best way to make permanent changes is to
find the appropriate file of constants for the mirror in question,
edit it, and upload the file to the Galil. Doing this assures that a
correct and current file of constants is always available to be
examined. At the time of this writing there is no permanent archive
for files of constants, please contact Russell
Owen to examine the files or to make permanent changes.
To examine the value of a variable use MG name. To change a
value, use name = value. After you change a value you
should propagate it using XQ
#COMPVAR
. Warning: after changing any
user-specified constant you must update the computed constants
using XQ #COMPVAR
, else all sorts
of strange and unpredictable behavior can result.
- AUXMAXN
- The maximum number of actual positions output from the auxiliary port before a commanded position is output. ("Maximum" because commanded position is output more often if the axis is moving).
- DOAUX
- If 1 (or nonzero) then status information is automatically emitted from the auxiliary serial port. See Auxiliary Port Status for details.
- ENCTIME
- Settling time (in seconds) after a move and after WTIME, before the encoders are read. Ignored if NCORR is zero. If ENCTIME > 0 and MOFF = 1 then the motors are turned off while waiting for ENCTIME.
See also NCORR, ENCRESx, MINCORRx and MAXCORRx.
- LSTIME
- Maximum time required to back out of a limit at low speed. This is only used as a time limit, so please be generous.
- MOFF
- Turn off all motors after each move? 1 (or nonzero) = yes, 0 = no. If 1 (turn motors off) then stepper motor positions are rounded to the nearest full step, and the Galil verifies that each stepper motor driver is reporting "on full step".
- NAXES
- Number of axes. Valid values are in the range 1-6.
- NCORR
- Determines how many encoder-based corrections are applied after a move. Correction is only made for actuators with an auxiliary encoder (ENCRESx nonzero) and for which MAXCORRx is nonzero.
See also ENCTIME, ENCRESx, MINCORRx and MAXCORRx.
- WTIME
- Settling time after a move, in seconds. If MOFF = 1 then the motors are left on for WTIME before being turned off. See also ENCTIME.
Axis-specific constants (x = A-F depending on the axis)
Unless otherwise noted, axes-specific constants must be > 0 if the axis exists and are ignored (and possibly overwritten) if the axis does not exist.
- RNGx
- Full range of motion, in microsteps. This should be approximately 10% less than the range delimited by the limit switches. Homing is done with respect to the reverse limit switch, so test RNGx by first homing and then moving to the positive soft limit. If RNGx is too large the positive limit switch will be touched or even tripped. If RNGx is too small, the full range of motion will not be used. If RNGx is less than 0.8 of the range set by the limit switches, it is possible for homing to fail on the first attempt and require an additional iteration.
- MARGx
- Margin between the hard and soft reverse limits, in microsteps. Set this just large enough that the reverse limit switch is not touched when homing is finished. Setting this too large needlessly reduces the full range of travel available to the actuator. If MOFF = 1 and you are using a rotary index pulse encoder, you should adjust MARGx so that after the move by MARGx the actuator ends up roughly halfway between index pulses. This gives you the best odds of always ending on the same index pulse after homing. (If you cannot make this adjustment then you may wish to disable the index pulse encoder by setting INDSEPx to 0.)
- SPDx
- Maximum speed, in microsteps/sec. Stepper motors have less torque the faster they go, and may also resonate at certain speeds, so be conservative. Test your setting to be sure the motor moves reliably and sounds good both loaded and unloaded.
- HMSPDx
- Maximum speed for finding the home switch, in microsteps/sec. Intuitively it ought to improve accuracy to home at a lower than normal speed than normal (SPDx). However, the Galil keeps track of counts as it decelerates, even if it hits a limit switch, so homing at a lower speed may not actually be important.
- ACCx
- Acceleration and deceleration of each axis, in microsteps/sec2. I'm not sure what sets the upper limit (besides resolution in the Galil), but in cases of low inertia, I suggest a value at least 10x the speed (SPDx). Stepper motors work better with fast acceleration.
- ST_FSx
- Step resolution, in microsteps per full step; set to 1 for a servo motor. This value must match the resolution set in the stepper motor driver.
- INDSEPx
- If this axis has an index pulse encoder and it is used for homing, then set to the separation between index pulses in microsteps. Otherwise 0. Subtlety: if MOFF = 1, you may wish to adjust the position of the reverse limit/home switch position or the index pulse encoder so that during homing the number of microsteps taken to find the full step (after finding the index pulse) is approximately half a full step (on the average over a number of homings). This gives you the best odds of always ending on the same full step after homing.
- ENCRESx
- Resolution of encremental auxiliary encoder in ticks per microstep; 0 if no auxiliary encoder. See also NCORR, ENCTIME, MINCORRx and MAXCORRx.
- MINCORRx
- The minimum error that will be corrected. 0 means correct any error, no matter how small. If MOFF=1 then this value is compared to position errors rounded to the nearest full step.
The error in question is measured by the auxiliary encoder at the end of the move.
See also NCORR, ENCTIME and ENCRESx and MAXCORRx.
- MAXCORRx
- The maximum error that will be corrected at the end of a move. Larger errors will cause an error message and no corrections will be applied. Set to 0 if no encoder or if there is an encoder but no correction is desired for that actuator. If MOFF=1 then this test is compared to position error rounded to the nearest full step. If MINCORRx > MAXCORRx then no correction is applied and no warning is given for errors > MAXCORRx.
The error in question is measured by the auxiliary encoder at the end of the move.
See also NCORR, ENCTIME and ENCRESx and MINCORRx.
Computed Constants
There are a number of constants computed by COMPVAR.
XQ #COMPVAR
should be run
whenever you change any user-set constant. It also runs automatically
whenever the Galil is powered up. Read the code for the #COMPVAR
program (including comments) for more information.
Parameters
Parameters have an effect similar to constants, but they are
implemented as commands built into the Galil rather than as
variables. To make your changes permanent (restored at power up or by
resetting with RS
), save parameters to flash memory
using BN
. Note: BN
also saves the state of
the digital outputs; this can be very handy, but be sure the outputs
are in the desired state before saving.
- MT 2, 2, 2, 2, 2, 2
- Motor type. See the Galil manual for more information. Warning: changing this changes both the polarity of the step pulse (which is how I determined the value to use) and also the direction of motion of the motor. Please don't change this setting unless you are willing to also reverse the motor direction (by swapping the A/A-bar or the B/B-bar wires).
- CN -1, -1, -1
- Configures the polarity of the limit switches. See the Galil manual for more information.
- MO
- Makes sure all motors are off when the Galil first wakes up.
Status Word
The status word is part of the information returned by the
STATUS command. The status word always reports
current conditions of the controller; unlike some hardware
controllers, the bits are not sticky.
With one exception (see below), good status after a move is simply
the stop code (details below). Reasonable stop codes are 1 and 4. 1
is expected after a successful XQ motion command (such as XQ#MOVE,
XQ#MOVEREL or XQ#HOME) that includes the axis in question. 4 is
expected after a successful XQ motion command that does not
include the axis in question (because all other axes are told to
stop), or after such a command fails with an error message.
Exception: if MOFF=0 (meaning leave motors on after a move), then
it is OK for the motors to be on (bit 14 set). However, as of this
writing, MOFF=1 for all mirror controllers at APO.
The status word consists of two parts:
The lower 8 bits (1-8) are a numeric stop code from the Galil SC
command:
Stop Code
(bits 1-8) | Meaning |
Hex | Dec | |
0 | 0 | Running in independent mode |
1 | 1 | Stopped at commanded position in independent mode. This is the expected stop code after a successful XQ#MOVE, XQ#MOVEREL or XQ#HOME involving this axis. See also code 4. |
2 | 2 | Stopping or stopped by forward software limit or switch |
3 | 3 | Stopping or stopped by reverse software limit or switch |
4 | 4 | Stopping or stopped by stop command (ST). This is the expected stop code after XQ#MOVE, XQ#MOVEREL or XQ#HOME involving other axes, but omitting this axis. It is also normal after any XQ motion command fails. See also code 1. |
6 | 6 | Stopped by abort input (not used) |
7 | 7 | Stopped by abort command (AB) |
8 | 8 | Servo error too large (only relevant to servomotors, e.g. 3.5m M3 rotation) |
9 | 9 | Stopped after finding transition in home switch (FE). |
10 | 10 | Stopped after homing (HM) or finding index pulse (FI). Despite appearances, this is not a normal stop code after XQ#HOME. |
32 | 50 | Running in contour mode (not used) |
33 | 51 | Stopped at commanded position in contour mode (not used) |
63 | 99 | MC timeout (MC and TW); axis not in position soon enough after motion sequence ended (not used) |
64 | 100 | Running in vector sequence mode (not used) |
65 | 101 | Stopped at commanded position in vector sequence mode (not used) |
Bits 9-32 of the status word report conditions represented by
individual bits. Bits 9-16 are from the TS command, but some bits
have been flipped to make them easier to understand
Bit | Hex | Meaning |
9 | 100 | Encoder position latch armed (not used) |
10 | 200 | Home switch activated (ganged to reverse limit) |
11 | 400 | Reverse limit switch activated |
12 | 800 | Forward limit switch activated |
| |
13 | 1000 | (undefined) |
14 | 2000 | Motor on, i.e. amplifier enabled (should be 0 if MOFF=1
and axis is halted) |
15 | 4000 | Error limit exceeded (not used) |
16 | 8000 | Axis in motion |
| |
17 | 10000 | Not on full step error (motor
should be on a full step, but is not). |
18 | 20000 | Amplifier fault, e.g. short
circuit (note: all amplifiers may have this signal
ganged together). |
19 | 40000 | Amplifier fault (alternate
input) |
20 | 80000 | (unused) |
| |
21-32 | (unused) |
Note: as of version 1.9 bit 17 means "On Full Step Error" and is
always supposed to be off (though an on full step error is
typically not serious). Before that, bit 17 meant something a bit
different and was supposed to be on for most axes.
Details of the Interface
Command Input
Every command must be typed in upper case. Commands must be
terminated with <cr> or semicolon. The length of any one
command must not exceed 80 characters. (There is no limit on the
length of a line containing multiple commands separated by
semicolons).
All positions are in microsteps and all times are in seconds
(hence velocities are in microsteps/sec, etc.).
Replies
The Galil echoes commands, displaying <cr><lf> for
<cr>. Prompting is, unfortunately, a bit strange. In the
general case (any Galil command except program editing):
- After you enter a valid command terminated with <cr> or
semicolon the Galil responds with a colon (:), indicating that the
command was correctly parsed. The
command is then executed.
- If there is an error (the Galil cannot parse your input or an
invalid program step is encountered) the Galil will return a one
line error message beginning with "?" (for more information see
Error Messages below).
- Note that for the built-in commands
you get no indication that a command has finished executing. This
makes sense when you consider that the Galil can multitask and
that you can talk to it while it is executing a program.
Nonetheless, it present a serious challenge to the controlling
computer. To ameliorate this problem, programs (
XQ
#progname
) do include indication of completion,
as described next.
For programs (XQ #progname
), the following
convention is also used:
- All programs terminate their output with
"OK<cr><lf>". Any informative or error messages will
come before the OK.
- In the case of programs that run in the background, such as
XQ #MOVE, there will be an indication of the
length of time for the move (before the OK). In the case of
programs that run in the foreground, the OK indicates that the
command has completed.
- If a program encounters an error condition, it will print one
or more error messages beginning with "?", which is consistent
with normal Galil behavior. In addition, any motion will be halted
and if the motors are normally turned off after a move then they
will be turned off (but not necessarily on a full step).
In summary:
- For programs (
XQ #progname
) keep
reading replies until you see "OK".
- For built-in commands there is no simple rule, but you can
keep reading until you see a "?" (error message) or the expected
number of replies, or a ":" if no replies are expected.
Error Messages
Error messages all begin with a question mark. Most messages also
have the name of a subroutine in upper case immediately following the
question mark. The message then follows. Logical values are
represented as 1=true, 0=false. If the error message refers to one or
more axes, it will end with a string of 1s and 0s indicating which
axes are at fault. Axes are listed in order (A, B, C...) and a 1
indicates the axis is a problem, 0 indicates the axis is not a
problem.
Auxiliary Port Status
If constant DOAUX = 1, regular status updates are emitted from the auxiliary serial port just as fast as the Galil can output them. Each line of status has the following format (note: controllers may append data; see device-specific information for this information):
- The number of characters on the line, excluding the terminating <CR> (but including device-specific extra data, if any). ignore it. You should check line length and ignore lines that are too short (they should never be too long).
- The position of axes 1 through NAxes
- Number showing which axes are homed; a decimal representation of a binary value. Axis A is the low order bit, B is next, etc. Hence 19 = binary 10011 means axes A, B and E are homed. C and D are not homed, nor is F if it exists.
- A data type code: 0 for commanded position, 1 for current position
- A time code: seconds since startup. Significant systematic rate error is likely. This number is supplied because terminal servers tend to combine multiple lines of status into one packet, thus losing time information. Note: the time code was added in software version 1.7b5.
- Any device-specific data.
- A terminating <CR>
Notes:
- Commanded position is the position to which the Galil has asked the motor to go. When the actuators are moved to a new target position, the commanded position follows as quickly as it can within the velocity and acceleration limits.
- Current position is defined as follows:
- For stepper motors: the encoder position if there is one, else the commanded position
- For servo motors: the auxiliary encoder if there is one, else the motor encoder position
- For axes that have not been homed:
- Commanded position should be completely ignored.
- If the current position is based on an incremental encoder
then changes in current position may be trusted but the zero
point is unknown. If there is no encoder then the current
position should be completely ignored.
- Commanded position is only output when it changes. This gives the highest possible data
rate for measured position.
- All positions are in microsteps. These are the natural units
for commanded position and servo motor position (where
"microsteps" actually mean motor encoder ticks). But auxiliary
encoder ticks are scaled, which may lead to minor quantization
errors.
- Numeric values may have any of a leading space, leading + or
-, leading zeros and/or a decimal point. They will not, however,
have exponential notation.
- Values are separated by a comma and zero or more spaces.
Example with NAXES = 3:
070, 000000000.0, 000000000.0, 000000000.0, 00, 0, 0001465051.23
070, 000000000.0, 000000000.0, 000000000.0, 00, 1, 0001465051.83
070, 000000000.0, 000000000.0, 000000000.0, 00, 1, 0001465052.43
070, 000000000.0, 000000000.0, 000000000.0, 00, 1, 0001465053.03
070, 000000000.0, 000000000.0, 000000000.0, 00, 1, 0001465053.63
070, 000000000.0, 000000000.0, 000000000.0, 00, 1, 0001465054.23
Warnings:
- The auxiliary port process will halt (in mid-output) if an ST
or RS command is issued or the device is reset or power cycled. In
the case of ST the aux output will start up (from the beginning of
a new line) when the next XQ# command is issued. In the case of
power cycle/reset, startup happens when the Galil finished
resetting.
- Because of this, please sanity check the data carefully. Use
the "number of characters in a line" parameter! However, I don't
recommend reading the data as fixed-width input unless you really
think this adds safety, because the field widths may change.
Configuring the auxiliary port:
- You may choose any serial port speed you wish. The faster you
run, the better the time resolution of the encoder positions.
- The serial port be configured for no handshaking.
Otherwise the Galil main serial port/command interpreter will
freeze while waiting for somebody to read the auxiliary port,
which will completely mess up control of the mirror.
Wiring
The following inputs and outputs are used by the basic software
for stepper motors. Slightly different predefined inputs and outputs
are used for servo motors and the "on full step" inputs are ignored.
Additional inputs and outputs may be used for device-specific
modifications.
Predefined Outputs
- Step
- Direction
- Amplifier Enable
Notes:
- The Galil cannot be configured to switch forward and reverse
motion, so the motor/driver wiring must have the correct
polarity.
Predefined Inputs
- Forward Limit
- Reverse Limit
- Home: jumper to reverse limit switch
- Encoders (if they exist)
- Index Pulses (if they exist)
Notes:
- The home input must be jumpered to the reverse limit switch
for each axis.
- If possible, the reverse direction should make the actuator
shorter. However, it is more important that the reverse limit
switch be highly accurate, so if only one limit switch is
accurate, that must define the reverse direction.
- If possible, the encoders should have the same polarity as the
motors.
General-Purpose Digital Inputs
- The following apply to any Galil:
- 1-4: A-D on full step. Pull low when on full step. Ignored
for servo motors.
- 5: fault input. Typically the amplifier fault outputs are
wire-or'd to this inputs. But this assumes that the amplifier
fault outputs pull down; otherwise more sophisticated circuitry
is required. See also input 13.
- The following only exist on a 5-8 axis Galil:
- 9-12: E-H on full step (G-H are in case we ever make an
8-axis version)
- 13: a second fault input, like input 5. This input is
ignored if NAXES <= 4, even if the Galil supports more axes.
(This restriction could easily be lifted if the program could
determine how many axes the Galil supports). It can be handy to
have a second fault input if, for instance, some motors use a
different ground (as in the 3.5m tertiary) or if one is using a
pair of standard breakout boards, one per set of connectors on
the Galil (one board for axes 1-4, the other for axes
5-6).
Notes:
- The "on full step" inputs for unused axes or servo motor axes
may be used for device-specific purposes.
- The two fault inputs (5 and 13) must only be used for
fault detection.
- The "on full step" inputs happen to use the latch inputs, but
we are not using the latching capability.
Device-Specific Information
3.5m Secondary
Overview
The 3.5m secondary mirror controller includes three axial actuators (A, B and C) to tilt and piston the mirror and two transverse actuators (D and E). All actuators have an associated linear encoder that is slightly offset from the actuator.
There are no device-specific modifications or commands.
Mechanical Information
Axes A, B, C (axial actuators)
- The axial actuators use a stepper motor that drives a screw through a harmonic drive reducer. This achieves a very high resolution with great strength.
- Drive resolution is 32e6 microsteps/inch
- Encoder resolution is 10.16e6 ticks/inch = -3.1496 microsteps/tick
- Actuator details:
- Superior Electric Slo-Syn KML061F02E stepper motors
- 40 threads/inch
- 80:1 harmonic drive reducer
- 200 full steps/revolution
- 50 microsteps/full step
- Encoders details:
- Heidenhain MT2581 heads
- Heidenhain IBV660 interpolators
- 2 μm period (with 4 ticks/period)
- 50x interpolation
- 400 ticks/μm
Axes D, E (transverse actuators)
- The transverse acutators use a stepper "linear actuator": a motor with a hollow threaded shaft that drives a non-rotating screw in and out.
- Motor resolution is 0.8e6 microsteps/inch
- Encoder resolution is 0.5080e6 ticks/inch = 1.5748 microsteps/tick
- Actuator details:
- Motors are Eastern Air Devices LA23ECKW-M100-6 stepper linear actuators.
- The "W" is for "special thread" (80 tpi in our case).
- These have 4 leads
- Each phase is rated at an RMS of 5.6 VDC, 1.00 Amps, 5.6 Ohms, 25.6 mH
- Encoders are Heidenhain MT2581 heads with Heidenhain IBV660 interpolators
- 80 threads/inch
- 200 full steps/revolution
- 50 microsteps/full step
- Encoder details:
- Heidenhain MT2571 encoder (with built in interpolator)
- 2 μm period (with 4 ticks/period)
- 2.5x interpolation
- 20 ticks/μm
3.5m Tertiary
Overview
The 3.5m tertiary mirror controller includes three axial actuators (A, B and C) to tilt and piston the mirror. Each consists of a stepper motor driving a screw through a harmonic drive reducer. Three Heidenhain linear encoders are also used to provide position feedback. At one time this Galil also controlled tertiary rotation, but that was split out into the 3.5m Tertiary Rotator Galil. Note that the Galil software was not changed at this time, so this Galil may still claim to control tertiary rotation, but that is a lie. Eventually the software will be made generic.
Mechanical Information
Axes A, B, C (axial actuators)
- The axial actuators use a stepper motor that drives a screw through a harmonic drive reducer. This achieves a very high resolution with great strength.
- Drive resolution is 32e6 microsteps/inch
- Encoder resolution is 10.16e6 ticks/inch = -3.1496 microsteps/tick
- Actuator details:
- Superior Electric Slo-Syn KML060F05E stepper motors? (may be out of date)
- 40 threads/inch
- 80:1 harmonic drive reducer
- 200 full steps/revolution
- 50 microsteps/full step
- Encoders details:
- Heidenhain MT2581 heads? (may be out of date)
- Heidenhain IBV660B interpolators? (may be out of date)
- 2 μm period (with 4 ticks/period)
- 50x interpolation
- 400 ticks/μm
3.5m Tertiary Rotator
Overview
The 3.5m tertiary rotator controller rotates the tertiary mirror to point to various instrument ports. It also controls mirror the primary covers and eyelids. For historical reasons this Galil also pretends to control actuators A-C (at one time this Galil also controlled the tertiary axial actuators), but now axes A-C do nothing.
The tertiary mirror mount is rotated by DC servo motor and drive reduction gearbox driving a ring gear. The motor rotates the mirror to the approximate desired position, then the ring gear is clamped by a precision clamping mechanism (precision jaws engaging one of a set of precision slots) to accurately set the final mirror rotation angle. An electric clutch between the reduction gearbox and the drive gear is automatically released as the mirror is clamped to avoid back-driving the drive reduction gearbox.
The tertiary rotation motor has a rotary shaft encoder to close the servo feedback loop and provide initial position information. But the position information is inaccurate because of slop in the gearbox and because the motor shaft encoder is decoupled from the ring gear when the clutch is released. Hence an additional encoder driven by the ring gear provides final position information. This is used to correct the rotation angle before closing the clamp. In Galil parlance the motor shaft encoder is the main encoder and the position encoder is the auxiliary encoder.
The rotator motor is axis E and there is no axis D. This is for historical reasons. At one time axes A-C were the tertiary axial actuators, and the it was easier to write the motor to a different bank of opto-isolated inputs.
Warning: the tertiary rotation home position is not at a slot. So after you home you will get an error reporting that the clamp failed to close. That is normal. We tried adjusting MARGE so that home was at the first slot, but this made motion to that slot unreliable.
Finally, the tertiary Galil can control the primary mirror covers and eyelids.
Device-Specific Software
The 3.5m Tertiary Rotator is controlled by device-specific software version 1.4, May 8, 2001.
Constants
- LCLTIME
- Time to close the clamp (sec)
- LOPTIME
- Time to open the clamp (sec)
- LSLTIME
- Time for the at slot sensor to settle (sec)
- LEYETIME
- Time to open or close an eyelid (sec)
- LCVADDT
- Additional time to run the primary mirror covers after the switches have fired (sec)
- LCVPOLLT
- Polling interval for checking the mirror cover switches during mirror cover motion (sec)
- LCVMAXT
- Maximum time to move a group of primary mirror covers, before the switches fire (sec). The maximum time the mirror cover motors can run is LCVMAXT + LCVADDT + LCVPOLLT.
XQ #LCLCOV
Close all mirror covers. This command will work unless any of the following is true, in which case it will complain and give up:
- Mirror cover group 1 is in an indeterminate state (neither fully open nor fully closed)
- Any eyelids are open
See also #LOPCOV.
XQ #LCLEYE
Close eyelid A, where A is in the range [1, 7]. Closes all eyelids if A is out of range or has not been set. See also #LOPEYE.
XQ #LOPCOV
Open all mirror covers. This command will work unless any of the following is true, in which case it will complain and give up:
- Mirror cover group 2 is in an indeterminate state (neither fully open nor fully closed)
- Any eyelids are open
See also #LCLCOV.
XQ #LOPEYE
Open eyelid A, where A is in range [1, 7]. Unlike #LCLEYE, returns an error if A is out of range or has not been set. You may have more than one eyelid open at one time, but you must call this command once for each eyelid.
XQ #STATUS
Displays two extra lines showing the state of various sensors via #LSTATUS. Example:
1 1 1 1 at slot, left, right jaw open, clutch engaged
1 1 0 0 0 cover groups 1 open, 2 open, 1 closed, 2 closed; eyelids closed
(note: only the first line is present in the release version 1.2)
Motion
For any move involving tertiary rotation (axis E), the following occurs:
Before the move, and only if the clamp is presently not fully unclamped:
- Turn axis E on.
- Open the clamp.
- Wait a fixed interval (see the code) for unclamping to finish.
- Verify that clamp is fully open: both "jaw open" signals on and the "clutch disengaged" signal off.
- On failure, leave the servo motor on, the clamp opening and return an error message.
After the move, and only if the clamp is not already fully clamped:
- If using the at-slot sensor: verify that the clamp is at a slot (turn on the at slot LED, wait for it to stabilize, read it, turn off the LED).
- Close the clamp.
- Wait a fixed interval (see the code) for clamping to finish.
- Verify that the clamp is fully closed: "clutch disenaged" signal on and both "jaw open" signals off.
- On failure, leave the servo motor on, start opening the clamp and return an error message.
Auxiliary Status
The auxiliary status includes one extra item of data: the axis E servo error (in microsteps = motor encoder ticks). This value is useful to determine a good value for parameter ERE, the maximum allowed servo error.
Additional Wiring
Predefined Inputs
- Axes A-C control the tip and tilt of the tertiary mirror. The actuators get longer, pushing the mirror towards the secondary and instrument port, for positive moves. With the telescope at zenith, the actuators are as follows if facing the mirror (i.e. looking into the appropriate instrument port):
- A is the upper actuator
- B is the lower left actuator
- C is the lower right actuator
- There is no axis D.
- Axis E is the tertiary rotation servo motor. The motor shaft encoder is connected to the regular encoder input. The gear pickoff position encoder is connected to the auxiliary encoder input. The servo loop uses the motor shaft encoder. After a move we verify position using the gear pickoff position encoder.
General-Purpose Digital Inputs
All digital inputs read 0 for true/sensed.
Bit | Description | Value |
4 | at "slot" sensor | 0 = at slot (not used; see note) |
6 | left jaw fully out | 0 = out |
7 | right jaw fully out | 0 = out |
8 | clutch disengaged | 0 = disengaged (see note) |
9 | mirror covers group 1 open | 0 = open |
10 | mirror covers group 2 open | 0 = open |
11 | mirror covers group 2 closed | 0 = closed |
12 | mirror covers group 1 closed | 0 = closed |
13 | (amplifier fault; a standard input) | |
14 | eyelids all closed | 0 = closed |
Notes:
- At Slot Sensor: You must apply power to the at slot LED and sensor before reading the at slot sensor. To save power and reduce stray light, turn off the power when you are done reading the sensor. We do not actually use this sensor because it turned out not to be useful.
- Clutch Disengaged Sensor: the clutch is directly controlled by the "clutch disengaged" sensor, which fires whenever the jaws are at least partially closed. This avoids back-driving the drive reduction gearbox.
General-Purpose Digital Outputs
Bit | Description | Value |
1 | power to "at slot" LED and sensor | 0 = power on (not used; see note) |
2 | air to clamp | 0 = open, 1 = close |
3 | (unused) | |
4 | mirror cover drive enable | 1 = enable |
5 | mirror cover group 1 open | 1 = open |
6 | mirror cover group 2 open | 1 = open |
7 | mirror cover group 2 close | 1 = close |
8 | mirror cover group 1 close | 1 = close |
9 | eyelid #1 (top center) open | 1 = open |
10 | eyelid #2 (top left) open | 1 = open |
11 | eyelid #3 (NA2) open | 1 = open |
12 | eyelid #4 (bottom left) open | 1 = open |
13 | eyelid #5 (bottom right) open | 1 = open |
14 | eyelid #6 (NA1) open | 1 = open |
15 | eyelid #7 (S-H) open | 1 = open |
16 | (unused) | |
Mechanical Information
Axis E (rotation)
- A microstep is one count of the motor shaft encoder (as is true for any servomotor).
- Motor resolution is 14487.704 microsteps/deg of tertiary rotation.
- Auxiliary encoder resolution is 151.58730 aux encoder counts/deg of tertiary rotation = 95.573333 microsteps/aux encoder count.
- Details:
- 8192 counts/rev on the motor shaft encoder (2048 lines/rev)
- 50:1 gear box reduction ratio
- 45 teeth on the drive gear
- 573 teeth on the big gear
- 4000 counts/rev for the gear encoder (1000 lines/rev)
- 42 teeth on the encoder gear
SDSS Primary
Overview
The SDSS primary mirror has six actuators: three axial (A, B, C = Axial A, B, C), one transverse perpendicular to the altitude axis (D = Transverse Vertical) and two parallel to the altitude axis (E, F = Lateral 1, 2). The lateral links are attached to the mirror via arms that contain air-driven force fuses. All other actuators control hard points which are used by the Yorke Brown air support servos.
The lateral link motors are weak and the axial air support pistons are high friction, so the lateral link force fuses must be disabled (air released) while moving the lateral links. To accomplish this, one of the Galil outputs drives an air valve. Note that turning on the air again will not position the mirror correctly; one must relax the system by driving it up and down axially 5-10 times, preferably while at the zenith.
In addition, there are also two proximity sensors on the lateral links; at present these are not in use, but they can be connected to analog inputs on the Galil. They are intended to help set the mirror rotation (by mechanically adjusting the relative lengths of the lateral links).
Device-Specific Software
SDSS primary software v1.6, March 7, 2001.
Constants
- LLATTIME
- Time required to fully engage or disengage the lateral link air force fuse (sec)
XQ #SHOWPAR
Displays an extra line showing the version of the device-specific software.
XQ #STATUS
Displays an extra line showing the state of the lateral link air force fuse.
Motion
For any move involving the lateral links (axes E or F), the following occurs:
Before the move begins, via #LMINIT:
- Turn off the lateral link air
- Wait a fixed interval (see the code) for the air to bleed
After the move is finished, via #LMSTOP:
- Turn on the lateral link air
Additional Wiring
General-Purpose Digital Outputs
- 9: lateral link air valve, 1 = air off, fuse disabled
Notes:
- The one air valve drives both lateral link air fuses
- The air fuses take less than a second to fully engage or fully disengage
Mechanical Information
Axes A, B, C (axial actuators) and D (transverse vertical)
- Resolution is 400,000 microsteps/inch
- 40 threads/inch
- 200 full steps/revolution
- 50 microsteps/full step
Axis E, F (transverse lateral links)
- Resolution is 8e5 microsteps/inch
- 80 threads/inch
- 200 full steps/revolution
- 50 microsteps/full step
SDSS Secondary
Overview
The SDSS secondary mirror has five actuators: three axial (A, B, C = Axial A, B, C) and two transverse (D, E). The axial actuators are stepper motors; each driving a screw through a harmonic drive reducer. They have separate Heidenhain incremental linear encoders that are a few inches from the actuators, and so have systematic error when the mirror is tilted. The transverse actuators are linear actuators (the motor turns a nut that drives a threaded shaft) that tilt the central linear bearing; they are oriented at 45 degrees from vertical and are in tension (when both contract the mirror is raised).
The axial actuators also contain piezoelectric actuators in series, for fine adjustment. Mirror-specific Galil code computes position error and tries to correct it via the piezos. The piezos are centered while the axial actuators is being moved so that the main actuators can get as close as possible to the correct position. It is possible to disable piezo corrections (see LCSTOP and XQ #LPAUSE below) or set the piezo positions manually (see XQ #LMOVE below).
The total time for one piezo correction is roughly LWTTIME = LCORTIME + (8 * LSETMS / 1000) (in seconds). The Galil has to wait for 8 bit flips, two to set the position for each axis plus one to command the piezos to move.
Device-Specific Software
SDSS secondary software v1.3, 2004-04-01.
Constants
- LCORFRAC
- Fraction of error to attempt to correct. Should be in the range (0.0, 1.0]. If the piezos are driven into oscillation then reducing this may help.
- LCORTIME
- Maximum time the piezos take to move (sec). This excludes the time required to send a command to the piezo controller (that is computed from LSETMS). Setting LCORTIME too small will cause position errors to be measured before the piezos have stopped moving. That is probably not very serious. Setting LCORTIME too large needlessly slows down each piezo move and each axial actuator move.
- LCSTOP
- Set to 0 to enable or 1 to disable background corrections. Note that the background process requires up to LWTTIME seconds to halt after being disabled.
- LSETMS
- Maximum time the Galil takes to set a piezo control bit and the piezo controller takes to recognize that it has been set (ms). Be careful not to set LSETMS too small, because this introduces errors into the communications between the Galil and the piezo controller. Such errors are nearly impossible to detect except by watching the resulting length of the axial actuator. Setting LSETMS too large needlessly slows down each piezo move and each axial actuator move.
- LMAXBIN = A90 hex
- Maximum position output (binary). The DAQ has 12 bits (4096) and outputs approx. 0-2.7 volts however, the output amplifier saturates at approximately 2V giving a maximum binary output of approximately A90 hex.
- LRES = 1.24 microsteps/piezo increment
- Resolution of piezos in microsteps/piezo increment; computed as follows:
1 microstep/8 nm resolution of the axial actuator
2.7V/4096 bits resolution of DAQ
3 nm/200e-6V resolution of the piezo actuator
XQ #LMOVE
Move the piezo actuators to the position specified by LDESPOSx, where x = A, B or C (in microsteps) and print status. Pauses automatic piezo corrections (otherwise the piezos would almost immediately move again). Notes:
- If piezo corrections are running, they are paused and the piezos are set to zero before being set to the final specified position (if any).
- Omitted positions are left alone (unless piezo corrections were running, in which case they are zeroed, as per the previous line).
- Position is automatically truncated to be within bounds.
- Automatic piezo corrections will resume (if LCSTOP=0) after any XQ #... command except the two obvious choices: XQ #LMOVE or XQ #LPAUSE. If you want to set LCSTOP=1 to prevent restarting automatic piezo corrections, please first determine the current value of LCSTOP via MG LCSTOP, then restore it when you are done with your testing.
Example (omitting colons):
LDESPOSA = 100
LDESPOSB = 4000 Out of range, so it will be adjusted
LDESPOSC = -1000
XQ#LMOVE
1, 1, 1, 1, 1 axis homed
000000000, 000000000, 000000000, 000000000, 000000000 commanded position
000000000, 000000000, 000000000, 000000000, 000000000 actual position
00331268, 00331268, 00331268, 00331268, 00273921 status word
3 piezo status word
000000100, 000001676, -000001000 piezo corrections (microsteps)
OK
XQ #LPAUSE
Zero the piezo actuators and pause automatic piezo corrections. Automatic piezo corrections will resume (if LCSTOP=0) after any XQ #... command except XQ #LMOVE or XQ #LPAUSE.
XQ#SHOWPAR
Displays four extra lines of data, as per this example:
01.00 version of M2-specific additions
-00001676.4874, 00001676.4874 min, max piezo position (microsteps)
00002705 number of steps of piezo position
00000001.2400 resolution (microsteps/piezo ctrl bit)
XQ #STATUS
Displays two extra lines showing the piezo status word and and the amount of the most recently applied correction as per this example:
0 piezo status word
000000100, 000001676, -000001000 piezo corrections (microsteps)
Auxiliary Port Output
The auxiliary port output includes some extra data about the piezo actuators. The following items are appended to the normal output:
Example:
126, 000000000.0, 000000000.0, 000000000.0, -000003400.0, 000000000.0, 00, 1, 0001230775.78, -02539, -02539, -02539, 0
126, 000000000.0, 000000000.0, 000000000.0, -000003400.0, 000000000.0, 00, 1, 0001230776.12, -02539, -02539, -02539, 0
126, 000841850.0, 000803250.0, 000873850.0, -000003400.0, 000000000.0, 00, 0, 0001230776.45, -02539, -02539, -02539, 0
Piezo Status Word
The piezo status word shows the status of various flags related to piezo correction. The word is displayed as decimal, even though hex is more traditional. Internally, each flag is 0 for cleared and nonzero (usually 1) for set.
- 1: piezo correction task halted. The task is automatically halted during any move of the axial actuators and restarted (if LCSTOP not set) after any command except XQ #LMOVE or XQ #LPAUSE.
- 2: piezo correction pause requested (the LCPAUSE flag is set). This flag is automatically set during any move of the axial actuators and cleared at the end of any command except XQ #LPAUSE or XQ #LMOVE.
- 3: piezo corrections disabled (the LCSTOP flag is set). The user is responsible for setting or clearing LCSTOP.
Typically at the beginning of a move you will see bit 2 set (pause requested) followed shortly by bit 1 (pause occurred). At the end of the move you will see both bits cleared.
Automatic Motion
For any move involving the axial actuators (axes A, B or C), the following occurs:
- Before the move begins, #LGO calls #LPAUSE to zero the piezos and disable piezo corrections. This is done so that the motor-driven actuators can do their best to correct all error themselves.
- After the move is finished, #LMSTOP re-enables piezo corrections by setting LCPAUSE to 0. Piezo automatic correction then resumes if LCSTOP=0.
Additional Wiring
General-Purpose Digital Outputs
- 16: Clear: 0/1 to enable/clear zero the voltage to all piezos
(clear all D/A converters).
- 15: Latch position data. Normally 1; 1->0->1 to latch.
- Data is read into latch on 1->0, output on 0->1
transition.
- 14-13: address bits: A = 10, B = 01, C = 00, use new data = 11
- For A-C a latch transition causes data to be loaded into a
buffer but the output of the piezo driver remains
unchanged.
- For "new data" a latch transition causes the buffered data
to be output.
- 12-1: position data (linear)
- 1111 1111 1111 = axial actuators are shortest, piezos are
longest
- 1111 1111 1110
- ...
- 0000 0000 0001
- 0000 0000 0000 = axial actuators are longest, piezos are
shortest
Notes:
- In the above, 1 means a high output (e.g. via SBx)
- The piezo driver has opto-isolated inputs which are driven low
for "on". Hence a 1 (high output from the Galil) corresponds to a
low state internal to the piezo controller.
Mechanical Information
Axes A, B, C (axial actuators)
- Motor resolution is 32e6 microsteps/inch
- Encoder resolution is -6.2992... microsteps/tick
- 40 threads/inch
- 80:1 reduction
- 200 full steps/rev
- 50 microsteps/full step
- Encoders are Heidenhain MT 2501 with 2 μm period, 4
ticks/period and a separate 100x interpolator
- Piezo resolution is roughly 1.24 microsteps/binary bit
- 1 ustep/8 nm resolution of the axial actuator
- 2.7V/4096 bits resolution of DAQ
- 3 nm/200e-6V resolution of the piezo actuator
Axes D, E (transverse actuators)
- Resolution is 8e5 microsteps/inch
- 80 threads/inch
- 200 full steps/revolution
- 50 microsteps/full step
Installing A Galil
The Galils must have code loaded into them before they can
function as described in this manual. (Without such code, only the
low-level commands described in the factory manual will work.)
Warning: a Galil that has not been programmed or has been
incorrectly configured may cause motors to run away when it is first
powered up. Never allow the Galil to control a motor until it
has been properly programmed and that programming has been saved to
flash memory and tested.
There are two configuration errors that can cause problems:
- A bad motor type (MT command) can cause the motors to run away
or move in the wrong direction. If they move in the wrong
direction, the limit switches become useless because they stop the
wrong direction of motion.
- A bad switch configuration (CN command) can cause the switches
to have their logic inverted (an unpressed switch is read as a
pressed switch and visa versa). This is dangerous if the system is
powered up while a limit switch is engaged (since it will then
seem to be disengaged).
Upload Code
You will need the following to upload Galil code:
- A subversion client, to obtain the code.
- Python (version 2.2.1 or later), to combine various files into the upload for one Galil. Note that python is standard with most non-Windows operating systems and is easily installed on Windows.
- A good connection to the Galil.
The procedure is as follows:
- Export the code from subversion repository
svn://svn.apo.nmsu.edu/galil/tags/
. The following commands list the available release versions and export a particular version:
svn ls svn://svn.apo.nmsu.edu/galil/tags/
svn export svn://svn.apo.nmsu.edu/galil/tags/v2.01 galil_v2.01
- Use python to combine the code files into one file for each desired mirror controller, as follows:
cd <directory of Galil code>
python combineGalilCode.py "<mirror name>"
where <mirror name> is one of 35m M2
, SDSS M1
, etc. For the full list, look for files named "Constants <mirror name>.gal"
.
The combined code is written to file: "Combined <mirror name> <date>.gal"
. For example, the command: 'python combineGalilCode.py "SDSS M2"'
might create file: "Combined SDSS M2 2005-01-31.gal"
.
- If the Galil does not presently contain mirror controller code for this mirror then make sure the Galil is not connected to the mirror actuators. If you can't do that, then you must disable the motors. Otherwise they may run away while you load the code. Any one of the following will work:
- If you have a force limit switch (as on the SDSS) then it is sufficient to disconnect the cable to that switch (thereby activing the force limit disable).
- You may disconnect the motors, but be sure to power down the system first to avoid damaging the drive amplifiers.
- Open the box containing the Galil and disconnected the header connectors from the Galil (but be sure you understand how to reconnect them!), leaving only the power and serial port connected to the Galil.
- Connect to the Galil's serial port. Do not use HOST from the TCC, because HOST does not lock out other users, which could corrupt the upload. If the Galil is attached to a terminal server, telnet to that. If the port is busy (e.g. if the tcc is hogging it), you can free it up by one of:
- Log out the port. You will need the terminal server's privileged password for this. Connect to the terminal server's console port and issue these commands:
set priv
logout port n
- Stop the TCC from talking to the controller by doing a telstop or disabling the collimation process (TCC command PROC DISABLE COLL) and waiting for the connection to time out.
- Send the appropriate file to the Galil, e.g. open the combined code file in any text editor and copy and paste the data to your connection. You will observe many lines go by normally, then many lines that may or may not overwrite each other (this seems to depend on the setup of the terminal server and/or your terminal emulator), then a few normal lines again. However, if you see one or more "?" or error messages, this indicates a failed upload.
- Issue the following commands. If any fail, the code cannot be used:
- XQ#COMPVAR (this should happen automatically at the end of the upload)
- XQ#SHOWPAR
- XQ#STATUS
- When you are satisfied with this upload, save the code ("burn it") using the following commands (which save the configuration, the variables and the program, respectively):
- Issue a RS (reset) command to simulate a power cycle.
- Execute XQ#STATUS again. This makes sure the code was properly
saved to flash memory.
- Test the system.
Test The System
- Make sure you understand and respect the limitations of the hardware for the mirror in question. For instance some mirrors don't like large tilts, others don't move well in certain directions at certain altitudes.
- Make sure the actuators are near their center of travel. For SDSS M2 axial and 3.5m M2 and M3 axial (A,B,C) actuators simply having them at least 1/16" away from the limit switch is adequate, as these actuators move very slowly.
- Power up the system in such a way that you can remove power if the motors run away. If the motors run away, turn off power and configure the Galil before proceeding.
- Check the limit switches. This is by far the most common source of problems after any engineering activity has occurred around the mirrors.
- Issue the "TS" command. This returns a number representing the state of the switches for each axis. Only the numbers for the axes we control matter: 1-6 for M1, 1-5 for M2.
- For each axis, convert the number from decimal to binary.
- Make sure bits 1-3 are all high (where bit 0 is the first bit). The bits are: home switch, reverse limit switch and forward limit switch.
- Fix any limit switch problems before proceeding. Common failures are:
- If bit 3 is high and 1 and 2 are low: the forward limit switch is pressed, a connector is off or a wire or switch is broken.
- If bits 1 and 2 are high and 3 is low: the reverse limit switch is pressed, a connector is off or a wire or switch is broken.
- If only bit 1 or 2 is high and all other bits are low: check the wiring of the reverse limit switch at the connector on the Galil (see the Galil manual for connector pinouts). The reverse limit switch is connected to both the reverse limit input and the home input, and the break must be after the wiring separates. Typically you'll find a pair of resistors at the connector; look there first.
- If bits 1, 2 and 3 are all high: both limit switches may be disconnected or the limit switch logic may be inverted (suggesting the Galil has not yet been configured).
- Check that the motors turn in the correct direction.
- Have somebody watch the actuator or a dial indicator.
- Start the motors moving slowly towards the home switch (which on the APO mirrors is also the reverse limit switch):
A=0
XQ#GOEDGE
When you are satisfied that motion is in the correct direction, halt it using:
ST
XQ#DONE
(Note: XQ#DONE is important, as it clears the A,B,C...variables). Then try the next axis.
- Home the axes. For this level of testing, it is not necessary to have the telescope at the standard altitude. On the other hand, that may save another homing later!
- Home them again (at the same altitude). If the errors seem large, something may be wrong.
- When you are finished testing, move the actuators well away from their reverse limits. Never leave them near a limit.
Troubleshooting
On Full Step Error
If a move should end on a full step and does not, the Galil will
complain. (Almost all APO mirror actuators are expected to end on a
full step; the except is 3.5m tertiary rotation, which is a servo
motor).
This error may be relatively benign, but should be investigated to
be sure. To investigate:
- Home the axis causing the problem. Be sure to follow the usual
rules
for homing, which means you'll probably have to move the
telescope to a particular altitude and home more than just the one
axis.
- Examine the position error reported by the homing
process.
- The "on full step" error is probably benign if the reported
position error is acceptably small (the definition of acceptable
depending on the actuator's resolution) and only a count or two
off from a multiple of 50. If either of these conditions is not
met, you may have a serious problem.
- If you are still not sure, move the mirror around and home
again. If you see a large error then you are definitely in
trouble.
If the error is benign, I suggest you continue to run, ignoring
the error messages, until the problem can be fixed.
This problem is fundamentally a counting error between the Galil
and the stepper motor driver amplifier. Either the Galil is emitting
the wrong number of pulses or the stepper motor driver amplifier is
mis-counting the pulses, or there is noise in the wires between them.
This is an error in the requested position and has nothing to do with
the actual motion of the motor; it cannot be caused by the
motor itself getting jammed. Things to check:
- If the axis never worked, or something was recently changed,
then verify the configuration:
- The stepper motor driver must be configured for the desired
number of microsteps per full step.
- The Galil must be configured for the desired number of
microsteps per full step -- the ST_FSx parameter.
- Noise is getting into the step or direction or enable lines
between the Galil and the stepper motor driver. Check the
wiring.
- The Galil sends out the correct number of counts. To test
this:
- Put the Galil on a work bench
- Connect the "step" output from the Galil to a pulse counter
and configure the pulse counter to count steps correctly. This
can be a surprising hassle for the HP models; turning on the
noise filter may help.
- Configure that Galil to have very large limits and high
speed and acceleration. (A Galil fresh from the factory does
not require this step, as it is already configured for fast
moves over the full range.)
- Perform moves of various sizes. Move the same amount
forwards and back and see if the Galil emits the correct number
of pulses. If even very large moves (several million steps)
occur without problems then the Galil is working
correctly.
- The stepper motor driver is working correctly. Try swapping out the driver. Make sure the new driver is configured correctly for 50 microsteps per full step.
Amplifier Fault
One or more motor driver amplifiers is reporting a fault. This is a serious problem. You will not be able to move any actuator for this mirror until you correct it.
An amplifier can report a fault for many reasons, including:
- A short circuit on the amplifier output.
- Amplifier logic power problem. Most of the stepper motor drivers have an external logic supply, to reduce heat dissipation (the external supply replaces an inefficient linear regulator in the stepper motor driver). This logic supply must be on for the drivers to be happy. It must also not come on any earlier than the main drive power. This leads us to the next item...
- Power on sequencing problem. Very rarely, we have seen an amplifier come up in a faulted state. Power cycling the amplifier or the mirror controller box should fix the problem (be sure to leave the power off for 10 seconds or so before turning it back on).
One difficulty with tracking down amplifier faults is that the Galil only has one or two fault inputs (one for 1-4 axis units; two for units with more axes), to conserve inputs. Typically the "fault" signal from several motor amplifiers are "wire-or"ed to a single fault input. Hence it may be difficult to tell which amplifier is causing the fault. In the long run, we ought to have an LED on each fault line or at least a resistor or diode, so one can figure out which line is faulting without taking fancy steps.
Galil Error Light
The error light on the Galil can indicate several different problems. Note that there is an error output bit that tracks the error light (though we don't monitor it as of 2007-07-23).
- If driving a servo motor and an error limit is set (using the ER command), the light will be on whenever an axis has exceeded its error limit. The Galil will continue to function normally, but this still probably indicates a very serious problem with your actuator. Note that the state of the light is independent of whether OE (off on error) is set for that axis or whether there is a #POSERR subroutine.
- A power supply glitch or internal fault will turn on the error light and send the Galil into a catatonic state. The only reliable way to recover from that is press the reset button (below the error light) or power cycle the Galil. This should never happen in normal operations, so please check the power supply and the Galil very carefully; one of them may need servicing.