EPICS sscan模块详细介绍1

1、介绍

sscan记录的目标是移动定位器通过一系列位置并且记录在每个位置的探测器数据。这种操作序列通常被称为一个扫描,或者作为一个多维扫描的一个循环。在定义扫描的参数被初始化并且这个扫描已经被启动后,sscan记录开始一个通常不需要进一步输入的长操作序列,并且根据扫描进度通知任何感兴趣的客户端。数据被采集到这个记录内的数组中,因而客户端不需要逐点处理它们。一个独立软件(“saveData”和sscan记录一起被包含在了synApps sscan模块)可以协同这个sscan记录把扫描数据写入磁盘。

注意:"scan"这个词在其它EPICS文档中经常用作表示与在这里含义非常不同的东西。在EPICS应用程序开发指南中,"scan"隐含表示记录运行或执行,如在"数据库扫描是用于决定如何运行一个记录的机制"。周期记录运行是由"扫描任务"执行,并且控制一个记录将何时被运行的字段被称为"SCAN"。"scan"的这些用法与sscan记录没有任何关系,并且这个词在此文档的其它部分没有这种EPICS含义。

单个sscan记录支持一维扫描。若干sscan记录可以被链接到一起来执行一个多维扫描。每个sscan记录可以最多控制4个定位器,最多触发4个探测器,并且最多从74个过程变量(70个探测器,值类型float;4个定位器,回读类型double)采集数据。

在最常见用法中,sscan记录移动电机并且在每个电机位置采集标量器(脉冲计数)数据,但它明显地也可以用于其它目的。可以扫描任何可写的EPICS PV(过程变量)经过值的一个集合,同时从任何其它PVs记录数据。例如,在一个扫描过程中,可以使用其中一个定位器PV更改一个探测器的增益或者停留时间。因而,贯穿这整个文档,术语定位器(positioner)应该被认为是表示"你能够写入一个数值的任何PV"。类似地,术语探测器触发器(detector trigger)将一般指向一个当向其写入时将引发数据采集启动的PV,但它可以被当成表示"你能够写入一个数值的任何PV"。最后,术语探测器(detector)是指任何可读的数值PV。(信号("signal")会是一个用于此的更佳词语)。

sscan记录通常采集标量数据值的集合并且组合它们到数组中,但它也可以从数组值的PVs直接采集数组。最终结果只能是一维数组;单个sscan记录不能采集多维数据。

使用可再分配的链接指定用于识别定位器,探测器以及探测器触发器的所有过程变量名。这允许在运行时,就在执行一个扫描前,配置这个扫描。当前,用与sscan模块一起发行的recDynLink库实现了这些链接。

在一个扫描可以启动前,不为空的所有链接必须连接了指定名称的PVs。此外,将写入的链接必须具有由EPICS访问安全授权的写权限。sscan记录不检查链接连接和写权限的一致性;在定义一个链接时,以及在每次扫描开始时,它检查。

1.1 简单的一维扫描

对应一个一维扫描的最简单合理完整的配置,使用以下字段:

1) P1PV:一个定位器的名称(例如:"myMotor.VAL")

2) P1SP:起始位置。将在这第一个位置采集数据。

3) P1EP:终止位置。将在这最后一个位置采集数据。

4) NPTS:要访问的总位置数目。

5) T1PV:探测器-触发器PV的名称。在定位器达到每个位置后,将写入这个PV,并且预计它初始化某个数据采集操作。

6) D01PV:一个探测器(信号)PV的名称。在探测器触发器结束采集数据后,将记录下这个PV的值。

当通过(写一个1到EXSC字段)启动一个扫描后,sscan记录命令定位器移动到它的起始位置。sscan记录使用recDynLinkPutCallback()告诉定位器移动,并且等待产生的回调,在进行这个扫描的下一个触发这个探测器的阶段前,表明那个定位器结束了。也使用recDynLinkPutCallback()触发这个探测器,并且在读取探测器并且继续执行采集另一个接下来数据(移动、触发,读取)点的序列前,sscan记录等待它结束。这种算法持续到sscan记录完成NPTS步,或者这个扫描被取消(通过客户端向EXSC字段写0)。在扫描结尾,sscan记录写入一个已访问位置的数组(P1RA)和一个采集的探测器值的数组(D01DA)中。

让我们再次过一遍,这次更详细的,更加通用,并且包含更多可用选项。

1) 定位器:你可以指定0到4个定位器。定位器是用于告诉sscan记录它们何时结束移动。在所有定位器声明它们结束后,sscan记录在写入探测器触发器前,等待一个用户指定的稳定时间(PDLY,通常0)。(如果没有定位器,则没有定位器稳定时间)。

2) 要访问的位置:在这里有很多可能性。你可以为每个定位器指定[start, end, center, width, step-size]集合的任意组合;你可以为每个定位器装载一个位置表;或者你在一个扫描过程中指定要被连续移动的定位器。你可以绝对或者相对于前个扫描位置指定位置。

3)探测器触发器:探测器触发器作用非常像定位器,它们向其写入一个值并且等待任何接下来的过程结束,但它们在每个数据点(TnCD)发送相同值。在所有被触发的探测器声明它们自己结束时,sscan记录在读取来自探测器信号PVs的数据前等待一个用户指定的稳定时间(DDLY,通常为0)。(如果没有探测器触发,则没有探测器稳定时间)。

4)探测器信号:一般,探测器信号是标量PVs,但他们可以是数组值的PVs。如果这样,sscan记录将在这个扫描结尾,从它们读取NPTS个值。如果数组值的PVs需要运行来采集它们的值,sscan记录可以写入一个特殊的数组触发器(A1PV A1CD,完全类似探测器触发器),并且在读取这些数组前,等待任何后续的运行结束。如果所有探测器信号是数组值的,使用数组采集类型(见ACQT)可能更好。

可以从扫描到扫描地累积探测器信号值,因而你可以扫描一个位置集合,构建统计精度并且对任何定位误差或者变量外部条件(ACQM)进行平均。

5)在扫描之后:你可以使用PASM字段告诉定位器在此扫描结束后要做什么。默认行为只是停在扫描留它所在地位置,但你可以告诉它们返回到它们扫描之前的位置,移动到它们的起始位置,或者移动到从采集数据计算出的位置(例如:在扫描过程中,一个指定探测器信号REFD达到它峰位值所在的位置)。

1.2 多维扫描

多维扫描是简单的:一个外层循环sscan记录(我们称它为"scan2"),把一个内层循环sscan记录(“scan1”)视作一个要被触发的探测器,并且每个sscan记录采集它自己的数据。因而,scan2.T1PV被设置成scan1.EXSC,而scan2.T1CD被设置成1。换句话,scan2写1到scan1的"执行扫描"字段(EXSC)。

要启动这个扫描,命令scan2记录启动(scan2.EXSC被设置成1)。scan2移动其定位器到它们的起始点,并且等待它们的回调。接着scan2写入其探测器触发器(s),其中一个触发器在此情况下使得scan1开始它自己的扫描。scan1记录现在将经历其整个编程好的扫描,在每个数据点从其探测器采集数据。

当scan1结束时,并且其数据已经被写了(或者至少被保护了),其结束时回调使scan2继续进行它的扫描过程--读取探测器值,移动定位器到新位置,并且使得scan1再次执行。

这种配置多维扫描的方法非常灵活,并且允许任何维度的扫描。注意:scan1可以独立于scan2被执行,因此可以构建一个复杂的多维扫描,并且一次测试一维。(原则上,从单个外层循环扫描并行地运行若干内层扫描是可能的,但实际上,此功能是使用受限制的,因为在内层循环扫描之间没有协同,并且不存在可以正确地理解采集数据地数据存储客户端。)

一个包含在一个多维扫描中的外层sscan记录不知道或者不关注其写入的探测器触发器实际上是另一个sscan记录,这个sscan记录将进行一整个内层扫描;外层sscan记录只是触发其当作一个探测器的东西,并且等待那个探测器结束。内层sscan记录也不知道自己是比自己更大的东西的一部分。必须知道一个多维扫描正在发生的唯一代码是存储此数据的客户端。这个客户端在那些数据被那个内层扫描的下次执行重写前从每个内层到目采集所有数据,因为sscan记录仅保存数据的一维数组。

这在客户端和在多维扫描中包含的sscan记录之间明显地需要某种握手。接下来的部分描述由sscan记录实现的握手机制。

1.3 与客户端交互

sscan记录的客户端包含启动,停止或者暂停一个扫描的软件;显示由一个扫描采集的数据的软件;写扫描数据到磁盘的软件;通过实现定位器或探测器操作参与扫描的软件。一个客户端可以做任何或者全部这些事情,但最好分开讨论它们。

1.3.1 启动一个扫描

客户端写数值1到sscan记录的EXSC字段启动一个扫描。如果这个sscan记录能够启动一个新扫描,在此新扫描进行时,它设置它的BUSY字段为1,并且当这个扫描结束时,它设置BUSY为0。

如果sscan记录不能启动一个新扫描,客户端将接收到一个错误指示,并且此命令可能被忽略。这个sscan记录将设置其SMSG字段为一个描述其为什么不能启动一个新扫描原因的字符串。可能原因包括以下:

1) "Waiting for PV's to connect":被指定为定位器,触发器,回读等的一个或多个PVs还未连接上。如果PV必须被写入,可能PV已经连接但这个IOC由于EPICS访问安全设置或者条件没有写入它的权限。

2)"Scan is paused":sscan记录字段PAUS有一个非0值,表明某个客户端已经告知sscan记录暂停到PAUS被设置回0。在这种情况下,这个sscan记录将设置FAZE为"SCAN_PENDING",并且在设置BUSY为0并且启动这个扫描前,等待到PAUS被撤销。

3) "waiting for client ...":sscan记录字段WTNG有一个非0值,表明某个客户端已经告知sscan记录要等待。(如下,详细见"与数据存储客户端握手"。)在这种情况下,这条命令有一个非0值。

4) "Already scanning":一个扫描已经进行中。当扫描进行时设置EXSC为1对那个扫描没有作用。在这种情况下,忽略这条命令。

5) "Waiting for saveData":因为数据存储客户端"saveData"仍然使用两个数据数组集合之一,并且另一个满扫描数据的集合也正在等待saveData提供服务。在这种情况下,sscan记录在设置BUSY为1并且启动这个扫描前将等待到saveData结使用这些数组(saveData通过写0到sscan记录的AWIT字段来表明)。

6) "Waiting for callback":先前的扫描实际上结束了,但这个sscan记录发出的其中一条命令还未结束。在这种情况下,启动一个新扫描的命令将被忽略。

在除了"Waiting for PV's to connect"和"Scan is paused"外的所有情况中,忽略start命令,并且在阻止其启动的条件解除时,扫描不会自动启动。必须发出一个新的启动命令。

1.3.2 停止一个扫描

一个客户端通过写0到EXSC字段告诉sscan记录停止扫描。但停止一个扫描有时是一个复杂过程,因为,当扫描进行时,sscan记录向其它软件发出命令,并且等待在那些命令结束时将出现的回调。sscan记录也与数据存储客户端(如果有)握手来确保在数据数组的内容完成写入磁盘前,它们不被重写。当一个sscan记录接收到一个"停止"命令,它能够容易地让自己停止,但它不能取消发送或者取消它已经发出地命令,并且不允许它认为已经发出地命令或者还未被写入地数据可以简单地被取消。如果它正在等待这二者之一,它将继续等待,知道使用者通过再次写0到EXSC字段告诉它停止。如果它正在等待数据存储,需要向EXSC两次写0。

当告诉一个sscan记录在其有待处理回调时停止,它设置其SMSG字段为字符串"Abort:waiting for callback"。当回调到来时,SMSG将变成"Scan aborted by operator",并且BUSY字段将被设置为0。

当告诉一个sscan记录在其等待数据存储客户端"saveData"服务时停止,它设置它的SMSG字段为"Killing scan (kill=n/3)",此处n是1,2或3。当saveData已经服务了sscan记录,SMSG将变成"Scan aborted by operator",并且BUSY字段将被设置成0。如果saveData没有服务这个sscan记录,一共3次写0到EXSC将使得这个扫描用"Abandoning unsaved scan data"消息结束。

如果sscan记录同时等待待处理回调和数据存储客户端,它写入SMSG的消息可能相互覆盖,并且不明确地指示正在发生什么。但使用者地操作过程总是一样的:

  • 向EXSC字段单次写0请求礼貌地取消扫描,等待回调和数据存储。
  • 向EXSC字段连续两次写0请求取消扫描,不等待待处理地回调。但,sscan记录将仍然等待数据存储客户端。
  • 向EXSC字段连续三次写0要求立即取消扫描,不关注后果。在这种情况下,将丢失数据。

当扫描被取消,并且需要向EXSC写入多次时,接下来地扫描可能继承了这个问题。如果问题是一个待处理回调,并且到下次告诉sscan记录启动时那个回调还没有出现,将不允许这个扫描写入其回调仍是待处理的PV。这表明不完美地实现了一个PV,并且不能被扫描;或者某个错误阻碍了操作结束;或者sscan记录丢失了结束消息;或者只是此操作需要很长时间结束。如果此操作不能被手动停止,唯一的恢复是擦除这个PV名并且再次写它。这关闭并且再次打开了对那个PV的通道访问连接,并且经常能够解决眼前的问题。

1.3.3 暂停一个扫描

通过写"PAUS"或者数值1到PAUS字段,可以暂停一个扫描。当一个sscan记录被暂停时,它将不再做进一步推进扫描进度的事情,但它保持接受待处理回调。通过写"GO"或者数值0到PAUS字段,继续一个被暂停的扫描。

通过写"PAUSE"到所有涉及到的sscan记录可以暂停一个多维扫描。(数据库standardScans.db通过实现了一个"PAUSE" PV并且写其值到此数据中所有sscan记录实现这个)。

1.3.4 显示扫描数据

sscan记录使用EPICS通道访问发布扫描数据,就像任何其它EPICS记录发布其字段的值。通过通道访问发布数据的操作在这里被称为提交,因为执行这个功能的EPICS函数是db_post_events()。在一个字段被提交后,一个客户端可以通过发送通道访问调用ca_get()获取新值。一个客户端通过监视也可以提前安排接收从一个特定字段提交的数据,也被称为订阅这个字段。如何做这件事的详情见通道访问参考手册(尤其ca_add_event()或ca_create_subscription())。这里的目的只是介绍术语提交(post)和监视(monitor),因而能够在此文档中使用它们。

sscan记录为扫描数据维护两个数组PV的集合:来自一个完成的扫描的数据以PnRA和DnnDA被提交(例如:P1RA, D01DA);来自一个进行中扫描的数据以PnCA和DnnCA被提交。在扫描过程中,只在用户通过设置数组-提交周期ATIME为一个岛屿或者等于0.1(秒)的值时,数组才被提交。在一个扫描结束后,所有数据数组被提交,用掩码DBE_LOG标记,并且在下次扫描结束前,已完成扫描提交(PnRA和DnnDA)仍然对客户端可访问。

因为sscan记录实现了双缓存数据数组,并且由于以在EPICS中完成提交的方式,扫描进行中数据数组的提交不可避免地导致了完成扫描的数据数组的再次提交。如果这对于数据显示或者数据存储客户端是一个问题,避免这个问题有两种方式:

1) 通过保留数组提交周期ATIME为默认的0值,告诉sscan记录在扫描过程中不要提交数组;

2)修改客户端使得它只监视带有DBE_LOG掩码的提交。

一种对于正在从一个进行中扫描获取数据的客户端更高效,但更困难的方法是监视标量的当前值PVs,诸如R1CV,D01CV等,并且采集它们的值到数组。

定位器实际上有两个字段,它们适合于在一个扫描进行时用于显示:定位器的所需值(PnDV)和回读的当前值(RnCV)。(如果没有回读PV,提交的回读值是所需值的副本)。

不确保一个扫描的所有数据点以标量值被提交,因为sscan记录节流它的提交,因而它不超过每秒20个数据点。(“数据点”表示"所有定位器和探测器")。这种节流是为了限制由一个扫描引起的网络活动,并且因为显示扫描数据重要性不高于采集它,并且因为sscan记录也使用网络采集数据,所以这是必要的。

拒绝提交一个其值从上次此字段被提交以来没有变化的字段的标准EPICS行为使得累积提交的标量值到数据数组的任务复杂了。如果一个客户端只是追加新提交到它正在累积的数据数组,它将不包含那些重复的值。以下算法将正确地累积数据:

1)创建本地变量来保存被监控字段地缓存数据,以及一个本地变量(我们称其"numPoints")来保存累积地数据点数目。

2)监视DnnCV, RmCV和VAL(标量数据和控制字段)。

3)监视DnnDA, PmRA,DATA和CPT(数组数据和控制字段)

4)当接收到DnnCV, RmCV或CPT时,在一个本地变量中缓存接收到标量值。

5) 当接收到DnnDA或PmRA时,在一个本地变量中缓存接收到地数组值。

6)当接收到DATA==0时,清除所有数据数组,并且重置numPoints为0。

7)当接收到VAL时,添加来自缓存的标量值到所有数据数组,并且增加numPoints。

8)当接收到DATA==1时,清除所有数据数组并且用缓存的数组值替代;设置numPoints为从CPT接收到的缓存值。

1.3.5 与数据存储客户端握手

1)使用AWAIT和AAWAIT字段的新方式

数据存储客户端等待DATA==1,这表明这个扫描结束了并且sscan记录结束了提交所有数组字段;写1到AWAIT字段防止sscan记录在客户都安读完数组字段前重写这些数组字段;当客户但结束读取时,写0到AWAIT。这种握手的一个优势是它允许sscan记录进行下个扫描(sscan记录的数据数组是双缓存的),直到该提交数据时。用此方式,数据存储客户都可以写入一个扫描数据集,同时sscan记录正在采集下个数据集。

对于非常快的扫描,或者非常慢的数据存储客户端,在一个数据集的提交和下个数据集采集之间,对于客户端写1到AWAIT(数组等待)字段,可能没有足够时间。在此情况中,你可以使得sscan记录在它提交数据时通过设置AAWAIT(自动数组等待)字段为1自动设置AWAIT=1。在synApps sscan模块中包含的数据存储客户端saveData为其监视的每个sscan记录设置AAWAIT。

注意:因为saveData为其监视的sscan记录设置AAWAIT,在saveData完成写先前扫描的数据到磁盘(或者做这件事已经尝试并且失败了一个预设次数)前,一个扫描不能执行到结束。sscan模块当前没有提供一种最终用户通过其可以开启和关闭数据存储的机制。对于每个sscan记录,通过告诉saveData监视那个sscan记录在启动时开启数据存储。关闭数据存储的唯一方法是编辑启动文件并且重启。

仅一个数据存储客户端可以使用AWAIT。如果你有多个数据存储客户端,你必须安排它们池化它们对AWAIT字段的使用,使得仅在所有客户端结束时它才被重置为0。(置位AWAIT多次是可以的。仅首次AWAIT=1写有作用)。

注意:AWAIT握手保护扫描数据,不论sscan记录如何被执行,不同于接下来描述的老方法。

2)在引入AWAIT字段前,握手的唯一方式是这种机制的扩展:sscan记录通过其等待探测器触发器发信号结束。在这种扩展中,sscan记录等待,直到所有探测器触发器已发结束信号,并且字段WAIT等于0。这种扩展的目的是支持不能用回调发结束信号的探测器,但能够写入一个PV,例如,一个探测器,其以一个通道访问客户端实现的,并且它仍然能用于那个目的,而数据存储客户端使用它保护从一个内层扫描采集的数据。

这是这种握手在一个数据存储程序中如何运作:数据存储客户端注意到一个内层sscan记录已经启动一个扫描(一般,它监视DATA字段,在一个扫描开始时其被设为0),并且写1到外层sscan记录的WAIT字段。这防止外层sscan记录在客户端完成读取内层扫描数据前继续运行。客户端等待DATA==1,其表明新数据是可以获取的。当客户端结束读取内层扫描数据时,它写0到外层sscan记录的WAIT字段,运行这个扫描继续运行。

如果有若干想要这个扫描等待它们的客户端,它们都能够写到WAIT字段。每个写1增加了这个扫描的等待计数字段WCNT,每个写0减少它。当WCNT达到0时,扫描继续。

在快速扫描中,客户端可能没有时间注意一个内层扫描已经启动并且在此内层扫描结束并且被再次出发前写1到外层扫描的WAIT字段。在这种情况下,使得外层扫描在其触发探测器时自动写1到其自己的WAIT字段。如果AutoWaitCountT(AWCT)字段被设置成1,它将做这件事。在这种情况中,客户端一定不能再写一个1到此外层扫描的WAIT字段(那将增加等待次数为2),但必须只写0到WAIT字段来表明它准备好扫描继续了。

如果有N个客户端,autoWaitCount可以设置为N,并且仅在完成了写N个0到WAIT字段后,此扫描才将继续。

autoWaitCount==0方法的优势是无论客户端是否能够写入WAIT字段都可以执行扫描。缺点是对于非常快速的扫描是不可靠的。

注意:这种握手形式没有做非常彻底的数据保护工作,因为它没有直接防止一个sscan记录重写其自己的数组;它仅防止一个外层循环sscan记录告诉一个内层循环启动一个新扫描。如果这个sscan记录是被其它代理执行,WAIT握手完全不保护数据。

1.3.6 与实现了定位器或探测器的CA客户端握手

如果满足以下两个标准,一个通道访问客户端可以参与由sscan记录驱动的扫描:

1)客户端时被一个PV驱动,sscan记录的定位器或探测器触发器链接写入此PV。

2)客户端用sscan记录理解的方式发送完成信号。

客户端可以使用两种机制来发出将与sscan记录一起使用的结束信号:

1) 基于putNotify的结束信号发送

此方法是sscan记录期望它驱动的所有东西用于发送结束信号,并且sscan记录自身使用这种方法发出结束信号。客户端不能直接使用putNotify发出结束信号,因为它们的执行不受EPICS管理。但它们能够通过写入一个busy记录间接地做这件事。

一个busy记录时一个自定义EPICS记录,以synApps包的组件被提供,其看着和操作几乎完全类似二进制输出记录"bo",除了只在其VAL字段有值0时,其才执行其转发链接FLNK。当其发生时,以转发链接的运行组成实现了EPICS的putNotify结束机制,因而busy记录允许CA客户端控制其转发链接的情况表示了客户端可以控制一个putNotify回调的计时。

在实际中这如何运行:

1)开发者向这个IOC装载一个busy记录(我们称之xxx:detBusy)。

2)sscan记录写1到xxx:detBusy.VAL,使得这个记录运行。

3)客户端监视xxx:detBusy.VAL,在其变为1时,开始某个操作。

4)当客户端结束了,它写0到xxx:detBusy.VAL。这使得这个记录运行了。因为其VAL字段是0,它执行其转发链接。

5)EPICS知道当一个记录执行其转发链接时,它结束运行了,因而它向sscan记录发送一个结束回调。

因而,busy记录在客户端实际执行时似乎正在执行,因而sscan记录可以知道客户端何时结束。

非常简单,但它需要在某个IOC中装载一个专用的记录。这是装载一个busy记录的数据库:

record(busy, "xxx:CCD_Busy")
{
}

在synApps中很多数据库为此目的包含了busy记录,尤其那些用作状态标记语言代码前端的那些数据库。虽然由sscan记录的需求激发,这种结束信号发送的功能可以在参加了EPICS程序的任何CA客户端中被使用。

WAIT-字段与sscan记录握手

此种握手是用于实现了探测器,以及没有使用busy记录进行结束信号发送的CA客户端。这是它如何运行:

1)客户端监视一个PV来查明何时某人想要它采集数据。

2)sscan记录写某个值到这个PV启动采集。

3)客户端写1到<scanrecord>.WAIT,表明它想要sscan记录等待。

4)客户端执行它的数据采集任务。

5)客户端写0到<scanrecord>.WAIT,表明它结束了。

若干客户端可以使用WAIT字段,每次写1增加了一个等待计数WCNT;每次写0减小WCNT;当WCNT减小到0时,sscan记录停止等待。sscan记录不关心谁写什么到WAIT;它只是等待WAIT==0写的数目等于WAIT==1写的数目。

但如果客户端反应优点慢怎么办,并且在客户端有时间写1到sscan记录前,这个sscan记录检查了它的等待计数WCNT?如果这是一个问题,你可以通过设置<scanrecord>.AWCT为慢客户端数目使得sscan记录在合适时间设置WCNT。(但现在那些慢客户端一定不能写1到WAIT。)

1.4 定位器和探测器触发器操作的结束

如先前提到,使用了reassignable链接指定了用于识别定位器,探测器和探测器触发器的所有过程变量名。实现这些链接不同于标准的EPICS链接。Reasignable链接用recDynLink库实现的通道访问链接(被修改成使用回调)。这些链接用通道访问函数ca_put_callback()执行写,并且sscan记录希望只在由这个写操作引起的所有运行结束后才调用结果回调函数。(我称结束-回调标准,在此文档中,我将描述在哪些下它被满足的条件)。

对于简单的定位器和探测器,这不是一个问题。单独的记录总是满足结束-回调标准。既不使用同步或异步策略的特殊的记录(motor,scaler,mca和sscan记录),在它们启动的操作结束前,通过让它们避免调用recGblFwdLink()(即:阻止执行它们的转发链接),被精心设计为满足结束-回调标准。

如果用一个相互链接记录的集合实现了一个定位器或探测器,所有这些记录单独都满足结束-回调标准,如果在运行链中由sscan记录的写启动的所有链接有属性PP,并且运行的所有记录都是被动的(即:它们的SCAN字段被设置成"Passive")。不满足这个标准的数据库仍然可以非常简单地满足结束-回调标准:在数据库中至少一个记录在操作结束前必须避免执行它的转发链接,并且那个记录必须是被写入的记录,或者它必须由那个记录通过一个没有损坏的PP链接系列驱动。

如果在CA客户端(诸如SNL程序)帮助下实现了定位器或探测器,见1.3.6 与实现了定位器或探测器的CA客户端握手中"基于putNotify的结束信号发送"部分。

数据库开发者应该注意在一个IOC中一个记录的PP链接指向另一个IOC中一个记录,它将默默地被转成一个CA链接,这将满足结束-回调标准。在此情况下,有两个选项:busy记录方法,和一个能够进行一个ca_put_callback()。我知道有6种记录类型能够进行ca_put_callback():sscan,swait和sseq记录;带有软异步设备支持的ai记录;以及sCalcout和aCalcout记录。(sscan, swait, sseq, sCalcout和aCalcout记录随着synApps一起发行,sCalcout和aCalcout是EPICS base种calcout记录的变体;sseq是EPICS base种seq记录的变体。)

1.5 飞行扫描

术语"飞行扫描"是若干扫描类型的通用说法,它们表现并且被不同地配置了,但在数据采集时,它们都包含了一个或多个正在移动的电机。这样的位移台被称为处于"飞行模式"。

当前,sscan记录对待飞行模式位移台实际上与用于所有飞行扫描类型相同的方式:它们被移动到起始位置(和任何非飞行模式位移台一起),并且sscan记录等待所有位移台结束;接着,在首(或唯一)次触发探测器时,飞行模式位移台被启动向终点移动,并且sscna记录不等待它们结束。

一个飞行模式位移台以哪种速度移动是飞行扫描的一个重要考虑因素,因为你想要知道在什么位置采集数据。但sscan记录对用其它扫描条件调整位移台速度没有提供任何支持,诸如起始和终点,要采集的数据点数,以及探测器停留时间。这必须由外部软件在扫描启动前完成,或者作为由sscan记录的链接之一触发的运行组成部分,诸如扫描前链接完成。

从sscan记录的视角,有两种飞行扫描类型:标量模式飞行扫描,在这种模式中,sscan记录逐点命令这个扫描;和数组模式飞行扫描,在这种模式中,扫描记录移交逐点方向给某个其它实体,诸如一个多通道scaler。这些类型是由ACQT(采集类型)的值区分。

1.5.1 标量模式飞行扫描

如果ACQT==SCALAR("标量模式",默认),sscan记录将各自命令NPTS个数据点的采集,如我们到目前认为的。即是,它将执行(移动、触发,读取)的NPTS次迭代。如果一个或多个位移台设置它们的步进模式PVs(PnSM)为FLY,一个标量扫描是一个飞行扫描。这种扫描类型和我们考虑到目前为止的扫描之间的差别是那些飞行模式位移台的移动。

在标量模式中,sscan记录按如下执行飞行扫描:

1) 执行扫描前链接。如果BSWAIT==Wait,等待完成。

2)移动所有位移台到它们的初始位置,并且等待完成。

3)移动飞行模式位移台到它们的终点位置。不等待完成。

4)触发探测器并且等待完成。

5)读取位移台和探测器。

6)移动非飞行模式位移台到它们的下一个位置并且等待。

7)触发探测器并且等待完成。

8)读取位移台和探测器。

9)在完成采集NPTS个数据点或者扫描被取消前重复(6,7,8).

10)执行数组触发链接,并且等待完成。

11)读取任何数组值的探测器的前NPTS个元素。

12)如果PASM!=STAY,移动所有位移台到指定位置,并且等待结束。(假设这些命令将重新定位任何仍然在移动的飞行模式位移台向它们的终端。)

13)执行扫描后链接。如果ASWAIT==WAIT,等待结束。

配置标量模式飞行扫描非常简单,因为必须被设定的唯一外部条件是位移台速度以及探测器停留时间。但位移台和探测器值之间的关联性一般没有在步进扫描中的精确和重复性。这是因为在飞行模式位移台移动时读取它们,并且因为那些读取的计时与位移台的移动不紧密同步。在最简单的情况(没有没有非飞行模式位移台),位移台读取之间的时间是探测器停留时间加上sscan记录的每点开销时间,因为IOC处理器除了扫描外做其它事件而变化。

1.5.2数组模式飞行扫描

如果ACQT=1D ARRAY(“数组模式”),sscan记录将命令仅单"数据点"的采集,并且那个数据点僵尸一个长度NPTS的一维数组的集合。在一个数组模式扫描中,所有位移台都被当成处于飞行模式,无论它们的步进模式PVs的值,因为sscan记录仅两次写入它们。在移动位移台到它们的起始位置后,sscan记录将仅执行一次(移动,触发,读取)的序列。

数组模式原来仅为了读取一个数组值的探测器(多通道分析谱仪)集合,并且完全不包含位移台。但在选择数组模式时,sscan记录不擦除任何已有的位移台,并且如果有任何存在,则必须对它们做某些事情,因而本文档必须描述它。

在数组模式中,sscan记录按如下执行飞行模式:

1)执行扫描前链接。如果BSWAIT==Wait,等待完成。

2)移动所有位移台到它们的初始位置,并且等待完成。

3)移动所有位移台到它们结束的位置。不等待完成。

4)触发探测器并且等待完成。

5)执行数组触发链接,并且等待完成。

6)读取任何数组值的探测器的前NPTS个元素。

7)如果PASM!=STAY,移动所有探测器到指定的位置,并且等待完成。(假设这些命令重新定向仍然向它们终点移动的任何飞行模式位移台)。

8)执行扫描后链接。如果ASWAIT=Wait,等待完成。

因为sscan记录在任何数组模式扫描中不进行任何逐点写入(或从读取)位移台,它采集的数据将表示在一个位置上的平均,除非某个外部软件执行位移台值和探测器数组元素之间的协同。数组模式飞行扫描相较标量模式飞行扫描的优点是这种协同可以由外部能够做好它的硬件来完成。缺点是必须安排硬件位移台/探测器的协同。

在一个数组模式扫描的常见实现中,探测器数据是由多通道scaler采集,其是由周期信号,或者来自电机的脉冲从通道到通道的进行。相较于以上讨论的标量飞行扫描,这种飞行扫描类型在位移台和探测器值之间有非常精确的和可重复的关联。

在早于2.7的sscan模块中,飞行模式实现略微不同,如下(不同用黑体)。如果sscan记录处于标量模式(ACQT=SCALAR),并且一个位移台的步进模式值为FLY,sscan记录在一个扫描开始时移动它到起始位置,等待其到位,采集一个数据点(触发读取),移动位移台到结束位置,并且在位移台移动到结尾位置时开始采集余下的数据点。如果记录处于数组模式(ACQT=1D ARRAY),不是显式位于飞行模式(PnSM=FLY)的位移台完全不被移动到结束位置。

猜你喜欢

转载自blog.csdn.net/yuyuyuliang00/article/details/130037211