diff --git a/documentation/trajectoryPlot1.gif b/documentation/trajectoryPlot1.gif new file mode 100644 index 00000000..5e308047 Binary files /dev/null and b/documentation/trajectoryPlot1.gif differ diff --git a/documentation/trajectoryPlot2.gif b/documentation/trajectoryPlot2.gif new file mode 100644 index 00000000..ea5086cf Binary files /dev/null and b/documentation/trajectoryPlot2.gif differ diff --git a/documentation/trajectoryScan.gif b/documentation/trajectoryScan.gif new file mode 100644 index 00000000..ecb4b70c Binary files /dev/null and b/documentation/trajectoryScan.gif differ diff --git a/documentation/trajectoryScan.html b/documentation/trajectoryScan.html new file mode 100644 index 00000000..d9e3b74e --- /dev/null +++ b/documentation/trajectoryScan.html @@ -0,0 +1,1042 @@ + +Trajectory Scanning with the Newport Diffractometer + + +
+

Trajectory Scanning with the Newport MM4005 and XPS Motor Controllers

+

Mark Rivers

+

January 20, 2007

+
+

Contents

+ + +

+

Overview

+

The Newport MM4005 and XPS motor controllers are capable of executing complex +coordinated motions. Trajectories can be defined which move any or all of +the axes through any set of complex motions. 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.

+ +

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. This can reduce data collection times dramatically relative to +traditional step scanning.

+ +

This document describes an EPICS interface to the trajectory capabilities of +the MM4005 and XPS. 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:

+ + +

+

Implementation

+

The EPICS implementation consists of the following:

+ + +

+

Safety

+

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:

+ + +

+

Notation

+

The database is loaded with $(P) (prefix) and $(R) +(record base) macros. For example, $(P) might be +13IDC: for the name of the IOC, and $(R) might be +Traj1: 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, Nelements is really +$(P)$(R)Nelements or in this case +13IDC:Traj1:Nelements.

+ +

There are 8 motors in the database, and thus 8 similar records for many +functions. For example, the records defining the trajectory positions are +M1Traj, M2Traj ... M8Traj. These are referred to in this document +either as M1Traj ... M8Traj or as MnTraj.

+ +

+

+

Defining a Trajectory

+

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

+ +

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. +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.

+ +

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.

+ +

The following table lists the EPICS Process Variables (PVs) which are used to +define the trajectory. Some of these are explained in more detail below.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PV NameRecord TypeDescription
NumAxeslongoutThe number of motors (axes) which are connected to the MM4005 or XPS.
NelementslongoutThe number of elements in the trajectory, i.e. the number of valid + points in the M1Traj...M8Traj and TimeTraj + arrays. Default=1.
MoveModembbiDefines the type of position information contained in + M1Traj...M8Traj. 0=Relative, + 1=Absolute, 2=Hydrid. + Default=Relative.
M1Traj ... M8Trajwaveform, doubleThe displacements or absolute positions of each motor for each element + of the trajectory. No defaults.
M1Move ... M8MoveboFlag defining whether each motor is to be moved during the trajectory. + 0=No, 1=Yes. Default=No.
NpulseslongoutNumber of synchronization pulses to be output by the MM4005/XPS. + Default=200.
StartPulseslongoutThe trajectory element number where synchronization pulses will start. + Default=1.
EndPulseslongoutThe trajectory element number where synchronization pulses should end. + Default=Nelements. The SNL program sets + EndPulses=Nelements whenever Nelements is + changed, since this is what is normally desired. EndPulses + can be changed again after changing Nelements if + desired.
TimeModeboThe mode being used to define the time per trajectory element. + 0=Total means that the total time for the trajectory is being + defined, and the TimeTraj array will be computed by setting + the execution time for each element = Time/Nelements. + 1=Per Element means that the time per element has already + been loaded into the TimeTraj array. This mode permits each + element to have a different execution time. Default = + Total.
TimeaoTotal trajectory execution time. Used when TimeMode=0. + Default=10.
TimeTrajwaveform, doubleThe array containing the execution time per trajectory element. This + array is computed by the SNL program if + TimeMode=Total, and must be loaded by the user + if TimeMode=Per Element.
AccelaoThe acceleration time for the trajectory. Default=0.5 seconds.
M1Name ... M8NamestringoutThe name of each motor. These are used for the labels on MEDM screens + and by channel access clients. These names are defined when the database + is loaded. These PVs are not otherwise used and are not required for the + trajectory definition.
+ +

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. MoveMode +can have the following 3 values:

+ +

Note that when programming TimeTraj in Absolute or +Hybrid mode TimeTraj[i] is the time to execute the +move from position MnTraj[i] to MnTraj[i+1].

+

The MM4005 requires the number of elements in a trajectory to be a multiple +of 4. This means that Nelements +should be a multiple of 4 in +Relative mode and a multiple of 4 +plus 1 in Absolute or +Hybrid mode. However, this can be an +inconvenience for EPICS channel access clients. The SNL program works around +this restriction as follows. If +Nelements is not a multiple of 4 for +MoveMode=Relative or a multiple +of 4 plus 1 for +MoveMode=Absolute or +Hybrid, 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.

+

The number of trajectory elements, Nelements is limited as +follows.

+ +

The number of output pulses, Npulses is limited as follows.

+ +

 

+

 

+

Building a Trajectory

+

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 MM4005 and checking it +for errors such as excess velocities or accelerations.

+

The following table describes the EPICS PVs used for building a +trajectory.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PV NameRecord TypeDescription
BuildbusySetting 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.
BuildStatembbiThe trajectory build state. 0=Done, + 1=Busy.
BuildStatusmbbiThe trajectory build status. 0=Undefined, + 1=Success, 2=Failure.
BuildMessagestringoutProgress messages while the build is in progress and error message if + BuildStatus=Failure.
M1MDVS ... M8MDVS (MM4005 only)aoThe 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.
M1MDVA ... M8MDVA (MM4005 only)aoThe actual maximum change in velocity between trajectory elements. + This value is read from the MM4005 after the trajectory is built. + MnMDVE gives the specific trajectory element in which this + maximum change in velocity occurred. If MnMDVA is greater + than MnMDVS then the trajectory build will fail. The acronym + is Maximum Delta Velocity Actual. Read-Only.
M1MDVE ... M8MDVE (MM4005 only)longoutThe trajectory element number where MnMDVA occurs. The + acronym is Maximum Delta Velocity Element. Read-Only.
M1MVA ... M8MVA (MM4005 only)aoThe actual maximum velocity. This value is read from the MM4005 after + the trajectory is built. MnMVE gives the specific trajectory + element in which this maximum velocity occurred. If MnMVA is + greater than the maximum velocity allowed for this motor then the build + will fail. The acronym is Maximum Velocity Actual. Read-Only.
M1MVE ... M8MVE (MM4005 only)longoutThe trajectory element number where MnMVA occurs. The + acronym is Maximum Velocity Element. Read-Only.
M1MAA ... M8MAA (MM4005 only)aoThe actual maximum acceleration. This value is read from the MM4005 + after the trajectory is built. MnMAE gives the specific + trajectory element in which this maximum acceleration occurred. If + MnMVA is greater than the maximum acceleration allowed for + this motor then the build will fail. The acronym is Maximum Acceleration + Actual. Read-Only.
M1MAE ... M8MAE (MM4005 only)longoutThe trajectory element number where MnMAA occurs. The + acronym is Maximum Acceleration Element. Read-Only.
+ +

Channel access clients should do the following to build a trajectory:

+ + +

If the build fails then it is useful to look at the +trajectoryScanDebug.adl MEDM screen to examine the maximum velocity +and acceleration values. See if one or more motors is being commanded to move +too fast.

+

 

+

 

+

Executing a Trajectory

+ +

After a trajectory has been successfully built it can be executed. The +trajectory execution consists of the following steps:

+ + +

The following table describes the EPICS PVs used for executing a +trajectory.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PV NameRecord TypeDescription
ExecutebusySetting 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.
ExecStatembbiThe trajectory execution state. 0=Done, 1=Move + Start, 2=Executing, 3=Flyback.
ExecStatusmbbiThe trajectory execute status. 0=Undefined, + 1=Success, 2=Failure, 3=Abort, + 4=Timeout.
ExecMessagestringoutProgress messages while the execution is in progress and error message + if ExecStatus is not Success.
SimMode (MM4005 only)boSimulation mode. 0=Real, 1=Simulate. The + MM4005 can execute a trajectory in simulation mode, not actually moving + any motors. Default=Real.
TimeScale (MM4005 only)aoScaling 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. TimeScale can range from .01 (100 + times faster) to 100 (100 times slower). Default=1.0
AbortboSetting Abort=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. Abort is set back to 0 automatically.
M1Current ... M8Current The current position of each motor. These values are updated and + posted during execution of the trajectory. They are not + 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.
DetOnaoThe .VAL field of this PV is written to its + .OUT field in order to turn on the detector just before the + trajectory is executed. The .VAL and .OUT fields + are defined when the database is loaded. This mechanism is a very flexible + way to turn on any sort of detector or set of detectors, since any value + can be written to any PV.
DetOffaoThe .VAL field of this PV is written to its + .OUT field in order to turn off the detector just after the + trajectory is executed. The .VAL and .OUT fields + are defined when the database is loaded. This mechanism is a very flexible + way to turn off any sort of detector or set of detectors, since any value + can be written to any PV.
+ +

Channel access clients should do the following to execute a trajectory:

+ + +

The execution can fail because the velocity or acceleration is too large, +even if the build succeeded, if TimeScale is less than 1.0.

+

 

+

 

+ +

Reading Back a Trajectory

+ +

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.

+

Reading back this information from the MM4005 (but not 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 following table describes the EPICS PVs used for reading back a +trajectory.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PV NameRecord TypeDescription
ReadbackbusySetting this PV to 1 will read back the results of the + trajectory motion from the MM4005. It will be set back to 0 automatically + when the readback is complete.
ReadStatembbiThe readback state. 0=Done, + 1=Busy.
ReadStatusmbbiThe readback status. 0=Undefined, + 1=Success, 2=Failure.
ReadMessagestringoutProgress messages while the readback is in progress and + error message if ReadStatus is not + Success.
NactuallongoutThe actual number of pulses output by the MM4005. This value + is normally equal to Npulses, but it could be less if a + trajectory did not complete.
M1Actual ... M8Actualwaveform, doubleThe actual position of the motor when each pulse was output + by the contoller during the trajectory scan.
M1Error ... M8Errorwaveform, doubleThe 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.
+ +

Channel access clients should do the following to read back a trajectory:

+ + +

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.

+

 

+

 

+ +

Interaction with EPICS Motor +Records

+

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 returns the motors +to their original positions, i.e. the positions where the motor records think +they are, after a trajectory execution is complete. One should not move any +motors on an MM4005 while a trajectory scan is in progress.

+ +

When a motion is aborted with the Abort PV it will be necessary +to home the motors and synchronize the motor records with the actual positions +of the motors.

+

 

+

 

+ +

Communication with the +MM4005

+

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 +asynSetTraceMask and asynSetTraceIOMask commands. +Communication with the XPS also uses asyn over a TCP/IP socket connection. Debugging +can be enabled and disabled in the same way. +

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 Nelements and Npulses +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.

+ +

Hardware Notes

+

The synchronization output pulses from the MM4005 are provided on pin 12 of +the DB-25 Auxilliary Connector. We have found it convenient to make a connector +with a short BNC pigtail coming from this pin. This pulse output from the MM4005 +is an open-collector circuit. The maximum rating is 30V and 40 mA.

+

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, since it will result in a +current of 5V/200 Ohm = 25 mA, which is less than the 40 mA maximum.

+

 

+

 

+

Installation

+

The source files for trajectory scanning are in the synApps +motor module +, in the motorApp/ tree. +

+NewportSrc/MM4005_trajectoryScan.st
+NewportSrc/XPS_trajectoryScan.st
+Db/trajectoryScan.db
+op/adl/trajectoryScan.adl
+op/adl/trajectoryScanDebug.adl
+op/adl/trajectoryPlot.adl
+
+ +

vxWorks startup file

+

The following are the comments from the beginning of +trajectoryScan.db which describe the macro parameters which must be +supplied in the dbLoadRecords command in the vxWorks startup +script.

+
# Database for Newport MM4005 trajectory scanning.
+# 
+# Mark Rivers
+# August 12, 2000
+#
+# Note: This database is completely general for the MM4005, 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.
+#
+# Macro paramters:
+# $(P)      - PV name prefix
+# $(R)      - PV base record name
+# $(NAXES)  - Number of axes to be used. Typically 6 for diffractometer.
+# $(NELM)   - Maximum number of trajectory elements
+# $(NPULSE) - Maximum number of output pulses
+# $(DONPV)  - Name of PV to turn detector on
+# $(DONV)   - Value to write to DONPV to turn detector on
+# $(DOFFPV) - Name of PV to turn detector off
+# $(DOFFV)  - Value to write to DOFFPV to turn detector off
+# $(C)      - Card # (0,1,2...) of the board with the IP slot for the
+#             generic serial records
+# $(IPSLOT) - IP slot (A-D) for the serial I/O module
+# $(CHAN)   - Channel (0-7) for the serial port
+# $(BAUD)   - Baud rate for the serial port
+#             Note: the MM4005 is assumed to be configured with 8 data bits,
+#             1 stop bit, no parity.
+
+

The following is an example of the lines which must be put in the vxWorks +startup file to load trajectoryScan.db. Note that the command line +is longer than the vxWorks limit, so the command must be built using +malloc, strcpy and strcat.

# Database for trajectory scanning with the MM4005/GPD
+# The required command string is longer than the vxWorks
+# command line, must use malloc and strcpy, strcat
+str = malloc(300)
+strcpy(str,"P=13IDC:,R=traj1,NAXES=6,NELM=1000,NPULSE=1000,C=0,IPSLOT=a,CHAN=2,BAUD=19200")
+strcat(str,",DONPV=13IDC:str:EraseStart,DONV=1,DOFFPV=13IDC:str:StopAll,DOFFV=1")
+strcat(str,",M1=Phi,M2=Kappa,M3=Omega,M4=Psi,M5=2-Theta,M6=Nu,M7=Unused,M8=Unused")
+dbLoadRecords("CARSApp/Db/trajectoryScan.db", str)
+
+

DONPV and DOFFPV in this example are for the +Struck/SIS multichannel scaler database (Struck8.db). For this +database writing a 1 to EraseStart clears and starts the +multichannel scaler, writing 1 to StopAll stops it. The names +M1 ... M8 are used to define the MnName records, which +in turn provide the motor labels on the MEDM displays.

+

After iocInit is called in the startup script the SNL program +must be started. Here is an example:

seq &trajectoryScan, "P=13IDC:, R=traj1" 
+

 

+

 

+

MEDM screens

+

The following show the MEDM screens with which the user can view and modify +the trajectory scanning parameters.

+

trajectoryScan.adl is the main screen used to define, build, +execute and read back trajectories. The only thing which cannot be done in MEDM +is to edit the MnTraj and TimeTraj arrays, since MEDM +does not provide a method to edit arrays. trajectoryScan.adl is +called with macro parameters P, R, TITLE, and M1 ... M8. P and +R are the prefix and record base used when the database was loaded. +M1 ... M8 are the names of the motors. These are used to label the +plots in trajectoryPlot.adl. For example +trajectoryScan.adl in this screen shot was called with +P=13IDC:, R=traj1, TITLE=GPD_Trajectory_Scan, M1=Phi, M2=Kappa, M3=Omega, +M4=Psi, M5=2-Theta, M6=Nu, M7=Unused, M8=Unused.

+

+

trajectoryPlot.adl is used to plot the requested trajectory in +position and time (MnTraj, TimeTraj), the readback +positions (MnActual) and the following errors +(MnError).

+

+

trajectoryScanDebug.adl is used to display detailed information, +useful for debugging.

+

+

 

+

 

+

Example IDL Procedure

+

The following IDL function illustrates how an EPICS channel access client can +define, build, execute and read back a trajectory.

function trajectory_demo1, build=build, execute=execute, read=read, $
+                          actual, error, counts
+
+;+
+; NAME:
+;       trajectory_demo1
+;
+; PURPOSE:
+;       This IDL function demonstates how a channel access client can 
+;       define, build, execute and read back a complex trajectory with the 
+;       MM4005.
+;
+;       The trajectory parameters are as follows:
+;       101 elements, 300 output pulses, 30 second execution time, 1 second
+;       acceleration time.
+;
+;       Only the Phi and Kappa axes are moved.
+;
+;       The Phi trajectory is a sin wave with two complete periods and an
+;       amplitude of +-8 degrees.
+;
+;       The Kappa trajectory is a sin wave with one complete period and an
+;       amplitude of +-20 degrees.
+;
+;       The readback includes the Phi, Kappa and Omega actual positions and
+;       following errors. Omega is interesting because although it was not
+;       moved during the trajectory it has some following error because of 
+;       the moving mass of the Kappa arm.
+;
+;       The function returns counts from an SIS multichannel scaler which is
+;       triggered by the output pulses.
+;
+; CATEGORY:
+;       EPICS trajectory scanning
+;
+; CALLING SEQUENCE:
+;       Result = TRAJECTORY_DEMO1(Actual, Error, Counts)
+;
+; INPUTS:
+;       None.
+;
+; KEYWORD PARAMETERS:
+;       BUILD:      Set this keyword to build the trajecotry
+;
+;       EXECUTE:    Set this keyword to execute the trajectory
+;
+;       READ:       Set this keyword to read back the trajectory into
+;                   Actual and Error
+;
+;       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, 3] containing the actual positions of
+;                   the Phi, Kappa and Omega axes.
+;       Error:      An array of [Nactual, 3] containing the following errors of
+;                   the Phi, Kappa and Omega axes.
+;       Counts:     An array of [Nactual, 4] containing the counts from the
+;                   SIS 3801 multi-channel scaler. The EPICS_MED class library
+;                   is used to communicate with this device.
+;
+;       NOTE: The Actual, Error and Counts outputs are only returned if the 
+;             READ keyword it set.
+;
+; SIDE EFFECTS:
+;       This procedure can move the diffractometer.  Be careful!
+;
+; EXAMPLE:
+;       status = trajectory_demo1(/build)
+;       status = trajectory_demo1(/execute)
+;       status = trajectory_demo1(/read, actual, error, counts)
+;       plot, actual[*,0]
+;       plot, error[*,0]
+;       plot, counts[*,0]
+;
+; MODIFICATION HISTORY:
+;       Written by:     Mark Rivers, August 13, 2000
+;-
+
+    prefix  = '13IDC:'
+    traj    = prefix + 'traj1'
+    phi     = traj + 'M1'
+    kappa   = traj+'M2'
+    omega   = traj+'M3'
+    mcs     = prefix + 'str:'
+
+    ; Make sure the MCS is in External channel advance mode
+    t = caput(mcs+'ChannelAdvance', 'External')
+
+    if (keyword_set(build)) then begin
+
+        ; 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.
+        MoveMode = 'Hybrid'
+        t = caput(traj+'MoveMode', MoveMode)
+
+        ; 101 elements in the trajectory. We use 4N+1 since we are defining the
+        ; trajectory in Hybrid mode
+        nelements = 101
+        t = caput(traj+'Nelements', nelements)
+
+        ; 300 output pulses during the trajectory
+        npulses = 300
+        t = caput(traj+'Npulses', npulses)
+
+        ; 30 seconds total time to execute the trajectory
+        t = caput(traj+'TimeMode', 'Total')
+        time = 30.
+        t = caput(traj+'Time', time)
+
+        ; 1 second acceleration time
+        accel = 1.
+        t = caput(traj+'Accel', accel)
+
+        ; The Phi and Kappa motors will move.
+        t = caput(phi+'Move', 1)
+        t = caput(kappa+'Move', 1)
+
+        ; The Phi trajectory is a sin wave with two complete periods and an
+        ; amplitude of +-8 degrees
+        phiTraj = 8.*sin(findgen(nelements)/(nelements-1.)*4.*!pi)
+        t = caput(phi+'Traj', phiTraj)
+
+        ; The Kappa trajectory is a sin wave with one complete period and an
+        ; amplitude of +-20 degrees
+        kappaTraj = 20.*sin(findgen(nelements)/(nelements-1.)*2.*!pi)
+        t = caput(kappa+'Traj', kappaTraj)
+
+        ; 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', Build)
+        endrep until (Build 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', Execute)
+        endrep until (Execute 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', Readback)
+        endrep until (Readback 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 Phi and Kappa actual and error arrays into IDL, return to
+        ; caller
+        t = caget(traj+'Nactual', nactual)
+        t = caget(Phi+'Actual', PhiActual, max=nactual)
+        t = caget(Phi+'Error',  PhiError,  max=nactual)
+        t = caget(Kappa+'Actual', KappaActual, max=nactual)
+        t = caget(Kappa+'Error',  KappaError,  max=nactual)
+        t = caget(Omega+'Actual', OmegaActual, max=nactual)
+        t = caget(Omega+'Error',  OmegaError,  max=nactual)
+        actual = [[PhiActual], [KappaActual], [OmegaActual]]
+        error  = [[PhiError],  [KappaError],  [OmegaError]]
+
+        ; Read the counts from the SIS multichannel scaler
+        med = obj_new('EPICS_MED', mcs, 4)
+        counts = med->get_data()
+        counts = counts[0:nactual-1,*]
+    endif
+
+    return, 0
+end
+
 
+

SPEC Interface

+

A set of SPEC macros allows SPEC to utilize trajectory scanning with EPICS +and the MM4005. +

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:

_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
+
It adds the following new macros:
traj_index        # Converts a SPEC motor index to an MM4005 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 motor positions
+traj_scans_on     # Enables trajectory scanning
+traj_scans_off    # Disables trajectory scanning, uses step scanning
+
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. +

It is easy to switch back and forth between traditional step scanning and +trajectory scanning. traj_scans_on turns on trajectory scanning for +all subsequent scans. traj_scans_off reverts back to traditional +step scanning. +

It is possible to have the motor positions and HKL values which SPEC prints +on the screen, plots and stores in the SPEC data file be based upon the +theoretical motor positions during the scan. Alternatively SPEC can use +values based upon the actual 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 +TRAC_USE_ACTUAL=0 to use the theoretical motor positions, and +TRAJ_USE_ACTUAL=1 to use the actual motor positions. +

diff --git a/documentation/trajectoryScanDebug.gif b/documentation/trajectoryScanDebug.gif new file mode 100644 index 00000000..604e9157 Binary files /dev/null and b/documentation/trajectoryScanDebug.gif differ