forked from epics_driver_modules/motorBase
1637 lines
68 KiB
HTML
1637 lines
68 KiB
HTML
<HTML>
|
|
<HEAD><TITLE>Trajectory Scanning</TITLE>
|
|
</HEAD>
|
|
<BODY>
|
|
<CENTER>
|
|
<H1> Trajectory Scanning with the Newport MM4005, Newport XPS, Aerotech Ensemble, and Pro-Dex MAXv
|
|
Motor Controllers</H1>
|
|
<H2> Mark Rivers</H2>
|
|
<H2> June 29, 2007</H2>
|
|
<H2> (Additions for Ensemble and MAXv: Tim Mooney, April 4, 2014)</H2>
|
|
|
|
</CENTER>
|
|
<H2>Contents</H2>
|
|
<UL>
|
|
<LI><A href="#Overview">
|
|
Overview</A>
|
|
<LI><A href="#Implementation">
|
|
Implementation</A>
|
|
<LI><A href="#Safety">
|
|
Safety</A>
|
|
<LI><A href="#Notation">
|
|
Notation</A>
|
|
<LI><A href="#Defining a Trajectory">
|
|
Defining a Trajectory</A>
|
|
<LI><A href="#Building a Trajectory">
|
|
Building a Trajectory</A>
|
|
<LI><A href="#Executing a Trajectory">
|
|
Executing a Trajectory</A>
|
|
<LI><A href="#Reading Back a Trajectory">
|
|
Reading Back a Trajectory</A>
|
|
<LI><A href="#Interaction with EPICS Motor Records">
|
|
Interaction with EPICS Motor Records</A>
|
|
<LI><A href="#Communication with the controller">
|
|
Communication with the controller</A>
|
|
<LI><A href="#Hardware Notes">
|
|
Hardware Notes</A>
|
|
<LI><A href="#Installation">
|
|
Installation</A>
|
|
<LI><A href="#Loading the database">
|
|
Loading the database</A>
|
|
<LI><A href="#Starting the SNL program">
|
|
Starting the SNL program</A>
|
|
<LI><A href="#Startup script">
|
|
Startup script</A>
|
|
<LI><A href="#MEDM screens">
|
|
MEDM Screens</A>
|
|
<LI><A href="#Autosave">
|
|
Autosave</A>
|
|
<LI><A href="#Example IDL Procedure">
|
|
Example IDL Procedure</A>
|
|
<LI><A href="#SPEC_Interface">
|
|
SPEC Interface</A>
|
|
<LI><A href="#Restrictions">
|
|
Restrictions</A>
|
|
</UL>
|
|
|
|
<P> </P>
|
|
<H2><A name=Overview>
|
|
Overview</A></H2>
|
|
<P>The Newport MM4005 and XPS, the Aerotech Ensemble, and the Pro-Dex MAXv motor controllers are capable of executing complex
|
|
coordinated motions. Trajectories can be defined that move any or all of
|
|
the axes through any set of complex motions. (Currently, the
|
|
Ensemble trajectory support can only control a single axis.) The controller will coordinate
|
|
these motions, keeping each axis very close to the theoretical position during
|
|
the entire motion. The controller can output logic pulses during the execution
|
|
of the trajectory, permitting external equipment to be synchronized to the
|
|
motion. These capabilities are ideally suited to “on-the-fly” data
|
|
collection.</P>
|
|
|
|
<P>At the APS one application of the MM4005 and XPS is to drive the large Newport
|
|
diffractometer. This diffractometer has rather long settling times because of
|
|
the mass of the moving elements. However, with this trajectory scanning software
|
|
one can use SPEC, for example, to compute a set of diffractometer positions for
|
|
a scan in HKL space, and then download these positions to the controller. The
|
|
entire scan can be executed without stopping, collecting data in a multi-channel
|
|
scaler or other triggered buffering detector.
|
|
This can reduce data collection times dramatically relative to
|
|
traditional step scanning.</P>
|
|
|
|
<P>This document describes an EPICS interface to the trajectory capabilities of
|
|
the MM4005, XPS, Ensemble, and MAXv. This interface is completely general for the controllers, it is not
|
|
specific to the Newport diffractometer. The interface lets any EPICS channel
|
|
access client do the following:</P>
|
|
<UL>
|
|
<LI>Define the total number of trajectory elements.
|
|
<LI>Define the absolute or relative position of each axis for each point in
|
|
the trajectory.
|
|
<LI>Define the time for each element of the trajectory, or alternatively the
|
|
total execution time with equal time per trajectory element.
|
|
<LI>Define the total number of output synchronization pulses. <i>The MAXv can
|
|
only send output pulses at trajectory points.</i>
|
|
<LI>Define the trajectory elements where pulse outputs begin and end.
|
|
<LI>Build and verify the trajectory, checking for errors.
|
|
<LI>Define a total time scaling factor from .01 to 100 that will speed up or
|
|
slow down the trajectory execution relative to its original definition
|
|
(MM4005, MAXv, and Ensemble only).
|
|
<LI>Execute the trajectory, checking for completion and errors. This can be
|
|
done repeatedly without rebuilding if the only changes are in the start
|
|
position or the execution time scale factor. <i>The MAXv must load the
|
|
trajectory before every execution.</i>
|
|
|
|
<LI>Read back the actual position of each axis when each synchronization pulse
|
|
was output. <i>The Ensemble and MAXv cannot do this. For these controllers,
|
|
position data are usually recorded with a multichannel scaler to which motor
|
|
pulses (MAXv) or PSO pulses (Ensemble) are sent. The Ensemble can record
|
|
and read back position error with an internal scope.</i>
|
|
<LI>Read back the following error (actual-theoretical positions) when each
|
|
synchronization pulse was output. <i>The Ensemble and MAXv cannot do this.</i>
|
|
</UL>
|
|
|
|
<P> </P>
|
|
<H2><A name=Implementation>
|
|
Implementation</A></H2>
|
|
<P>The EPICS implementation consists of the following:</P>
|
|
<UL>
|
|
<LI>A database file, <CODE>trajectoryScan.db.</CODE> This database
|
|
contains almost no "logic" with no links between records in the database. The
|
|
records are simply variables that channel access clients and the State
|
|
Notation Language (SNL) program use.
|
|
<LI>SNL programs, <CODE>MM4005_trajectoryScan.st, XPS_trajectoryScan.st,
|
|
MAX_trajectoryScan.st, and EnsembleTrajectoryScan.st</CODE>. These programs
|
|
implement all of the logic for communicating with the controller and with
|
|
channel access clients via the database.
|
|
<LI>MEDM screens, <CODE>trajectoryScan.adl,
|
|
trajectoryScanDebug.adl, trajectoryPlot.adl</CODE>. These screens are
|
|
used to control the building, execution, readback, debugging and plotting of
|
|
trajectory scans. <i>MAXv and Ensemble currently use a different display:
|
|
<CODE>MAX_trajectoryScan.adl</CODE>.</i>
|
|
|
|
</UL>
|
|
|
|
<P> </P>
|
|
<H2><A name=Safety>
|
|
Safety</A></H2>
|
|
<P>The MM4005 and XPS are used at the APS to control the large Newport
|
|
diffractometer. This device is capable of moving large masses at high speeds.
|
|
The trajectory scanning software does not use the EPICS motor record, and so
|
|
does not obey any software limits defined in the motor record. It is very
|
|
important that:</P>
|
|
<UL>
|
|
<LI>The controller be programmed via the front panel (MM4005) or Web interface (XPS)
|
|
to have safe software limits
|
|
to prevent collisions whenever possible. The trajectory scanning software does
|
|
obey the MM4005 internal soft limits. However, the MultipleAxesPVTExecution command
|
|
on the XPS <i>does not obey the soft limits</i>! The XPS trajectory scan SNL code
|
|
checks that the limits of the trajectory do not exceed the soft limits, and will not
|
|
execute the trajectory if they do.
|
|
<LI>Care be taken to avoid trajectory execution whenever personnel could be
|
|
harmed. The following error thresholds for each axis on the controller should be
|
|
set tight enough that the motor power will turn off when a significant
|
|
resistance is met. An emergency stop button should be within reach whenever
|
|
personnel are working on the diffractometer, and the switch should be in the
|
|
Stop position whenever personnel are working for extended periods or in
|
|
vulnerable positions on the diffractometer.
|
|
</UL>
|
|
|
|
<P> </P>
|
|
<H2><A name=Notation>
|
|
Notation</A></H2>
|
|
<P>
|
|
The database is loaded with <CODE>$(P)</CODE> (prefix) and <CODE>$(R)</CODE>
|
|
(record base) macros. For example, <CODE>$(P)</CODE> might be
|
|
<CODE>13IDC:</CODE> for the name of the IOC, and <CODE>$(R)</CODE> might be
|
|
<CODE>Traj1:</CODE> for the first trajectory in this IOC. The prefix and
|
|
record bases are
|
|
omitted from the Process Variable (PV) names in this document, but one should be
|
|
aware that, for example, <CODE>Nelements</CODE> is really
|
|
<CODE>$(P)$(R)Nelements</CODE> or in this case
|
|
<CODE>13IDC:Traj1:Nelements</CODE>.</P>
|
|
|
|
<P>
|
|
There are 8 motors in the database, and thus 8 similar records for many
|
|
functions. For example, the records defining the trajectory positions are
|
|
<CODE>M1Traj, M2Traj ... M8Traj</CODE>. These are referred to in this document
|
|
either as <CODE>M1Traj ... M8Traj</CODE> or as <CODE>MnTraj</CODE>.</P>
|
|
|
|
<P> </P>
|
|
<H2><A name="Defining a Trajectory">
|
|
Defining a Trajectory</A></H2>
|
|
<P>
|
|
The MM4005 and XPS always define a trajectory in terms of displacements (i.e.
|
|
relative positions) of each motor for each element of the trajectory. Each
|
|
trajectory element has an execution time associated with it, and hence there is
|
|
a velocity defined for each motor (displacement/time) for each trajectory
|
|
element. The MM4005 supports trajectories of up to 2000 elements, while the XPS
|
|
supports an essentially unlimited number of elements. </P>
|
|
|
|
<P>The MAXv controller allows a maximum of 2500 trajectory elements. The number of
|
|
elements supported by the Ensemble controller depends on the number of global
|
|
double variables specified in the controller's configuration. The default
|
|
configuration supports around 70 trajectory elements; the maximum is around
|
|
40,000 elements.</P>
|
|
|
|
<P>
|
|
During execution of the trajectory the MM4005/XPS can output a user-definable
|
|
number of logic pulses. The trajectory elements where these output pulses
|
|
begin and end can also be selected. On the MM4005 these pulses are evenly spaced in distance
|
|
along the trajectory, which is a distance in up to 8-dimensional space. On the XPS
|
|
the pulses are evenly spaced in time.
|
|
|
|
The MAXv can output a pulse only at a trajectory point. Ensemble controllers can
|
|
output pulses equally spaced in distance; some models (ML, HPe, HLe) can output
|
|
pulses at each of an array of user specified positions.
|
|
|
|
<P>
|
|
These output pulses are typically used for the channel-advance of a
|
|
multi-channel scaler, allowing detector pulses to be collected in hardware, with
|
|
no software overhead at each point. At the time that each pulse is output the
|
|
controller captures the theoretical and actual (encoder) position of each
|
|
motor. These positions can be read back when the trajectory is complete.
|
|
<i>The MAXv and Ensemble controllers do not record positions at each output
|
|
pulse.</i></P>
|
|
|
|
<P>
|
|
It is important to remember that the number of data points in a scan is
|
|
determined by the number of output pulses, not by the number of trajectory
|
|
elements. For example, a constant velocity theta/2-theta scan over 10 degrees
|
|
can be defined with a only 1 trajectory element, but could be used to collect 1000
|
|
data points at .01 degree steps.</P>
|
|
|
|
<P>
|
|
The following table lists the EPICS Process Variables (PVs) that are used to
|
|
define the trajectory. Some of these are explained in more detail below.</P>
|
|
<TABLE border=1>
|
|
<TBODY>
|
|
<TR>
|
|
<TD><STRONG>PV Name</STRONG></TD>
|
|
<TD><STRONG>Record Type</STRONG></TD>
|
|
<TD><STRONG>Description</STRONG></TD></TR>
|
|
<TR>
|
|
<TD><CODE>NumAxes</CODE></TD>
|
|
<TD>longout</TD>
|
|
<TD>The number of motors (axes) to be moved. For the MM4005 this is the total number
|
|
of axes connected. For XPS it is the number of axes in this MultipleAxes group.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>Nelements</CODE></TD>
|
|
<TD>longout</TD>
|
|
<TD>The number of elements in the trajectory, i.e. the number of valid
|
|
points in the <CODE>M1Traj...M8Traj</CODE> and <CODE>TimeTraj</CODE>
|
|
arrays. Default=1.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>MoveMode</CODE></TD>
|
|
<TD>mbbi</TD>
|
|
<TD>Defines the type of position information contained in
|
|
<CODE>M1Traj...M8Traj</CODE>. 0=<CODE>Relative</CODE>,
|
|
1=<CODE>Absolute</CODE>, 2=<CODE>Hydrid</CODE>.
|
|
Default=<CODE>Relative</CODE>. The MAXv and Ensemble support
|
|
does not yet handle Hybrid mode.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>M1Traj ... M8Traj</CODE></TD>
|
|
<TD>waveform, double</TD>
|
|
<TD>The displacements or absolute positions of each motor for each element
|
|
of the trajectory. No defaults.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>M1Move ... M8Move</CODE></TD>
|
|
<TD>bo</TD>
|
|
<TD>Flag defining whether each motor is to be moved during the trajectory.
|
|
0=<CODE>No</CODE>, 1=<CODE>Yes</CODE>. Default=<CODE>No</CODE>.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>Npulses</CODE></TD>
|
|
<TD>longout</TD>
|
|
<TD>Number of synchronization pulses to be output by the MM4005/XPS.
|
|
Default=200.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>StartPulses</CODE></TD>
|
|
<TD>longout</TD>
|
|
<TD>The trajectory element number where synchronization pulses will start.
|
|
Default=1.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>EndPulses</CODE></TD>
|
|
<TD>longout</TD>
|
|
<TD>The trajectory element number where synchronization pulses should end.
|
|
Default=<CODE>Nelements</CODE>. The SNL program sets
|
|
<CODE>EndPulses=Nelements</CODE> whenever <CODE>Nelements</CODE> is
|
|
changed, since this is what is normally desired. <CODE>EndPulses</CODE>
|
|
can be changed again after changing <CODE>Nelements</CODE> if
|
|
desired.</TD></TR>
|
|
|
|
<TR>
|
|
<TD><CODE>TimeMode</CODE></TD>
|
|
<TD>bo</TD>
|
|
<TD>The mode being used to define the time per trajectory element.
|
|
0=<CODE>Total</CODE> means that the total time for the trajectory is being
|
|
defined, and the <CODE>TimeTraj</CODE> array will be computed by setting
|
|
the execution time for each element = <CODE>Time/Nelements</CODE>.
|
|
1=<CODE>Per Element</CODE> means that the time per element has already
|
|
been loaded into the <CODE>TimeTraj</CODE> array. This mode permits each
|
|
element to have a different execution time. Default =
|
|
<CODE>Total</CODE>.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>Time</CODE></TD>
|
|
<TD>ao</TD>
|
|
<TD>Total trajectory execution time. Used when <CODE>TimeMode</CODE>=0.
|
|
Default=10.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>TimeTraj</CODE></TD>
|
|
<TD>waveform, double</TD>
|
|
<TD>The array containing the execution time per trajectory element. This
|
|
array is computed by the SNL program if
|
|
<CODE>TimeMode</CODE>=<CODE>Total</CODE>, and must be loaded by the user
|
|
if <CODE>TimeMode</CODE>=<CODE>Per Element</CODE>.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>Accel</CODE>(MM4005 and MAXv only)</TD>
|
|
<TD>ao</TD>
|
|
<TD>The acceleration time for the trajectory. Default=0.5 seconds.
|
|
<i>Currently, the Ensemble support gets this value from the motor
|
|
record.</i></TD></TR>
|
|
|
|
<TR> <TD><CODE>PulseDir</CODE> (Ensemble only)</TD> <TD>mbbo</TD> <TD>The
|
|
encoder direction in which output pulses will be generated. Choices are
|
|
0=<code>Both</code>, 1=<code>Pos</code>, and 2=<code>Neg</code>.
|
|
Default=<code>Both</code>.</TD></TR>
|
|
|
|
<TR>
|
|
<TD><CODE>PulseLenUS</CODE> (Ensemble only)</TD>
|
|
<TD>ao</TD>
|
|
<TD>The pulse length in microseconds. Default=25.</TD></TR>
|
|
|
|
<TR> <TD><CODE>PulseSrc</CODE> (Ensemble only)</TD> <TD>longout</TD>
|
|
<TD>The pulse source. This depends on the controller and
|
|
from where it gets its encoder signal. Normally, the value is 1 or 3.
|
|
Default=1.</TD></TR>
|
|
|
|
</TBODY>
|
|
</TABLE>
|
|
|
|
<P>The EPICS interface permits the motor positions for each element of the
|
|
trajectory to be defined in one of 3 ways. This flexibility can remove the
|
|
burden of converting absolute positions to displacements from the EPICS channel
|
|
access client and let the SNL program do the calculations. <CODE>MoveMode
|
|
</CODE>can have the following 3 values:</P>
|
|
<UL>
|
|
<LI><CODE>Relative</CODE>.
|
|
This mode maps directly to the way the MM4005 and XPS work internally.
|
|
Each trajectory element is a
|
|
displacement or distance for the motor to move during that element.
|
|
<LI><CODE>Absolute</CODE>.
|
|
In this mode
|
|
each trajectory element is an absolute motor position to which the controller
|
|
will move at each point in the trajectory. In practice the SNL program
|
|
computes an internal trajectory with <CODE>Nelements-1</CODE> elements where
|
|
<CODE>InternalTraj[i] = MnTraj[i+1]-MnTraj[i]</CODE>.
|
|
The SNL program drives all the motors to
|
|
the first point in the trajectory, waits for them to get there, and then
|
|
executes the internal trajectory. The disadvantage of
|
|
<CODE>Absolute</CODE> mode is that a new
|
|
trajectory needs to be downloaded and built each time the absolute position of
|
|
any motor in the trajectory is changed.
|
|
<LI><CODE>Hybrid</CODE>.
|
|
In this mode the
|
|
trajectory is defined in absolute coordinates, as in <CODE>Absolute</CODE>
|
|
mode. Again, an internal trajectory is computed from
|
|
<CODE>MnTraj[i+1]-MnTraj[i]</CODE>. However,
|
|
when the trajectory is executed the motors are <STRONG>not</STRONG> moved to
|
|
the position of the first point of the trajectory. Thus,
|
|
<CODE>Hybrid</CODE> mode permits a trajectory to
|
|
be defined in absolute coordinates, but executed as motions relative to the
|
|
current positions of the motors when the trajectory is executed. Thus the
|
|
motors can be moved using the EPICS motor record, and the trajectory executed
|
|
at a new absolute position without downloading new values to
|
|
<CODE>MnTraj</CODE> or rebuilding the trajectory. </LI>
|
|
</UL>
|
|
|
|
<P>Note that when programming <CODE>TimeTraj</CODE> in <CODE>Absolute</CODE> or
|
|
<CODE>Hybrid</CODE> mode <CODE>TimeTraj[i]</CODE> is the time to execute the
|
|
move from position <CODE>MnTraj[i]</CODE> to <CODE>MnTraj[i+1]</CODE>.</P>
|
|
|
|
<P>The MAXv and Ensemble currently do not support <CODE>Hybrid</CODE> mode.
|
|
MAXv may, and Ensemble always does, send the motor to a starting point that is
|
|
the acceleration distance from the start position, whether the trajectory mode
|
|
is <CODE>Absolute</CODE> or <CODE>Relative</CODE>. The acceleration distance is
|
|
AccelTime*velocity[0]/2, where AccelTime is the acceleration time, and
|
|
velocity[0] is the average velocity over the first trajectory segment.
|
|
Currently, the Ensemble support reads the acceleration time directly from the
|
|
motor record.
|
|
|
|
<P>The MM4005 requires the number of elements in a trajectory to be a multiple
|
|
of 4. This means that <CODE>Nelements</CODE>
|
|
should be a multiple of 4 in
|
|
<CODE>Relative</CODE> mode and a multiple of 4
|
|
plus 1 in <CODE>Absolute</CODE> or
|
|
<CODE>Hybrid</CODE> mode. However, this can be an
|
|
inconvenience for EPICS channel access clients. The SNL program works around
|
|
this restriction as follows. If
|
|
<CODE>Nelements</CODE> is not a multiple of 4 for
|
|
<CODE>MoveMode=Relative </CODE>or a multiple
|
|
of 4 plus 1 for
|
|
<CODE>MoveMode=Absolute</CODE> or
|
|
<CODE>Hybrid</CODE>, then up to 3 padding elements
|
|
are automatically added to the user defined trajectory to satisfy the
|
|
requirement. The padding elements always have a time of 0.1 seconds. The
|
|
displacements of the motors in these padding elements is computed to maintain
|
|
the same velocity as the last element in the original trajectory. Thus the
|
|
padding elements will cause the trajectory to execute for up to 0.3 seconds
|
|
longer than requested, and the motors will move slightly farther than requested.
|
|
However, there will be no velocity change, and hence no unexpected accelerations
|
|
during the padding elements.</P>
|
|
|
|
<P>The MM4000 has a concept of accelerating onto the trajectory, so that the time
|
|
per trajectory element will actually be longer than the specified times for the
|
|
first few and last few trajectory elements, as the motors accelerate and deccelerate.
|
|
This is typically normalized out during data processing by having a scaler channel
|
|
that measures the time (or integrated incident intensity) during each trajectory element.
|
|
|
|
<P>
|
|
The XPS does not do this acceleration automatically, rather the acceleration must be explicitly
|
|
defined in the trajectory file that is downloaded to the XPS. The XPS SNL program adds
|
|
one padding element at the beginning of the file and one padding element at the end of
|
|
the file. The first padding element is calculated to be the minimum time to accelerate
|
|
all of the motors from 0 to the velocity of the first actual trajectory element.
|
|
This time is calculated using an acceleration of 90% of the maximum allowed
|
|
acceleration for each axis (to avoid roundoff problems). It also calculates how far
|
|
each axis moves during this acceleration time.
|
|
Similarly the final padding element is calculated to be the minimum time to deccelerate
|
|
all of the motors from the velocity of the last actual trajectory element to 0.
|
|
These padding elements cause the actual range of motion of each of the motors
|
|
to be somewhat larger than the range in the trajectory itself. This means that trajectories
|
|
cannot execute right up to the software or hardware limits for an axis, because there
|
|
will not be room for the acceleration motion.
|
|
|
|
<P> The MAXv and Ensemble controllers also do not automatically accelerate onto
|
|
the trajectory. The SNL programs add an element to the beginning of the
|
|
trajectory and one (MAXv) or two (Ensemble) elements to the end. (Ensemble
|
|
always does this; MAXv does it if <code>AddAccelDecel=Yes</code>.) These
|
|
elements cause the actual range of motion of each of the motors to be somewhat
|
|
larger than the range in the trajectory itself. This means that trajectories
|
|
cannot execute right up to the software or hardware limits for an axis, because
|
|
there will not be room for the acceleration motion.
|
|
|
|
<P>
|
|
The number of trajectory elements, <CODE>Nelements </CODE>is limited as
|
|
follows.</P>
|
|
<UL>
|
|
<LI>The MM4005 allows a maximum of 2000 trajectory elements.
|
|
<li>The MAXv allows a maximum of 2500 trajectory elements.
|
|
<li>The Ensemble allows a maximum of 70 trajectory elements as delivered, but
|
|
its configuration can be modified to support up to 40,000 elements.
|
|
|
|
<LI>Channel access on EPICS 3.13 is limited to 2000 points, since it has a
|
|
16,000 byte limit, and all arrays are double precision, requiring 8 bytes
|
|
per element. In EPICS 3.14, the number of points Channel Access can send
|
|
is the environment variable <code>EPICS_CA_MAX_ARRAY_BYTES</code> divided
|
|
by eight.
|
|
|
|
<LI>There are 9 double precision arrays that are dimensioned
|
|
<CODE>MAX_ELEMENTS</CODE> in the SNL program, and 9 waveform records
|
|
(<CODE>MnTraj</CODE> and <CODE>TimeTraj</CODE>) that are dimensioned
|
|
<CODE>NELM</CODE> in the database. If 2000 points are allowed then the total
|
|
memory used in the IOC is 2000*9*8*2 = 288,000 bytes. This is a significant
|
|
amount of memory for an IOC. <CODE>MAX_ELEMENTS</CODE> is presently
|
|
defined to be 2000 in the SNL programs. This value can be changed (up to
|
|
2000 for the MM4005) and the SNL program recompiled. The value of
|
|
<CODE>NELM</CODE> can be set to any value up to <CODE>MAX_ELEMENTS</CODE> when
|
|
the database is loaded. </LI>
|
|
</UL>
|
|
|
|
<P>The number of output pulses, <CODE>Npulses</CODE> is limited as follows.</P>
|
|
<UL>
|
|
<LI>The MM4005 allows a maximum of 2000 output pulses.
|
|
|
|
<li>The MAXv can only output pulses at trajectory points, so
|
|
<CODE>Npulses</CODE> is ignored.
|
|
|
|
<li>The Ensemble controller can send output pulses equally spaced in position,
|
|
and imposes no limit on the number of such pulses. Some Ensemble controllers
|
|
(ML, HPe, and HLe) can also generate output pulses at user-specified
|
|
positions. Aerotech documentation does not specify the maximum number of
|
|
positions.
|
|
|
|
<LI>Channel access R3.13 is limited to 2000 points, since it has a 16,000 byte
|
|
limit, and all arrays are double precision, requiring 8 bytes per element.
|
|
In EPICS 3.14, the number of points Channel Access can send
|
|
is the environment variable <code>EPICS_CA_MAX_ARRAY_BYTES</code> divided
|
|
by eight.
|
|
|
|
<LI>There are 16 double precision arrays that are dimensioned.
|
|
<CODE>MAX_PULSES</CODE> in the SNL program, and 16 waveform records
|
|
(<CODE>MnActual</CODE> and <CODE>MnError</CODE>) that are dimensioned
|
|
<CODE>NPULSE</CODE> in the database. If 2000 points are allowed then the total
|
|
memory used in the IOC is 2000*16*8*2 = 512,000 bytes. This is a significant
|
|
amount of memory for an IOC. <CODE>MAX_PULSES</CODE> is presently defined
|
|
to be 2000 in the SNL program. This value can be changed (up to 2000 for the MM4005) or
|
|
and the SNL program recompiled. The value of <CODE>NPULSE</CODE>
|
|
<STRONG>must</STRONG> be set to exactly the value of <CODE>MAX_PULSES</CODE>
|
|
when the database is loaded. </LI>
|
|
</UL>
|
|
|
|
<P> </P>
|
|
<H2><A name="Building a Trajectory">
|
|
Building a Trajectory</A></H2>
|
|
<P>After a trajectory has been defined by setting the values of the PVs
|
|
described in the previous section it must be built before it can be executed.
|
|
Building the trajectory consists of downloading it to the controller and checking it
|
|
for errors such as excess velocities or accelerations.</P>
|
|
<P>
|
|
The following table describes the EPICS PVs used for building a
|
|
trajectory.</P>
|
|
<TABLE border=1>
|
|
<TBODY>
|
|
<TR>
|
|
<TD><STRONG>PV Name</STRONG></TD>
|
|
<TD><STRONG>Record Type</STRONG></TD>
|
|
<TD><STRONG>Description</STRONG></TD></TR>
|
|
<TR>
|
|
<TD><CODE>Build</CODE></TD>
|
|
<TD>busy</TD>
|
|
<TD>Setting this PV to 1 will build the trajectory, downloading it to the
|
|
controller. It will be set back to 0 automatically when the build is
|
|
complete.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>BuildState</CODE></TD>
|
|
<TD>mbbi</TD>
|
|
<TD>The trajectory build state. 0=<CODE>Done</CODE>,
|
|
1=<CODE>Busy</CODE>.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>BuildStatus</CODE></TD>
|
|
<TD>mbbi</TD>
|
|
<TD>The trajectory build status. 0=<CODE>Undefined</CODE>,
|
|
1=<CODE>Success</CODE>, 2=<CODE>Failure</CODE>.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>BuildMessage</CODE></TD>
|
|
<TD>stringout</TD>
|
|
<TD>Progress messages while the build is in progress and error message if
|
|
<CODE>BuildStatus=Failure</CODE>.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>M1MDVS ... M8MDVS</CODE> (MM4005 only)</TD>
|
|
<TD>ao</TD>
|
|
<TD>The maximum change in velocity allowed between trajectory elements.
|
|
This value can be set. These values are read from the MM4005 when the SNL
|
|
program starts, so the current values can be seen. The acronym is Maximum
|
|
Delta Velocity Set.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>M1MDVA ... M8MDVA</CODE> (MM4005 only)</TD>
|
|
<TD>ao</TD>
|
|
<TD>The actual maximum change in velocity between trajectory elements.
|
|
This value is read from the MM4005 after the trajectory is built.
|
|
<CODE>MnMDVE</CODE> gives the specific trajectory element in which this
|
|
maximum change in velocity occurred. If <CODE>MnMDVA</CODE> is greater
|
|
than <CODE>MnMDVS</CODE> then the trajectory build will fail. The acronym
|
|
is Maximum Delta Velocity Actual. Read-Only.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>M1MDVE ... M8MDVE</CODE> (MM4005 only)</TD>
|
|
<TD>longout</TD>
|
|
<TD>The trajectory element number where <CODE>MnMDVA</CODE> occurs. The
|
|
acronym is Maximum Delta Velocity Element. Read-Only.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>M1MVA ... M8MVA</CODE></TD>
|
|
<TD>ao</TD>
|
|
<TD>The actual maximum velocity. This value is read from the controller after
|
|
the trajectory is built. <CODE>MnMVE</CODE> gives the specific trajectory
|
|
element in which this maximum velocity occurred (MM4005 only).
|
|
If <CODE>MnMVA</CODE> is
|
|
greater than the maximum velocity allowed for this motor then the build
|
|
will fail. The acronym is Maximum Velocity Actual. Read-Only.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>M1MVE ... M8MVE</CODE> (MM4005 only)</TD>
|
|
<TD>longout</TD>
|
|
<TD>The trajectory element number where <CODE>MnMVA</CODE> occurs. The
|
|
acronym is Maximum Velocity Element. Read-Only.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>M1MAA ... M8MAA</CODE></TD>
|
|
<TD>ao</TD>
|
|
<TD>The actual maximum acceleration. This value is read from the controller
|
|
after the trajectory is built. <CODE>MnMAE</CODE> gives the specific
|
|
trajectory element in which this maximum acceleration occurred (MM4005 only). If
|
|
<CODE>MnMVA</CODE> is greater than the maximum acceleration allowed for
|
|
this motor then the build will fail. The acronym is Maximum Acceleration
|
|
Actual. Read-Only. (<i>The Ensemble support sets this PV to 0.</i>)</TD></TR>
|
|
<TR>
|
|
<TD><CODE>M1MAE ... M8MAE</CODE> (MM4005 only)</TD>
|
|
<TD>longout</TD>
|
|
<TD>The trajectory element number where <CODE>MnMAA</CODE> occurs. The
|
|
acronym is Maximum Acceleration Element. Read-Only.</TD></TR>
|
|
|
|
<TR>
|
|
<TD><CODE>AddAccelDecel</CODE> (MAXv only)</TD>
|
|
<TD>bo</TD>
|
|
|
|
<TD>Tell software whether or not to add trajectory elements for accel and
|
|
decel. Read-Write.</TD></TR>
|
|
|
|
<TR>
|
|
<TD><CODE>M1Start ... M8Start</CODE> (MAXv, Ensemble only)</TD>
|
|
<TD>bo</TD>
|
|
|
|
<TD>Actual start position of motor, including any distance needed to
|
|
accelerate onto the trajectory. Read-Only.</TD></TR>
|
|
|
|
</TBODY>
|
|
</TABLE>
|
|
|
|
<P>
|
|
Channel access clients should do the following to build a trajectory:</P>
|
|
<UL>
|
|
<LI>Set <CODE>Build</CODE>=1
|
|
<LI>Repeatedly read <CODE>Build</CODE>, wait for it to go to
|
|
0=<CODE>Done</CODE>.
|
|
<LI>When <CODE>Build=Done</CODE> check <CODE>BuildStatus</CODE>. If it is not
|
|
1=<CODE>Success</CODE>, then something went wrong.
|
|
<LI><CODE>BuildMessage</CODE> can be used to determine what the error was,
|
|
although this will probably require a human rather than a program. </LI>
|
|
</UL>
|
|
|
|
<P>
|
|
If the build fails then it is useful to look at the
|
|
<CODE>trajectoryScanDebug.adl</CODE> MEDM screen to examine the maximum velocity
|
|
and acceleration values. See if one or more motors is being commanded to move
|
|
too fast.</P>
|
|
|
|
<P> </P>
|
|
<H2><A name="Executing a Trajectory">
|
|
Executing a Trajectory</A></H2>
|
|
|
|
<P>After a trajectory has been successfully built it can be executed. The
|
|
trajectory execution consists of the following steps:</P>
|
|
<UL>
|
|
<LI>Remember the initial positions of all the motors.
|
|
|
|
<LI>Move to the start position defined by <CODE>MnTraj[0]</CODE>. This is
|
|
only done if <CODE>MoveMode=Absolute</CODE>. (MAXv moves to
|
|
a start position if <CODE>MoveMode=Absolute</CODE> or if
|
|
<CODE>AddAccelDecel=Yes</CODE>. Ensemble always moves to a start position,
|
|
because it always adds a accelerate-onto-trajectory element.)
|
|
|
|
<LI>Trigger the detector start PV.
|
|
<LI>Execute the trajectory in either <CODE>Real</CODE> or
|
|
<CODE>Simulate</CODE> mode, with the execution time scaled by
|
|
<CODE>TimeScale</CODE>. Poll during execution and post channel access monitors
|
|
for the current element being executed, for the current positions of the
|
|
motors and for any errors.
|
|
<LI>When the trajectory is complete:
|
|
<UL>
|
|
<LI>Trigger the detector stop PV.
|
|
<LI>Command the EPICS motors to move to the final position in the trajectory. This does
|
|
not actually move the motors, but syncs the EPICS motor VAL and RBV fields
|
|
to the actual motor positions.
|
|
</UL>
|
|
</UL>
|
|
|
|
<P>
|
|
The following table describes the EPICS PVs used for executing a
|
|
trajectory.</P>
|
|
<TABLE border=1>
|
|
<TBODY>
|
|
<TR>
|
|
<TD><STRONG>PV Name</STRONG></TD>
|
|
<TD><STRONG>Record Type</STRONG></TD>
|
|
<TD><STRONG>Description</STRONG></TD></TR>
|
|
<TR>
|
|
<TD><CODE>Execute</CODE></TD>
|
|
<TD>busy</TD>
|
|
<TD>Setting this PV to 1 will execute the trajectory, performing the steps
|
|
described above. It will be set back to 0 automatically when the execution
|
|
is complete.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>ExecState</CODE></TD>
|
|
<TD>mbbi</TD>
|
|
<TD>The trajectory execution state. 0=<CODE>Done</CODE>, 1=<CODE>Move
|
|
Start</CODE>, 2=<CODE>Executing</CODE>, 3=<CODE>Flyback</CODE>.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>ExecStatus</CODE></TD>
|
|
<TD>mbbi</TD>
|
|
<TD>The trajectory execute status. 0=<CODE>Undefined</CODE>,
|
|
1=<CODE>Success</CODE>, 2=<CODE>Failure</CODE>, 3=<CODE>Abort</CODE>,
|
|
4=<CODE>Timeout</CODE>.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>ExecMessage</CODE></TD>
|
|
<TD>stringout</TD>
|
|
<TD>Progress messages while the execution is in progress and error message
|
|
if <CODE>ExecStatus</CODE> is not <CODE>Success</CODE>.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>SimMode</CODE> (MM4005 only)</TD>
|
|
<TD>bo</TD>
|
|
<TD>Simulation mode. 0=<CODE>Real</CODE>, 1=<CODE>Simulate</CODE>. The
|
|
MM4005 can execute a trajectory in simulation mode, not actually moving
|
|
any motors. Default=<CODE>Real</CODE>.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>TimeScale</CODE> (MM4005, MAXv, and Ensemble only)</TD>
|
|
<TD>ao</TD>
|
|
<TD>Scaling time for the trajectory execution. Although a trajectory is
|
|
defined with a particular time per element, the execution time can be
|
|
scaled from this value. <CODE>TimeScale</CODE> can range from .01 (100
|
|
times faster) to 100 (100 times slower). Default=1.0</TD></TR>
|
|
<TR>
|
|
<TD><CODE>Abort</CODE></TD>
|
|
<TD>bo</TD>
|
|
<TD>Setting <CODE>Abort</CODE>=1 will immediately abort any motion on the
|
|
controller. It sends the AB command to the MM4005 which turns off the motor
|
|
power to all motors. To recover from this it is usually necessary to
|
|
re-home the motors, and to rebuild the trajectory at least twice before it
|
|
will succeed. <CODE>Abort</CODE> is set back to 0 automatically.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>M1Current ... M8Current</CODE></TD>
|
|
<TD> </TD>
|
|
<TD>The current position of each motor. These values are updated and
|
|
posted during execution of the trajectory. They are <STRONG>not</STRONG>
|
|
continuously updated when the trajectory is not executing because that
|
|
could interfere with EPICS motor records. This conflict will be eliminated
|
|
in a future release of the MM4005 support for the EPICS motor
|
|
record.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>OutBitNum</CODE> (MAXv and Ensemble only)</TD>
|
|
<TD>longout</TD>
|
|
|
|
<TD>If this PV is non-negative, it tells the MAXv which digital
|
|
output bit on which to send output pulses. For the Ensemble, it merely
|
|
enables output pulses if the number is in the range [0,15].</TD></TR>
|
|
|
|
<TR>
|
|
<TD><CODE>InBitNum</CODE> (MAXv only)</TD>
|
|
<TD>longout</TD>
|
|
|
|
<TD>If this PV is non-negative, it specifies the digital input bit that the
|
|
controller will monitor for a rising edge which tells it to begin the
|
|
trajectory.</TD></TR>
|
|
|
|
|
|
|
|
|
|
</TBODY>
|
|
</TABLE>
|
|
|
|
<P>
|
|
Channel access clients should do the following to execute a trajectory:</P>
|
|
<UL>
|
|
<LI>Set <CODE>Execute</CODE>=1
|
|
<LI>Repeatedly read <CODE>Execute</CODE>, wait for it to go to
|
|
0=<CODE>Done</CODE>.
|
|
<LI>When Execute=<CODE>Done</CODE> check ExecStatus. If it is not
|
|
1=<CODE>Success</CODE>, then something went wrong.
|
|
<LI><CODE>ExecMessage</CODE> can be used to determine what the error was,
|
|
although this will probably require a human rather than a program. </LI>
|
|
</UL>
|
|
|
|
<P>The execution can fail because the velocity or acceleration is too large,
|
|
even if the build succeeded, if <CODE>TimeScale</CODE> is less than 1.0.</P>
|
|
|
|
<P> </P>
|
|
<H2><A name="Reading Back a Trajectory">
|
|
Reading Back a Trajectory</A></H2>
|
|
|
|
<P>After a trajectory has been executed it is possible to read back from the
|
|
MM4005 or XPS the theoretical and actual positions of the motors when each
|
|
synchronization pulse was output. The EPICS interface presents this information
|
|
as the actual positions and the following errors (actual position minus
|
|
theoretical position) since these are usually of most interest to the user.
|
|
Obviously the theoretical position can be computed from the actual position and
|
|
the following error.</P>
|
|
|
|
<P>
|
|
Reading back this information from the MM4005 (but not from the XPS) is rather slow,
|
|
but in many cases this does not
|
|
need to be done for each scan. Once it is established that the following errors
|
|
are small enough it is possible to execute scans without reading back from the
|
|
MM4005 each time. The readback time is determined by the speed of the
|
|
communications interface to the MM4005. Each point returned from the MM4005 is
|
|
about 200 characters. Using RS-232 at 19,200 baud this requires 0.1 seconds per
|
|
point, where the number of points is equal to the number of output pulses. This
|
|
is thus 30 seconds for a scan with 300 output pulses. The XPS uses FTP over Ethernet
|
|
to read the "Gathering.dat" file containing the theoretical and actual motor
|
|
positions. The time to copy this file is very short, even for a large number of points.</P>
|
|
|
|
<P>
|
|
The MAXv controller cannot read back trajectory data. The Ensemble controller
|
|
can record actual motor positions periodically during a trajectory. Currently,
|
|
this is a compile-time option. (See <code>#define USE_SCOPE 1</code> in
|
|
EnsembleTrajectoryScan.st.)
|
|
|
|
<P>
|
|
The following table describes the EPICS PVs used for reading back a
|
|
trajectory.</P>
|
|
<TABLE border=1>
|
|
<TBODY>
|
|
<TR>
|
|
<TD><STRONG>PV Name</STRONG></TD>
|
|
<TD><STRONG>Record Type</STRONG></TD>
|
|
<TD><STRONG>Description</STRONG></TD></TR>
|
|
<TR>
|
|
<TD><CODE>Readback</CODE></TD>
|
|
<TD>busy</TD>
|
|
<TD>Setting this PV to 1 will read back the results of the
|
|
trajectory motion from the controller. It will be set back to 0 automatically
|
|
when the readback is complete.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>ReadState</CODE></TD>
|
|
<TD>mbbi</TD>
|
|
<TD>The readback state. 0=<CODE>Done</CODE>,
|
|
1=<CODE>Busy</CODE>.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>ReadStatus</CODE></TD>
|
|
<TD>mbbi</TD>
|
|
<TD>The readback status. 0=<CODE>Undefined</CODE>,
|
|
1=<CODE>Success</CODE>, 2=<CODE>Failure</CODE>.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>ReadMessage</CODE></TD>
|
|
<TD>stringout</TD>
|
|
<TD>Progress messages while the readback is in progress and
|
|
error message if <CODE>ReadStatus</CODE> is not
|
|
<CODE>Success</CODE>.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>Nactual</CODE></TD>
|
|
<TD>longout</TD>
|
|
<TD>The actual number of pulses output by the controller. This value
|
|
is normally equal to <CODE>Npulses</CODE>, but it could be less if a
|
|
trajectory did not complete.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>M1Actual ... M8Actual</CODE></TD>
|
|
<TD>waveform, double</TD>
|
|
<TD>The actual position of the motor when each pulse was output
|
|
by the contoller during the trajectory scan.</TD></TR>
|
|
<TR>
|
|
<TD><CODE>M1Error ... M8Error</CODE></TD>
|
|
<TD>waveform, double</TD>
|
|
<TD>The following error of the motor when each pulse was output
|
|
by the controller during the trajectory scan. The following error is defined
|
|
as the actual position minus the theoretical position. </TD></TR>
|
|
</TBODY>
|
|
</TABLE>
|
|
|
|
<P>Channel access clients should do the following to read back a trajectory:</P>
|
|
<UL>
|
|
<LI>Set <CODE>Readback</CODE>=1
|
|
<LI>Repeatedly read <CODE>Readback</CODE>, wait for it to go to
|
|
0=<CODE>Done.</CODE>
|
|
<LI>When <CODE>Readback=Done</CODE> check <CODE>ReadStatus.</CODE> If it is
|
|
not 1=<CODE>Success</CODE>, then something went wrong.
|
|
<LI><CODE>ReadMessage </CODE>can be used to determine what the error was,
|
|
although this will probably require a human rather than a program. </LI>
|
|
</UL>
|
|
|
|
<P>Note that the readback command reads the global trace buffer of the MM4005.
|
|
It can be used to read back this trace buffer even if the previous operation was
|
|
not a trajectory execution. This can be useful for debugging operations in
|
|
general.</P>
|
|
|
|
<P> </P>
|
|
<H2><A name="Interaction with EPICS Motor Records">
|
|
Interaction with EPICS Motor Records</A></H2>
|
|
|
|
<P>The trajectory scanning does not use the EPICS motor records, but rather
|
|
talks directly to the controller. In order to keep the motor records in
|
|
sync with the actual motor positions the SNL program always sends the motors
|
|
to the final position in the trajectory scan, i.e. the positions where the motors actually
|
|
are, after a trajectory execution is complete. This should not result in any actual
|
|
motor motion (except for small following errors), but serves to resynchronize the
|
|
EPICS motor VAL and RBV fields with the actual motor positions.
|
|
One should not move any
|
|
motors on the involved controller with the EPICS motor records
|
|
while a trajectory scan is in progress. For the MAXv, one
|
|
<b>must</b> not move any motor on the involved controller.</P>
|
|
|
|
<P>
|
|
When a motion is aborted with the <CODE>Abort</CODE> PV it will be necessary
|
|
to home the motors and synchronize the motor records with the actual positions
|
|
of the motors. (This is not necessary for the MAXv and Ensemble controllers.)</P>
|
|
|
|
<P> </P>
|
|
<H2><A name="Communication with the controller">
|
|
Communication with the controller</A></H2>
|
|
|
|
<P>
|
|
The communication with the MM4005 uses asyn. It can be used with either the
|
|
RS-232 or GPIB interfaces. Debugging can be enabled with the
|
|
<CODE>asynSetTraceMask</CODE> and <CODE>asynSetTraceIOMask</CODE> commands.
|
|
Communication with the XPS also uses asyn over a TCP/IP socket connection. Debugging
|
|
can be enabled and disabled in the same way.
|
|
|
|
<P>
|
|
The timeout for communication with the MM4005 is set to 30 seconds, because
|
|
some commands can take a very long time to response. This was found to be necessary to allow for
|
|
the long time it takes the MM4005 to respond to the TB command after a VC
|
|
command is issued when verifying the trajectory. However, it would probably be
|
|
better to determine empirically how long it takes the MM4005 to verify
|
|
trajectories as a function of <CODE>Nelements</CODE> and <CODE>Npulses
|
|
</CODE>and have the SNL program wait that long after sending the VC command and
|
|
before sending the TB command. These measurements have not been done yet.</P>
|
|
|
|
<P> </P>
|
|
<H2><A name="Hardware Notes">
|
|
Hardware Notes</A></H2>
|
|
<P>
|
|
The synchronization output pulses from the MM4005 are provided on pin 12 of
|
|
the DB-25 Auxilliary Connector.
|
|
The synchronization output pulses from the XPS are provided on pin 12 of
|
|
the GPIO2 connector. We have found it convenient to make DB-25 connectors
|
|
with a short BNC or LEMO pigtail coming from these pins. The pulse outputs from both
|
|
the MM4005 and XPS
|
|
are open-collector circuits. The maximum rating in both cases is 30V and 40 mA.</P>
|
|
|
|
<P>
|
|
When using the pulse output as the channel-advance input of the Struck 7201
|
|
or SIS 380x multi-scaler some modifications are required. The SIS 380x manual
|
|
states that with the LEMO TTL input configuration the inputs are pulled up to
|
|
+5V with 1K Ohm resistors in a resistor pack. For our module the factory
|
|
configuration was actually a 4.7K Ohm resistor pack. These resistors did pull
|
|
the open-collector output up to +5V. However, when driving the cable over a long
|
|
distance (~80 feet) the rise time of the signal was quite slow, about 8
|
|
microseconds to go from 0V to the TTL threshold. This slow rise time caused the
|
|
SIS 380x to double count the channel advance signal most of the time. By
|
|
replacing the 4.7K Ohm resistor pack with a 200 Ohm pull-up resistor pack the
|
|
rise time was reduced to about 2 microseconds, and the module does not double
|
|
count. 200 Ohms is within the spec of the MM4005 and XPS, since it will result in a
|
|
current of 5V/200 Ohm = 25 mA, which is less than the 40 mA maximum.</P>
|
|
|
|
<P>The synchronization output pulses from the MAXv are sent on one of the pins
|
|
<code>IO0</code> - <code>IO15</code>, selected with the PV
|
|
<code>OutBitNum</code>, which must be in the range[0,15] inclusive. If the
|
|
number is outside this range, no output pulses will be generated. The MAXv is
|
|
able to start a trajectory on the rising edge of an input pulse, selected by the
|
|
PV <code>InBitNum</code>, with the same range. If <code>InBitNum</code> is
|
|
outside this range, the controller will start the trajectory as soon as it has
|
|
been loaded. These signals are available from the 50-pin SCSI connector on the
|
|
front panel of the MAXv.
|
|
|
|
<P>The synchronization output pulses from the Ensemble are sent on the "Auxiliary
|
|
Marker Output". Different controller models have different connectors and pin
|
|
numbers for this signal. This signal is RS422. Some Ensemble controllers
|
|
implement RS422 in such a way that the differential signals can be used as
|
|
complementary TTL signals.
|
|
|
|
<P>The Ensemble controller must be prepared with the AeroBasic program
|
|
<code>motor/motorApp/AerotechSrc/doCommand.ab</code>. You must copy
|
|
<code>doCommand.ab</code> to into the user-file directory of Aerotech's
|
|
<i>Motion Composer</i> program, load it into <i>Motion Composer</i>, and compile
|
|
it to produce the file <code>doCommand.bcx</code>. This file must be copied to
|
|
the controller, so it can be executed immediately when EnsembleTrajectoryScan.st
|
|
sends the command <code>PROGRAM RUN 1 "doCommand.bcx"</code>. The controller
|
|
also must be configured (using Aerotech's <i>Configuration Manager</i>) to
|
|
increase the number of global integers and doubles. For N trajectory points,
|
|
the number of global doubles (the <code>GlobalDoubles</code> parameter) must be
|
|
at least (N+3)*3 (for one motor), and the number of global integers (the
|
|
<code>GlobalIntegers</code> parameter) must be at least N+50. Also, the
|
|
controller must use the same units as the motor record that talks to it.
|
|
|
|
<P> </P>
|
|
<H2><A name=Installation>
|
|
Installation</A></H2>
|
|
<P>
|
|
The source files for trajectory scanning are in the synApps
|
|
<A href="https://github.com/epics-modules/motor">motor module
|
|
</A>, in the motorApp/ tree.
|
|
</P>
|
|
<PRE>
|
|
NewportSrc/MM4005_trajectoryScan.st
|
|
NewportSrc/XPS_trajectoryScan.st
|
|
OmsSrc/MAX_trajectoryScan.st
|
|
AerotechSrc/EnsembleTrajectoryScan.st
|
|
Db/trajectoryScan.db
|
|
op/adl/trajectoryScan.adl
|
|
op/adl/trajectoryScanDebug.adl
|
|
op/adl/trajectoryPlot.adl
|
|
op/adl/MAX_trajectory*.adl
|
|
</PRE>
|
|
|
|
<P> </P>
|
|
<H2><A name="Loading the database">
|
|
Loading the database</A></H2>
|
|
<P>
|
|
The database file is called <CODE>trajectoryScan.db.</CODE>.
|
|
This database is completely general for the MM4005 and XPS, it makes no
|
|
assumptions about the motors defined on particular axis. Thus it can be used
|
|
with the Newport diffractometer or any other set of up to 8 motors.
|
|
It takes the following macro parameters:
|
|
<TABLE style="TEXT-ALIGN: left" cellSpacing=2 cellPadding=2 border=1>
|
|
<TBODY>
|
|
<TR>
|
|
<TH>Macro parameter</TH>
|
|
<TH>Description</TH>
|
|
</TR>
|
|
<TR>
|
|
<TD><CODE>$(P)</CODE></TD>
|
|
<TD>PV name prefix</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD><CODE>$(R)</CODE></TD>
|
|
<TD>PV base record name</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD><CODE>$(NAXES)</CODE></TD>
|
|
<TD>Number of axes to be used. 6 for our Newport diffractometers.</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD><CODE>$(NELM)</CODE></TD>
|
|
<TD>Maximum trajectory elements</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD><CODE>$(NPULSE)</CODE></TD>
|
|
<TD>Maximum number of output pulses</TD>
|
|
</TR>
|
|
</TBODY>
|
|
</TABLE>
|
|
|
|
<P> </P>
|
|
<H2><A name="Starting the SNL program">
|
|
Starting the SNL program</A></H2>
|
|
<P>
|
|
There are different SNL programs for the different controllers. The MM4005 SNL program
|
|
is defined as follows:
|
|
<PRE>
|
|
program MM4005_trajectoryScan("P=13IDC:,R=traj1,M1=M1,M2=M2,M3=M3,M4=M4,M5=M5,M6=M6,M7=M7,M8=M8,PORT=serial1")
|
|
</PRE>
|
|
The parameters are defined as follows:
|
|
<TABLE style="TEXT-ALIGN: left" cellSpacing=2 cellPadding=2 border=1>
|
|
<TBODY>
|
|
<TR>
|
|
<TH>Macro parameter</TH>
|
|
<TH>Description</TH>
|
|
</TR>
|
|
<TR>
|
|
<TD><CODE>P</CODE></TD>
|
|
<TD>PV name prefix</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD><CODE>R</CODE></TD>
|
|
<TD>PV base record name</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD><CODE>M1-M8</CODE></TD>
|
|
<TD>EPICS motor record names for axes 1-8.</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD><CODE>PORT</CODE></TD>
|
|
<TD>asyn port name for the RS-232 or GPIB port connected to the MM4005</TD>
|
|
</TR>
|
|
</TBODY>
|
|
</TABLE>
|
|
|
|
<P>
|
|
The XPS SNL program is defined as follows:
|
|
<PRE>
|
|
program XPS_trajectoryScan("P=13BMC:,R=traj1,IPADDR=164.54.160.34,PORT=5001,"
|
|
"USERNAME=Administrator,PASSWORD=Administrator,"
|
|
"M1=m1,M2=m2,M3=m3,M4=m4,M5=m5,M6=m6,M7=m7,M8=m8,"
|
|
"GROUP=g1,"
|
|
"P1=p1,P2=p2,P3=p3,P4=p4,P5=p5,P6=p6,P7=p7,P8=p8")
|
|
|
|
</PRE>
|
|
The parameters are defined as follows:
|
|
<TABLE style="TEXT-ALIGN: left" cellSpacing=2 cellPadding=2 border=1>
|
|
<TBODY>
|
|
<TR>
|
|
<TH>Macro parameter</TH>
|
|
<TH>Description</TH>
|
|
<TR>
|
|
<TD><CODE>P</CODE></TD>
|
|
<TD>PV name prefix</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD><CODE>R</CODE></TD>
|
|
<TD>PV base record name</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD><CODE>IPADDR</CODE></TD>
|
|
<TD>IP address of the XPS. Can be an IP name if the IOC supports DNS.</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD><CODE>PORT</CODE></TD>
|
|
<TD>IP port number that XPS uses for socket connections</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD><CODE>USERNAME</CODE></TD>
|
|
<TD>The user name to use to login to XPS for FTP</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD><CODE>PASSWORD</CODE></TD>
|
|
<TD>The password for the USERNAME account for FTP</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD><CODE>M1-M8</CODE></TD>
|
|
<TD>EPICS motor record names for axes 1-8.</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD><CODE>GROUP</CODE></TD>
|
|
<TD>The name of the MultiAxes group for the motors to be moved</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD><CODE>P1-P8</CODE></TD>
|
|
<TD>XPS positioner names for axes 1-8 in this GROUP</TD>
|
|
</TR>
|
|
</TBODY>
|
|
</TABLE>
|
|
|
|
|
|
|
|
|
|
<P>The MAXv SNL program
|
|
is defined as follows:
|
|
<PRE>
|
|
program MAX_trajectoryScan("P=13IDC:,R=traj1,M1=m1,M2=m2,M3=m3,M4=m4,M5=m5,M6=m6,M7=m7,M8=m8,PORT=none")
|
|
</PRE>
|
|
The parameters are defined as follows:
|
|
<TABLE style="TEXT-ALIGN: left" cellSpacing=2 cellPadding=2 border=1>
|
|
<TBODY>
|
|
<TR>
|
|
<TH>Macro parameter</TH>
|
|
<TH>Description</TH>
|
|
</TR>
|
|
<TR>
|
|
<TD><CODE>P</CODE></TD>
|
|
<TD>PV name prefix</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD><CODE>R</CODE></TD>
|
|
<TD>PV base record name</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD><CODE>M1-M8</CODE></TD>
|
|
<TD>EPICS motor record names for axes 1-8. You can specify fewer than eight motors, but you can't choose an arbitrary
|
|
motor ordering, and you can't skip any motors.</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD><CODE>PORT</CODE></TD>
|
|
<TD>Not used. The MAXv trajectory support talks directly to the driver.</TD>
|
|
</TR>
|
|
</TBODY>
|
|
</TABLE>
|
|
|
|
<P>The Ensemble SNL program
|
|
is defined as follows:
|
|
<PRE>
|
|
program EnsembleTrajectoryScan("P=13IDC:,R=traj1,M1=m1,M2=m2,M3=m3,M4=m4,M5=m5,M6=m6,M7=m7,M8=m8,PORT=tcp1")
|
|
</PRE>
|
|
The parameters are defined as follows:
|
|
<TABLE style="TEXT-ALIGN: left" cellSpacing=2 cellPadding=2 border=1>
|
|
<TBODY>
|
|
<TR>
|
|
<TH>Macro parameter</TH>
|
|
<TH>Description</TH>
|
|
</TR>
|
|
<TR>
|
|
<TD><CODE>P</CODE></TD>
|
|
<TD>PV name prefix</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD><CODE>R</CODE></TD>
|
|
<TD>PV base record name</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD><CODE>M1-M8</CODE></TD>
|
|
<TD>EPICS motor record names for axes 1-8. Note that only the first motor actually is used.</TD>
|
|
</TR>
|
|
<TR>
|
|
<TD><CODE>PORT</CODE></TD>
|
|
<TD>asyn port name for the connection to the Ensemble. This is the port name specified
|
|
as the second argument in the command <code>EnsembleAsynConfig(0, "tcp1", 0, 1, 50, 1000)</code>.
|
|
</TD>
|
|
</TR>
|
|
</TBODY>
|
|
</TABLE>
|
|
|
|
|
|
<P> </P>
|
|
<H2><A name="Startup script">
|
|
Startup script</A></H2>
|
|
<H3>XPS</H3>
|
|
The following is an example of the lines from a startup script on a Linux system
|
|
to load <CODE>trajectoryScan.db</CODE> and start the sequencer for an XPS system.
|
|
Note that the <CODE>dbLoadRecords</CODE> and <CODE>seq</CODE> commands are shown on multiple
|
|
lines here for clarity, but they must each actually be on a single long line.
|
|
<PRE>
|
|
# Database for trajectory scanning with the XPS
|
|
dbLoadRecords("$(MOTOR)/motorApp/Db/trajectoryScan.db",
|
|
"P=13BMC:,R=traj1,NAXES=6,NELM=2000,NPULSE=2000")
|
|
|
|
iocInit
|
|
|
|
dbpf("13BMC:traj1DebugLevel","1")
|
|
seq(&XPS_trajectoryScan, "P=13BMC:,R=traj1,M1=m33,M2=m34,M3=m35,M4=m36,M5=m37,M6=m38,
|
|
IPADDR=164.54.160.124,PORT=5001,GROUP=GROUP1,
|
|
P1=PHI,P2=KAPPA,P3=OMEGA,P4=PSI,P5=2THETA,P6=NU")
|
|
</PRE>
|
|
|
|
<H3>MM4005</H3>
|
|
The following is an example of the lines from a startup script on a
|
|
vxWorks system to load <CODE>trajectoryScan.db</CODE> and start the sequencer
|
|
for a vxWorks system.
|
|
|
|
<PRE>
|
|
# Database for trajectory scanning with the MM4005
|
|
dbLoadRecords("$(CARS)/CARSApp/Db/trajectoryScan.db", "P=13IDC:,R=traj1,NAXES=6,NELM=2000,NPULSE=2000")
|
|
|
|
iocInit
|
|
|
|
# Trajectory scanning with MM4005
|
|
seq(&MM4005_trajectoryScan, "P=13IDC:, R=traj1, M1=m25,M2=m26,M3=m27,M4=m28,M5=m29,M6=m30,M7=m31,M8=m32,PORT=serial13")
|
|
|
|
</PRE>
|
|
|
|
<H3>MAXv</H3>
|
|
|
|
The following is an example of the lines from a startup script to load
|
|
<CODE>trajectoryScan.db</CODE> and start the sequencer for a MAXv system.
|
|
|
|
<PRE>
|
|
# Database for trajectory scanning with the MAXv
|
|
dbLoadRecords("$(MOTOR)/motorApp/Db/trajectoryScan.db",
|
|
"P=13BMC:,R=traj1,NAXES=6,NELM=2000,NPULSE=2000")
|
|
|
|
iocInit
|
|
|
|
# MAXV trajectory scan
|
|
seq &MAX_trajectoryScan, "P=xxx:,R=traj1:,M1=m1,M2=m2,M3=m3,M4=m4,M5=m5,M6=m6,M7=m7,M8=m8,PORT=none"
|
|
</PRE>
|
|
|
|
<H3>Ensemble</H3>
|
|
|
|
The following is an example of the lines from a startup script to load
|
|
<CODE>trajectoryScan.db</CODE> and start the sequencer program for an Ensemble system. Note
|
|
that the <CODE>dbLoadRecords</CODE> and <CODE>seq</CODE> commands are shown on
|
|
multiple lines here for clarity, but they must each actually be on a single long
|
|
line.
|
|
|
|
<P>The Ensemble trajectory support uses the same infrastructure that the motor record
|
|
uses to talk to the controller. Here's are typical commands that set that up:
|
|
<PRE>
|
|
dbLoadTemplate("AeroAsyn.substitutions")
|
|
drvAsynIPPortConfigure("tcp1","164.54.51.77:8000", 0, 0, 0)
|
|
EnsembleAsynSetup(1)
|
|
EnsembleAsynConfig(0, "tcp1", 0, 1, 50, 1000)
|
|
drvAsynMotorConfigure("AeroE1","motorEnsemble",0,1)
|
|
</pre>
|
|
|
|
where the file AeroAsyn.substitutions might have the following content:
|
|
|
|
<pre>
|
|
file "$(MOTOR)/db/asyn_motor.db"
|
|
{
|
|
pattern
|
|
{P, N, M, DTYP, PORT, ADDR, DESC, EGU, DIR, VELO, VBAS, ACCL, BDST, BVEL, BACC, MRES, PREC, DHLM, DLLM, INIT}
|
|
{xxxL:, 17, "m$(N)", "asynMotor", AeroE1, 0, "motor $(N)", mm, Pos, .1, 0, .2, 0, 1, .2, 1.25E-5, 7, 0, 0, "SCURVE 100"}
|
|
}
|
|
</pre>
|
|
|
|
Here are the database-load and sequencer-start commands:
|
|
<pre>
|
|
# Database for trajectory scanning with the Ensemble
|
|
dbLoadRecords("$(MOTOR)/motorApp/Db/trajectoryScan.db",
|
|
"P=13BMC:,R=traj1,NAXES=6,NELM=2000,NPULSE=2000")
|
|
|
|
iocInit
|
|
|
|
# Ensemble trajectory scan
|
|
seq &EnsembleTrajectoryScan, "P=15iddLAX:,R=traj1:,M1=aero:c0:m1,M2=none,M3=none,M4=none,M5=none,M6=none,M7=none,M8=none,PORT=tcp1"
|
|
|
|
</PRE>
|
|
|
|
<P> </P>
|
|
<H2><A name="MEDM screens">
|
|
MEDM screens</A></H2>
|
|
<P>
|
|
The following show the MEDM screens with which the user can view and modify
|
|
the trajectory scanning parameters.</P>
|
|
<P><CODE>trajectoryScan.adl</CODE> is the main screen used to define, build,
|
|
execute and read back trajectories. The only thing that cannot be done in MEDM
|
|
is to edit the <CODE>MnTraj</CODE> and <CODE>TimeTraj</CODE> arrays, since MEDM
|
|
does not provide a method to edit arrays.
|
|
|
|
<P>
|
|
<CODE>trajectoryScan.adl</CODE> is
|
|
called with macro parameters <CODE>P, R, TITLE, and M1 ... M8. P</CODE> and
|
|
<CODE>R</CODE> are the prefix and record base used when the database was loaded.
|
|
<CODE>M1 ... M8</CODE> are the names of the EPICS motors. These are used to label the
|
|
plots in <CODE>trajectoryPlot.adl</CODE> using the .DESC fields of the motors. For example
|
|
<CODE>trajectoryScan.adl</CODE> in this screen shot was called with
|
|
<CODE>
|
|
P=13BMC:, R=traj1, TITLE=Trajectory Scans, M1=m33,M2=m34,M3=m35,M4=m36,M5=m37,M6=m38,M7=m25,M8=m26
|
|
</CODE>.
|
|
|
|
<P>
|
|
<IMG src="trajectoryScan_files/trajectoryScan.png"></P>
|
|
|
|
<P>
|
|
<CODE>trajectoryPlot.adl</CODE> is used to plot the requested trajectory in
|
|
position and time (<CODE>MnTraj</CODE>, <CODE>TimeTraj</CODE>), the readback
|
|
positions (<CODE>MnActual</CODE>) and the following errors
|
|
(<CODE>MnError</CODE>).</P>
|
|
|
|
<P>
|
|
<IMG src="trajectoryScan_files/trajectoryPlot1.png"><IMG src="trajectoryScan_files/trajectoryPlot2.png"></P>
|
|
|
|
<P>
|
|
<CODE>trajectoryScanDebug.adl</CODE> is used to display detailed information,
|
|
useful for debugging.</P>
|
|
|
|
<P>
|
|
<IMG src="trajectoryScan_files/trajectoryScanDebug.png"></P>
|
|
|
|
|
|
<P>MEDM displays for the MAXv and Ensemble are very similar, but also include
|
|
start-position PVs written by the MAXv sequencer program, and some controller
|
|
specific PVs on the separate displays <code>trajectoryScan_MAXv.adl</code>, and
|
|
<code>trajectoryScan_Ensemble.adl</code>. These displays can be called up from
|
|
the "More" menu button on the MAX_trajectoryScan.adl display. The plotting
|
|
displays for these controllers are different in that they plot as functions of
|
|
time, rather than trajectory point.
|
|
|
|
<P> </P>
|
|
<H2><A name="Autosave">Autosave</A></H2>
|
|
|
|
<P>The user-modifiable PVs that control an instance of trajectoryScan.db can
|
|
be autosaved by including a line like the following in the autosave-request
|
|
file:
|
|
<pre>
|
|
file trajectoryScan_settings.req P=$(P),R=traj1:
|
|
</pre>
|
|
|
|
The macros 'P' and 'R' are the same as those specified for the database file.
|
|
|
|
|
|
<P> </P>
|
|
<H2><A name="Example IDL Procedure">
|
|
Example IDL Procedure</A></H2>
|
|
<P>
|
|
The following IDL function illustrates how an EPICS channel access client can
|
|
define, build, execute and read back a trajectory.</P>
|
|
<PRE>
|
|
function trajectory_scan, traj, positions, relative=relative, hybrid=hybrid, $
|
|
time=time, accel=accel, npulses=npulses, $
|
|
build=build, execute=execute, read=read, $
|
|
actual=actual, errors=errors
|
|
|
|
;+
|
|
; NAME:
|
|
; trajectory_scan
|
|
;
|
|
; PURPOSE:
|
|
; This IDL function loads and execute a complex trajectory
|
|
; using the EPICS trajectory scan databases and SNL programs. The EPICS
|
|
; support current exists for the Newport MM4005 and XPS motor controllers.
|
|
;
|
|
;
|
|
; CATEGORY:
|
|
; EPICS trajectory scanning
|
|
;
|
|
; CALLING SEQUENCE:
|
|
; Result = TRAJECTORY_SCAN(Trajectory, Positions)
|
|
;
|
|
; INPUTS:
|
|
; TRAJ: The EPICS record name for this trajectory, for example '13BMC:traj1'.
|
|
;
|
|
; POSITIONS: [NELEMENTS, NMOTORS]. The positions of the motors at each element in the trajectory.
|
|
; By default the positions are absolute motor positions. If the RELATIVE
|
|
; keyword is present then the positions are deltas, i.e. the difference in position
|
|
; from the previous point.
|
|
;
|
|
;
|
|
; KEYWORD PARAMETERS:
|
|
; RELATIVE: Set this keyword if the positions are deltas, i.e. the difference in position
|
|
; from the previous point. Default mode=ABSOLUTE.
|
|
; HYBRID: Set this keyword if the trajectory should be executed in "Hybrid" mode, i.e.
|
|
; the positions are absolute rather than deltas, but the trajectory should be
|
|
; executed from the current motor positions without moving to the first point
|
|
; in the postions array. Default mode=ABSOLUTE.
|
|
; TIME: If this keyword is a scaler, then it specifies the total time to execute
|
|
; the trajectory. If it is an array then it specifies the time per element.
|
|
; Default=1 second per element.
|
|
; ACCEL: The acceleration time for the trajectory. Only for the MM4005. Default=1 second.
|
|
; NPULSES: The number of output pulses during the trajectory. Default=NELEMENTS, the number
|
|
; of points in the input Positions array.
|
|
; BUILD: Set this keyword to build and verify the trajectory. This is the default.
|
|
;
|
|
; EXECUTE: Set this keyword to execute the trajectory. This is the default.
|
|
;
|
|
; READ: Set this keyword to read back the trajectory into ACTUAL and ERROR.
|
|
; The default is to not read back.
|
|
;
|
|
; NOTE: Any or all of these keywords can be set. If none is set then the
|
|
; function does not do anything.
|
|
;
|
|
; OUTPUTS:
|
|
; Result: This function returns a status indicating whether the
|
|
; selected operations were successful or not. 0=success,
|
|
; anything else is a failure.
|
|
; ACTUAL: An array of [Nactual, NMOTORS] containing the actual positions of
|
|
; each axis.
|
|
; ERRORS: An array of [Nactual, NMOTORS] containing the following errors of
|
|
; each axis.
|
|
; NOTE: The ACTUAL and ERROR outputs are only returned if the READ keyword it set.
|
|
;
|
|
; SIDE EFFECTS:
|
|
; This procedure can move the motors. Be careful!
|
|
;
|
|
; EXAMPLE:
|
|
; positions = [[1,2,3],[.1, .2, .3], [0,3,4]]
|
|
; status = TRAJECTORY_SCAN('13IDC:traj1', positions, /read, actual, errors)
|
|
; plot, actual[*,0]
|
|
; oplot, errors[*,0]
|
|
;
|
|
; MODIFICATION HISTORY:
|
|
; Written by: Mark Rivers, December 15, 2006
|
|
;-
|
|
|
|
t = caget(traj+'NumAxes', maxAxes)
|
|
|
|
MoveMode = 'Absolute'
|
|
if (keyword_set(relative)) then MoveMode = 'Relative'
|
|
if (keyword_set(hybrid)) then MoveMode = 'Hybrid'
|
|
t = caput(traj+'MoveMode', MoveMode)
|
|
|
|
if (n_elements(build) eq 0) then build=1
|
|
if (n_elements(execute) eq 0) then execute=1
|
|
|
|
if (keyword_set(build)) then begin
|
|
|
|
dims = size(positions, /dimensions)
|
|
nelements = dims[0]
|
|
naxes = dims[1]
|
|
if (n_elements(npulses) eq 0) then npulses = nelements
|
|
|
|
t = caput(traj+'Nelements', nelements)
|
|
|
|
t = caput(traj+'Npulses', npulses)
|
|
|
|
; Default is 1 second per element
|
|
if (n_elements(time) eq 0) then time = nelements * 1.0
|
|
if (n_elements(time) eq 1) then begin
|
|
t = caput(traj+'TimeMode', 'Total')
|
|
t = caput(traj+'Time', time)
|
|
endif else begin
|
|
t = caput(traj+'TimeMode', 'Per element')
|
|
t = caput(traj+'TimeTraj', time)
|
|
endelse
|
|
|
|
if (n_elements(accel) eq 0) then accel = 1.
|
|
t = caput(traj+'Accel', accel)
|
|
|
|
; The first naxes motors will move.
|
|
for i=0, maxAxes-1 do begin
|
|
axis = traj + 'M' + strtrim(i+1,2)
|
|
if (i lt naxes) then begin
|
|
t = caput(axis+'Move', 1)
|
|
pos = positions[*,i]
|
|
t = caput(axis+'Traj', pos)
|
|
endif else begin
|
|
t = caput(axis+'Move', 0)
|
|
endelse
|
|
endfor
|
|
|
|
; Trajectory is now defined. Build it.
|
|
t = caput(traj+'Build', 1)
|
|
; Wait for the build to complete. Wait 0.1 second between polls.
|
|
repeat begin
|
|
wait, 0.1
|
|
t = caget(traj+'Build', busy)
|
|
endrep until (busy eq 0)
|
|
|
|
; Make sure the build was successful
|
|
t = caget(traj+'BuildStatus', BuildStatus, /string)
|
|
if (BuildStatus ne 'Success') then begin
|
|
t = caget(traj+'BuildMessage', BuildMessage)
|
|
print, 'Build failed, error = ', BuildMessage
|
|
return, BuildStatus
|
|
endif
|
|
endif
|
|
|
|
if (keyword_set(execute)) then begin
|
|
t = caput(traj+'Execute', 1)
|
|
; Wait for the execute to complete. Wait 0.1 second between polls.
|
|
repeat begin
|
|
wait, 0.1
|
|
t = caget(traj+'Execute', busy)
|
|
endrep until (busy eq 0)
|
|
|
|
; Make sure the execution was successful
|
|
t = caget(traj+'ExecStatus', ExecStatus, /string)
|
|
if (ExecStatus ne 'Success') then begin
|
|
t = caget(traj+'ExecMessage', ExecMessage)
|
|
print, 'Execution failed, error = ', ExecMessage
|
|
return, ExecStatus
|
|
endif
|
|
endif
|
|
|
|
if (keyword_set(read)) then begin
|
|
t = caput(traj+'Readback', 1)
|
|
; Wait for the readback to complete. Wait 0.1 second between polls.
|
|
repeat begin
|
|
wait, 0.1
|
|
t = caget(traj+'Readback', busy)
|
|
endrep until (busy eq 0)
|
|
|
|
; Make sure the readback was successful
|
|
t = caget(traj+'ReadStatus', ReadStatus, /string)
|
|
if (ReadStatus ne 'Success') then begin
|
|
t = caget(traj+'ReadMessage', ReadMessage)
|
|
print, 'Read failed, error = ', ReadMessage
|
|
return, ReadStatus
|
|
endif
|
|
|
|
; Read the actual and error arrays into IDL, return to
|
|
; caller
|
|
t = caget(traj+'Nactual', nactual)
|
|
actual = dblarr(nactual, maxAxes)
|
|
errors = dblarr(nactual, maxAxes)
|
|
for i=0, maxAxes-1 do begin
|
|
axis = traj + 'M' + strtrim(i+1,2)
|
|
t = caget(axis+'Actual', temp, max=nactual)
|
|
actual[0,i] = temp
|
|
t = caget(axis+'Error', temp, max=nactual)
|
|
errors[0,i] = temp
|
|
endfor
|
|
endif
|
|
|
|
return, 0
|
|
end
|
|
</PRE>
|
|
<P>
|
|
This is an IDL main program that defines a trajectory and executes it using trajectory_scan.pro above.
|
|
<PRE>
|
|
; This program builds a trajectory and executes it.
|
|
|
|
; The trajectory definition is hybid mode, meaning the positions are
|
|
; definined in absolute coordinates rather than displacements from on
|
|
; element to the next. However, the motors do not move to the absolute
|
|
; position of the first element before executing the trajectory.
|
|
|
|
; 101 elements in the trajectory. We use 4N+1 since we are defining the
|
|
; trajectory in Hybrid mode
|
|
nelements = 101
|
|
|
|
; We will move the first 2 motors (Phi and Kappa)
|
|
naxes=2
|
|
|
|
; Define array of positions
|
|
positions = dblarr(nelements, naxes)
|
|
|
|
; The Phi trajectory is a sin wave with two complete periods and an
|
|
; amplitude of +-8 degrees
|
|
positions[*,0] = 8.*sin(findgen(nelements)/(nelements-1.)*4.*!pi)
|
|
|
|
; The Kappa trajectory is a sin wave with one complete period and an
|
|
; amplitude of +-20 degrees
|
|
positions[*,1] = 20.*sin(findgen(nelements)/(nelements-1.)*2.*!pi)
|
|
|
|
trajectory = '13BMC:traj1'
|
|
|
|
; Total time for trajectory
|
|
time = 20.
|
|
|
|
status = trajectory_scan(trajectory, positions, /hybrid, /build, /execute, /read, $
|
|
time=time, npulses=300, actual=actual, errors=errors)
|
|
|
|
end
|
|
</PRE>
|
|
|
|
<P>
|
|
These are the IDL commands to execute the above program, and plot the results:
|
|
<PRE>
|
|
IDL> .run trajectory_test1
|
|
IDL> iplot, actual[*,0]
|
|
IDL> iplot, actual[*,1], /overplot
|
|
IDL> iplot, errors[*,0]
|
|
IDL> iplot, errors[*,1], /overplot
|
|
</PRE>
|
|
<P>
|
|
These are the resulting plots:
|
|
<P>
|
|
<IMG src="trajectoryScan_files/IDL_trajectory_actual.png"></P>
|
|
|
|
<P>
|
|
<IMG src="trajectoryScan_files/IDL_trajectory_errors.png"></P>
|
|
|
|
|
|
<P> </P>
|
|
<H2><A name=SPEC_Interface>
|
|
SPEC Interface</A></H2>
|
|
<P>
|
|
A set of SPEC macros allows SPEC to utilize trajectory scanning with EPICS
|
|
and the MM4005 or XPS. It requires a multi-channel scaler or some other
|
|
detector that can be triggered and has buffering.
|
|
<P>
|
|
The implementation is done at a low level, so that all of SPEC's standard
|
|
scans can be done "on-the-fly" utilizing this trajectory scanning software.
|
|
This
|
|
was done by providing replacement macros for:
|
|
<PRE>
|
|
_ascan # Used by all ascan and dscan macros
|
|
mesh
|
|
hklscan # Used by hscan, kscan and lscan
|
|
_hklmesh
|
|
_hklline # Used by hkcircle, hlcircle, klcircle, hkradial, hlradial and klradial
|
|
_scanabort
|
|
resume
|
|
_loop
|
|
</PRE>
|
|
It adds the following new macros:
|
|
<PRE>
|
|
traj_index # Converts a SPEC motor index to an MM4005 or XPS motor index
|
|
traj_build # Builds a trajectory
|
|
traj_exec # Executes a trajectory
|
|
traj_read_counts # Reads the data from the multi-channel scaler
|
|
traj_read_actual # Reads back the actual MM4005 or XPS motor positions
|
|
traj_scans_on # Enables trajectory scanning
|
|
traj_scans_off # Disables trajectory scanning, uses step scanning
|
|
</PRE>
|
|
The improvement in performance is dramatic. Using step scanning the
|
|
overhead per point is about 1 second, so a 500 point scan takes a minimum of 500
|
|
seconds or more than 8 minutes. Using trajectory scanning the total time to
|
|
execute a 500 point scan with .002 seconds per point is 3 seconds, including the
|
|
time to print and plot the data and write it to the data file.
|
|
<P>
|
|
It is easy to switch back and forth between traditional step scanning and
|
|
trajectory scanning.
|
|
<CODE>traj_scans_on</CODE> turns on trajectory scanning for
|
|
all subsequent scans. <CODE>traj_scans_off</CODE> reverts back to traditional
|
|
step scanning.
|
|
<P>
|
|
It is possible to have the motor positions and HKL values that SPEC prints
|
|
on the screen, plots and stores in the SPEC data file be based upon the
|
|
<I>theoretical</I> motor positions during the scan. Alternatively SPEC can use
|
|
values based upon the <I>actual</I> motor positions at each point in the scan.
|
|
Using the actual motor positions is slower, because the values must be read from
|
|
the MM4005 at the end of the trajectory execution. Set the SPEC global variable
|
|
<CODE>TRAC_USE_ACTUAL=0</CODE> to use the theoretical motor positions, and
|
|
<CODE>TRAJ_USE_ACTUAL=1</CODE> to use the actual motor positions.
|
|
|
|
<<P> </P>
|
|
<H2><A name="Restrictions">
|
|
Restrictions</A></H2>
|
|
<P>The following are restrictions and problems with the trajectory scanning.
|
|
<UL>
|
|
<LI>At short trajectory element times with velocity changes the XPS can exceed
|
|
the maximum acceleration, even when a simple calculation (delta velocity/delta time)
|
|
says that it should not. The fix will be to use the actual spline function that the
|
|
XPS uses when calculating the velocities in the trajectory file. We have not run into
|
|
this problem at trajectory times larger than 0.01 second.
|
|
|
|
<li>The MAXv controller does not actually have a trajectory capability, but
|
|
instead has a variable velocity capability that can be programmed to
|
|
produce the effect of a trajectory. This works well when there are many
|
|
motor pulses between trajectory points. When there are few, the times
|
|
at which the motors hit trajectory points become erratic.
|
|
|
|
</UL>
|
|
|
|
</BODY>
|
|
</HTML>
|