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 two models:
Both of these units 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 quadEM software includes asyn drivers and an SNL program that provide support for the following:
Detailed information on the APS electrometer can be found in the Electrometer Users Guide.
Detailed information on the AH401B electrometer can be found in the AH401B Users Manual.
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 AH401B (drvAH401B.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 | Description | |
---|---|---|---|---|---|---|
QE_ACQUIRE | $(P)$(R)Acquire | bo | asyInt32 | r/w | Acquire command. This command turns acquisition on (1) and off (0). | |
QE_RANGE | $(P)$(R)Range | mbbo | asyInt32 | r/w |
Range command. This selects the feedback capacitor, which controls the gain of the
device. There are 8 capacitor choices. For the AH401B the choices are in units of
saturation charge:
|
|
QE_PING_PONG | $(P)$(R)PingPong | mbbo | asyInt32 | r/w |
Both the AH401B 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 AH401B 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 |
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 AH401B 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_SAMPLE_TIME | $(P)$(R)SampleTime_RBV | ai | asynFloat64 | r/w | Contains the actual time between sample readings from the device. This is controlled by the value of IntegrationTime, and for the AH401B also by the value of PingPong. | |
QE_TRIGGER | $(P)$(R)Trigger | bo | asynInt32 | r/w | Controls whether acquistion is free-running ("No") or triggered by an external pulse ("Yes"). This is only supported on the AH401B, the APS_EM does not support external triggering. | |
QE_RESET | $(P)$(R)Reset | bo | asyInt32 | r/w | 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 AH401B 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 | 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 | Offset that will be subtracted from the computed position. | |
QE_POSITION_SCALE | $(P)$(R)PositionScale[12,34] | ao | asynInt32 (addr=0-1) | r/w | Scale factor used when computing the position. | |
QE_DATA | $(P)$(R)Current[1-4] | ai | asynInt32 (addr=0-3) | r/o | 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 AH401B 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 | 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 | 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 | 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 | 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 | 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 1000Hz (AH401B) 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 sampling time, which is in the range 0.001s to 1.0s for the AH401B and 0.00123s to 0.002622s for the APS_EM, depending on the IntegrationTime record. 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 1000 Hz (AH401B) or 813 Hz (APS_EM). 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 sampling time. 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 AH401B communicates via TCP/IP, so it must be configured with an IP address reachable from the host IOC machine.
An example startup script for Linux (or Windows) is provided in quadEM/iocBoot/iocTest.st.cmd.linux. This will need to be edited to set the correct IP address of the AH401B to be used.
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 with the APS_EM is provided in quadEM/iocBoot/iocTest.st.cmd.vxWorks. This example startup script actually starts both an AH401B ($(R)=QE1:) and an APS_EM ($(R)=QE2:) driver. One or the other can be commented out for testing if both devices are not available.