EnsemblePSOFly.db supports fly scans of a single motor controlled by an Aerotech Ensemble controller. It uses the motor record to move the motor, and read position, and to read control fields such as offset and direction. It uses an asyn port to talk to the controller about capabilities that the motor record doesn't support, such as the control of PSO (position synchronized output) pulses. Commands to tell the Aerotech Ensemble to output pulses every scanDelta units, beginning at startPos and ending at scan_end. Note that the Ensemble fires pulses at positions n*delta from the position at which the PSOCONTROL X ARM command was invoked. Thus, the pre-fly ("taxi") position of the motor must be an integer multiple of scanDelta. {start} = startPos - scanDelta {end} = scan_end + scanDelta/2 PSOCONTROL X RESET ' Reset PSO. PSOPULSE X TIME 50,25 ' Define a pulse of width ' 50 usec, with 25 usec ' on time. PSOOUTPUT X PULSE WINDOW MASK ' Set PSO output type to PULSE. ' PSO pulses are masked by ' the window. PSOTRACK X INPUT 1 ' Track primary encoder for ' axis. PSODISTANCE X FIXED scanDelta UNITS ' Set the incremental firing ' distance ((units). PSOWINDOW X 1 INPUT 1 ' Track primary encoder for ' Window 1. PSOWINDOW X 1 RANGE {start},{end} UNITS ' Set the fixed range (in units) for ' the window. ' Note that the following command establishes the origin for ' distance-based output pulses as the motor's current position. ' (i.e., it simply clears a counter that will be clocked by encoder pulses.) PSOCONTROL X ARM ' Enable PSO and start tracking. PSOWINDOW X 1 OFF ' Turn off window. PSOCONTROL X OFF ' Stop PSO tracking. ------------------------------------------------------------------------------ Start, end positions, etc. Before the motor's fly motion begins, the motor is moved to the "taxi" position, which is chosen so that the motor can accelerate to constant speed before data acquisition begins. For constant acceleration from a possibly nonzero base speed, the acceleration distance is given by accelDist = accelTime * (baseSpeed + slewSpeed)/2 In EPICS motorRecord PVs, this is accelDist = motor.ACCL * (motor.VBAS + M.VELO)/2 Data acquisition occurs at N locations during the motor motion, where N = (endPos - startPos) / scanDelta The locations are given by dataStart + i*scanDelta*dir where i is an integer in the range [0, N-1], and dir = (endPos-startPos)>0 ? 1 : -1 Because of the way the Ensemble motor controller's position-synchronized output is implemented, dataStart is determined by the taxi position and the pulse-window open and close positions, such that the taxi position must be an integer multiple, M, of scanDelta away from dataStart. The taxi position must also be at least accelDist away from dataStart, giving a lower limit on M: taxi = dataStart - M*scanDelta*dir <= dataStart - accelDist*dir M >= accelDist/scanDelta M = ceil(accelDist/scanDelta) ------------------------------------------------------------------------------- The Ensemble PSO output is RS422, via an interface cable that ends with a female DB9 connector with an entirely custom pinout that includes 5V power. If conversion to TTL is needed, the following chips and boards seem useful: Analog Devices ADM483E chip Linear Technology LTC485 chip Microbotics SLC10422-TTL board -------------------------------------------------------------------------------