spec

Software for Diffraction

2.4.8.1. - Controlling Motors



move_all
This command sets motors in motion. The sequence of events is as follows. For some motor controllers, spec first examines the controller registers of all nonbusy motors and makes sure the contents agree with the current positions in program memory. If there is a discrepancy, the user is asked to choose the correct position. Next, spec prepares to move all motors that are not already at the positions specified in the built-in A[] array, interpreted in user units. A motor will not be moved if it is currently moving or if it is marked as protected (via the configuration file) or unusable (due to failure of a hardware presence test). If the target position of any of the motors is outside the software limits, the entire move is canceled, and the program resets to command level. Otherwise, the motors are started, and the command returns.

The sequence of commands when using move_all should almost always be,
wait(1)         # Wait for moving to finish
read_motors(0)  # Put current positions of all motors in A[]
(Assign new values to elements of A[] to be moved)
move_all        # Move to those positions
If read_motors() is called before the motors have stopped, the values in A[] will reflect the motor positions before they stopped. If read_motors() is not called at all, or if you do not explicitly assign a value to each element of A[], then you will not know for sure where some motors will be going when move_all is called.

A ^C halts moving, as does the sync command.

move_cnt
This command is similar to move_all, described above, but with the following differences. Just before the motors are started, the clock/timer is enabled and programmed to gate the scalers with a longer-than-necessary count time. The motors are then started at the base rate set in the config file, but are not accelerated to the steady-state rate. No backlash correction is done at the end of the move. When the move is completed, the clock/timer is stopped. The move_cnt command is used in powder-averaging scans. (See the powder-mode macros 3.9.5

sync
If any motors are moving, they are halted. The motor positions maintained by the motor controller are then compared with the motor positions currently set in the program. If there is a discrepancy, the user is asked which should be changed. The sync command is used to place the motor hardware in a known state and is supposed to fix any problems in communicating with the controllers.

motor_mne(motor)
Returns the string mnemonic of motor number motor as given in the configuration file. (Mnemonics are, at most, 7 characters long.) Resets to command level if not configured for motor.

motor_name(motor)
Returns the string name of motor number motor as given in the configuration file. (Names are, at most, 15 characters long.) Returns "?" if not configured for motor.

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, -1 is returned.

motor_par(motor, par [, val ])
Returns or sets configuration parameters for motor motor. Recognized values for the string par follow. Note, not all parameters are meaningful for all motor controllers.


"step_size"
returns the current step-size parameter. The units are generally in steps per degree or steps per millimeter. If val is given, then the parameter is set to that value, but only if changes to the step-size parameter have been enabled using spec_par("modify_step_size", "yes").

"acceleration"
returns the value of the current acceleration parameter. The units of acceleration are the time in milliseconds for the motor to accelerate to full speed. If val is given, then the acceleration is set to that value.

"base_rate"
returns the current base-rate parameter. The units are steps per second. If val is given, then the base rate is set to that value.

"velocity"
returns the current steady-state velocity parameter. The units are steps per second. If val is given, then the steady-state velocity is set to that value.

"backlash"
returns the value of the backlash parameter. Its sign and magnitude determine the direction and extent of the motor's backlash correction. If val is given, then the backlash is set to that value. Setting the backlash to zero disables the backlash correction.

"config_step_size"
returns the step-size parameter contained in the config file.

"config_acceleration"
returns the acceleration parameter contained in the config file.

"config_velocity"
returns the steady-state velocity parameter contained in the config file.

"config_base_rate"
returns the base-rate parameter contained in the config file.

"config_backlash"
returns the backlash parameter contained in the config file.

"controller"
returns a string containing the controller name of the specified motor. The controller names are those used in spec's config files.

"unit"
returns the unit number of the specified motor. Each motor controller unit may contain more than one motor channel.

"channel"
returns the channel number of the specified motor.

"responsive"
returns a nonzero value if the motor responded to an initial presence test or appears otherwise to be working.

"active"
returns a nonzero value if the motor is currently moving.

"disable"
returns a nonzero value if the motor has been disabled by software. If val is given and is nonzero, then the motor is disabled. If val is given and is zero, 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.

"slop"
returns the value of the slop parameter. If val is given, sets the slop parameter. When this parameter is present, 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. (Not yet implemented for all motor controllers.)

"home_slew_rate"
returns the value of the home-slew-rate parameter. If val is given, sets the parameter. This parameter is the steady-state velocity used during a home search. (Only available for selected controllers.)

"home_base_rate"
returns the value of the home-base-rate parameter. If val is given, sets the parameter. This parameter is the base-rate velocity used during a home search. (Only available for selected controllers.)

"home_acceleration"
returns the value of the home-acceleration parameter. If val is given, sets the parameter. This parameter is the acceleration used during a home search. (Only available for selected controllers.)

"dc_dead_band"
returns the value of the dead-band parameter for certain DC motors. Sets the parameter if val is given.

"dc_settle_time"
returns the value of the settle-time parameter for certain DC motors. Sets the parameter if val is given.

"dc_gain"
returns the value of the gain parameter for certain DC motors. Sets the parameter if val is given.

"dc_dynamic_gain"
returns the value of the dynamic-gain parameter for certain DC motors. Sets the parameter if val is given.

"dc_damping_constant"
returns the value of the damping-constant parameter for certain DC motors. Sets the parameter if val is given.

"dc_integration_constant"
returns the value of the integration-constant parameter for certain DC motors. Sets the parameter if val is given.

"dc_integration_limit"
returns the value of the integration-limit parameter for certain DC motors. Sets the parameter if val is given.

"dc_following_error"
returns the value of the dc-following parameter for certain DC motors. Sets the parameter if val is given.

"dc_sampling_interval"
returns the value of the sampling-interval parameter for certain DC motors. Sets the parameter if val is given.

"encoder_step_size"
returns the value of the encoder step size parameter. Sets the parameter if val is given.

"step_mode"
returns the value of the step-mode parameter. Sets the parameter if val is given. A zero indicates full-step mode, while a one indicates half-step mode.

"deceleration"
returns the value of the deceleration parameter. Sets the parameter if val is given.

"torque"
returns the value of the torque parameter. Sets the parameter if val is given.


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

In addition, device-dependent values for par are available for specific motor controllers. See the Hardware Reference for values for specific controllers.

dial(motor, user_angle)
Returns the dial angle for motor motor corresponding to user angle user_angle using the current offset between user and dial angles for motor. The value returned is (user_angle - offset) / sign, where sign is ±1 and is set in the config file. The value is rounded to the motor resolution as set by the step-size parameter in the config file. Resets to command level if not configured for motor motor.

read_motors(how)
Reads the current motor positions from the motor controllers and places the values in the A[] array, depending on the value of the argument how. If bit 1 is set, the function returns dial values, otherwise user values are returned. If bit 2 is set, a forced read of all hardware takes place. (For efficiency, normally most motor controllers are not read if the position hasn't been changed by a move.) If bit 3 is set and if there is a discrepancy between the software and hardware, the software will be silently corrected to match the hardware. Note, the forced-read and "silent-sync" features are not yet implemented for all motor controllers. Check the Hardware Reference or contact CSS for hardware-specific information.

move_info([motor|keyword|motor, keyword])
The move_info() function returns information about what would happen on a subsequent move_all command given the current motor positions and current values in the A[] array. Such a function might be called, for example, within the user_premove macro to determine which motors will be moved to allow extra limit checking involving the relative postions of motors.

If called with no arguments, returns a two-dimensional associative array containing the move information. The array is indexed by motor number and information keyword. The keywords are:
 @to_move@   nonzero if motor will move 
 @error@   reason the motor will not move 
 @commanded@   the commanded position 
 @magnitude@   magnitude of the move in user units 
 @current@   current position in user units 
 @current_dial@   current position in dial units 
 @target@   target position in user units 
 @target_dial@   target position in dial units 
 @backlash@   backlash for this move in user units 
 @leftover@   remainder due to motor resolution 

If called with a single argument that is one of the above keywords, the function returns a one-dimensional associative array indexed by motor number containing values for that keyword for each motor. If called with a motor number or mnemonic as a single argument, the function returns a one-dimensional associative array, indexed by the above keywords containing values for the one motor. If called with two arguments, motor number and keyword, the function returns the corresponding single value.

No matter how the function is called, the internal code will calculate values for all motors. Thus, if multiple values are needed, it is most efficient and recommended to call the function once selecting arguments that will return all the needed values.

The "to_move" element will be 1 or 0, indicating whether the motor would move or not. If there is condition that prevents the move, the "error" element will contain one of these strings:
 @low limit@   move exceeds low limit 
 @high limit@   move exceeds high limit 
 @busy@   motor is busy 
 @read only@   motor is configured as read only 
 @protected@   motor configuration does not allow moving 
 @disabled@   motor has been disabled 
 @externally disabled@   shared motor has been disabled 
 @unusable@   motor did not respond to presence test 

Otherwise, there will be no "error" array element.

The "target" and "target_dial" values are the final position after backlash. The "magnitude" value contains the distance to the target position and does not include the magnitude of the backlash.

The "leftover" value is the fractional value that is the difference between the requested position and the achievable position given the finite resolution of the motor. For example, if a motor has 1000 steps per degree, each step corresponds to 0.001 degrees. If one asks to move the motor to a position of 1.0004 degrees, the motor will move to 1 degree and the leftover value will be 0.0004 degrees.

The "commanded" value is the target position in user units to the full precision requested. The other postion-related values are rounded to the motor resolution. The "commanded" position is saved after a move and is available using special arguments to the built-in read_motors() functions.

As mentioned above, if multiple values are needed, it is better to make a single call of move_info() saving the return values in an array, rather than making multiple calls, as each call involves calculations for all the motor positions and values, even if only selected values are returned. For example,
{
   local i, m[]
   m = move_info()
   for (i = 0; i < MOTORS; i++)
        if (m[i]["to_move"]) {
                ...
        }
}
For the most part, the move_info() function will reflect what will happen on the next move_all command. However, for shared motors that can be moved by other processes or for motors that have positions that drift or have jitter, the status and position may change between the move_info() call and the move_all call.

chg_dial(motor, dial_angle)
Sets the dial position of motor motor to dial_angle. Returns nonzero if not configured for motor or if the protection flags prevent the user from changing the limits on this motor. Resets to command level if any motors are moving.

chg_dial(motor, cmd)
Starts motor motor on a home or limit search, according to the value of cmd 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. (At present, most motor controllers do not implement the home or limit search feature.) Returns -1 if not configured for motor motor or if the motor is protected, unusable or moving, else returns zero.

get_lim(motor, flag)
Returns the dial limit of motor number motor. If flag > 0, returns the high limit. If flag < 0, returns the low limit. Resets to command level if not configured for motor.

user(motor, dial_angle)
Returns the user angle for motor corresponding to dial angle dial_angle using the current offset between user and dial angles for motor. The value returned is sign × dial_angle + offset, where sign is ±1 and is set in the config file. The value is rounded to the motor resolution as set by the step-size parameter in the config file. Resets to command level if not configured for motor.

chg_offset(motor, user_angle)
Sets the offset between the dial angle and the user angle, using the current dial position and the argument user_angle for motor motor according to the relation user_angle = offset + sign × dial_angle where sign is ±1 and is set in the config file. Returns nonzero if not configured for motor. Resets to command level if any motors are moving.

set_lim(motor, low, high)
Sets the low and high limits of motor number motor. low and high are in dial units. It does not actually matter in which order the limits are given. Returns nonzero if not configured for motor or if the protection flags prevent the user from changing the limits on this motor. Resets to command level if any motors are moving.