}

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. EncoderAux. Encoder
Stepper Motorcommanded positionaux. encoder position
Servo Motormotor 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
HexDec
00Running in independent mode
11Stopped 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.
22Stopping or stopped by forward software limit or switch
33Stopping or stopped by reverse software limit or switch
44Stopping 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.
66Stopped by abort input (not used)
77Stopped by abort command (AB)
88Servo error too large (only relevant to servomotors, e.g. 3.5m M3 rotation)
99Stopped after finding transition in home switch (FE).
1010Stopped after homing (HM) or finding index pulse (FI). Despite appearances, this is not a normal stop code after XQ#HOME.
3250Running in contour mode (not used)
3351Stopped at commanded position in contour mode (not used)
6399MC timeout (MC and TW); axis not in position soon enough after motion sequence ended (not used)
64100Running in vector sequence mode (not used)
65101Stopped 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

BitHexMeaning
9100Encoder position latch armed (not used)
10200Home switch activated (ganged to reverse limit)
11400Reverse limit switch activated
12800Forward limit switch activated
131000(undefined)
142000Motor on, i.e. amplifier enabled (should be 0 if MOFF=1 and axis is halted)
154000Error limit exceeded (not used)
168000Axis in motion
1710000Not on full step error (motor should be on a full step, but is not).
1820000Amplifier fault, e.g. short circuit (note: all amplifiers may have this signal ganged together).
1940000Amplifier fault (alternate input)
2080000(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.

BitDescriptionValue
4at "slot" sensor0 = at slot (not used; see note)
6left jaw fully out0 = out
7right jaw fully out0 = out
8clutch disengaged0 = disengaged (see note)
9mirror covers group 1 open0 = open
10mirror covers group 2 open0 = open
11mirror covers group 2 closed0 = closed
12mirror covers group 1 closed0 = closed
13(amplifier fault; a standard input)
14eyelids all closed0 = 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

BitDescriptionValue
1power to "at slot" LED and sensor0 = power on (not used; see note)
2air to clamp0 = open, 1 = close
3(unused)
4mirror cover drive enable1 = enable
5mirror cover group 1 open1 = open
6mirror cover group 2 open1 = open
7mirror cover group 2 close1 = close
8mirror cover group 1 close1 = close
9eyelid #1 (top center, BC1) open1 = open
10eyelid #2 (top left, TR2: Agile) open1 = open
11eyelid #3 (NA2) open1 = open
12eyelid #4 (bottom left, TR3) open1 = open
13eyelid #5 (bottom right, TR4: S-H) open1 = open
14eyelid #6 (NA1: Echelle) open1 = open
15eyelid #7 (top right, TR1) open1 = 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:

  1. 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
          
  2. 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".
  3. 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.
  4. 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.
  5. 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.
  6. 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
  7. 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):
    • BN
    • BV
    • BP
  8. Issue a RS (reset) command to simulate a power cycle.
  9. Execute XQ#STATUS again. This makes sure the code was properly saved to flash memory.
  10. Test the system.

Test The System

  1. 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.
  2. 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.
  3. 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.
  4. Check the limit switches. This is by far the most common source of problems after any engineering activity has occurred around the mirrors.
    1. 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.
    2. For each axis, convert the number from decimal to binary.
    3. 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.
    4. Fix any limit switch problems before proceeding. Common failures are:
      1. 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.
      2. 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.
      3. 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.
      4. 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).
  5. Check that the motors turn in the correct direction.
    1. Have somebody watch the actuator or a dial indicator.
    2. 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.
                  
  6. 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!
  7. Home them again (at the same altitude). If the errors seem large, something may be wrong.
  8. 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.