EPICS数据库

 

 分布式EPICS设置

1) 操作接口 

2) 输入/输出控制器(IOC)

IOC

1) 数据库:数据流,基本上周期运行

2) sequencer:状态机,基本上按需

"硬" IOCs运行vxWorks并且直接连接到A/D, D/A, LLRF...硬件。

"软"IOCs运行在Linux等上,并且除了串口或网络设备(Moxa到电机控制器...)外没有I/O硬件。

IOC数据库

1) 'iocCore'软件装载并且执行'记录'--记录的配置替代了自定义编写代码。

2) 所有控制系统工具箱都有:

  • GUI工具
  • 网络协议
  • 硬件驱动

但很少有一个相当的数据库。

示例:基本的温度控制

任务:

1) 读取温度

2) 根据需要闭合/打开开关

3) 重复

一个鱼缸数据库

由三个记录组成:temp, check以及switch。

1) 模拟输入记录temp用于表示读取鱼缸温度,SCAN字段表示1秒种读取一次,DTYP和INP字段表示硬件读取接口和硬件读取需要的格式,PREC是精度小数点后1位,LINR表示用表格转换温度,EGU表示工程单位。LOPR和HOPR表示上下温度限制,SMOO是读取所用平滑参数,HIGH表示上阈值,HSV表示当读取的值超过了HIGH设定值时,将触发MAJOR严重性警报。

2) 计算输出记录check,INPA表示用通道访问过程被动的方式(即:temp记录运行结束时本记录开始运行)从temp记录VAL字段读取输入,将这个输入与10进行比较,如果新产生的结果与上次结果不同时,将此次的VAL字段输出到switch记录。

 3) 二进制输出记录,DTYP和OUT字段决定了硬件类型和输出的格式,当check记录运行结束后,如果其VAL发生变化了,则VAL的值将输出到switch记录,switch根据得到的值是0或1,对加热开关进行控制。IVOA字段决定了,当switch得到一个无效输入时,采取的行动是把输出值设置为0,即断开加热开关。

数据库 = 记录 + 字段 + 链接

1) IOC装载并且执行一个或多个数据库。

2) 每个数据库有若干记录

3)每个记录有:

  • 名称(在整个网络上唯一)
  • 类型(决定字段和它们的功能)
  • 字段(属性,可以在运行时被读取,大部分也可以被写入)

记录是活动的

1) 记录做事情:它们能做什么,取决于记录类型,字段值以及设备支持

  • 从硬件或其它记录获取数据
  • 执行计算
  • 检查值范围,产生警报
  • 写到其它记录或硬件

2) 当它们被运行时:除非一个记录被运行,否则什么事情都不会发生

记录周期地或者被事件或者其它记录触发而运行。

示例数据库"first.db"

[blctrl@rockygu db]$ cat first.db
# 最简单地记录,它做某件事情并且产生变化地数值
record(calc, "$(USER):random")
{
        field(SCAN, "1 second")
        field(INPA, "10")
        field(CALC, "RNDM*A")
}

1) 执行 softIoc -m USER="TEST" -d first.db加载这个数据库:

[blctrl@rockygu db]$ softIoc -m USER="TEST" -d first.db
dbLoadDatabase("/EPICS/base-R7.0.4.1/bin/linux-x86_64/../../dbd/softIoc.dbd")
softIoc_registerRecordDeviceDriver(pdbbase)
dbLoadRecords("first.db", "USER=TEST")
iocInit()
Starting iocInit
############################################################################
## EPICS R7.0.4.1
## Rev. 2022-06-14T15:34+0800
############################################################################
iocRun: All initialization complete
epics> 

2) 在另一个终端执行:camonitor TEST:random

[blctrl@rockygu ~]$ camonitor TEST:random
TEST:random                    2023-03-19 23:10:08.702282 2.3917
TEST:random                    2023-03-19 23:10:09.702263 8.34287
TEST:random                    2023-03-19 23:10:10.702296 1.3489
^C

 3) 在ioc环境中尝试dbl, dbpr, dbpr命令:

epics> dbl
TEST:random
epics> dbpr TEST:random
A   : 10            ASG :               B   : 0             C   : 0
CALC: RNDM*A        D   : 0             DESC:               DISA: 0
DISP: 0             DISV: 1             E   : 0             F   : 0
G   : 0             H   : 0             I   : 0             J   : 0
K   : 0             L   : 0             NAME: TEST:random   SEVR: NO_ALARM
STAT: NO_ALARM      TPRO: 0             VAL : 6.53513389791714
epics> dbpf TEST:random VAL
DBF_DOUBLE:         0.425726710918
epics> dbpf TEST:random VAL
DBF_DOUBLE:         5.78789959564

记录类型

1) ai/ao:模拟输入/输出。读取/写入数值,映射成工程单位

2)bi/bo:二进制输入/输出。读/写单个bit位,映射成字符串

3) calc:公式计算

4) mbbi/mbbo:多位二进制输入/输出。读/写16位数值,映射位模式为字符串

5) stringin/stringout, longin/longout, seq, compress, histogram, waveform, sub, ...

公共字段

1) 设置时:

a) NAME:记录名,在网络上唯一。

b) DESC:描述。

c) SCAN:扫描机制。

d) PHAS:扫描阶段。

e) PINI:在初始化时运行一次。

f) FLNK:转发的链接。

2) 运行时:

a) TIME:时间戳。

b) SEVR, STAT:警报严重性,状态。

c) PACT:PROCESS活跃的。

d) UDF:未定义?从不被运行。

e) PROC:强制运行。

3) 二者都有:

TPRO:跟踪运行,设置为1来调试记录运行。

记录扫描

1) SCAN字段:

a) 当由其它记录使其运行:Passive(默认)

b) 周期地:".1 second", ".2 second", ".5 second", "1 second", "2 second", "5 second",  "10 second",    

c) 遇到事件:

  • "Event": (EVNT字段选择事件)
  • "I/O Intr":(如果设备支持允许这个选项)

2) PHAS字段

为在相同周期扫描上地记录添加顺序: 首先PHAS=0, 接着PHAS=1, ...

3) PINI:

设置"Yes"强制在启动时运行记录一次。对"操作输入"记录是个好办法,其几乎从不更改,因而它们有一个初始值。

4) PROC:

写入这个字段将运行一个记录。

 数据库 vs IOC地其它部分

1) 记录扫描运行的优先级高于通道访问或PV访问:在高CPU负载时,在记录仍然被运行时,PV可能未连接。

2) 0.1秒扫描运行的优先级高于10秒扫描。

3) PRIO字段为异步完成以及事件扫描的记录选择优先级。

你的里程会不不同:RTOS或普通的Linux?

公共的输入/输出记录字段

1) DTYP:设备类型。

2) INP/OUT:如何读/写,格式依赖于DTYP。

3) RVAL:原始值(例如:16位整数)

4) VAL:工程单位值(例如:64位浮点数)

仅限输出

1) DOL:所需的输出链接。输出记录读取这个链接来获取VAL,接着写到OUT...

2) OMSL:如果Output Mode Select = closed_loop。

3) IVOA:无效输出时的操作。

4) DRVL, DRVH:驱动限制。

扩展"first.db"

# 一个斜率从0到'limit', 限制可以通过一个单独记录被设置
# 使用模拟输出记录,输入也也有作用,由于没有进行读或写的硬件,但仅输出记录有DRVH...
record(ao, "$(S):limit")
{
        field(DRVH, "100")
        field(DOL, "10")
        field(PINI, "YES")
}


# 读取输入:A=我自己当前的值,B等于limit记录的值
# 在自身值小于limit的值时,每次1秒运行一次,自身值增加1,自身值等于limit值时,
# 下次运行,自身值变为0
record(calc, "$(S):ramp")
{
        field(SCAN, "1 second")
        field(INPA, "$(S):ramp")
        field(INPB, "$(S):limit")
        field(CALC, "A<B ? A + 1 : 0")
}

模拟记录字段

1) EGU:工程单位名称。

2) SMOO:平滑。

  • VAL = (1-SMOO) * new_value + SMOO * last_value
  • SMOO=0:VAL=new_value, 默认行为。
  • SMOO=1:VAL=last_value, 不再起作用的行为。
  • 0<SMOO<1:VAL ’平滑‘按照最新的读取。

3) LINR:线性(无,斜率,断点表):EGUL,EGUF,ESLO,EOFF:用于LINR的参数。

4) LOLO, LOW, HIGH, HIHI:警报限制。LLSV, LSV,HSV,HHSV是对应相关联的警报严重性。

二进制记录字段

1) ZNAM,ONAM:对应"zero", "one"的状态名。

2) ZSV, OSV:警报严重性。

记录链接

1) 输入或输出链接可能是:

a)其它记录的字段的名称:"other", "other.VAL", "other.A"

  • 如果其它记录是在相同IOC中:"数据库链接"
  • 如果名称未找到:"通道访问链接"

b)  硬件链接

  • 依赖设备支持的详情
  • DTYP字段选择设备支持
  • 格式示例:"@plc12 some_tag", "C1 S4"

2) 输入链接可能是:常量"0", "3.14", "-1.6e-19"

3) 一个记录的FLNK字段在当前记录结束后运行另一个记录。

 数据库链接

1) 格式:”record.field {flags}“

VAL是用于field的默认。

2) 标记:

  • PP:运行一个被动的目标记录。INP,DOL:在读取前;OUT:在写入后
  • NPP:非运行被动(默认)
  • MS:最大化严重性
  • NMS:不最大化严重性(默认)
  • MSS:最大化严重性和状态。
  • MSI:当severity=INVALID时,最大化严重性。

3) 示例:field(INP, "other_rec.VAL PP MS")

通道访问链接

当链接的记录不在这个IOC中时,自动使用通道访问链接。

标记:

1) PP:忽略。不触发在其它IOC上的运行。

2) MS,MSI:最大化严重性(当无效时)

通道访问链接标记

1) CA:即使目标在相同IOC中,强制为CA链接,可以用于打破’锁集‘

2) CP:对于INP链接,在接收的CA监视器上运行。一般在链接的值变化时引起运行。细节取决于源的MDEL。

3) CPP:CP,但仅在SCAN=Passive时。

转发链接

1) 触发运行,但不传递数据

2) 如果目标记录SCAN=Passive, 运行目标记录。

3) 可以使用CA链接

  • 必须使用FLNK=”other.PROC“(其它IOC)或者使用FLNK="other.PROC CA"(相同IOC)
  • 总是触发运行,即使对于SCAN!="Passive"。

运行链

1) 

 Input_1, Calculation_1和Output_1都是按从左到右顺序每0.1秒运行一次,一个时刻仅运行一个记录。运行顺序受控于记录的PHAS字段,从小到大运行。

2)

 Input_2记录每0.1秒运行一次,在其获取数据并结束运行后,通过FLINK使得Calculation_2记录运行,运行过程中INPA从Input_2记录的VAL字段获取值,并且根据设置进行计算,在其运行结束后,通过FLNK使得Output_2记录运行,在运行过程中DOL从Calculation_2的VAL获取值,并进行转换,将结果输出。

3)

Output_3记录每0.1秒运行一次,在其运行中,它将从Calculation_3的VAL获取值,但由于这个记录SCAN=Passive并且链接属性时PP,则Calculation_3记录开始运行,然后INPA字段将从Input_3记录的VAL字段读取输入值,但由于SCAN=Passive并且输入链接是PP属性,则Input_3记录开始运行,获取一个输入值,并且放到了VAL字段,Input_3记录到此运行结束,运行返回到Calculation_3记录,此时INPA获取了输入值,进行内部计算,并把结果放入到VAL,此时Calculation_3记录运行结束,运行返回到了Output_3记录,从Calculation_3记录VAL获取了值,进行转换后输出。 

4) Calulation_1记录不会被运行。Output_1记录每0.1秒运行一次,其DOL字段是输入链接,在其获取输入前,会使Calculation_2记录运行,同样INPA字段是输入链接,在其获取输入前,使Input_1记录运行。Input_1记录和Calculation_1记录INPA之间的链接是NPP,而Calculation_1记录SCAN=Passive,所有这个记录不会运行。

5)同一个锁集中Output_1和Calculation_2都是0.1秒运行一次,而这两个记录通过输入链接使得上游数据源记录都可以运行,所以Input_1记录每0.1秒能够运行两次。(假设整个记录链运行时间相较于扫描时间0.1秒可以忽略不计)。

 6)当通过输入链接和链接PP属性,记录运行权转移到了Input_1记录时,当其运行结束时,通过FLNK使得Calculation_1记录运行,而Calculation_1记录的INPA记录通过PP链接读取Input_1记录的VAL时,会使Input_1记录再次运行,运行权将在Input_1和Calculation_1之间轮流,所以其余记录将不会再运行了。

变化率的示例

计算一个输入的"变化率"

 INPA获取获取前1秒的输入数据,因为它不请求ai记录Input运行。INPB获取当前数据,因为它请求ai记录Input运行,并且获取其运行后的数据。这两个值相减反映了压力读取的'变化率'(差别/秒)。

仿真模式

当在仿真模式中,AO记录不调用设备支持并且AI记录从AO记录获取它的输入。

多次扫描触发

具有快速变边响应的慢速周期扫描:AI记录每5秒种以及当AO记录被更改时得到运行。这提供了对操作变化的即刻响应,即使正常扫描速率非常慢。对电源设置的更改被BO记录继承,此记录代表本地/远程切换。

 

设备支持

1)记录(AI, AO,..)靠其自身仅从其他记录读或写。

2) 设备支持连接它们到硬件。

3) 硬件设备支持是EPICS 'base'之外的。根据需要添加到IOC。

4) DTYP选择一个设备支持模块。

5) INP/OUT提供具体连接。

同步/异步

1) "快速",同步设备支持在记录被运行时读或写一个记录的值。

2) "慢速",异步设备支持在记录被运行时启动取读或写入。这个记录保持PACT=true状态,并且当完成了数据的读取或写入时,设备支持触发运行结束。

3) 通道访问'获取/写入'当前值,无论这个记录是否正在运行。

4) 当运行结束时,通道访问‘get/put回调’将结束。

'软'设备支持

EPICS base包含了DTYP=

1) "Soft Channel"用于AI, AO,BI,BO,...:读取/写入VAL字段。

2) “Raw Soft Channel”用于AI,AO,BI,BO, ...:读取/写入RVAL字段,转换成VAL,或者从VAL转换。

3) "Async Soft Channel"用于AI,AO,BI,BO:执行一个get/put回调,等待结束。

以下记录链的问题:Output_1记录0.1秒运行一次,其引起ai记录0.1秒运行一次,Output_2记录5秒运行一次,其通过Calculation_2触发Input_1记录运行时,发现Input_1记录正在运行,则其将直接读取其当前值。

 

锁集

1) 由链接连接起来的记录组。

2) 运行一个记录锁定其锁集:

  •  防止由多个线程运行。
  • 类似,但技术上与PACT分开

趋于透明地避免问题:除非你非常不幸运,则使用"CA"标记了打破锁集

记录上锁 vs PACT

1) 取决于其设备支持,一个记录可以"运行"很长时间:运行设置PACT并且触发驱动获取数据。一段时间后,驱动再次运行,并且清除PACT。

2) 当以下情况时,在锁集中地记录被锁定:

  • 运行启动,在其结束时,再次运行,但在这之间的时间中不运行。
  • 读取一个字段。
  • 写一个字段。

警报

1) 公共字段:

SEVR:警报严重性:None,MINOR, MAJOR, INVALID

STAT: 警报状态:UDF, READ,WRITE, CALC, HIGH,STATE, ...

2) 二进制记录:

ZSV, OSV:对应"zero"和"one"状态的严重性。

3) 模拟记录:

a) LOLO, LOW, HIGH, HIHI:阈值

b) LLSV, LSV, HSV, HHSV:相关联阈值的严重性。

c) HYST:回滞

警报示例:

# 当温度接近沸点时产生警报

record(ai , $(USER):tank)

{

        field(DESC, "Water Temperature")

        field(SCAN, "1 second")

        field(INP, "xxxx")

        field(EGU, "C")

        field(PREC "1")

        field(HIGH, "90")

        field(HSV, "MINOR")

        field(HIHI, "100")

        field(HHSV, "MAJOR")

}

监视死区

模拟记录发送更新给CA客户端:

1) MDEL:对于大部分客户端变化阈值

2) ADEL:用于存档客户端

 

记录隐含提示

1) 使用AO,模拟量输出记录,用于用户输入:DRVL, DRVH可以限制输出的范围。

2)BO记录可以用于计时器:

  • HIGH字段:当写值VAL=1时,保持1时长HIGH秒。
  • 对操作接口按钮有用:按钮写1,在HIGH=1时,记录恢复为0。

3) MBBI, MBBO记录映射状态:

  • 通过ZRVL/ZRST, ONVL/ONST, TWVL/TWST, ...定义值和状态。
  • 可以像BI/BO一样使用:ZRVL=0, ONVL=1, ZRST ZNAM, ONST ONAM
  • 对于除了0,1外的值:ZRVL=0, ONVL=255
  • 从位解码限位开关状态:

ZRVL=0         ZRST="Moving"

ONVL=1         ONST="At Left Limit"

TWVL=2        TWST="At Right Limit"

THVL=3`        THST="Broken", THSV=MAJOR

4) 使用CALCOUT用于if-then-else逻辑:

  • INP*和CALC同在CALC记录中国
  • OOPT "On Change", "When Zero", "Transition to Zero"等。
  • 输出可以使用CALC或者一个单独的OCAL

5) SEQ, FANOUT, DFANOUT可以运行一个记录列表:

  • 仅运行或者写值
  • SEL可以从运行所有变成运行所选的记录

6) COMPRESS记录:

  • 在一个环形缓存中维持最新的N个值
  • 计算数组的平均,最小或最大值

7) ASUB记录可以调用C代码:

  • INAM, SNAM:initial()和sub()的名称。
  • 很多INP*和VAL*字段。

8) EVENT记录可以提交数据库事件:触发SCAN=Event并且EVNT=那个事件的记录。

Calcout记录详情

1) 组合了calc记录和模拟输出功能:

  • INPA,INPB,..., INPL和CALC来计算VAL
  • OUT指向了写VAL的位置

2) OOPT确定了是否/何时写OUT:

"Every Time", "On Change" , "When Non-zero", "Transition to Zero"

3) 默认,VAL被写,但也可以配置

  • field(OCAL ,"A/B+.."):计算备选的OVAL
  • field(DOPT, "Use OCAL"):选择写OVAL,替代写VAL到OUT

在一个记录中两个计算以及一个'if'类型选择器。

calcout示例:

record(calcout, "Corrector")
{
    field(SCAN, ".1 second")
    field(INPA, "Enable")
    field(INPB, "SetPoint")
    field(INPC, "Readback")
    field(INPD, "17.54")
    field(CALC, "A")
    field(OOPT, "When None-zero")
    field(DOPT, "Use OCAL")
    field(OCAL, "D*(B-c)")
    field(OUT, "SteeringMagnet PP")
}

CALC确定我们是否应该做任何事情,OCAL用于实际计算。

EPICS base外的synApps记录

1)MOTOR记录:一个用于控制电机的整个生态系统。

2) BUSY记录可以用于支持put-callback:

  • 某些setpoint记录FLNKs,逻辑设置BUSY记录=1
  • 当设备达到设定点,设置BUSY记录VAL=0

CA 'put-callback'到设置点将在设备到达这个设定点后结束。

电机记录

1) 具有100+字段的记录。

2)基本控制:

  • VAL:所想要的电机位置。支持Put-callback
  • RBV:回读值,实际电机位置
  • DONE:我们结束了移动这个电机吗?
  • HLS,LLS:我们在高或低限位吗?
  • STOP

3) 分辨率:

  • MRES,DIR,OFF,EGU...:把电机刻度变为"mm"或"角度"
  • 它是步进电机或伺服电机?我们有编码器吗,如何标定它。

4) 移动:

  • VBAS, VMAX,ACCL,HVEL, JVEL, ...:速度,加速度
  • HLM,LLM,...:电机范围限制。
  • BDST, BACC, RTRY, ...:齿隙补偿,重试。

5) 更多:Homing, jog, tweak, status

大型或小型记录?

一个Motor记录?

motor.VAL        设定点

motor.RBL        回读

motor.DONE        结束?

motor.HLS        在高限位

motor.MRES        每个单位的步数

记录的集合?

record(ao, "$(M)_Set")

record(ai, "$(M)_Pos")

record(bi, "$(M)_Done")

record(bi, "$(M)_AtHighLim")

record(ao, "$(M)_StepsPerUnit")

record(waveform, "$(M)_Profile")

一个伺服电机步使用每个单位步数。步进电机支持一个移动profile。

没有一般化共享的'电源', “相机”, “PID”..记录。首选方法是记录集合。

时间戳

1) TIME一般被设置成这个记录上次被运行时的事件。

2) TSE=-2:设备支持已经设置了TIME,例如,设为从硬件获取的确切触发时间。

3) TSE=1...255:设置TIME为从计时系统获取的事件1..255的上次发生。

4) TSEL:允许从另一个记录获取时间戳。

线性转换

模拟记录转成RVAL为VAL:

LINR=NO CONVERSION:VAL=RVAL

LINR=SLOPAE:VAL=(RVAL)*ESLO + EOFF

这认为设备支持填充(整数)RVAL字段。如果设备支持已经有一个浮点值,它放置到(double)VAL字段。其余转换,则使用CALC记录。

断点表转换

模拟记录可以设置LINR=typeKdegC:这在一个*.dbd文件中:

 

  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值