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:
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 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.template database provides control of the electrometer and analog input records using the standard asyn device support. This provides digitally averaged readings of the current, sum, difference and position at speeds up to 10 Hz with standard EPICS scan times. For the data values the analog input records use asynInt32Average device support, which averages all callback readings between record processing. The driver also does callbacks for these same values on the asynFloat64 interface, which is required by the fast feedback device support for the EPID record. It also does asynInt32Array callbacks with an array for each of the 11 values (Current1 to Position34), which is required by the drvFastSweep driver for time-series data.
Records in quadEM.template | ||||||
drvInfo string | EPICS record name | EPICS record type | asyn interface | Access | Models supported | Description |
---|---|---|---|---|---|---|
QE_MODEL | $(P)$(R)Model | mbbi | asyInt32 | r/o | All |
The model of the electrometer. This is determined automatically by the driver. Values
are:
|
QE_ACQUIRE | $(P)$(R)Acquire | bo | asyInt32 | r/w | All | Acquire command. This command turns acquisition on (1) and off (0). |
QE_RANGE | $(P)$(R)Range | mbbo | asyInt32 | r/w | All |
Range command. This selects the sensitivity of the electrometer (A/D units per nanoamp). For the AH501 series the choices are:
|
QE_PING_PONG | $(P)$(R)PingPong | mbbo | asyInt32 | 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 | ao | 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 | mbbo | 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:
|
QE_RESOLUTION | $(P)$(R)Resolution | mbbo | 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 26-bits. Allowed choices are:
|
QE_BIAS_STATE | $(P)$(R)BiasState | bo | asynInt32 | r/w | AH501C and AH501D |
Selects the state of the bias supply output voltage. Allowed choices are:
|
QE_BIAS_VOLTAGE | $(P)$(R)BiasVoltage | ao | asynFloat64 | r/w | AH501C and AH501D | Controls the voltage of the bias supply output. |
QE_NUM_AVERAGE | $(P)$(R)NumAverage | longout | asynInt32 | r/w | All |
Controls the number of readings from the meter that are averaged in the driver before
it does callbacks. The default is 1 (no averaging). Setting NumAverage > 1 will
reduce the CPU time for 2 reasons:
|
QE_SAMPLE_TIME | $(P)$(R)SampleTime_RBV | ai | asynFloat64 | r/w | All |
Provides the actual time between sample readings from the device. This is controlled
by the following parameters:
The sample time on the AH401 series is controlled by the following algorithm:
For the APS_EM the sample time is controlled only by NumAverage and the IntegrationTime, which ranges from 0.00123 to 0.02622 s, or a sampling frequency range of about 813 Hz to 38.1 Hz. |
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"). |
QE_RESET | $(P)$(R)Reset | bo | asyInt32 | 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_OFFSET | $(P)$(R)CurrentOffset[1-4] | ao | asynInt32 (addr=0-3) | r/w | All | Offset that will be subtracted from each reading before calculating the Current[1-4]. |
QE_POSITION_OFFSET | $(P)$(R)PositionOffset[12,34] | ao | asynInt32 (addr=0-1) | r/w | All | Offset that will be subtracted from the computed position. |
QE_POSITION_SCALE | $(P)$(R)PositionScale[12,34] | ao | asynInt32 (addr=0-1) | r/w | All | Scale factor used when computing the position. |
QE_DATA | $(P)$(R)Current[1-4] | ai | asynInt32 (addr=0-3) | r/o | All | The value of the current. This is calculated as measuredValue-CurrentOffset. These records use asynInt32Average device support so they average the readings from the device since the time the record was last processed. For example with the AH401 series if PingPong="On" and the integration time is 0.002s (500 Hz), if the Read record .SCAN field is 1 second then 500 readings will be averaged. |
QE_DATA | $(P)$(R)Sum[12,34,1234] | ai | asynInt32 (addr=4-6) | r/o | All | The sum of diodes 1+2, 3+4, and 1+2+3+4. These records use asynInt32Average device support so they average the readings from the device since the time the record was last processed. |
QE_DATA | $(P)$(R)Diff[12,34] | ai | asynInt32 (addr=7-8) | r/o | All | The difference of the diode pair 2-1 and 4-3. These records use asynInt32Average device support so they average the readings from the device since the time the record was last processed. |
QE_DATA | $(P)$(R)Position[12,34] | ai | asynInt32 (addr=9-10) | r/o | All | The position of the diode pair. This is calculated as ((Diff/Sum)*PositionScale - PositionOffset). These records use asynInt32Average device support so they average the readings from the device since the time the record was last processed. |
QE_DOUBLE_DATA | N.A. | N.A. | asynFloat64 (addr=0-10) | r/o | All | The QE_DOUBLE_DATA drvInfo string is used to read the same information as QE_DATA, but using the asynFloat64 interface rather than the asynInt32 interface. This is provided to support the fast feedback device support for the EPID record, which is provided in the synApps "std" module. That device support expects callbacks on the asynFloat64 interface for its input data. |
N.A. | $(P)$(R)Read | ai | N.A. | r/w | All | Processing this record reads all of the Position, Sum, Diff, and Position records using forward links. |
This is the medm screen to control the quadEM with the records in quadEM.template.
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 | Starts all the MCA records without erasing them first. |
$(P)$(R)StopAll | bo | Stops time-series data acquisition. |
$(P)$(R)Acquiring | bo | Stops time-series data acquisition. |
$(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[12,34,1234]TS | waveform | The time-series values for the diode sums. |
$(P)$(R)Diff[12,34]TS | waveform | The time-series values for the diode sums. |
$(P)$(R)Position[12,34]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[12,34,1234]FFT | waveform | The frequency power-spectra for the diode sums. |
$(P)$(R)Diff[12,34]FFT | waveform | The frequency power-spectra for the diode sums. |
$(P)$(R)Position[12,34]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.
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.
This is an medm screen that displays the FFTs of the Current, Sum, and Position for the time-series data above.
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.
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.
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.
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"} }
The following table shows the CPU utilization of a Linux machine (Xeon E5630 2.53GHz), vxWorks MVME2100, and vxWorks MVME5100 with the AH501 electometer as a function of the parameters that control the SampleTime. It can be seen that the load on Linux is very low. Tests on a Windows 7 64-bit machine (Intel Core i7-2820QM 2.3GHz) gave almost identical 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 NumAverage=1 for either resolution. The MVME2100 on the other hand cannot run with NumAverage=1 at all, it completely saturates the system. It does work NumAverage=4 or 10.
Performance of AH501 using UDP | ||||
System | NumChannels | Resolution | NumAverage | %CPU time |
---|---|---|---|---|
Linux Xeon | 4 | 24 | 1 | 4% |
Linux Xeon | 4 | 24 | 2 | 2% |
Linux Xeon | 2 | 24 | 1 | 5% |
Linux Xeon | 1 | 24 | 1 | 9% |
Linux Xeon | 4 | 16 | 1 | 4% |
Linux Xeon | 2 | 16 | 1 | 6% |
Linux Xeon | 1 | 16 | 1 | 7% |
MVME5100 | 4 | 24 | 1 | 37% |
MVME5100 | 4 | 24 | 2 | 18% |
MVME5100 | 4 | 24 | 4 | 9% |
MVME5100 | 2 | 24 | 1 | 50% |
MVME5100 | 2 | 24 | 2 | 24% |
MVME5100 | 4 | 16 | 1 | 43% |
MVME5100 | 4 | 16 | 2 | 20% |
MVME5100 | 2 | 16 | 1 | 66% |
MVME5100 | 2 | 16 | 2 | 36% |
MVME5100 | 1 | 16 | 1 | 91% |
MVME5100 | 1 | 16 | 2 | 48% |
MVME5100 | 1 | 16 | 4 | 27% |
MVME2100 | 4 | 24 | 2 | 77% |
MVME2100 | 4 | 24 | 3 | 52% |
MVME2100 | 4 | 24 | 4 | 43% |
MVME2100 | 4 | 24 | 10 | 19% |
MVME2100 | 4 | 16 | 4 | 41% |
MVME2100 | 4 | 16 | 10 | 15% |
MVME2100 | 1 | 16 | 10 | 50% |
MVME2100 | 1 | 16 | 20 | 29% |
The following table shows the CPU utilization of the Linux machine, vxWorks MVME2100, and vxWorks MVME5100 with the AH401B electometer as a function of the parameters that control the SampleTime. It can be seen that the load on Linux is almost unmeasurable. The load on the MVME5100 is small. The MVME2100 uses almost 50% of the CPU at the fastest sampling time, but increasing NumAverage or IntegrationTime reduces this to a small value.
Performance of AH401B using TCP | ||||
System | IntegrationTime | PingPong | NumAverage | %CPU time |
---|---|---|---|---|
Linux Xeon | 0.001 | 1 | 1 | 1% |
Linux Xeon | 0.001 | 1 | 2 | <1% |
MVME5100 | 0.001 | 1 | 1 | 12% |
MVME5100 | 0.001 | 1 | 2 | 7% |
MVME2100 | 0.001 | 1 | 1 | 47% |
MVME2100 | 0.001 | 1 | 2 | 27% |
MVME2100 | 0.001 | 1 | 4 | 16% |
The following table shows the CPU utilization of vxWorks MVME2100, with the APS electometer as a function of the parameters that control the SampleTime. The MVME2100 uses almost 50% of the CPU at the fastest sampling time, but increasing NumAverage or IntegrationTime reduces this to a small value. The MVME2700 and MVME5100 would show significantly lower CPU values, but measurements were not done with those systems with the test application.
Performance of APS Electometer | |||
System | IntegrationTime | NumAverage | %CPU time |
---|---|---|---|
MVME2100 | 0.0006 | 1 | 49% |
MVME2100 | 0.0006 | 2 | 35% |
MVME2100 | 0.001 | 1 | 40% |
MVME2100 | 0.002 | 1 | 20% |
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.
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.