EPICS sscan模块是一个用于扫描的功能模块,它支持步进扫描,基于表格的扫描和飞行扫描三种模式,以及一维以及多维扫描等扫描类型,这个记录中包含了大量功能字段,通过对这些功能字段的设置,可以实现一个复杂的扫描功能,本文主要是详细解析这些功能字段。
很多选项可用于控制一个扫描的执行。在启动扫描前,一个特定sscan记录的所有参数必须被配置,因为在扫描进行中,sscan记录将不允许大部分字段被写入。然而,在一个多维扫描中,外层扫描可以修改内层扫描的参数,因为在一个外层sscan记录正在写入定位器时,所有内层sscan记录是空闲的。在编程这样的自修改扫描中,你应该小心使用,因为显示或分析多维扫描数据的客户端可能遇到在扫描过程中处理参数变化的麻烦。在本文中,在表格中列出的sscan记录很多字段包含以下信息头:
- Field:字段,sscan记录字段的名称。
- summary:概要,字段的基本目的。
- type:字段的数据类型。如果这个字段是一个菜单,在引号中列出了这个菜单选项(文本字符串)。(当你写入这个字段时,不要包括这些引号)。注意:如果你写数值到一个菜单字段,这个数值将被解析成对菜单选项列表的一个索引。在这个列表中第一项索引为0。
- dct:这个字段能够被数据库配置工具修改吗?
- initial/default:如果在.db文件中没有指定这个字段时的值。如果这个字段是一个菜单,将显示文本字符串,后跟对应的索引。
- read:用户可以读取这个字段吗?
- modify:允许用户写入这个字段吗?(注意:在一个扫描正在进行时,sscan记录将拒绝对某些别的情况可写字段的写入)。
- posted:如果记录应该修改这个字段,将提交这个新值吗?
- pp:对这个字段的通道访问写入引起记录运行吗?
1 控制字段
字段 | 概要 | 类型 | DCT | 初始/默认 | 读取 | 修改 | 提交 | PP |
NPTS | 点数 | LONG | YES | 100 | YES | YES | YES | NO |
MPTS | 最大点数 | LONG | YES | 100 | YES | NO | NO | NO |
PASM | 定位器扫描后模式 | 菜单* | YES | "STAY"(0) | YES | YES | NO | NO |
*(“STAY”, "STAY POS", "PRIOR POS", "PEAK POS", "VALLEY POS", "+EDGE POS", "-EDGE POS", "CNTR OF MASS")
PASM允许用户控制在扫描结束后定位置停留在哪里。这是可能性:
- “STAY”:什么也不做。定位器停在采集最后数据点所在位置。
- "STAY POS":移动到采集第一个数据点的位置。
- "PRIOR POS":移动到扫描之前它们占据的位置。
- "PEAK POS":尝试源自由REFD字段指定的探测器数据中找到最高点。如果找到了一个最高点,移动到它的位置,否则"STAY"。
- "VALLEY POS":尝试源自由REFD字段指定的探测器数据中找到最低点。如果找到了一个最低点,移动到它的位置,否则"STAY"。
- "+EDGE POS":对REFD数据进行微分,接着做"PEAK POS"。
- "-EDGE POS":对REFD数据进行微分,接着做"VALLEY POS"。
- "CNTR OF MASS":如"PEAK POS",但移动定位器到数据的质心位置,用对定位器1的参考计算。注意:计算的质心取决于定位器数据的分布。如果在一个扫描中涉及到了多个定位器,它们一般将不会有相同的质心。
字段 | 概要 | 类型 | DCT | 初始/默认 | 读取 | 修改 | 提交 | PP |
REFD | 用于扫描后模式 的参考探测器 | SHORT | YES | 1 | YES | YES | NO | NO |
BSPV | 扫描前过程 变量链接 | STRING [40] | YES | Null | YES | YES | NO | NO |
BSNV | BSPV名称有效 | MENU* | NO | 0 | YES | NO | YES | NO |
BSCD | 扫描前命令数据 | FLOAT | YES | 1 | YES | YES | NO | NO |
BSWAIT | 等待结束 | MENU ("YES"/"NO") | YES | “YES”(0) | YES | YES | YES | NO |
*("PV OK", "No PV", "PV NoRead", "PV illggal1", "PV NoWrite", "PV illegal2", "PV BAD") “PV OK”和"No PV"是正常状态;所有其它状态将阻止一个扫描启动。
BSPV, BSNV, BSCD 和 BSWAIT允许使用者在每次扫描开始前指定一个要被写入的PV。(如果sscan记录是一个多维扫描的组成部分,每个参加的sscan记录有自己的扫描前参数集合,所以你能够在整个扫描开始前,以及每个嵌套的循环开始前使得一个操作发生。)要指定一个扫描后PV写,把这个PV名写到ASPV,而要被写入的值到ASCD。如果你想要sscan记录等待由这个写触发的运行结束,在继续余下扫描前,设置ASWAIT为"YES"(1)。通过查看ASNV,你可以检测这个链接的状态。如果链接是正常的,ASNV将为0。注意:允许扫描后链接仅更改它自己ssscan记录的所选字段:它不能更改PV名(即:链接);并且它不能更改采集类型(ACQT)或模式(ACQM)。如果这个sscan记录是一个多维扫描的一部分,扫描后链接可以更改一个下一级sscan记录的任何字段(即:它正在驱动的它的记录),而没有高一级扫描记录的字段。
字段 | 概要 | 类型 | DCT | 初始/默认 | 读取 | 修改 | 提交 | PP |
A1PV | 数组读取触发器1 PV名称 | STRING [40] | Yes | Null | Yes | Yes | No | No |
A1NV | A1PV名有效 | MENU* | No | 0 | Yes | No | Yes | No |
A1CD | A1 Cmnd | FLOAT | Yes | 1 | Yes | Yes | No | No |
*(“PV OK”, "No PV", "PV NoRead", "PV illegal1","PV NoWrite", "PV illegal1", "PV NoWrite", "PV illegal2" "PV BAD")
A1PV, A1NV和A1CD允许使用者在sscan记录尝试读取数组值的数据前指定一个要被写入的PV。(这可能是需要的,例如,在sscan记录采集数据前,使得它从硬件被读取到一个EPICS PVs的集合,或者对这些数据执行某个计算。)sscan记录在读取数组前将等待由这个写触发的运行完成。要指定一个数组准备PV写,写这个PV的名称到A1PV,并且要被写的值到A1CD。你可以通过查看A1NV,检查这个链接的状态。如果链接正常,A1NV将是0。
字段 | 概要 | 类型 | DCT | 初始/默认 | 读取 | 修改 | 提交 | PP |
ATIME | 数组提交 时间周期 | FLOAT | Yes | 0.0 | Yes | Yes | No | No |
COPYTO | 复制上个数组点 | LONG | Yes | 0 | Yes | Yes | No | No |
这些字段在一个扫描中控制数组数据的提交。ATIME是在扫描中数组提交之间努埃为单位的最小时间段。 如果ATIME大于0.1(秒),并且如果从这个扫描的数据上次数组提交后消耗比这个时段更多时间,则在完成下个数据点采集后,将提交当前数据数组。注意:提交当前数据数组也使得完成扫描的数据数组也被提交(无用,因为它们在前个扫描结束时被提交,并且它们包含的数据还未变化)。某些显示或者存储客户端可能对sscan记录的这种新行为有问题。如果这样,有两种别的选择:1) 让ATIME保留默认值0.0,或者,2) 让客户端在其订阅数据数组时(使用ca_add_event()或者ca_create_subscription())指定DBE_LOG。(如果一个客户端不监视数据数组,而是使用ca_get()读取它们,则它不在意多久提交它们)。某些数据显示客户端(明显地:MEDM)不能使用一个PV告诉它们多少个有效数据点正在被发送。这导致形状怪异的绘图,通过重复上个有效数组值来填充未用的数组元素来使得以上导致的怪异图看起来正常。 这是一个耗时的过程,因此默认只在一个扫描结束时仅做一次。但在一个扫描中提交的数组也将不被这样的客户端正确地绘制,因此通过设置COPYTO为在客户端地数据缓存中数组元素的数组,指定在一个扫描中为提交数组复制的上个有效数组元素。如果COPYTO==0,将不进行复制;如果COPYTO==-1,上个值将不复制给sscan记录的数据缓存中所有未被使用的数组元素。如果COPYTO被设置成一个大于MPTS的值,使用的值将是MPTS。
2 定位器字段
每个sscan记录可以最多控制4个定位器,它通过这些定位器设置在哪些条件下将采集数据。一个定位器是sscan记录能够向其写入的任何数值PV,并且你通过输入其PV名到sscan记录的字段PnPV之一指定一个要被扫描的定位器。如果被写入这个PV(所需值)的值可能没有准备地反映底层定位器地真值,你可以指定一个回读PV来获取一个更准确的值。我有时称sscan记录写入的PV为"驱动"PV。如果没有指定回读PV,驱动PV将也被用作回读PV。有三种用于为定位器确定所需值得可能模式:LINEAR,TABLE和FLY。每个定位器有它自己得模式PV,并且通过设置定位器得PnSM字段(例如,P1SM对应定位器1),指定你想要为其指定哪种模式。如果PnSM==LINEAR,从诸如起始位置,步长增量,点数和终止位置等参数确定所需值。如果PnSM==TABLE,在数组(PnPA)中找到所需的值。如果PnSM==FLY,所需值是LINEAR模式的起始和终止位置。
除了定位器扫描模式PnSM外,有零个sscan记录字段,它影响如何扫描定位器。ACQT(采集类型)字段影响所有定位器,并且要么命令它们按如上描述表现(当ACQT==SCALER时),要么命令它们都在飞行模式中有效(当ACQT=1D ARRAY。我有时称这为"数组模式")。详见"飞行扫描"部分。
对于每个定位器,使用者可以在R1PV-R4PV字段中指定一个过程变量,这些字段对应电机实际(或测量)位置。如果配置了这个回读字段,sscan记录在每次移动后确认回读位置插值不大于所需位置一个指定的值。插值限制是在R1DL-R4DL字段中指定。如果它为0,不执行检查。否则,如果超过了这个插值限制,扫描将中止并且记录将进入到一个警报状态。一个在此记录中文本字段(SMSG)将通告这个错误情况的操作。
定位器-回读字段通常包含一个PV的名称,从其读取回读值,但它也可能包含静态文本"TIME"或"time"。在这种情况中,sscan记录设置标量回读字段RnCV为从扫描开始以来的以秒为单位的时间,并且用这些值填充回读数组PnRA。
驱动字段
对于在[1..4]中的n:
字段 | 概要 | 类型 | DCT | 初始/默认 | 读取 | 修改 | 提交 | PP |
PnPV | 定位器n 过程变量名 | STRING[40] | Yes | Null | Yes | Yes | No | No |
PnNV | PnPV名 有效 | MENU* | No | 0 | Yes | Yes | Yes | No |
PnSM | 定位器n 步进模式 | 菜单("LINEAR", "TABLE", "FLY") | Yes | “LINEAR(0)” | Yes | Yes | No | No |
PnAR | 定位器n绝对/ 相对模式 | 菜单("ABOSOLTUE", "RELEATIVE") | Yes | “ABSOLUTE(0)” | Yes | Yes | No | No |
PnDV | 定位器n所需值 | DOUBLE | No | 0 | Yes | No | Yes | No |
PnLV | 定位器n上个值 | DOUBLE | No | 0 | Yes | No | No | No |
PnEU | 定位器n工程单位 | STRING[10] | Yes | 16 | Yes | Yes | No | No |
PnHR | 定位器n高量程 | DOUBLE | Yes | 0 | Yes | Yes | No | No |
PnLR | 定位器n下量程 | DOUBLE | Yes | 0 | Yes | Yes | No | No |
PnPR | 定位器n精度 | DOUBLE | Yes | 0 | Yes | Yes | No | No |
PnPA | 定位器n步进 数组 | DOUBLE[] | No | 0 | Yes | Yes | No | No |
PnPP | 在扫描前 定位器n位置 | Double | No | 0 | Yes | No | No | No |
*("PV OK","No PV", "PV NoRead", "PV illegal1", "PV NoWrite", "PV illegal2", "PV BAD")
其中"PV OK" 和 "No PV"是正常状态。所有其它情况将阻止一个扫描启动。
反馈字段
n在[1..4]中。
字段 | 概要 | 类型 | DCT | 初始/默认 | 读取 | 修改 | 提交 | PP |
RnPV | 回读n 过程变量 | STRING[40] | Yes | Null | Yes | Yes | No | No |
RnNV | 回读/n名称 有效 | Menu* | No | 0 | Yes | Yes | Yes | No |
RnDL | 回读n 差值限制 | DOUBLE | Yes | 0 | Yes | Yes | No | No |
RnCV | 回读n 当前值 | DOUBLE | No | 0 | Yes | No | Yes | No |
RnLV | 回读n 上个值 | DOUBLE | No | 0 | Yes | No | No | No |
RnRA | Pn回读数组 | DOUBLE[] | No | 0 | Yes | No | Yes | No |
RnCA | Pn当前回读 数组 | DOUBLE[] | No | 0 | Yes | No | Yes | No |
*("PV OK","No PV", "PV NoRead", "PV illegal1", "PV NoWrite", "PV illegal2", "PV BAD")
其中"PV OK" 和 "No PV"是正常状态。所有其它情况将阻止一个扫描启动。
显示扫描数据的客户端将仅对两个定位器数组字段:PnCA或PnRA之一最感兴趣。这些数组字段由相同的双缓存数组支持,因此不能分别提交它们。
PnCA将从当前正在执行的扫描产生数据。在扫描过程中,可以在任何时间读取这个数组,并且在扫描进行时用掩码DBE_VALUE提供它。(ATIME控制这个)。当扫描结束时,将用掩码DBE_VALUE|DBE_LOG提交PnCA。
PnRA将从最近结束的扫描产生数据。当正在采集下个扫描的数据时,这个数组的数据将仍然可用,并且在那个扫描结束时,将变得不可用。
仅对完成的扫描数据感兴趣的客户端应该使用这个字段。监视这个字段的客户端应该总是在它们的ca_add_event()或ca_create_subscription()调用中指定这个掩码DBE_LOG。如果用掩码DBE_VALUE监视的字段,客户端会接收相同数据的多次提交。
1) LINEAR模式
如果一个定位器的步进模式字段(例如:P1SM)有值LINEAR,一个扫描完全被三个参数定义,例如,起始位置(P1SP),步进增量(P1SI)以及数据点数目(NPTS)。一个包含N个定位器的扫描仅有2N+1个参数定义,由于NPTS应用于所有定位器。为了交互用户方便,并且支持定义扫描不同地通道访问客户端,第一个定位器可以用六个参数指定:启动位置(P1SP),终止位置(P1EP),中心位置(P1CP),扫描宽度(P1WD),步进增量(P1SP),以及NPTS。对于另外三个定位器,除了NPTS字段外的参数可用,由于NPTS应用到所有定位器。属于相同定位器的参数是一个集合。记录对NPTS执行一个上限制(MPTS)。MPTS和NPTS由使用者配置。定位器宽度,在P1WD-P4WD字段中可配置,可以是负数。对于n在[1..4]:
字段 | 概要 | 类型 | DCT | 初始/默认 | 读取 | 修改 | 提交 | PP |
PnSP | 定位器n 起始点 | DOUBLE | Yes | 0 | Yes | Yes | Yes | No |
PnEP | 定位器n 终点 | DOUBLE | Yes | 0 | Yes | Yes | Yes | No |
PnCP | 定位器n 中心点 | DOUBLE | Yes | 0 | Yes | Yes | Yes | No |
PnWD | 定位器n 宽度 | DOUBLE | Yes | 0 | Yes | Yes | Yes | No |
PnSI | 定位器n 步长增量 | DOUBLE | Yes | 0 | Yes | Yes | Yes | No |
这些字段可以是冗余的。例如,定位器宽度(P1WD-P4WD)只是从起始位置到终止位置(PnEP-PnSP)的宽度。如果这些参数被留为未定义,记录为相同集合计算冗余。然而,使用者仍然可以配置冗余参数。消除冗余参数之间不一致性,没有唯一方法,并且在参数之间没有硬编码的首选设置可能让人更喜欢。因而,sscan记录允许使用者用标记"冻结"参数,使得它们将不被记录内部尝试更改来确保在参数集合之间的一致性。冻结的参数可以被使用者和任何其它客户端更改,但不被记录更改。确保冻结的参数不阻止自由地指定未被冻结的参数是使用者的责任。例如,PnSI和NPTS都被冻结,更改PnWD将被拒绝。类似,如果PnSP和PnCP被冻结,更改PnEP和PnWD将没有作用。默认,PnSP, PnSI和NPTS被冻结。当记录不能调整参数来保持一致性,在警告字段(ALRT)中产生一个标记,并且在状态消息字段(SMSG)中报告一条消息。
冻结标记重写字段(FFO)有两个选项:使用F-Flags和Override。Override引起所有冻结标记的当前设置被保存并且为已经更改的那些设置调用监视器。如果任何发生了变化,使用F-Flags使得用Override命令保存的标记被恢复。在运行时更改这个字段的选择使得special记录支持例程执行这些操作。因此,如果在运行时选择了Override,则所有当前设置被保存,并且在之后通告更改FFO字段使用F-Flags,可以被恢复。
对于n在[1..4]:
字段 | 概要 | 类型 | DCT | 初始/默认 | 读取 | 修改 | 提交 | PP |
FPTS | NPTS的 冻结标记 | 菜单 ("NO", "FREEZE") | YES | FREEZE(1) | Yes | Yes | No | No |
FFO | 冻结标记 重写 | 菜单( "USE F-FLAGS", "OVERRIDE") | YES | "USE F-FLAGS" (0) | Yes | Yes | No | No |
PnFS | PnSP的定位器 n冻结标记 | 菜单 ("NO", "FREEZE") | YES | "NO"(0) | Yes | Yes | No | No |
PnFE | PnEP的定位器 n冻结标记 | 菜单 ("NO", "FREEZE") | YES | "NO"(0) | Yes | Yes | No | No |
PnFI | PnSI的定位器 n冻结标记 | 菜单 ("NO", "FREEZE") | YES | "NO"(0) | Yes | Yes | No | No |
PnFC | PnCP的定位器 n冻结标记 | 菜单 ("NO", "FREEZE") | YES | "NO"(0) | Yes | Yes | No | No |
PnFW | PnFW的定位器 n冻结标记 | 菜单 ("NO", "FREEZE") | YES | "NO"(0) | Yes | Yes | No | No |
虽然这种方法看起来会在它遇到线性扫描时向使用者提供了非常多的选项,应该注意:为了完全定义一个扫描器的扫描,使用者默认只需配置NPTS,以及对应每个定位器的起始点(PnSP)和步长增量(PnSI)字段。操作接口(通常MEDM,或另外的CA客户端)只需要向使用者显示这些字段。然而,通过更改默认值的冻结标记,并且向使用者显示要填入的不同字段,可以用完全灵活方法定义这个扫描。结论是容易地定义一个简单扫描,但高级使用者灵活性上不受限制。
2) TABLE模式
如果一个定位器地步进模式字段(例如:P1SM)值为TABLE模式,通过在一个扫描启动前写所有位置到一个数组(例如:P1PA),使用者指定在扫描中要访问的所有位置。这些数组仅在TABLE模式中被使用。例如:n在[1..4]中:
字段 | 概要 | 类型 | DCT | 初始/默认 | 读取 | 修改 | 提交 | PP |
PnPA | 定位器n 位置数组 | DOUBLE 数组 | No | Null | Yes | Yes | Yes | No |
要装载一个位置数组到PnPA,你可以使用知道如何写入数值数组的任何通道访问客户端。有若干版本的能够做这件事的命令行程序caput。对于一个版本,你指定选项-a并且写一个逗号分割的值列表:
# 从数组起始位置开始写5个值
blctrl@main-machine ~]$ caput -a ARIES:scan1.P1PA 5 -2000 -1000 0 1000 2000
# 读取数组的前5个值
blctrl@main-machine ~]$ caget -# 5 ARIES:scan1.P1PA
ARIES:scan1.P1PA 5 -2000 -1000 0 1000 2000
你也可以从Python使用pyepics做这件事:
[blctrl@main-machine ~]$ python3
Python 3.6.8 (default, Jun 20 2023, 11:53:23)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import epics
>>> epics.caput("ARIES:scan1.P1PA",[-3000,-2000,-1000,0,1000,2000,3000])
1
>>> epics.caget("ARIES:scan1.P1PA")
array([-3000., -2000., -1000., ..., 0., 0., 0.])
>>>
3) FLY模式
如果定位器的步进模式字段(例如:P1SM)值为FLY,也说定位器处于"飞行模式",并且它仅进行两次移动。首次移动与线性-或表格-模式定位器相同:sscan记录将定位器移动到其起始位置,并且等待它到哪里。下次移动不同:当sscan记录首次触发探测器时,它也启动飞行模式定位器到它们的终点位置。sscan记录不等待飞行模式定位器到达它们结束位置,并且不能再次指挥飞行模式定位器,除非定位器扫描后模式(PASM)需要这个(例如,通过指定所有定位器返回到它们扫描前的位置)。注意:PV ACQT(ACQuisition类型)也影响定位器移动:当ACQT==1D ARRAY,所有定位器在飞行模式中有效,因为sscan记录将只采集一个(数组值的)数据点。在这种情况中,PVs PnSM只用于确定定位器运动的起始和终点。详见以下用于定位器1的表格:
scan模式 (P1SM) | 采集类型 (ACQT) | 起点 | 终点 | 移动 |
LINEAR | SCALAR | P1SP | P1EP | 逐点 |
TABLE | SCALAR | P1PA[0] | P1PA [npts-1] | 逐点 |
FLY | 1D ARRAY | P1SP | P1EP | 飞行 |
LINEAR | 1D ARRAY | P1SP | P1EP | 飞行 |
TABLE | 1D ARRAY | P1SP[0] | P1PA [npts-1] | 飞行 |
FLY | 1D ARRAY | P1SP | P1EP | 飞行 |
当飞行模式定位器正在向它们终点移动,sscan记录经历所有正常扫描阶段-触发探测器并且等待它们结束,读取任何探测器和定位器回读,移动任何非飞行模式定位器到它们的下个位置并且等待它们到那里。
如果一个飞行模式定位器有一个指定的回读PV(RnPV),在扫描过程中将读取它的值,但在很多情况中,值将仅近似正确,因为在读取过程中,定位器在运动中,并且因为sscan记录不引发读取PV运行。如果定位器是一个电机,例如,并且回读PV被周期地提交,sscan记录将读取与扫描不完全同步的值。
3 探测器触发字段
如果向探测器触发字段(T1PV-T4PV)输入有效的过程变量名,sscan记录将在定位阶段和数据采集阶段之间写指定的命令数据(浮点数值T1CD-T4CD)到到那些过程变量。如果没有探测器触发器字段包含一个有效PV,sscan记录将跳过这个步骤并且立即采集数据。对于n在[1..4]中:
字段 | 概要 | 类型 | DCT | 初始/默认 | 读取 | 修改 | 提交 | PP |
TnPV | 探测器触发器n 过程变量 | STRING [40] | Yes | Null | Yes | Yes | No | No |
TnNV | 触发器n名称游戏 | MENU* | No | 0 | Yes | Yes | Yes | No |
TnCD | 触发器n命令数据 | FLOAT | Yes | 1 | Yes | Yes | No | No |
*(“PV OK”,”No PV”, “PV NoRead”, “PV illegal1”, “PV NoWrite”, “PV illegal2”, “PV BAD”) “PV OK” 和 “No PV” 是正常状态; 所有其它将阻止一个扫描开始。
4 延迟字段
通常,在sscan记录写入定位器并且等待所有定位器宣布它们结束后,它再等待一个稳定时间,被秒为单位由PDLY字段指定。类似地,在探测器触发器宣布它们结束后,在读取定位器和探测器数据前,sscan记录等待DDLY秒。如果没有定义定位器,则忽略DDLY。PDLY不对扫描后定位器移动使用。
5 客户端握手字段
就在数据被从定位器和探测器读取前,sscan记录检查WCNT字段。如果这个字段非0,在读取数据并且继续扫描前,sscan记录等到到它被设成0。WCNT不是客户端直接可写地。而是,一个想要暂停这个扫描的客户端写一个1到WAIT字段,这将WCNT加1。当客户端准备好扫描继续时,它写0到WAIT字段,这对WCNT字段减1。此机制允许若干客户端独立地与sscan记录握手,并且它有两个目的:
1)数据存储客户端可以通过写入AWAIT字段暂停一个它在写其数据的sscan记录。此暂停不阻止记录执行,或者甚至采集新数据,但它阻止这个记录切换数据缓存。
2)在多维扫描中,一个数据存储客户端可以通过写入WAIT字段在它正在写来自scan1的数据时暂停scan2。此非常低效的握手仍然被某些数据存储客户端使用。
3)一个不通过EPICS的putNotify机制宣告结束的数据采集客户端可以使用WAIT宣告结束。
一个客户端可能不能够足够快地写入WAIT来确保在数据采集前扫描暂停。在这种情况中,客户端可以通过增加AWCT字段的值使得在探测器被触发时sscan记录自动写入WCNT。客户端必须记住在推出前减小AWCT,否则扫描将为一个不存在的客户端暂停。
一个客户端可能不能足够快地写入AWAIT来确保在切换缓存前扫描暂停。在这种情况中,通过设置AAWAIT字段为1,在数据被提交前,使得sscan记录自动写入AWAIT。
字段 | 概要 | 类型 | DCT | 初始/默认 | 读取 | 修改 | 提交 | PP |
WAIT | 等待 客户端 | SHORT | NO | 0 | Yes | Yes | No | No |
WCNT | 等待 数目 | SHORT | NO | 0 | Yes | No | Yes | No |
AWCT | 自动等待 | SHORT | NO | 0 | Yes | Yes | No | No |
WTNG | 等待中 | SHORT | NO | 0 | Yes | No | Yes | No |
AWAIT | 等待数据 存储客户端 | SHORT | NO | 0 | Yes | Yes | Yes | Yes |
AAWAIT | 自动等待 数据存储客户端 | MENU ("NO", "YES") | Yes | 0 | Yes | Yes | No | No |
6 探测器字段
每个sscan记录在扫描中每个点可以最多从74个过程变量采集数据(70个探测器信号,D01-D70,以及四个定位器回读R1-R4)。这些数据通常来自一个探测器或者来自一个位置回读(它会记住每个点地实际电机位置,并且接着与所需位置作比较)。虽然定位器回读R1-R4通常用于确定实际在那个点采集数据(不同于sscan记录告诉一个定位器移向那个位置),它们可以用于记录任何数据。这四个变量是记录双精度扫描数据的唯一位置。注意:这些回读不是全面的探测器,因为sscan记录当前不能从一个数组值PV's读入它们,如对于实际探测器能够的。
扫描结果将最频繁地被当作位置数组(P1RA-P4RA)和探测器数组(D01DA-D70DA)读取。
一维扫描在BUSY字段变回0时(在扫描中,它地值是1)结束。一个监视这个扫描的客户端程序在DATA字段被设为1时可以读取位置和数据数组。(客户端在数据数组字段上设置了一个监视器,因而这个记录在扫描结束时提交它们)。
对于二维扫描,客户端应该在每个内层扫描结束后从scan1读取数组并且关联这些数据和当前外层扫描信息。(让我们称内层扫描'x',而外层扫描'y'。)。这将允许客户端在每个x扫描后显示数据。sscan记录将仅为一个x扫描缓存数据,因而客户端必须在下个x扫描结束前读取数组。如果扫描对此太快,见章节3.4 与数据存储客户端握手。
在扫描中,程序可能想要逐点显示扫描数据。sscan记录对它在每点更新的字段提交监视,但它提交逐点监视不快于每秒20次。如果一个扫描以慢于每秒20个点的速率运行,将提交每个点。如果一个扫描以每秒100步进行,将近似每5个点提交标量值。在任何一种情况,数组数据将在扫描结束时包含每个点。
特殊采集参数:
字段 | 概要 | 类型 | DCT | 初始/默认 | 读取 | 修改 | 提交 | PP |
版本5.16 以及更早 | ||||||||
ACQM | 采集模式 | 菜单*1 | Yes | "NORMAL" (0) | Yes | Yes | No | No |
版本5.17 以及更早 | ||||||||
ACQM | 采集模式 | 菜单*2 | Yes | "NORMAL" (0) | Yes | Yes | No | No |
ACQT | 采集类型 | 菜单*3 | Yes | “SCALER” (0) | Yes | Yes | No | No |
1*:Menu (“NORMAL”, “ACCUMULATE”, “ADD TO PREV”, “GET ARRAYS”)
2*:Menu (“NORMAL”, “ACCUMULATE”, “ADD TO PREV”)
3*: Menu (“SCALAR”, “1D ARRAY”)
数据和相关的PV's:对于nn在[01..70](例如:"D01PV", "D02PV", ..., "D70PV")
字段 | 概要 | 类型 | DCT | 初始/默认 | 读取 | 修改 | 提交 | PP |
DnnPV | 数据nn 过程变量名 | STRING [40] | Yes | Null | Yes | Yes | No | No |
DnnNV | 数据nn名称 有效 | MENU* | No | 0 | Yes | Yes | Yes | No |
DnnDA | 探测器nn扫描 结束的数据数组 | FLOAT[] | NO | Null | Yes | No | Yes | No |
DnnCA | 探测器nn当前 数据数组 | FLOAT[] | No | Null | Yes | No | Yes | No |
DnnEU | 探测器nn工程 单位 | STRING [16] | Yes | 16 | Yes | Yes | No | No |
DnnHR | 探测器nn 上限 | DOUBLE | Yes | 0 | Yes | Yes | No | No |
DnnLR | 探测器nn 下限 | DOUBLE | Yes | 0 | Yes | Yes | No | No |
DnnPR | 探测器nn 精度 | FLOAT | No | 0 | Yes | No | No | No |
DnnCV | 探测器nn 当前值 | FLOAT | No | 0 | Yes | No | Yes | No |
DnnLV | 探测器nn 上个值 | FLOAT | No | 0 | Yes | No | No | No |
*1:MENU(“PV OK”,”No PV”, “PV NoRead”, “PV illegal1”, “PV NoWrite”, “PV illegal2”, “PV BAD”) “PV OK” 和 “No PV” 是正常状态; 所有其它将阻止一个扫描启动,虽然"PV NoWrite"用于这些回读PVs是不可能的。
7 执行字段
当一个客户端写1到EXSC字段时,启动一个扫描。
在开始一个实际扫描前,可以命令这个记录检查扫描参数来确定所有定位器请求是在定位器限位内。通过写1到CMND字段,做这件事。记录将通过计算每个定位器值(或者查找表格)并且将它与与那个定位器的过程变量相关联的高限和低限值(P1HR-P4HR和P1LR-P4LR)做比较进行一个"干跑"。(驱动限制是大部分过程变量一个属性)。如果任何步子超过这个驱动限制,通过SMSG字段通告操作者。(注意:sscan记录在它们被更改时没有获取定位器限位,但仅在sscan记录连接(进行链接)到)定位器。由于这个原因,sscan记录在每个扫描开始时,断开和重新连接定位器。虽然如果最近扫描结束少于sscanRecordLookupTme秒前,它拒绝做这件事。sscanRecordLookupTime的默认值是1。)
字段 | 概要 | 类型 | DCT | 初始/默认 | 读取 | 修改 | 提交 | PP |
EXSC | 执行扫描 标记 | SHORT | No | 0 | Yes | Yes | Yes | No |
CMND | 命令字段 | ENUM | No | 0 | Yes | Yes | Yes | No |
命令(CMND)字段支持8个命令,如下:
CMND | 命令 |
0 | 清除状态消息字段(SMSG) |
1 | 执行"干跑",对照它们的限位,检查定位器。 |
2 | 使用定位器和探测器数组PnCA和DnnCA显示扫描预览:写数据点数值到DnnCA,和对应的定位器值到PnCA和DnnCA:写数据点数值到DnnCA以及对应的定位器值到PnCA。 |
3 | 清除所有PVs,冻结标记,模式,和switches等。 |
4 | 清除所有定位器名称PVs,冻结标记,模式和switches。 |
5 | 清除定位器名称PVs。 |
6 | 清除所有定位器名称和回读名PVs,冻结标记,模式和switches。 |
7 | 清除定位器名称和回读名称PVs。 |
8 状态/过程字段
这些字段用于运行这个记录,为某些字段实现监视,和/或为运行和/或操作者跟踪数据。这些字段都不是数据库配置工具配置的。它们大部分在运行时能够被访问,并且很多在运行时可以被修改。当前点(CPT)字段包含一个活动扫描的当前点。
BUSY字段表明一个扫描是(1)否(0)在运行中。
DATA字段表明数据数组的状态。在一个扫描开始时DATA被设为0,在数据数组已经被提交后,被设置为1。注意:数据数组在扫描过程中不被提交,而仅在结束时。
VAL字段仅用作一个过程指示器。在所有逐点PVs(例如:R1CV,D01CV)已经被提交后,它被提交。(因此,如果一个你感兴趣的PV到你获取VAL字段监视时未被提交,从它上次被提交以来,PVs值没有变化)。
状态消息(SMSG)字段保存这个记录发送的一条消息,它警告操作者一个错误情况。通过些0到命令字段(CMND),可以清除它。
警告(ALRT)字段是一个标记,它指示一个错误情况当前存在。1表示YES,0,No。在SMSG字段中将显示这个情况的原因。
字段 | 概要 | 类型 | DCT | 初始/默认 | 读取 | 修改 | 提交 | PP |
CPT | 当前点 | LONG | No | 0 | Yes | No | Yes | No |
BUSY | 扫描忙标记 | SHORT | No | 0 | Yes | No | Yes | No |
DATA | 数据准备好标记 | SHORT | No | 0 | Yes | No | Yes | No |
VAL | 值字段 | DOUBLE | No | 0 | Yes | Yes | No | No |
SMSG | 状态消息 | STRING [40] | No | Null | Yes | Yes | Yes | No |
ALRT | 警告字段 | UCHAR | No | 0 | Yes | No | Yes | No |
扫描阶段(FAZE)字段表明记录当前处于一个扫描的哪个阶段。可能阶段如下:
阶段 | 消息 | 含义 |
0 | IDLE | 没有在进行的。 |
1 | INIT_SCAN | 一个扫描正在开始 |
2 | DO:BEFORE_SCAN | 要做的下一件事是触发before-scan链接。 |
3 | WAIT:BEFORE_SCAN | before-scan链接已经被触发。我们正在等待它的回调到来。 |
4 | MOVE_MOTORS | 要做的下一件事是写入定位器。 |
5 | WAIT:MOTORS | 告诉我们电极移动了。现在我们等待它们的回调到来。 |
6 | TRIG_DETECTORS | 要做的下一件事是触发探测器。 |
7 | WAIT:DETECTORS | 我们已经触发了探测器。现在我们等待他们的回调到来。 |
8 | RETRACE_MOVE | 要做的下一件事是移动定位器到潭门post-scan位置。 |
9 | WAIT_RETRACE | 我已经告诉定位器移动到它们post-scan位置。现在我们等待它们的回调到来。 |
10 | DO:AFTER_SCAN | 要做的下一件事是触发after-scan链接。 |
11 | WAIT:AFTER_SCAN | after-scan链接已经被触发。我们正在等待它们的回调到来。 |
12 | SCAN_DONE | 扫描结束。 |
13 | SCAN_PENDING | 已经命令一个扫描,但它还未启动。 |
14 | PREVIEW | 我们正在进行扫描预览。 |
15 | RECORD SCALAR DONE | 记录标量数据。 |
数据状态(DSTATE)字段指明数据数组的运行处于什么状态。可能状态如下:
状态 | 消息 | 含义 |
0 | UNPACKED | 数据数组要么空闲,要么被填充。如果一个客户端现在应该读取一个数组,它会获取到上个扫描的数据。 |
1 | TRIG_ARRAY_READ | 要做的下一件事是触发数组读取PV,A1_PV。如果一个客户端现在应该读取一个数组,它会得到上个扫描的数据。 |
2 | ARRAY_READ_WAIT | A1PV已经被触发,并且回调仍然是待处理。如果一个客户端现在应该读取一个数组,它会得到上个扫描的数据。 |
3 | ARRAY_GET _CALLBACK_WAIT | recDynLinkGetCallback()已经为数组值PVs发出,并且一个或者多个回调仍然待处理。 |
4 | RECORD_ARRAY_ DATA | 是时候读取数组数据。如果任何数组值的PVs存在,在等待回调时,数据状态将变为ARRAY_GET_CALLBACK_WAIT。 |
5 | SAVE_DATA_WAIT | 数组被填充,但还不能被提交,因为数据存储客户端还未完成写上个扫描的数据。如果客户端现在应该读取一个数组,它会得到上个扫描的数据。 |
6 | PACKED | 数组被填充,并且缓存已经被切换,但它们还未被提交。如果一个客户端现在应该读取一个数组,它会得到上个扫描的数据。 |
7 | POSTED | 数据数组已经被提交。现在数据存储客户端可以读取这个扫描的数组数据。 |
10 杂项字段
字段 | 概要 | 类型 | DCT | 初始/默认 | 读取 | 修改 | 提交 | PP |
NAME | 记录名称 | STRING [29] | Yes | 0 | Yes | No | No | No |
DESC | 描述 | STRING [29] | Yes | Null | Yes | Yes | No | No |
PCPT | 先前当前点 | LONG | No | 0 | Yes | Yes | No | No |
PXSC | 先前执行扫描 | UCHAR | No | 0 | Yes | No | No | No |
TOLP | 上次提交的时间 | ULONG | No | 0 | Yes | No | No | No |
TLAP | 上次数组提交的时间 | ULONG | No | 0 | Yes | No | No | No |
VERS | 版本(这个字段未被保持到最新) | FLOAT | No | 1.0 | Yes | No | No | No |
XSC | EXSC的内部副本 | SHORT | No | 0 | Yes | No | Yes | No |
私有字段
字段 | 概要 | 类型 | DCT | 初始/默认 | 读取 | 修改 | 提交 | PP |
RPVT | 记录私有 | NOACCESS | No | Null | No | No | No | No |
PnDB | 位置n dbAddr | NOACCESS | No | Null | No | No | No | No |
RnDB | 回读n dbAddr | NOACCESS | No | Null | No | No | No | No |
DnnDB | 探测器nn dbAddr | NOACCESS | No | Null | No | No | No | No |
数据块地址字段(xxDB)包含了指向相应过程变量的dbAddr的指针。例如,P1DB指向了P1PV的dbADDr结构体。