adds gating stuff, writes all thresholds simultaneously, updates readme with example
This commit is contained in:
100
README.md
100
README.md
@ -56,6 +56,7 @@ runScript "$(sinqDAQ_DIR)daq_2nd_gen.cmd" "NAME=DAQ, DAQ_IP=TestInst-DAQ1, DAQ_P
|
|||||||
| \$(INSTR)\$(NAME):ELAPSED-TIME | Time DAQ has been measuring for |
|
| \$(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):M_ | Current count on channel. (1-10 depending on DAQ system) |
|
||||||
| \$(INSTR)\$(NAME):CHANNELS | Number of available channels (4, 8 or 10) |
|
| \$(INSTR)\$(NAME):CHANNELS | Number of available channels (4, 8 or 10) |
|
||||||
|
| \$(INSTR)\$(NAME):GATE-_ | Configuration for Gating in newer hardware |
|
||||||
|
|
||||||
## Generating Test Signals
|
## Generating Test Signals
|
||||||
|
|
||||||
@ -71,6 +72,105 @@ runScript "$(sinqDAQ_DIR)daq_2nd_gen.cmd" "NAME=DAQ, DAQ_IP=TestInst-DAQ1, DAQ_P
|
|||||||
|
|
||||||
See the file [daq\_2nd\_gen\_test.db](./db/daq_2nd_gen_test.db)
|
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
|
||||||
|
|
||||||
|
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 = [],
|
||||||
|
visibility = {'metadata', 'namespace'},
|
||||||
|
),
|
||||||
|
Threshold = device(
|
||||||
|
'nicos_sinq.devices.epics.sinqdaq.DAQMinThreshold',
|
||||||
|
daqpvprefix = countprefix,
|
||||||
|
min_rate_channel = 'ThresholdChannel',
|
||||||
|
visibility = {'metadata', 'namespace'},
|
||||||
|
),
|
||||||
|
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'},
|
||||||
|
),
|
||||||
|
TestGen = device('nicos_sinq.devices.epics.sinqdaq.DAQTestGen',
|
||||||
|
daqpvprefix = countprefix,
|
||||||
|
visibility = {'metadata', 'namespace'},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
Simulation of the Hardware can be toggled on as follows:
|
Simulation of the Hardware can be toggled on as follows:
|
||||||
|
@ -48,6 +48,15 @@ record(longout, "$(INSTR)$(NAME):C$(CHANNEL)")
|
|||||||
field(FLNK, "$(INSTR)$(NAME):T$(CHANNEL)")
|
field(FLNK, "$(INSTR)$(NAME):T$(CHANNEL)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
record(ao,"$(INSTR)$(NAME):THRESH$(CHANNEL)")
|
||||||
|
{
|
||||||
|
field(DESC, "Sets minimum rate for counting to proceed")
|
||||||
|
field(OMSL, "supervisory")
|
||||||
|
field(OROC, "0")
|
||||||
|
field(OUT, "@$(PROTO) setMinRate($(INSTR)$(NAME):, $(CHANNEL)) $(ASYN_PORT)")
|
||||||
|
field(DTYP, "stream")
|
||||||
|
}
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# Read all monitors values
|
# Read all monitors values
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@ startWithTimePreset {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setMinRate{
|
setMinRate{
|
||||||
out "DL %(\$1THRESHOLD-MONITOR_RBV)d %.3f";
|
out "DL \$2 %.3f";
|
||||||
in;
|
in;
|
||||||
@mismatch{in "%(\$1MsgTxt)s";}
|
@mismatch{in "%(\$1MsgTxt)s";}
|
||||||
}
|
}
|
||||||
|
@ -41,5 +41,38 @@ record(seq, "$(INSTR)$(NAME):CORRECT-MONITOR-CHANNEL")
|
|||||||
################################################################################
|
################################################################################
|
||||||
# Count Commands
|
# Count Commands
|
||||||
|
|
||||||
|
# The hardware stores a separate threshold for each channel, which is somewhat
|
||||||
|
# unintuitive for the user, as only one can actually be made use of at a time.
|
||||||
|
# So, we just write the threshold value to all channels when it is changed.
|
||||||
|
record(dfanout,"$(INSTR)$(NAME):THRESHOLD-F")
|
||||||
|
{
|
||||||
|
field(OMSL, "supervisory")
|
||||||
|
field(SELM, "All")
|
||||||
|
field(OUTA, "$(INSTR)$(NAME):THRESHOLD-F1 PP")
|
||||||
|
field(OUTB, "$(INSTR)$(NAME):THRESHOLD-F2 PP")
|
||||||
|
}
|
||||||
|
|
||||||
|
record(dfanout,"$(INSTR)$(NAME):THRESHOLD-F1")
|
||||||
|
{
|
||||||
|
field(OMSL, "supervisory")
|
||||||
|
field(SELM, "All")
|
||||||
|
field(OUTA, "$(INSTR)$(NAME):THRESH1 PP")
|
||||||
|
field(OUTB, "$(INSTR)$(NAME):THRESH2 PP")
|
||||||
|
field(OUTC, "$(INSTR)$(NAME):THRESH3 PP")
|
||||||
|
field(OUTD, "$(INSTR)$(NAME):THRESH4 PP")
|
||||||
|
field(OUTE, "$(INSTR)$(NAME):THRESH5 PP")
|
||||||
|
field(OUTF, "$(INSTR)$(NAME):THRESH6 PP")
|
||||||
|
field(OUTG, "$(INSTR)$(NAME):THRESH7 PP")
|
||||||
|
field(OUTH, "$(INSTR)$(NAME):THRESH8 PP")
|
||||||
|
}
|
||||||
|
|
||||||
|
record(dfanout,"$(INSTR)$(NAME):THRESHOLD-F2")
|
||||||
|
{
|
||||||
|
field(OMSL, "supervisory")
|
||||||
|
field(SELM, "All")
|
||||||
|
field(OUTA, "$(INSTR)$(NAME):THRESH9 PP")
|
||||||
|
field(OUTB, "$(INSTR)$(NAME):THRESH10 PP")
|
||||||
|
}
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# Read all monitors values
|
# Read all monitors values
|
||||||
|
@ -28,5 +28,18 @@ record(longin, "$(INSTR)$(NAME):MONITOR-CHANNEL_RBV")
|
|||||||
################################################################################
|
################################################################################
|
||||||
# Count Commands
|
# Count Commands
|
||||||
|
|
||||||
|
# The hardware stores a separate threshold for each channel, which is somewhat
|
||||||
|
# unintuitive for the user, as only one can actually be made use of at a time.
|
||||||
|
# So, we just write the threshold value to all channels when it is changed.
|
||||||
|
record(dfanout,"$(INSTR)$(NAME):THRESHOLD-F")
|
||||||
|
{
|
||||||
|
field(OMSL, "supervisory")
|
||||||
|
field(SELM, "All")
|
||||||
|
field(OUTA, "$(INSTR)$(NAME):THRESH1 PP")
|
||||||
|
field(OUTB, "$(INSTR)$(NAME):THRESH2 PP")
|
||||||
|
field(OUTC, "$(INSTR)$(NAME):THRESH3 PP")
|
||||||
|
field(OUTD, "$(INSTR)$(NAME):THRESH4 PP")
|
||||||
|
}
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# Read all monitors values
|
# Read all monitors values
|
||||||
|
@ -28,5 +28,22 @@ record(longin, "$(INSTR)$(NAME):MONITOR-CHANNEL_RBV")
|
|||||||
################################################################################
|
################################################################################
|
||||||
# Count Commands
|
# Count Commands
|
||||||
|
|
||||||
|
# The hardware stores a separate threshold for each channel, which is somewhat
|
||||||
|
# unintuitive for the user, as only one can actually be made use of at a time.
|
||||||
|
# So, we just write the threshold value to all channels when it is changed.
|
||||||
|
record(dfanout,"$(INSTR)$(NAME):THRESHOLD-F")
|
||||||
|
{
|
||||||
|
field(OMSL, "supervisory")
|
||||||
|
field(SELM, "All")
|
||||||
|
field(OUTA, "$(INSTR)$(NAME):THRESH1 PP")
|
||||||
|
field(OUTB, "$(INSTR)$(NAME):THRESH2 PP")
|
||||||
|
field(OUTC, "$(INSTR)$(NAME):THRESH3 PP")
|
||||||
|
field(OUTD, "$(INSTR)$(NAME):THRESH4 PP")
|
||||||
|
field(OUTE, "$(INSTR)$(NAME):THRESH5 PP")
|
||||||
|
field(OUTF, "$(INSTR)$(NAME):THRESH6 PP")
|
||||||
|
field(OUTG, "$(INSTR)$(NAME):THRESH7 PP")
|
||||||
|
field(OUTH, "$(INSTR)$(NAME):THRESH8 PP")
|
||||||
|
}
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# Read all monitors values
|
# Read all monitors values
|
||||||
|
@ -178,15 +178,14 @@ record(longout, "$(INSTR)$(NAME):STOP")
|
|||||||
record(ao,"$(INSTR)$(NAME):THRESHOLD")
|
record(ao,"$(INSTR)$(NAME):THRESHOLD")
|
||||||
{
|
{
|
||||||
field(DESC, "Minimum rate for counting to proceed")
|
field(DESC, "Minimum rate for counting to proceed")
|
||||||
field(VAL, "0") # Rate
|
field(VAL, "1") # Default Rate
|
||||||
# Could perhaps still be improved.
|
# Could perhaps still be improved.
|
||||||
# It seems to only accept whole counts?
|
# It seems to only accept whole counts?
|
||||||
field(DRVL, "1") # Minimum Rate
|
field(DRVL, "1") # Minimum Rate
|
||||||
field(DRVH, "100000") # Maximum Rate
|
field(DRVH, "100000") # Maximum Rate
|
||||||
field(OMSL, "supervisory")
|
field(OMSL, "supervisory")
|
||||||
field(OROC, "0")
|
field(OROC, "0")
|
||||||
field(OUT, "@$(PROTO) setMinRate($(INSTR)$(NAME):) $(ASYN_PORT)")
|
field(OUT, "$(INSTR)$(NAME):THRESHOLD-F PP")
|
||||||
field(DTYP, "stream")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
record(ai,"$(INSTR)$(NAME):THRESHOLD_RBV")
|
record(ai,"$(INSTR)$(NAME):THRESHOLD_RBV")
|
||||||
|
102
db/gating_channels.db
Normal file
102
db/gating_channels.db
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
# EPICS Database for streamdevice specific to gating channels
|
||||||
|
#
|
||||||
|
# Macros
|
||||||
|
# INSTR - Prefix
|
||||||
|
# NAME - the device name, e.g. EL737
|
||||||
|
# PROTO - Stream device protocol file
|
||||||
|
# ASYN_PORT - Low level Asyn IP Port to DAQ
|
||||||
|
# CHANNEL - the number associated with the measurment channel
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
# Records for configuring gating settings
|
||||||
|
record(mbbo, "$(INSTR)$(NAME):GATE-$(CHANNEL)")
|
||||||
|
{
|
||||||
|
field(DESC, "Sets the current gate state")
|
||||||
|
field(DTYP, "Soft Channel")
|
||||||
|
field(OUT, "$(INSTR)$(NAME):GATE-$(CHANNEL)-SET PP")
|
||||||
|
field(ZRST, "Disabled")
|
||||||
|
field(ONST, "Trigger Low")
|
||||||
|
field(TWST, "Trigger High")
|
||||||
|
}
|
||||||
|
|
||||||
|
record(dfanout, "$(INSTR)$(NAME):GATE-$(CHANNEL)-SET")
|
||||||
|
{
|
||||||
|
field(OUTA, "$(INSTR)$(NAME):GATE-$(CHANNEL)-SEL.SELN PP")
|
||||||
|
field(OUTB, "$(INSTR)$(NAME):GATE-$(CHANNEL)-SEL2.SELN PP")
|
||||||
|
}
|
||||||
|
|
||||||
|
record(seq, "$(INSTR)$(NAME):GATE-$(CHANNEL)-SEL")
|
||||||
|
{
|
||||||
|
field(SELM, "Specified")
|
||||||
|
field(DO0, 0)
|
||||||
|
field(LNK0, "$(INSTR)$(NAME):GATE-$(CHANNEL)-ENABLE PP")
|
||||||
|
field(DO1, 1)
|
||||||
|
field(LNK1, "$(INSTR)$(NAME):GATE-$(CHANNEL)-ENABLE PP")
|
||||||
|
field(DO2, 1)
|
||||||
|
field(LNK2, "$(INSTR)$(NAME):GATE-$(CHANNEL)-ENABLE PP")
|
||||||
|
}
|
||||||
|
|
||||||
|
record(bo, "$(INSTR)$(NAME):GATE-$(CHANNEL)-ENABLE")
|
||||||
|
{
|
||||||
|
field(DESC, "Enable Gating Channel")
|
||||||
|
field(ZNAM, "Disabled")
|
||||||
|
field(ONAM, "Enabled")
|
||||||
|
field(DTYP, "stream")
|
||||||
|
field(OUT, "@$(PROTO) setGateStatus($(INSTR)$(NAME):, $(CHANNEL)) $(ASYN_PORT)")
|
||||||
|
}
|
||||||
|
|
||||||
|
record(seq, "$(INSTR)$(NAME):GATE-$(CHANNEL)-SEL2")
|
||||||
|
{
|
||||||
|
field(SELM, "Specified")
|
||||||
|
field(DO1, 0)
|
||||||
|
field(LNK1, "$(INSTR)$(NAME):GATE-$(CHANNEL)-TRIG PP")
|
||||||
|
field(DO2, 1)
|
||||||
|
field(LNK2, "$(INSTR)$(NAME):GATE-$(CHANNEL)-TRIG PP")
|
||||||
|
}
|
||||||
|
|
||||||
|
record(bo, "$(INSTR)$(NAME):GATE-$(CHANNEL)-TRIG")
|
||||||
|
{
|
||||||
|
field(DESC, "Set Count when first Gate high/low")
|
||||||
|
field(ZNAM, "Low")
|
||||||
|
field(ONAM, "High")
|
||||||
|
field(DTYP, "stream")
|
||||||
|
field(OUT, "@$(PROTO) setGateStatus($(INSTR)$(NAME):, $(CHANNEL)) $(ASYN_PORT)")
|
||||||
|
}
|
||||||
|
|
||||||
|
# Records for reading configured gating settings
|
||||||
|
record(mbbi, "$(INSTR)$(NAME):GATE-$(CHANNEL)_RBV")
|
||||||
|
{
|
||||||
|
field(DESC, "The current gate state")
|
||||||
|
field(ZRST, "Disabled")
|
||||||
|
field(ONST, "Trigger Low")
|
||||||
|
field(TWST, "Trigger High")
|
||||||
|
}
|
||||||
|
|
||||||
|
record(calcout, "$(INSTR)$(NAME):GATE-$(CHANNEL)-SEL_RBV")
|
||||||
|
{
|
||||||
|
field(INPA, "$(INSTR)$(NAME):GATE-$(CHANNEL)-ENABLE_RBV NPP")
|
||||||
|
field(INPB, "$(INSTR)$(NAME):GATE-$(CHANNEL)-TRIG_RBV NPP")
|
||||||
|
field(CALC, "A=0?0:B=0?1:2")
|
||||||
|
field(OOPT, "On Change")
|
||||||
|
field(OUT, "$(INSTR)$(NAME):GATE-$(CHANNEL)_RBV PP")
|
||||||
|
field(FLNK, "$(INSTR)$(NAME):GATE-$(CHANNEL)_RBV")
|
||||||
|
}
|
||||||
|
|
||||||
|
record(bi, "$(INSTR)$(NAME):GATE-$(CHANNEL)-ENABLE_RBV")
|
||||||
|
{
|
||||||
|
field(DESC, "Is Gating Channel Enabled")
|
||||||
|
field(ZNAM, "Disabled")
|
||||||
|
field(ONAM, "Enabled")
|
||||||
|
field(DTYP, "stream")
|
||||||
|
field(INP, "@$(PROTO) getGateStatus($(INSTR)$(NAME):, $(CHANNEL)) $(ASYN_PORT)")
|
||||||
|
field(SCAN, "2 second")
|
||||||
|
field(FLNK, "$(INSTR)$(NAME):GATE-$(CHANNEL)-SEL_RBV")
|
||||||
|
}
|
||||||
|
|
||||||
|
record(bi, "$(INSTR)$(NAME):GATE-$(CHANNEL)-TRIG_RBV")
|
||||||
|
{
|
||||||
|
field(DESC, "Count when first Gate high/low")
|
||||||
|
field(ZNAM, "Low")
|
||||||
|
field(ONAM, "High")
|
||||||
|
}
|
Reference in New Issue
Block a user