1.3.10. - Moving Motors
A primary purpose of spec is to manipulate an X-ray diffractometer according to a calculated geometry. The automation of the angular settings is accomplished through the use of motor controllers interfaced to the computer. spec can be configured to control any number of motors.
As explained earlier, motor positions are referred to as dial positions and user positions. The diffractometer is operated in user positions. Dial positions are used to provide a stable point of reference. The two differ possibly by a sign and/or an offset. Dial positions should be set to always agree with the physical dials of the diffractometer motors. The user positions are then set in the line-up procedure of the diffractometer. For example, they may be set to zero at the direct beam. The relations between the two positions are:
dial = hardware_register / steps_per_unit user = sign × dial + offsetThe hardware_register contains the value maintained by the stepper motor controller. The value of steps_per_unit is assigned in the hardware configuration file, as is sign. The latter must be chosen to agree with the conventions of the built-in geometry calculations.
The motor positions are often placed in the
A[]
array.
The array is built-in and its elements can be used like any other variables.
What makes it special, however, are
the commands that use the array
to convey the
positions of the diffractometer motors.
For example, the command
getangles
sets
all
of the elements of the
A[]
array to the current motor positions in user angles, while
the
move_all
command sends the motors to the positions contained in
A[]
(in user angles).
Typical usage is,
1.FOURC> waitmove # Make sure no motors are active.
2.FOURC> getangles # load A[] with user angles.
3.FOURC> A[0] = 3 # move motor #0 to 3.
4.FOURC> move_all # start the move.
5.FOURC>
(The
#
symbols introduce comments.)
It is important to first wait for any previous motions to complete.
Then
getangles
is used
to load the angle array with the current positions.
Only the values for the motors to be moved are reassigned
before using
move_all
to set the motors in motion.
A macro that would list the user positions of all the configured motors might be:
1.FOURC> def wa '
2.quot> getangles
3.quot> for (i = 0; i < MOTORS; i++)
4.quot> printf("%9.9s = %g\n", motor_name(i), A[i])
5.quot> '
6.FOURC> wa
Two Theta = 3 Theta = 1.5 Chi = 0 Phi = 0 7.FOURC>
The
motor_name()
function returns the motor name
assigned in the configuration file.
The motor positions are stored in three locations: in program memory, on the computer's hard disk and in the hardware registers associated with the motor controller. The program manipulates the angles in its memory. The values on the hard disk are updated every time a motor is moved but are only read when the program is initialized, or after the
reconfig
command is invoked.
The controller registers count the actual number of steps moved
and should be the true positions of the motors
(unless a motor was switched off).
Before each motor is moved,
the controller registers are compared with program memory.
If there are discrepancies, you are notified
and asked which value is correct.
The
sync
command can also be used to synchronize the controller registers
with program memory.
The angles can get out-of-sync
by moving the motors with manual controls,
by turning off the power to motor controllers
or perhaps by a computer crash.
Although the motor controllers work in steps, it is much more convenient to use real units such as degrees (or, for linear motion, millimeters). The user and dial angles are in these units, converted from steps by the step-size parameters that are read from the configuration file.
The
chg_dial(motor, dial_angle)
function sets the dial register to
dial_angle
for one motor.
The
chg_offset(motor, user_angle)
function sets the offset used to convert
from dial positions to user positions for one motor.
Often during the line-up procedure you will want to
zero a particular angle:
1.FOURC> chg_offset(th, 0) # set motor theta to zero
2.FOURC>
The
set
macro includes the above and documents the change on the printer
and in the data file.
1.FOURC> set th 0
Wed Aug 19 11:53:33 1987. Theta reset from 1.5 to 0 2.FOURC>
Dial and user settings may also be set by the spec administrator using the program edconf. See 5.5.2 in the Administrator's Guide for further details.
Usually, diffractometer motions have a limit of travel, beyond which physical damage may occur (or a hardware limit switch tripped). Software limits therefore exist to prevent you from accidentally moving a motor out of range. The lower and upper limits for each motor are contained in internal arrays accessed through the
set_lim(motor_number, low, high)
and
get_lim(motor_number, flag)
functions.
With the latter, the lower limit is returned
if
flag
is less than zero, otherwise the upper limit is returned.
If a
move_all
command would take any motor outside of its limits,
an error message is printed and no motors are moved.
The limit values are stored in
dial
angles since they correspond to physical limitations to the motion.
The limit values are therefore preserved as the
user-angle offsets are changed.
The
set_lm
macro can be used to set a single motor's limits:
1.FOURC> set_lm tth 0 360
Two theta limits set to 0 360 (dial units). 2.FOURC>
The angle arguments to the macro
set_lm
are given in
user
angles.
(In this example, dial and user angles are the same.)