quadEM Driver

R5-0

June 29, 2014

Mark Rivers, University of Chicago

Contents

Overview

quadEM supports quad electrometers/picoammeters, typically used for photodiode-based x-ray beam position monitors, or split ion chambers. They can also be used for any low-current measurement that requires high speed digital input. There is support for several models:

  1. The AH401 series (AH401B, AH401D) and AH501 series (AH501, AH501C, AH501D) picoammeters originally designed by Synchrotron Trieste (elettra). They are now sold commerically by CAENels. These devices communicate using TCP or UDP over 100 Mbit/s Ethernet or high-speed serial. They provide 4-channel current measurements at up to 6510 Hz (AH501 series) or 1000 Hz (AH401 series).
  2. The Quad Electrometer built by Steve Ross from the APS (called APS_EM in this document). This device consists of a 4-channel digital electrometer unit and 2 VME boards. The device provides 2 readings per diode at up to 813 Hz.

The AH401 series and the APS_EM are based on the same principle of an op-amp run as a current amplifier with a large feedback capacitor, and a high resolution ADC. The AH501 series are based on a transimpedance input stage for current sensing, combined with analog signal conditioning and filtering stages. The AH501C and AH501D have an integrated programmable bias supply.

The quadEM software includes asyn drivers and an SNL program that provide support for the following:

The following manuals provide detailed information on these devices:

The support is based on asynNDArray driver from areaDetector, which in turn is based on asynPortDriver. It consists of a base class (drvQuadEM.cpp) which is device-independent. There are device-dependent classes for the AH401 and AH501 series (drvAHxxx.cpp) and the APS electrometer (drvAPS_EM.cpp). There is an EPICS State Notation Language (SNL) program (quadEM_SNL.st) is used to synchronize acquisition of time-series data, and to compute FFT power-spectra of the time-series data.

The quadEM driver works as follows:

Note: For the AH501D firmware version 2.0 fixes two problems with previous versions:

The AH501D must be updated to firmware 2.0 for proper operation with quadEM R4-1 or later.

Prior to R5-0 the quadEM driver assumed the following geometry for the 4 current inputs:

             4
             
          1     2
             
             3
  

The PV for the computed quantities were called Sum12, Sum34, Sum1234, Diff12, Diff34, Position12, and Position34. The differences, and hence positions, were computed as 2-1 and 4-3, which would correspond to Position12 being positive to the right and Position34 being positive up in the above diagram.

For R5-0 two geometries are supported, and the names of the Sum, Diff and Position PVs were changed. The computed quantities are called SumX, SumY, SumAll, DiffX, DiffY, PositionX, and PositionY.

The first geometry is the same as that illustrated above, and is called Diamond. For this geometry only 2 diodes are used for the position calculation in each direction. SumX=(1+2), SumY=(3+4), DiffX=(2-1), DiffY=(4-3). This geometry is identical to the geometry assumed prior to R5-0. The X diodes are 1&2 rather than 1&3 so that it is possible to use just the first 2 inputs on the AH501 series to increase readout speed in cases where all 4 diodes are not used. This would not be possible if diodes 1 and 3 were used for the X calculations.

The second geometry is:


          1     2
       
             
          4     3
  

This geometry is called Square. For this geometry all 4 diodes are used for the position calculation in each direction. SumX=SumY=(1+2+3+4), DiffX=(2+3)-(1+4), DiffY=(1+2)-(3+4).

For both geometries SumAll=(1+2+3+4), PositionX=DiffX/SumX, and PositionY=DiffY/SumY. X positive is to the right and Y positive is up for both geometries.

Databases

quadEM.template

The quadEM.template database provides control of the electrometer using the standard asyn device support. NDStats.template from areaDetector provides digitally averaged readings of the current, sum, difference and position with user-defined averaging time. It also provides the standard deviation, miniumim, maximum, and other statistics, including a histogram of array values.

Records in quadEM.template
drvInfo string EPICS record name EPICS record type asyn interface Access Models supported Description
QE_MODEL $(P)$(R)Model mbbi asynInt32 r/o All The model of the electrometer. This is mormally determined automatically by the driver by reading the firmware version. It can also be specified in the configuration command. Values are:
  • 0: Unknown
  • 1: APS_EM
  • 2: AH401B
  • 3: AH401D
  • 4: AH501
  • 5: AH501C
  • 6: AH501D
QE_FIRMWARE $(P)$(R)Firmware stringin asynOctet r/o All The firmware version of the electrometer.
QE_ACQUIRE_MODE $(P)$(R)AcquireMode
$(P)$(R)AcquireMode_RBV
bo
bi
asynInt32 r/w All Acquire mode. Values are:
  • 0: Continuous
  • 1: One-shot
In continuous mode setting Acquire=1 acquires data continuously until Acquire is set back to 0.
In one-shot mode setting Acquire=1 will acquire a data for a single AveragingTime time period. This will result in a single call to the plugins, and thus a single set of averaged values. The driver will then set Acquire back to 0. This mode is intended for data acquisition, for example with the sscan record. With the AH401 and AH501 series One-shot works in triggered mode as well. When Acquire is set to 1 it will wait for the trigger to acquire NumAverage_RBV samples. This may require multiple trigger pulses depending on the length of the pulses, the AveragingTime and the SampleTime_RBV.
QE_ACQUIRE $(P)$(R)Acquire busy asynInt32 r/w All Acquire command. This command turns acquisition from the device on (1) and off (0) Since it is a "busy" record the device can be used with the sscan record when AcquireMode=One-shot.
Important note: Operation in One-shot mode with the sscan record also requires that the statistics plugins be set to have CallbacksBlock=Yes so that the driver waits for the statistics plugins to compute before it sets Acquire back to 0.
QE_RANGE $(P)$(R)Range
$(P)$(R)Range_RBV
mbbo
mbbi
asynInt32 r/w All Range command. This selects the sensitivity of the electrometer (A/D units per nanoamp).
For the AH501 series the choices are:
  • ±2.5mA
  • ±2.5uA
  • ±2.5nA
For the AH401 series this selects the feedback capacitor, which controls the gain of the device. There are 8 capacitor choices in units of saturation charge:
  • 1800 pC
  • 350 pC
  • 300 pC
  • 250 pC
  • 200 pC
  • 150 pC
  • 100 pC
  • 50 pC
For the APS_EM this selects the feedback capacitor, which controls the gain of the device. There are 8 capacitor choices:
  • External
  • 17.6 pf
  • 8.80 pF
  • 5.87 pF
  • 4.40 pF
  • 3.52 pF
  • 2.93 pF
  • 2.51 pF
On the APS_EM all gains except the first External gain use capacitors that are built in to the Burr Brown chip. These are quite small capacitors and only cover a narrow range, so the gains are quite high, and only rather low currents can be measured with them, even at the shortest integration times. The external capacitors can be replaced to select the first gain, and boards are normally built with 220 pF external capacitors. At APS 13-ID we have used much larger values, 1000 to 5000 pF, because the currents from our undulator beam position monitor are large. There are actually 8 external capacitors: 4 of them control the gain for each input for the "ping" channel, and the other 4 control the gain for the "pong" channel. By using one capacitor value for the 4 diodes on the ping channel and a different capacitor value for the 4 diodes on the pong channel, then two user-selectable gains are available. One must then select the appropriate channel in the PingPong record, and not use the average.
QE_PING_PONG $(P)$(R)PingPong
$(P)$(R)PingPong_RBV
mbbo
mbbi
asynInt32 r/w AH401 series, APS_EM Both the AH401 series and the APS_EM have 2 input channels, which we call Ping and Pong here. This doubles the speed of the unit, because one channel is being digitized while the other is integrating. This record selects how the two channels are treated.
On the AH401 series the choices are "Off" (0) and "On" (1). "Off" only returns the data from the Ping channel. This reduces noise because only a single integration capacitor is used, but it reduces the data rate by a factor of two, because data are only returned on every other integration time. "On" returns the data from both channels, which doubles the data rate at some expense in noise.
On the APS_EM both values are always transmitted from the device, and the choices are #1 (Ping), #2 (Pong), and Avg. which averages the values from the Ping and Pong channels. Note that if Range=External and the two external capacitors are different, then one should not use Avg. because that will mix data from two different gains.
QE_INTEGRATION_TIME $(P)$(R)IntegrationTime
$(P)$(R)IntegrationTime_RBV
ao
ai
asynFloat64 r/w AH401 series, APS_EM Selects the integration time of the amplifier. As the integration time is increased the sensitivity increases, but the number of readings/sec sent from the device is decreased.
For the AH401 series values range from 0.001s to 1.000s. The data are sent after one integration time if PingPong="On" or after 2 integration times if PingPong="Off".
For the APS_EM the values range from .000615s to 0.1311s. The data are sent to the VME card from the amplifier after 2 integration times, one value in the Ping channel and one value in the Pong channel. The data period is thus 0.00123 to 0.02622 s, or a frequency range of about 813 Hz to 38.1 Hz.
QE_NUM_CHANNELS $(P)$(R)NumChannels
$(P)$(R)NumChannels_RBV
mbbo
mbbi
asynInt32 r/w AH501 series Selects the number of channels to measure and transmit data for. Using fewer than 4 channels increases the sampling rate. Allowed choices are:
  • 1: channel 1 only
  • 2: channels 1 and 2 only
  • 4: channels 1-4
QE_GEOMETRY $(P)$(R)Geometry
$(P)$(R)Geometry_RBV
mbbo
mbbi
asynInt32 r/w All Selects the geometry of the current inputs as discussed above. Allowed choices are:
  • 0: Diamond
  • 1: Square
QE_RESOLUTION $(P)$(R)Resolution
$(P)$(R)Resolution_RBV
mbbo
mbbi
asynInt32 r/w AH501 series Selects the resolution of the ADC in bits. Using 16-bits increases the sampling rate by a factor of 2 relative to 24-bits. Allowed choices are:
  • 16: 16-bit data
  • 24: 24-bit data
QE_BIAS_STATE $(P)$(R)BiasState
$(P)$(R)BiasState_RBV
bo
bi
asynInt32 r/w AH501C and AH501D Selects the state of the bias supply output voltage. Allowed choices are:
  • 0: Off
  • 1: On
QE_BIAS_VOLTAGE $(P)$(R)BiasVoltage
$(P)$(R)BiasVoltage_RBV
ao
ai
asynFloat64 r/w AH501C and AH501D Controls the voltage of the bias supply output.
QE_VALUES_PER_READ $(P)$(R)ValuesPerRead
$(P)$(R)ValuesPerRead_RBV
longout
longin
asynInt32 r/w All Controls the number of values that are read from the meter in a single call. These values are averaged in the driver before it does callbacks. The default is 1 (no averaging). Setting ValuesPerRead > 1 will reduce the CPU time for 2 reasons:
  1. On the AH401 and AH501 series the driver reduces the frequency of asynOctet->read() calls by a factor of ValuesPerRead, because it can obtain multiple readings from the meter in a single call. This is particularly significant on the AH501 series, which can transmit up to 26,040 packets per second!
  2. It reduces the frequency of callbacks to device support.
The potential disadvantages of setting ValuesPerRead > 1 are:
  • It will change the statistics computed by the NDPluginStats plugin because an initial averaging operation has already been performed, which reduces the standard deviation, changes the histogram, etc.
  • It will reduce the sampling frequency of the TimeSeries support
  • It will reduce the the update frequency of the EPID fast feedback support.
QE_SAMPLE_TIME $(P)$(R)SampleTime_RBV ai asynFloat64 r/o All Provides the actual time between sample readings from the device. This is controlled by the following parameters:
  • ValuesPerRead: All models
  • IntegrationTime: AH401 series and APS_EM
  • PingPong: AH401 series
  • NumChannels: AH501 series
  • Resolution: AH501 series
The sample time on the AH501 series is controlled by the following algorithm:
  • SampleTime = 38.4 microseconds * NumChannels * ValuesPerRead
  • If Resolution == 24 then SampleTime = SampleTime * 2
The minimum sample time (NumChannels=1, ValuesPerRead=1, Resolution=16) is 38.4 microseconds, or a sampling frequency of 26.04 kHz. The maximum sample time with ValuesPerRead=1, NumChannels=4, Resolution=24 is 307.2 microseconds, or a sampling frequency of 3.255 kHz. Setting ValuesPerRead > 1 will increase the sample time and reduce the sampling frequency proportionally.

The sample time on the AH401 series is controlled by the following algorithm:
  • SampleTime = IntegrationTime * ValuesPerRead
  • If PingPong == 0 then SampleTime = SampleTime * 2
The minimum sample time is 0.001 seconds, or 1 kHz sampling frequency. The maximum sampling time (PingPong=0) is 2 seconds, or 0.5 Hz sampling frequency. Setting ValuesPerRead > 1 will increase the sample time and reduce the sampling frequency proportionally.

For the APS_EM the sample time is controlled only by ValuesPerRead and the IntegrationTime. For ValuesPerRead=1 it ranges from 0.00123 to 0.02622 s, or a sampling frequency range of about 813 Hz to 38.1 Hz. Setting ValuesPerRead > 1 will increase the sample time and reduce the sampling frequency proportionally.
QE_AVERAGING_TIME $(P)$(R)AveragingTime
$(P)$(R)AveragingTime_RBV
ao
ai
asynFloat64 r/w All Controls the time period over which values are accumulated in the ring buffer before they are read out into NDArray objects and any registered plugins are called. AveragingTime is actually used to compute NumAverage_RBV=AveragingTime/SampleTime_RBV. The callbacks are done when the number of values in the ring buffer equals NumAverage_RBV, and exactly NumAverage_RBV values will be passed to the plugins.
However, setting AveragingTime=0 will set NumAverage_RBV=0 as well, and will disable automatic callbacks to areaDetector plugins. In this case data will only be read from the ring buffer when the ReadData record is processed. This will read out all available data from ring buffer, and the actual number of values read will be NumAveraged_RBV. This mode is useful when the quadEM is being used for data acquisition, for example in a scan. In this case processing the ReadData record will read all values that have accumulated in the ring buffer since ReadData was last processed.
QE_NUM_AVERAGE $(P)$(R)NumAverage_RBV longin asynInt32 r/o All Provides the number of values that will be accumulated in the ring buffer before they are read out into NDArray objects and any registered plugins are called. NumAverage_RBV is computed as (int)((AveragingTime / SampleTime_RBV) + 0.5).
QE_NUM_AVERAGED $(P)$(R)NumAveraged_RBV longin asynInt32 r/o All Provides the number of values that were actually accumulated in the ring buffer before they were read out into NDArray objects and any registered plugins were called. If AveragingTime>0 then NumAveraged_RBV will be the same as NumAverage_RBV. However, if AveragingTime=0. then NumAverage_RBV=0 and NumAveraged_RBV gives the actual number of values read from the ring buffer when the ReadData record was processed.
QE_READ_DATA $(P)$(R)ReadData busy asynInt32 r/o All Writing 1 to this record reads all data from the ring buffer and does the NDArray callbacks to all registered plugins. This is typically done when the quadEM is being used for data acquisition, for example in a scan. In this case AveragingTime is set to 0 and processing the ReadData record will read all values that have accumulated in the ring buffer since ReadData was last processed.
QE_RING_OVERFLOWS $(P)$(R)RingOverflows longin asynInt32 r/o All It is possible for the ring buffer to overflow. The rate at which values are added to the ring buffer is controlled by SampleTime_RBV. The rate at which values are removed is determined by AveragingTime, or by the rate at which ReadData is processed if AveragingTime=0. The size of the ring buffer is determined by the ringBufferSize argument to the driver constructor. This defaults to 2048 if it is not specified in configuration command in the startup script. If the ring buffer is full when the driver tries to add a new value, then the oldest value in the buffer is discarded, the new value is added, and RingOverflows is incremented. RingOverflows is set to 0 the next time the ring buffer is read out.
QE_TRIGGER $(P)$(R)Trigger bo asynInt32 r/w AH501 and AH401 series Controls whether acquisition is free-running ("No") or triggered by an external pulse ("Yes"). On the AH501D the trigger is actually a gate. The meter acquires data only when the trigger is in the logic high state. This allows it to be controlled by a scaler gate output signal, so that the AH501D is acquiring for the same time period as the scaler, for example.
QE_RESET $(P)$(R)Reset bo asynInt32 r/w All Reset command. Processing this record will reset the electrometer. On the APS_EM this operation takes about 1 second, and may be required to establish communication if the amplifier unit is power-cycled or disconnected and reconnected. On the AH401 and AH501 series this operation downloads all of the EPICS settings to the electrometer, and must be done if the electrometer is power-cycled without rebooting the EPICS IOC.
QE_CURRENT_NAME $(P)$(R)CurrentName[1-4] stringin N.A. r/w All User-defined name to give each of the Current[1-4] inputs.
QE_CURRENT_OFFSET $(P)$(R)CurrentOffset[1-4] ao asynFloat64 (addr=0-3) r/w All Offset that will be subtracted from each reading when calculating the Current[1-4]. The current is calculated as Current = Raw*CurrentScale - CurrentOffset, where Raw is the raw value from the device.
N.A. $(P)$(R)ComputeCurrentOffset[1-4] calcout N.A. r/w All Processing this record will compute a new value of CurrentOffset that will set value of the current to 0 under the current conditions. It computes CurrentOffset(new) = Current[1-3]:MeanValue_RBV + CurrentOffset(old). This record is provided to convenience set the CurrentOffset when the input signal is 0.
QE_CURRENT_SCALE $(P)$(R)CurrentScale[1-4] ao asynFloat64 (addr=0-3) r/w All Scale factor that each reading is multiplied by when calculating the Current[1-4]. The current is calculated as Current = Raw*CurrentScale - CurrentOffset, where Raw is the raw value from the device. This record provides a way to convert the current readings into engineering units.
QE_POSITION_OFFSET $(P)$(R)PositionOffset[X,Y] ao asynFloat64 (addr=0-1) r/w All Offset that will be subtracted from each reading when calculating the Position[X,Y]. The position is calculated as Position = Diff/Sum * PositionScale - PositionOffset.
N.A. $(P)$(R)ComputePosOffset[X,Y] calcout N.A. r/w All Processing this record will compute a new value of PositionOffset that will set value of the position to 0 under the current conditions. It computes PositionOffset(new) = Pos[X,Y]:MeanValue_RBV + PositionOffset(old). This record is provided to convenience set the PositionOffset when the position should be defined as 0.
QE_POSITION_SCALE $(P)$(R)PositionScale[X,Y] ao asynFloat64 (addr=0-1) r/w All Scale that will be used when calculating the Position[X,Y]. The position is calculated as Position = Diff/Sum * PositionScale - PositionOffset.

This is the medm screen to control the quadEM with the records in quadEM.template.

quadEM.adl

quadEM.png

Plugins

The example IOCs provided with quadEM load a file called commonPlugins.cmd, which loads the following set of plugins from the areaDetector module. For more information see the documentation on NDPluginStats, NDPluginStdArrays, and NDFileNetCDF. Other plugins can also be loaded, for example the TIFF, HDF5 or Nexus file writing plugins, etc.

Plugins loaded by commonPlugins.cmd
Plugin type Record prefixes Description
NDPluginStats $(P)$(R)Current[1-4]: Statistics for the current values. The average value is $(P)$(R)Current[1-4]:MeanValue_RBV. Many other statistics are available, including the minimum, maximum, standard deviation, and histogram of values.
NDPluginStats $(P)$(R)Sum[X,Y,All]: Statistics for the sum of currents 1+2, 3+4, and 1+2+3+4. The average value is $(P)$(R)Sum[X,Y,All]:MeanValue_RBV. Many other statistics are available, including the minimum, maximum, standard deviation, and histogram of values.
NDPluginStats $(P)$(R)Diff[X,Y]: Statistics for the differences of current 2-1 and 4-3. The average value is $(P)$(R)Diff[X,Y]:MeanValue_RBV. Many other statistics are available, including the minimum, maximum, standard deviation, and histogram of values.
NDPluginStats $(P)$(R)Pos[X,Y]: Statistics for the positions. The average value is $(P)$(R)Pos[X,Y]:MeanValue_RBV. Many other statistics are available, including the minimum, maximum, standard deviation, and histogram of values.
NDPluginStdArrays $(P)$(R)image1: Plugin that receives NDArray callbacks of dimension [11,NumAveraged_RBV] and puts this data into an EPICS waveform record. This can be used to provide access to all of the data from quadEM to any Channel Access client.
NDFileNetCDF $(P)$(R)netCDF1: Plugin that receives NDArray callbacks of dimension [11,NumAveraged_RBV] and writes this data into a netCDF file. This can be done in Single mode, writing one array per file. o It can also be done in Stream mode, which continuously appends arrays to a single netCDF file.

Note that the first time the IOC is started all of the plugins will have EnableCallbacks=Disable. It is necessary to enable each of the plugins that will be used. The plugins will also initially start with CallbacksBlock=No. Setting CallbacksBlock=Yes can reduce CPU load on slow processors like the MVME2100 (see the performance tables below). The values of EnableCallbacks and CallbacksBlock are saved by autosave, and will be restored the next time the IOC is started.

This is the medm screen for all of the plugins defined in commonPlugins.cmd.

QECommonPlugins.adl

QECommonPlugins.png

This is the medm screen for the Current1: NDPluginStats plugin loaded by commonPlugins.cmd.

NDStats.adl

QENDStats.png

This is the medm screen for the netCDF1: NDFileNetCDF plugin loaded by commonPlugins.cmd.

NDFileNetCDF.adl

QENetCDF.png

Time Series

The quadEM_TimeSeries.template database provides a time-history (like a digital scope) of the current, sum, difference and position at speeds up to 6510 Hz (AH501 series), 1000Hz (AH401 series) or 813 Hz (APS_EM). The time per point can be greater than the sampling time, in which case it does averaging. It also optionally uses FFTs to compute the frequency power-spectrum of each signal. The time-series support requires the drvFastSweep driver from the synApps mca module, and also the quadEM_SNL SNL program in this quadEM module. The time-series and frequency spectra are contained in standard EPICS waveform records.

Records in quadEM_TimeSeries.template
EPICS record name EPICS record type Description
$(P)$(R)SNL_Connected bi Indicates whether the SNL program has successfully connected to all required records in quadEM_TimeSeries.template.
$(P)$(R)EraseAll bo Erases all time-series waveform records.
$(P)$(R)EraseStart bo Erases and starts time series data acquisition.
$(P)$(R)StartAll bo Re-starts acquisition without erasing the data first.
$(P)$(R)StopAll bo Stops time-series data acquisition.
$(P)$(R)Acquiring busy Indicates if tacquisition is Done or Acquiring.
$(P)$(R)MaxChannels longin The maximum number of time-series points that can be acquired. Controlled by the value specified when the quadEM_TimeSeries.template file and quadEM_SNL SNL program were loaded.
$(P)$(R)NuseAll longout Controls the number of time-series points to acquire before acquisition stops automatically.
$(P)$(R)CurrentChannel longin The current time-series data point being acquired.
$(P)$(R)ReadAll bo Forces all the time-series waveform records to process and read the current time-series data. This record can be periodically processed to read the time-series data as it is being acquired. Even if this record is Passive the time-series data will be read once when time-series data acquisition is complete.
$(P)$(R)Dwell ao The dwell time per point. This time is constrained to be an integer multiple of the SampleTime, whose range is discussed above. The readback value of $(P)$(R)Dwell_RBV gives the actual dwell time per point.
$(P)$(R)Dwell_RBV ai The actual dwell time per point, which may differ from Dwell, because the time per point is constrained to be a multiple of the sampling time.
$(P)$(R)ElapsedReal ao The elapsed real time since time-series data acquisition started.
$(P)$(R)PresetReal dfanout The preset real time. Time-series acquisition will stop if this value is reached. If this value is 0 then there is no preset real time.
$(P)$(R)AutoRestartTS bo Controls whether time-series data acquisition is automatically restarted as soon as it completes. Choices are "No" and "Yes". This can be useful for producing a continuously updating display of frequency power-spectra, for example.
$(P)$(R)Current[1-4]TS waveform The time-series values for the diode currents.
$(P)$(R)Sum[X,Y,All]TS waveform The time-series values for the diode sums.
$(P)$(R)Diff[X,Y]TS waveform The time-series values for the diode differences.
$(P)$(R)Position[X,Y]TS waveform The time-series values for the diode positions.
$(P)$(R)TimeAxis waveform An array of the times for the x-axis of time series plots.
$(P)$(R)ComputeFFT bo Controls whether FFTs power-spectra are computed when time-series data acquisition completes. Choices are "No" and "Yes". The FFT calculations are done in the SNL program using the Numerical Recipes "four1" function.
$(P)$(R)Current[1-4]FFT waveform The frequency power-spectra for the diode currents.
$(P)$(R)Sum[X,Y,All]FFT waveform The frequency power-spectra for the diode sums.
$(P)$(R)Diff[X,Y]FFT waveform The frequency power-spectra for the diode differences.
$(P)$(R)Position[X,Y]FFT waveform The frequency power-spectra for the diode positions.
$(P)$(R)FreqAxis waveform An array of the frequencies for the x-axis of frequency power-spectrum plots.
$(P)$(R)EnableClientWait bo A flag to control whether time-series data acquisition waits for a client to reset the ClientWait record.
$(P)$(R)ClientWait busy A busy record which a client must set back to 0 to enable time-series data acquisition to continue if EnableClientWait is "Enable".

This is the medm screen to control the records in quadEM_TimeSeries.template.

quadEM_TimeSeries.adl

quadEM_TimeSeries.png

This is the medm screen for the first 2 channels. It contains the currents, sum and position as a function of time. The dwell time was 0.002s, and there are 2048 channels (time points), so the total time is 4.096 seconds.

quadEM_PlotAll.adl

quadEM_TimeSeriesPlot.png

This is an medm screen that displays the FFTs of the Current, Sum, and Position for the time-series data above.

quadEM_plotAll.adl

quadEM_FFTPlot.png

fast_pid_control.db

The quadEM can be used to do fast feedback with the EPID record from the synApps "std" module. The EPID record will process at up to the SampleTime discussed above. The DT field of the EPID record controls the time between feedback calculations, and this is constrained to be an integer multiple N of the quadEM SampleTime. If N>1 then N samples are averaged for each feedback operation.

This is the medm screen that controls the fast feedback of the pitch of the monochromator on APS beamline 13-ID. The readback and control PVs cannot be changed after iocInit. The update rate (SCAN rate of EPID record) only controls the rate at which the EPID record displays "snapshots" of the values of the input, output, and error. It does not affect the rate at which the feedback is actually being done, which is controlled by the DT field in the EPID record, can be much faster than the SCAN value.

pid_control.adl

quadEM_pid_control.png

This is the medm screen that controls the PID parameters. These include the feedback coefficients KP, KI, and KD. The DT (delta time) field controls the rate at which the feedback is actually been run. In this case DT=68.0 ms, which is 55 times longer than the sampling time (1.23 ms), so 55 position readings are being averaged each time the feedback is run.

pid_parameters.adl

quadEM_pid_parameters.png

This is an medm screen that displays the setpoint of the pitch of the monochromator (in red), and the actual readback from the quadEM (in blue). Note that the readback here is only the snapshot values from the EPID record. For full-speed readings of the readback the waveform records from the quadEM_TimeSeries.template database would be used.

pid_plot_readback.adl

quadEM_plot_readback.png

This is pid_fast.template, an example substitutions file. This example uses a quadEM asyn port driver named "APS_EM". ICHAN is set to read from addr=9 and 10, which are the two position values of the quadEM driver. The INPUT_DATA and INPUT_INTERVAL strings are the drvInfo strings for these parameters in the driver. The output is sent to an asyn port driver named DAC1, which is a dac128V 12-bit A/D converter in this data. OCHAN is set to write to addr=1 and 2, which are the second and third DAC channels on that card. The OUTPUT_DATA string is the drvInfo string for the double precision data in the dac128V.

file "$(STD)/stdApp/Db/fast_pid_control.db"
{
pattern
{P,                 PID,  INPUT,     INPUT_DATA,   INPUT_INTERVAL, ICHAN, OUTPUT, OCHAN,  OUTPUT_DATA,    LOPR,     HOPR,  DRVL,  DRVH,  PREC,   KP,    KI,  KD,   DT,        SCAN}
{quadEMTest:, MonoPitch, APS_EM, QE_DOUBLE_DATA,   QE_SAMPLE_TIME,     9,   DAC1,     1,  DOUBLE_DATA,  -32767,    32767,     0,  4095,     3,  .02,  100.,  0., .001, ".1 second"}
{quadEMTest:,  MonoRoll, APS_EM, QE_DOUBLE_DATA,   QE_SAMPLE_TIME,    10,   DAC1,     2,  DOUBLE_DATA,  -32767,    32767,     0,  4095,     3,  .02,  100.,  0., .001, ".1 second"}
}

Performance

The following table shows the CPU utilization of a Linux machine (Xeon E5630 2.53GHz), vxWorks MVME5100, and vxWorks MVME2100 with the AH501 electometer. The CPU load was measured as a function of the parameters that control the SampleTime (ValuesPerRead, NumChannels, Resolution). The CPU load also depends on the AveragingTime, since that controls the rate of callbacks to the statistics and other plugins. The AveragingTime was mostly held constant at 0.1 seconds on vxWorks, but was changed between 0.1 second and 0.01 seconds on Linux. Measurements were also done with all of the plugins set to CallbacksBlock=Yes and CallbacksBlock=No. When CallbacksBlock=No then each plugin runs in its own thread. On a multi-core system this can improve performance because each plugin runs in its own core. On a single-core system CallbacksBlock=Yes can improve performance because a single thread runs all of the the plugin code, and thread context switches are avoided.

It can be seen that the load on Linux is less than 10% when the AveragingTime is 0.1 second, and less than 25% when it is 0.01 second. Tests on a Windows 7 64-bit machine (Intel Core i7-2820QM 2.3GHz) gave very similar results to Linux. Note that the Linux (and Windows CPU) values listed are the percent of a single CPU core. These are 8-core systems, so the percent of the total system CPU is 8 times less. The load on the MVME5100 is significant, but it can handle NumChannels=4 with ValuesPerRead=1 for either resolution. The MVME2100 on the other hand cannot run with ValuesPerRead=1 at all, it completely saturates the system. It does work with ValuesPerRead=4 or 10. On the MVME 2100 setting CallbacksBlock=Yes does signficantly reduce the CPU load.

Performance of AH501 using TCP
System ValuesPerRead NumChannels Resolution AveragingTime CallbacksBlock %CPU time
Linux Xeon 1 4 16 0.1 No 5%
Linux Xeon 1 4 24 0.1 No 4%
Linux Xeon 1 4 16 0.01 No 25%
Linux Xeon 1 4 16 0.01 Yes 19%
Linux Xeon 1 4 24 0.01 No 25%
Linux Xeon 1 4 24 0.01 Yes 18%
Linux Xeon 1 2 16 0.1 No 7%
Linux Xeon 1 2 24 0.1 No 6%
Linux Xeon 1 1 16 0.1 No 10%
Linux Xeon 1 1 24 0.1 No 8%
MVME5100 1 4 16 0.1 No 28%
MVME5100 1 4 16 0.1 Yes 29%
MVME5100 1 4 24 0.1 No 22%
MVME5100 1 4 24 0.1 Yes 23%
MVME5100 2 4 24 0.1 No 11%
MVME5100 1 2 24 0.1 No 32%
MVME5100 1 1 24 0.1 No 55%
MVME5100 2 1 16 0.1 No 45%
MVME2100 4 4 16 0.1 No 65%
MVME2100 4 4 24 0.1 No 55%
MVME2100 4 4 24 0.1 Yes 45%
MVME2100 10 4 24 0.1 Yes 31%
MVME2100 10 4 24 0.2 Yes 22%
MVME2100 10 2 24 0.1 Yes 35%
MVME2100 10 1 24 0.1 Yes 42%
MVME2100 10 4 16 0.1 No 46%
MVME2100 10 1 16 0.1 Yes 54%

The following table shows the CPU utilization of the Linux machine, vxWorks MVME5100, and vxWorks MVME2100 with the AH401B electometer as a function of the AveragingTime and CallbacksBlock at the shortest integration time (0.001 seconds). It can be seen that the load on Linux and on the MVME5100 are both less than 10% when AveragingTime=0.1 second. The MVME2100 uses about 50% of the CPU under these conditions, but increasing ValuesPerRead and/or AveragingTime reduces this.

Performance of AH401B using TCP
System ValuesPerRead IntegrationTime AveragingTime CallbacksBlock %CPU time
Linux Xeon 1 0.001 0.1 No 4%
Linux Xeon 1 0.001 0.1 Yes 3%
Linux Xeon 1 0.001 0.01 No 13%
Linux Xeon 1 0.001 0.01 Yes 14%
MVME5100 1 0.001 0.1 No 7%
MVME5100 1 0.001 0.1 Yes 9%
MVME5100 1 0.001 0.01 No 56%
MVME5100 1 0.001 0.01 Yes 36%
MVME2100 1 0.001 0.1 No 55%
MVME2100 1 0.001 0.1 Yes 50%
MVME2100 1 0.001 0.2 No 20%
MVME2100 4 0.001 0.2 Yes 15%

The following table shows the CPU utilization of vxWorks MVME5100 and vxWorks MVME2100 with the APS electometer as a function of the ValuesPerRead, IntegrationTime, AveragingTime, and CallbacksBlock. The MVME5100 uses less than 10% of the CPU under the conditions measured. The MVME2100 uses almost 70% of the CPU at the fastest sampling time, but doubling ValuesPerRead and AveragingTime reduces this to less than 25%.

Performance of APS Electometer
System ValuesPerRead IntegrationTime AveragingTime CallbacksBlock %CPU time
MVME5100 1 0.0006 0.1 No 10%
MVME5100 1 0.0006 0.1 Yes 9%
MVME5100 2 0.0006 0.1 No 5%
MVME5100 2 0.0006 0.1 Yes 7%
MVME5100 1 0.001 0.1 No 6%
MVME5100 1 0.001 0.1 Yes 5%
MVME2100 1 0.0006 0.1 No 68%
MVME2100 1 0.0006 0.1 Yes 55%
MVME2100 2 0.0006 0.1 No 53%
MVME2100 2 0.0006 0.1 Yes 41%
MVME2100 1 0.001 0.1 No 50%
MVME2100 1 0.001 0.1 Yes 40%
MVME2100 2 0.001 0.2 Yes 22%

Common Setup

All of the device-dependent startup scripts invoke quadEM/iocBoot/iocTest/commonPlugins.cmd. This file can be edited to add additional plugins, such as the TIFF, HDF5, or Nexus file writers, etc.

AH401 and AH501 Series Setup

These meters communicates via IP, so they must be configured with an IP address reachable from the host IOC machine. The Lantronix module in the meters can be configured to use either UDP (recommended to reduce CPU load, particularly on AH501 series) or TCP. The startup script must include the UDP qualifier on the drvAsynIPPortConfigure command if UDP is selected.

Example startup scripts for Linux or Windows are provided in
quadEM/iocBoot/iocTest/st.cmd.AH401B and
quadEM/iocBoot/iocTest/st.cmd.AH501

These will need to be edited to set the correct IP address of the meters to be used.

These scripts each invoke a generic script:
quadEM/iocBoot/iocTest/st.cmd.AHxxx.

APS Electrometer Setup

The APS_EM VME card cannot generate interrupts, but it can output a TTL pulse each time new data is available, at up to 815 Hz. If this pulse is input to an Ip-Unidig (or other asyn digital I/O device with interrupt and callback capabilities), then the ipUnidig interrupt routine will call the APS_EM driver each time new data is available. The Ip-Unidig channel where the APS_EM pulse is connected is specified in the unidigChan argument to drvAPS_EMConfigure command in the startup script. If an Ip-Unidig or other interrupt source is not being used then the APS_EM driver will poll for new data at the system clock rate, typically 60Hz.

An example startup script for vxWorks is provided in
quadEM/iocBoot/iocTest/st.cmd.vxWorks.

This example startup script can be edited to start either the APS_EM, the AH401B, or the AH501. For the APS_EM this script invokes
quadEM/iocBoot/iocTest/st.cmd.APS_EM.