* Implemented support for diabling theshold channel * Separate proton current simulation db. * Separate startup snippet with support for simulation mode. * Short readme entry
316 lines
11 KiB
Markdown
316 lines
11 KiB
Markdown
SINQDAQ Epics Module
|
|
-----------------------
|
|
|
|
A Stream and Asyn based driver for configuring the Data Acquisition Systems at
|
|
SINQ.
|
|
|
|
This supports the older 4 and 8 channel EL737 models and the new 10CH 2nd
|
|
generation systems.
|
|
|
|
**Note:** the epics side of this interface is also implemented/shared by the
|
|
[StreamGenerator](https://gitea.psi.ch/lin-epics-modules/StreamGenerator)
|
|
module.
|
|
|
|
## Functional Differences Between Models
|
|
|
|
The 2nd Generation DAQ offers some additional features that aren't available on the
|
|
older EL737 Counterboxes. Specifically,
|
|
|
|
* the possibility to change the channel monitored by the count-based preset (on
|
|
the older EL737 boxes, only the 1st channel can be used)
|
|
* two gating inputs, that enable counting to be halted via configurable
|
|
high/low electrical inputs.
|
|
* a test signal generator
|
|
|
|
Furthermore, the 2nd Generation DAQ's have 10 input channels, in place of the 8
|
|
or 4 channels on the older EL737 Counterboxes.
|
|
|
|
## How to Use
|
|
|
|
Unless a custom database is needed, a device can be configure simply by setting
|
|
the required environment variables when calling the correct DAQ interface
|
|
script.
|
|
|
|
Required Variables
|
|
|
|
| Environment Variable | Purpose |
|
|
|----------------------|-----------------------------------------|
|
|
| INSTR | Prefix of all device specific PVs |
|
|
| NAME | First field in all PVs after Prefix |
|
|
| DAQ\_IP | Network IP of device |
|
|
| DAQ\_PORT | Network Port of device |
|
|
|
|
All PVs take the form
|
|
|
|
```
|
|
$(INSTR)$(NAME):*
|
|
```
|
|
|
|
Available device startup scripts
|
|
|
|
* scripts/daq\_4ch.cmd
|
|
* scripts/daq\_8ch.cmd
|
|
* scripts/daq\_2nd\_gen.cmd
|
|
|
|
A device can be configured using one of the startup scripts as follows
|
|
|
|
```
|
|
epicsEnvSet("INSTR", "SQ:INSTRUMENT:") # can also be set in runScript call
|
|
|
|
runScript "$(sinqDAQ_DIR)daq_2nd_gen.cmd" "NAME=DAQ, DAQ_IP=TestInst-DAQ1, DAQ_PORT=2000"
|
|
```
|
|
|
|
## PVs of Interest
|
|
|
|
| PV | Description |
|
|
|-------------------------------------|----------------------------------------------------------------------|
|
|
| \$(INSTR)\$(NAME):MsgTxt | Contains unexpected response to executed command |
|
|
| \$(INSTR)\$(NAME):STATUS | 0: Idle, 1: Counting, 2: Low rate, 3: Paused, 4: Error |
|
|
| \$(INSTR)\$(NAME):MONITOR-CHANNEL | Channel that PRESET-COUNT monitors (has RBV, only v2 can be changed) |
|
|
| \$(INSTR)\$(NAME):PRESET-COUNT | Run count until specified pv value reached |
|
|
| \$(INSTR)\$(NAME):PRESET-TIME | Run count until specified pv value in seconds reached |
|
|
| \$(INSTR)\$(NAME):THRESHOLD | Minimum rate for counting to preceed. (has RBV) |
|
|
| \$(INSTR)\$(NAME):THRESHOLD-MONITOR | Channel monitored for minimum rate (has RBV) |
|
|
| \$(INSTR)\$(NAME):ELAPSED-TIME | Time DAQ has been measuring for |
|
|
| \$(INSTR)\$(NAME):M_ | Current count on channel. (1-10 depending on DAQ system) |
|
|
| \$(INSTR)\$(NAME):CHANNELS | Number of available channels (4, 8 or 10) |
|
|
| \$(INSTR)\$(NAME):GATE-_ | Configuration for Gating in newer hardware |
|
|
|
|
## Generating Test Signals
|
|
|
|
The 2nd Generation DAQ's have two test channels that can be used to output
|
|
signals at a variable rate. These can be used to ensure the other channels are
|
|
working and to check the IOC - Nicos integration. These can be loaded at
|
|
runtime via the following
|
|
|
|
```
|
|
epicsEnvSet("LOAD_TEST_PVS","")
|
|
runScript "$(sinqDAQ_DIR)daq_2nd_gen.cmd" "NAME=DAQ, DAQ_IP=TestInst-DAQ1, DAQ_PORT=2000"
|
|
```
|
|
|
|
See the file [daq\_2nd\_gen\_test.db](./db/daq_2nd_gen_test.db)
|
|
|
|
## Nicos Interface
|
|
|
|
A set of Nicos devices have been developed which allow control of the Detector
|
|
Hardware via this Epics Driver. The corresponding code can be found in
|
|
[sinqdaq.py](https://gitea.psi.ch/lin-instrument-computers/Nicos/src/branch/release-3.12/nicos_sinq/devices/epics/sinqdaq.py).
|
|
|
|
## Full Example of 8 Channel EL737 Counterbox
|
|
|
|
Include the following snippet in your IOC
|
|
|
|
```
|
|
# st.cmd at TASP
|
|
|
|
epicsEnvSet("STREAM_PROTOCOL_PATH","./db")
|
|
epicsEnvSet("INSTR","SQ:SINQTEST:")
|
|
|
|
require sinqDAQ
|
|
runScript "$(sinqDAQ_DIR)daq_8ch.cmd" "NAME=counter, DAQ_IP=tasp-ts0, DAQ_PORT=3004"
|
|
```
|
|
|
|
What follows is an example Nicos setup file.
|
|
|
|
```
|
|
# simplified tasp.py
|
|
|
|
countprefix = 'SQ:TASP:counter'
|
|
|
|
configured_channels = ['detector', 'protoncount']
|
|
|
|
devices = dict(
|
|
elapsedtime = device(
|
|
'nicos_sinq.devices.epics.sinqdaq.DAQTime',
|
|
daqpvprefix = countprefix,
|
|
),
|
|
detector = device(
|
|
'nicos_sinq.devices.epics.sinqdaq.DAQChannel',
|
|
description = 'Actual neutron detector',
|
|
daqpvprefix = countprefix,
|
|
channel = 1,
|
|
type = 'counter',
|
|
),
|
|
protoncount = device(
|
|
'nicos_sinq.devices.epics.sinqdaq.DAQChannel',
|
|
description = 'Monitor for proton current',
|
|
daqpvprefix = countprefix,
|
|
channel = 2,
|
|
type = 'monitor',
|
|
),
|
|
DAQPreset = device(
|
|
'nicos_sinq.devices.epics.sinqdaq.DAQPreset',
|
|
description = '8 Channel EL737 Counterbox',
|
|
daqpvprefix = countprefix,
|
|
channels = configured_channels,
|
|
time_channel = ['elapsedtime'],
|
|
),
|
|
ThresholdChannel = device(
|
|
'nicos_sinq.devices.epics.sinqdaq.DAQMinThresholdChannel',
|
|
daqpvprefix = countprefix,
|
|
channels = configured_channels,
|
|
),
|
|
Threshold = device(
|
|
'nicos_sinq.devices.epics.sinqdaq.DAQMinThreshold',
|
|
daqpvprefix = countprefix,
|
|
min_rate_channel = 'ThresholdChannel',
|
|
),
|
|
taspdet = device(
|
|
'nicos_sinq.devices.epics.sinqdaq.SinqDetector',
|
|
description = 'Detector Interface',
|
|
timers = ['elapsedtime'],
|
|
monitors = ['DAQPreset'] + configured_channels,
|
|
others = [],
|
|
liveinterval = 1,
|
|
),
|
|
)
|
|
|
|
startupcode = '''
|
|
SetDetectors(taspdet)
|
|
ThresholdChannel.move('protoncount')
|
|
'''
|
|
```
|
|
|
|
## Full Example of 2nd Generation DAQ
|
|
|
|
Include the following snippet in your IOC
|
|
|
|
```
|
|
# st.cmd at SINQTEST
|
|
|
|
epicsEnvSet("STREAM_PROTOCOL_PATH","./db")
|
|
epicsEnvSet("INSTR","SQ:SINQTEST:")
|
|
|
|
require sinqDAQ
|
|
runScript "$(sinqDAQ_DIR)daq_2nd_gen.cmd" "NAME=DAQ, DAQ_IP=TestInst-DAQ1, DAQ_PORT=2000"
|
|
```
|
|
|
|
What follows is an example Nicos setup file. The "channels" are created in the loop
|
|
at the bottom.
|
|
|
|
```
|
|
# DAQDetector.py
|
|
description = 'Devices for the detectors'
|
|
|
|
countprefix = 'SQ:SINQTEST:DAQ'
|
|
|
|
devices = dict(
|
|
ElapsedTime = device(
|
|
'nicos_sinq.devices.epics.sinqdaq.DAQTime',
|
|
daqpvprefix = countprefix,
|
|
),
|
|
DAQPreset = device(
|
|
'nicos_sinq.devices.epics.sinqdaq.DAQPreset',
|
|
description = '2nd Generation Data Acquisition',
|
|
daqpvprefix = countprefix,
|
|
channels = [],
|
|
time_channel = ['ElapsedTime'],
|
|
),
|
|
DAQV2 = device(
|
|
'nicos_sinq.devices.epics.sinqdaq.SinqDetector',
|
|
description = 'Detector Interface',
|
|
timers = ['ElapsedTime'],
|
|
counters = [],
|
|
monitors = ['DAQPreset'],
|
|
images = [],
|
|
others = [],
|
|
liveinterval = 2,
|
|
saveintervals = [2]
|
|
),
|
|
ThresholdChannel = device(
|
|
'nicos_sinq.devices.epics.sinqdaq.DAQMinThresholdChannel',
|
|
daqpvprefix = countprefix,
|
|
channels = [],
|
|
),
|
|
Threshold = device(
|
|
'nicos_sinq.devices.epics.sinqdaq.DAQMinThreshold',
|
|
daqpvprefix = countprefix,
|
|
min_rate_channel = 'ThresholdChannel',
|
|
),
|
|
Gate1 = device(
|
|
'nicos_sinq.devices.epics.sinqdaq.DAQGate',
|
|
daqpvprefix = countprefix,
|
|
channel = 1,
|
|
visibility = {'metadata', 'namespace'},
|
|
),
|
|
Gate2 = device(
|
|
'nicos_sinq.devices.epics.sinqdaq.DAQGate',
|
|
daqpvprefix = countprefix,
|
|
channel = 2,
|
|
visibility = {'metadata', 'namespace'},
|
|
),
|
|
# Only necessary if you want to use the signal generator in the
|
|
# 2nd Generation DAQ for testing.
|
|
TestGen = device('nicos_sinq.devices.epics.sinqdaq.DAQTestGen',
|
|
daqpvprefix = countprefix,
|
|
visibility = {'metadata', 'namespace'},
|
|
),
|
|
)
|
|
|
|
# On an actual instrument, it might be better if instead of just calling
|
|
# your channels 'Monitor <num>', you describe what is actually plugged
|
|
# into the DAQ on each channel.
|
|
for i in range(10):
|
|
devices[f'monitor{i+1}'] = device(
|
|
'nicos_sinq.devices.epics.sinqdaq.DAQChannel',
|
|
description = f'Monitor {i + 1}',
|
|
daqpvprefix = countprefix,
|
|
channel = i + 1,
|
|
type = 'monitor',
|
|
)
|
|
devices['DAQPreset'][1]['channels'].append(f'monitor{i+1}')
|
|
devices['ThresholdChannel'][1]['channels'].append(f'monitor{i+1}')
|
|
devices['DAQV2'][1]['monitors'].append(f'monitor{i+1}')
|
|
|
|
startupcode = '''
|
|
SetDetectors(DAQV2)
|
|
'''
|
|
```
|
|
|
|
## Simulation
|
|
|
|
Simulation of the Hardware can be toggled on as follows:
|
|
|
|
```
|
|
epicsEnvSet("SET_SIM_MODE","") # run DAQ simulation instead of connecting to actual system
|
|
runScript "$(sinqDAQ_DIR)daq_2nd_gen.cmd" "NAME=CB_TEST, DAQ_IP=localhost, DAQ_PORT=2000"
|
|
```
|
|
|
|
In such a case, the provided `DAQ_IP` is ignored, and a python program
|
|
simulating the hardware is started in the background, listening at the
|
|
specified `DAQ_PORT`. So, if you have multiple devices listening on the same
|
|
port, you might have to change this port value of one of the devices when
|
|
simulating hardware. You can then interact with the PVs as with the normal
|
|
hardware. Keep in mind, however, that not all functionality has been
|
|
implemented.
|
|
|
|
See [sim/daq\_sim.py](sim/daq_sim.py).
|
|
|
|
## Testing
|
|
|
|
An IOC with the 2nd generation DAQ started in simulation mode can be started
|
|
via the [test/ioc.sh](test/ioc.sh) script.
|
|
|
|
There is also a simple automated test that can be run for a simple check of
|
|
functionality and that the PVs load [test/test.py](test/test.py).
|
|
|
|
Both require that the module has been built and installed as is normal in the
|
|
require based module system.
|
|
|
|
You might have to change the specified version in the
|
|
[test/st.cmd](test/st.cmd) file to the version you compiled and want to test.
|
|
|
|
## Software based proton current DAQ
|
|
This repository also contain a software based DAQ implementation that just
|
|
requires a channel access link (remote Process Variable) to a proton rate.
|
|
From that it implements the same interface as the counter boxes, and is
|
|
compatible with the sinqdaq device in Nicos, albeit with only one channel.
|
|
|
|
### Simulated software based proton current DAQ
|
|
You can start a proton current DAQ based on a simulation with the following
|
|
command on any PC having the SINQ epics environment installed.
|
|
```
|
|
iocsh -r sinqDAQ,0.4.0 -c 'epicsEnvSet(SET_SIM_MODE,"" )' -c 'epicsEnvSet(INSTR,SQ:TEST:)' -c 'epicsEnvSet(NAME, SPC)' -c 'runScript($(sinqDAQ_DIR)daq_soft_proton.cmd'
|
|
```
|
|
|