spec

Software for Diffraction

motors

commands and functions for controlling motors

DESCRIPTION

Motor positions are stored in memory, in the settings file and (if the hardware allows) in motor-controller registers. The user has access to the motor positions through the built-in array A[]. The number of steps per degree (or millimeter, inch, etc.), direction of motion, rate of rotation, direction of backlash, etc., are defined in a configuration file. Each motor has an associated name and mnemonic, also assigned in the configuration file.

spec employs two methods for specifying motor position, dial units and user units. Dial units should be set to correspond to the physical dial settings of the spectrometer. Doing so makes it easier to recover motor positions in the event controller and software positions are simultaneously lost. User units are related to dial units by a simple linear relation. User angles are set to nominal values during the lineup procedure.

The settings file contains a copy of the most recent value written to the motor controller register, the user-units offset and the software limits for each motor. The settings file is read at program start up and on the reconfig command. The settings file is written each time a motor is moved or when the offset or limits are changed.

Dial and user units are related by the following expressions.

user = sign * dial + offset
dial = controller_register / steps_per_unit

sign and steps_per_unit are set in the configuration file.

For example, if sign = 1 and steps_per_unit = 200, the current position would be

user = controller_register / 200 + offset

Motor positions displayed by spec are generally rounded to the precision allowed by the steps-per-unit parameter. With spec release 5.10.01-1, it is now possible to retrieve the "commanded" motor position, which is the position requested with a move command. The commanded position can be retrieved using read_motors().

BUILT-IN COMMANDS, FUNCTIONS AND VARIABLES

A[]
An array used to transfer motor positions between the user and the program.
read_motors(mode [, which])

Reads the motors and places the motor positions in the A[] array with options set by mode, as follows:

Bit 0 (0x01)
If clear, user positions are put into A[]. If set, dial positions are put into A[].
Bit 1 (0x02)
If set, forces reading the hardware. For many motor controllers, spec doesn't necessarily read the hardware if the position hasn't been changed by spec since the controller was last read.
Bit 2 (0x04)
If set, position discrepancies between spec and the motor hardware will be silently resolved in favor of the hardware. Otherwise, spec will prompt the user as to whether the software or hardware positions should be considered correct.
Bit 3 (0x08)
If set, the hardware is read, but the contents of the A[] array are not modified.
Bit 4 (0x10)
If set, the "commanded" positions are placed in A[]. The hardware is not accessed. If the optional argument which is set to a particular motor number or mnemonic, A[] is not modified, and the return value will be the commanded position for the specified motor.

The optional argument which is currently only used for return of the commanded position.

The following macro definitions are included in the standard set:

def getangles 'read_motors(0)'
def getdials  'read_motors(1)'
def get_angles 'read_motors(0); user_getangles'

The get_angles definition includes a call to user-hook macro, user_getangles, that can be defined locally. It is recommended to use get_angles in local macros.

Note, prior to the introduction of read_motors() in spec release 4.03.07, getangles and getdials were built-in commands.

move_all

Move all motors to the user positions specified in A[].

The following macro definition is included in the standard macro set:

def move_em 'user_premove; move_all; user_postmove'

The move_em macro includes calls to user-hook macros that can be defined locally. It is recommended that local macros use move_em rather than move_all.

move_cnt
As move_all, but gates scalers open during move and does not perform backlash correction. This command is used by the "powder mode" macros. The parameters "powder_base", "powder_slew" and "powder_acceleration" are used for these moves.
motor_mne(i)
Returns the string mnemonic of motor i as given in the configuration file or a -1 for an invalid argument.
motor_name(i)
Returns the string name of motor i as given in the configuration file or a -1 for an invalid argument.
motor_num(mne)
Returns the motor number corresponding to the motor mnemonic mne, or -1 if there is no such motor configured. As of spec release 6.05.01, mne can be a variable or an expression. If mne is an uninitialized variable, the function returns -1.
motor_par(i, s, v, "add")
Creates a temporary run-time motor parameter for motor i named s with initial value v.
motor_par(i, s [, v])
Returns or sets configuration parameters for motor i. The optional argument v is used to set a value for the parameter s. Otherwise, see MOTOR PARAMETERS below for recognized values for the parameter name.
get_lim(i, w)
Returns the dial limit of motor i. If w > 0, returns high limit. If w < 0, returns low limit. If w > 1, returns high limit corrected for configured backlash. If w < 1, returns low limit corrected for configured backlash.
set_lim(i, u, v)
Sets the low and high dial limits of motor i. It doesn't matter which order the limits, u and v, are given. Returns -1 if not configured for motor i or if the motor is protected, unusable or moving, else returns 0.
dial(i, u)
Returns the motor dial position for motor i corresponding to user angle u.
user(i, d)
Returns the user angle for motor i corresponding to dial position u.
chg_dial(i, u)
Sets the dial position of motor i to u by changing the contents of the controller registers. Returns -1 if not configured for motor i or if the motor is protected, unusable or moving, else returns 0.
chg_dial(i, s [, u])

Starts motor i on a home or limit search, according to the value of s, as follows:

"home+"
move to home switch in positive direction.
"home-"
move to home switch in negative direction.
"home"
move to home switch in positive direction if current dial position is less than zero, otherwise move to home switch in negative direction.
"lim+"
move to limit switch in positive direction.
"lim-"
move to limit switch in negative direction.

Positive and negative direction are with respect to the dial position of the motor. (Not all motor controllers implement the home or limit search feature.) If present, the value of the third argument is used to set the motor's dial position when the home or limit position is reached (as of spec release 4.05.10-3). Returns -1 if not configured for motor i or if the motor is protected, unusable or moving, else returns 0.

chg_offset(i, u)
Sets offset (determining user angle) of motor i to u. Returns -1 if not configured for motor i or if the motor is unusable or moving, else returns 0.

MOTOR PARAMETERS

The motor_par() function, described above, is used to get and set various motor parameters. There are several types of parameters as follows:

Read-Only Status Parameters

These parameters return information concerning the state and hardware selection for a motor. All are read only.

"controller"
Returns a string containing the controller name of the specified motor. The controller names are those used in spec's config files.
"device_id"
For responsive controllers, returns a string identifying the device, otherwise returns a question mark (?). For example, for serial interfaces, the string is the device node, such as "/dev/ttyS0", while for socket devices, the string is the hostname or IP address. For macro hardware, the string is the base name of the macros used. For other hardware types, a device address or device name is returned, if available. Otherwise the return string may just contain the type of interface, such as "USB" or "VXI11".
"unit"
Returns the unit number of the specified motor. Each motor controller unit may contain more than one motor channel. Each motor controller type has its own sequence with unit numbers starting at zero. Controllers are of the same type if they are from the same vendor and use the same command protocol and syntax.
"module"
Returns the module number of the specified motor as set in the config file. Not all controllers use module numbers.
"channel"
Returns the channel number of the specified motor as set in the config file. Some controller channels numbers start from zero, while others start with channel one.
"active"
Returns a nonzero value if the motor is currently moving.
"responsive"
Returns a nonzero value if the motor responded to an initial presence test or appears otherwise to be working.
"writable"
Returns a value indicating the permission status of the motor, as set in the config file. If bit 1 is set, the motor can be moved. If bit 2 is set, the limits can be changed. A fully protected motor will return zero. A fully open motor will return 3.
"depends"
For pseudo motors that depend on real motors or for real motors that are depended on by pseudo motors, returns an associative array where each element is the motor mnemonic of a related motor. If there is no dependency, returns an empty array.
"high_lim_hit"
Returns nonzero if the high limit is active (for most supported motor controllers).
"low_lim_hit"
Returns nonzero if the low limit is active (for most supported motor controllers).

Run-Time Parameters

"low_limit"
Returns or sets the low limit. Using motor_par() is an alternative to using the get_lim() and set_limt() functions.
"high_limit"
Returns or sets the high limit. Using motor_par() is an alternative to using the get_lim() and set_limt() functions.
"disable"
Returns a nonzero value if the motor has been disabled by software. If an nonzero argument is included, the motor is disabled. If a zero argument is given, the motor becomes no longer disabled. A disabled motor channel will not be accessed by any of spec's commands, and, of course, cannot be moved. Any cdef()-defined macros will automatically exclude the portions of the macro keyed to the particular motor when the motor is software disabled.

Standard Parameters

These parameters are available for all motor controllers and values are assigned on the Motor screen of the hardware configuration editor. Note, though, not all motor controllers use all of the standard parameters. For example, some controllers don't have a programmable base rate.

"acceleration"
The acceleration parameter. The units of acceleration are the time in milliseconds for the motor to accelerate to full speed from the base rate.
"backlash"
The backlash parameter. Its sign and magnitude determine the direction and extent of the motor's backlash correction. Setting the backlash to zero disables the backlash correction. Units are steps.
"base_rate"
The base-rate parameter. The units are steps per second. The base rate is the the speed at which stepping motors begin movement, chosen to avoid possible resonances at very low speeds.
"offset"
The "offset" motor parameter, which is the difference between the user and dial motor positions. This is a read-only parameter, but can be changed using the chg_offset() function.
"sign"
Returns 1 or -1, indicating the rotation sense of the user angle versus the dial angle, as set in the config file. This is a read-only parameter.
"slew_rate" or "velocity"
The steady-state velocity parameter. The units are steps per second.
"step_size"

Returns a parameter related to the step size. However, the parameter name is misleading. The value is actually the number of steps per unit (where the unit is generally degrees, millimeters, microns, etc.), which is the inverse of the step size.

Note, the parameter can be negative, which might be needed to make the dial position agree with the rotation sense of the motor.

Since changing this parameter seriously affects the motor position calculation, the function spec_par("modify_step_size", 1) must be entered first to enable step-size modifications using motor_par().

For some motor controllers, the syntax for specifying positions requires natural units (as degrees or millimeters, for example). For these motor controllers the "step_size" parameter determines how spec rounds motor positions. spec stores motor positions as 64-bit integers for all motor controllers. For the majority of motor controllers that work with position registers, the internal position registers mirror the controller registers. For controllers that work in natural units, spec still stores positions as integers, but uses the "step_size" parameter to scale the positions read from and sent to the controller. Thus, the magnitude of the parameter determines the precision with which spec maintains the positions. The value should be set to correspond to the controller resolution.

Configuration File Values

These are read-only parameters that return the value of the primary standard parameters as set in the hardware config file.

"config_acceleration"
Returns the value of the "acceleration" parameter as set in the config file.
"config_backlash"
Returns the value of the "backlash" parameter as set in the config file.
"config_base_rate"
Returns the value of the "base_rate" parameter as set in the config file.
"config_step_size"
Returns the value of the "step_size" parameter as set in the config file.
"config_velocity" or "config_slew_rate"
Returns the value of the "velocity" parameter as set in the config file.

Standard Optional Parameters

These parameters are available for motor controllers that support them. They are configured on the two secondary screens reached by typing successive m commands on the from the main motor screen.

"home_acceleration"
The home-acceleration parameter. This parameter is the acceleration used during a home search. If supported by the controller, but unset, spec uses the configured "acceleration".
"home_base_rate"
The home-base-rate parameter. This parameter is the base-rate velocity used during a home search. If supported by the controller, but unset, spec uses the configured "base_rate".
"home_slew_rate"
The home-slew-rate parameter. This parameter is the steady-state velocity used during a home search. If supported by the controller, but unset, spec uses the configured "slew_rate".
"home_position"
The home position in dial units. This is the position assigned to the motor position register after a successful home search.
"home_method"
Returns the current home method parameter. The parameter may be a number or a string, depending on the motor controller.
"dc_dead_band"
The dead-band parameter for DC motors.
"dc_settle_time"
The settle-time parameter for DC motors.
"dc_proportional_gain"
The proportional-gain parameter for DC motors.
"dc_derivative_gain"
The derivative-gain parameter for DC motors.
"dc_integral_gain"
The integral-gain parameter for DC motors.
"dc_integration_limit"
The integration-limit parameter for DC motors.
"dc_veloc_feedforward"
The velocity-feedforward parameter for DC motors.
"dc_accel_feedforward"
The acceleration-feedforward parameter for DC motors.
"dc_following_error"
The following-error parameter for DC motors.
"dc_sampling_interval"
The sampling-interval parameter for DC motors.
"encoder_step_size"
The encoder step size parameter.
"step_mode"
The step-mode parameter. A zero indicates full-step mode, while a one indicates half-step mode.
"rotary"
Returns or sets the linear/rotary parameter. A value of one sets rotary mode.
"disable_limit_checks"
The disable-limit-checks parameter. A nonzero value disables software limit checks for the associated motor.
"slop"
The slop parameter. When this parameter is greater than zero, discrepancies between hardware and software motors positions are silently resolved in favor of the the hardware when the number of steps in the discrepancy is less than the value of the slop parameter. If the value is negative, discrepancies less than the absolute value of the parameter are resolved in favor of software by changing the hardware controller position, if possible.
"read_mode"

The hardware read-mode parameter. The read-mode parameter allows setting spec's behavior for motors that are likely to be moved by other programs while spec is monitoring the position of the motor, or that have encoders and positions that fluctuate. The return value and the value for v is coded as follows:

Bit 0 (0x01)
spec will always read the hardware before moving the motor. Normally, spec assumes the motor is at its last position.
Bit 1 (0x02)
spec will always read the hardware whenever the get_angles command is run from user level. Normally, spec does not access hardware if the motor hasn't been moved since the controller was last read.
Bit 2 (0x04)
spec will always assume the hardware is correct and not query the user if the returned hardware position differs from the current software position.
"deceleration"
The deceleration parameter. Units are in milliseconds, just as with the "acceleration" parameter.
"torque"
The torque parameter.
"misc_par_1", "misc_par_2", "misc_par_3", "misc_par_4", "misc_par_5", "misc_par_6"
These parameters set assorted parameters for certain controllers.

Non-Standard Optional Parameters

The non-standard optional parameters are mostly specific to particular motor controllers and may be documented in the help files for those controllers or mentioned in the update notes. Both the parameter name and parameter value are entered on the screen reached by typing p from one of the motor screens. Each motor has its own non-standard optional parameter screen. Note, though, the following parameters are available for all motors, but need to be configured on the non-standard optional parameter screen.

"powder_base"
The base rate for powder-mode moves initiated with move_cnt.
"powder_slew"
The slew rate for powder-mode moves initiated with move_cnt.
"powder_acceleration"
The acceleration for powder-mode moves initiated with move_cnt.
"backlash_rate"
Returns or sets a backlash speed parameter. Note, although the parameter is recognized, no current motor controller support uses it, although it could be used with macro hardware motors.
"move_timeout"
Returns or sets the move timeout for a single motor.

Rereading the config file resets the values of all the motor parameters to the values in the config file. Only moderate consistency checking is done by spec on the values programmed with motor_par(). Be sure to use values meaningful to your particular motor controller.

MOTOR NUMBERING

For most motor controllers, unit and channel numbers can be explicitly assigned to individual motors channels in the hardware configuration editor. The unit numbers start from zero for each different model of motor controller and are implicitly assigned to consecutive units as they are listed in the configuration editor.

Channel numbers start from zero for most motor controllers. For the following controllers, where the hardware clearly labels the motor channels, the channel numbers start from one: AllMotion EZStepper, Attocube ANC150, Attocube ANC300, Attocube ANC350, Bruker D8, Compumotor 6K, Delta Tau PMAC/PMAC2, EPICS standard motor record, EPICS CLS motor record, Hanaro MCU, HMT HCC1, IMS MDrive 17/23/34, IMS MicroLYNX 4/7, JVL SMI20B, Kohzu KOSMOS, Kohzu Seiki PMC-2/3/4 GT, Kohzu SC-200/400/800, Labo NT-2400, MAC Science MXC, Micos MMC-100, Micos VENUS-1/2/3 Compatible, MicroMo MVP-2001, Munich BR-tronik IPS, New Focus 8742, Newport Agilis, Newport CONEX-AGP, Physik Instrumente C-630, Physik Instrumente E-710 and E-712, PMC DCX-100 and DCX-PCI300, Rigaku RINT-2000, RISO ECB, SCIPE Actuator, Siemens D5000, Sigmatech FC-501A and Velmex VXM-1/VXM-2.

If the optional unit/channel numbering is left blank, motors are assigned to motor controller channels in the order they each appear in the config file. For example, if several motor controllers of the same type are configured and each can control eight motors, the first eight motors configured are assigned to the first controller, the next eight, to the next controller, and so on. If a controller channel is unusable, a motor must still be configured for that channel, although if given the name "unused", information about that motor won't be displayed by the standard macros.

Note, support for the following older motor controllers hasn't been updated to recognize unit/channel numbering: Joerger SMC, Oriel 18011, Compumotor 3000/4000 and SX, Micro-Controle IP28 and SIX19, Klinger MC4, ACS MCB, NSLS MMC32, NSK and Inel XRGCI. For these controllers, the consecutive numbering rule applies.

Standard macros such as wh display only the motors most relevant to a particular geometry. Other macros that display information about all the motors, such as wa, list these most relevant motors first. For a particular geometry configuration, the relevant motors are established in the _assign macro, which is normally in geometry-specific macro file. A user can change the order in which the motors are displayed by redefining the _assign macro.

MOTION

Motors are set in motion by the command move_all, which simultaneously moves all motors to the positions in the array A[] (in user units). Note, though, the standard macros use move_em, which incorporates the user_premove and user_postmove user-hook macros before and after the move_all call. It is recommended that local macros also use move_em rather than move_all.

When move_all is executed, the code makes several checks on the validity of the move, including checks on whether any of the dial positions corresponding to the user angles in A[] are outside the dial limits. If so, no motors are moved, and the program responds with an error.

Note, moving motors is asynchronous. The program returns while the motors are still in motion. However, moving motors can be synchronized using the function wait().

When writing macros to move motors, you should always wait for motors to stop, do a get_angles command to fill A[] with the current positions, assign new values to the elements of A[] for the motors that are to be moved, and then do the move_em.

Study the definitions of the standard macros mv, umv, br, an, pl, etc., to see normal usage.

SECURE MOTORS

At some spec installations, the spec administrator may prevent users from moving particular motors and/or changing the limits of particular motors.

EXAMPLE

Here is a primitive macro to move one motor:

def mv '
   if ($# != 2) {
        print "usage:  mv motor position"
        exit
   }
   wait()       # Let previous motions finish.
   get_angles   # Make sure A[] is current so no
                #   other motors start moving.
   A[$1]=$2     # Change the relevant A[].
   move_em      # Start the motors.
'