pyepics Device:PVs的集合
概要
device模块提供了对一个PVs集合的一个简单接口。这里,一个epics device.Device是一个保存了一个PVs集合的对象,所有都共享一个前缀,但有很多attributes。很多PVs有由prefix+attribute组成的名称,用一个公共前缀对应若干相关联的PVs。这基本描述了一个EPICS记录,但由于只关注PV名称,对一个EPICS记录的映射不准确。另一方面,device的概念比一个预定义EPICS记录更灵活,由于它可以从若干不同记录保存PVs。
motor1 = epics.Device('XXX:motor1.', attrs=('VAL', 'RBV', 'DESC', 'RVAL','LVIO', 'HLS', 'LLS'))
motor1.put('VAL', 1)
print 'Motor %s = %f' % ( motor1.get('DESC'), motor1.get('RBV'))motor1.VAL = 0
print 'Motor %s = %f' % ( motor1.DESC, motor1.RBV )
虽然靠自己像这样有用,一个device地真实角度是作为基类,被继承和扩展。实际上,在EPICS Motor Device下描述了更高级地Motor device。
class device.Device(prefix=None[,delim=''[,attr=None]])
根据需要构造attribute PVs,并且被保存在一个内部缓存self._pvs。这个类被特意地保持简单使得它可能被子类化。
在初始化时预加载attribute名称,用attr选项提供一个attributes列表或元组。
注意:前缀实际是一个可选的。当不用时,这个类可以用作为一个PVs的任意容器,或者转化任何子类成一个epics Device。
一般,PV名称将被映射成prefix+delim+attr。如何重写这个的详情见add_pv()。
device.PV(atrr[,connect=True[,**kw]])
为一个device attribute返回PV对象。连接参数和任何其它关键字被传递给epics.PV()。
devcie.put(attr,value[,wait=False[,time=10.0]])
写入一个attribute值,可选地等待连接完成或者到提供的超时值。
device.get(attr[,as_string=False])
获取一个attribute值,选项as_string返回一个string表示。
device.add_callback(attr,callback)
为一个attribute PV添加一个回调函数,因而在这个attribute的值变化时,将被运行。
device.add_pv(pvname[,attr=None[,**kw]])
即使它可能破坏正常的命名规则,显式地添加名称epics.PV()到这个device(attr在这里被映射成epics.PV(prefix+delim+attr))。即是,可以说:
import epics
m1 = epics.Device('XXX:m1', delim='.')
m1.add_pv('XXX:m2.VAL', attr='other')
print m1.VAL # print value of XXX:m1.VAL
print m1.other # prints value of XXX:m2.VAL
device.save_state()
返回一个所有当前值的字典--"当前状态"
device.restore_state(state)
恢复一个保存的状态,由save_state保存。
device.write_state(fname[,state=None])
写一个保存的状态到一个文件。如果没有提供状态,写当前状态。
device.read_state(fname[,restore=False])
从一个文件读取一个状态,由write_state()写,并且返回它。如果"restore"为True,将恢复读状态。
device._pvs
一个组成这个device的PVs的字典。
EPICS Motor Device
EPICS Motor记录有超过100个字段与它相关联。经常倾向于认为1个具有超过100个attribute的Motor或者单独的PVs。Motor记录的很多字段是相关关联的并且影响其它设置,包括对需要考虑的移动范围的限制,并且其可能在超出范围时发送通知。因而,对于一个Motor有非常多的功能。一般,用户只想要通过设置它的驱动位置移动电机,但一个完全能用的Motor应该允许更改和读取很多Motor参数的使用。
Motor类帮助用户创建和使用EPICS motors。一个简单时用法为:
import epics
m1 = epics.Motor('XXX:m1')print 'Motor: ', m1.DESC , ' Currently at ', m1.RBVm1.tweak_val = 0.10
m1.move(0.0, dial=True, wait=True)for i in range(10):m1.tweak(direction='forward', wait=True)time.sleep(1.0)print 'Motor: ', m1.DESC , ' Currently at ', m1.RBV
这将通过一个位置集合步进这个电机。对于这个电机,你将注意:
- 电机将使用对应电机记录字段的属性的英文别名。'VAL'可以被拼为'drive',而'DESC'可以是'description'。Table of Motor Attributes给出了一个可以使用的名称列表。
- 设置位置的方法可以使用User, Dial或者Step坐标系统,并且可以等待完成。
epics.Motor类
class motor.Motor(pvname[,timeout=30])
为指定名称的EPICS过程变量创建一个Motor对象。
参数:
- pvname(string):对应一个Motor的EPICS过程变量的前缀(不需要'.VAL')
- timeout(float):在放弃尝试连接前,等待的时间。
一旦创建了,一个Motor应该准备使用。
>>> from epics import Motor
>>> m = Motor('XX:m1')
>>> print m.drive, m.description, m.slew_speed
1.030 Fine X 5.0
>>> print m.get('device_type', as_string=True)
'asynMotor'
一个Motor有非常多的字段。在初始化时仅创建了少数字段--根据需要获取余下的字段。要么用一个attribute或者用get()方法可以获取motor字段。在Table of Motor Attributes中给出了一个用于电机记录的完整的Motor Attributes和它们别名的列表。
对应EPICS motor 类的attributes的别名以及Motor记录字段的对应attribute名称的表格
alias |
Motor Record field |
alias |
Motor Record field |
|
---|---|---|---|---|
disabled |
_able.VAL |
moving |
MOVN |
|
acceleration |
ACCL |
resolution |
MRES |
|
back_accel |
BACC |
motor_status |
MSTA |
|
backlash |
BDST |
offset |
OFF |
|
back_speed |
BVEL |
output_mode |
OMSL |
|
card |
CARD |
output |
OUT |
|
dial_high_limit |
DHLM |
prop_gain |
PCOF |
|
direction |
DIR |
precision |
PREC |
|
dial_low_limit |
DLLM |
readback |
RBV |
|
settle_time |
DLY |
retry_max |
RTRY |
|
done_moving |
DMOV |
retry_count |
RCNT |
|
dial_readback |
DRBV |
retry_deadband |
RDBD |
|
description |
DESC |
dial_difference |
RDIF |
|
dial_drive |
DVAL |
raw_encoder_pos |
REP |
|
units |
EGU |
raw_high_limit |
RHLS |
|
encoder_step |
ERES |
raw_low_limit |
RLLS |
|
freeze_offset |
FOFF |
relative_value |
RLV |
|
move_fraction |
FRAC |
raw_motor_pos |
RMP |
|
hi_severity |
HHSV |
raw_readback |
RRBV |
|
hi_alarm |
HIGH |
readback_res |
RRES |
|
hihi_alarm |
HIHI |
raw_drive |
RVAL |
|
high_limit |
HLM |
dial_speed |
RVEL |
|
high_limit_set |
HLS |
s_speed |
S |
|
hw_limit |
HLSV |
s_back_speed |
SBAK |
|
home_forward |
HOMF |
s_base_speed |
SBAS |
|
home_reverse |
HOMR |
s_max_speed |
SMAX |
|
high_op_range |
HOPR |
set |
SET |
|
high_severity |
HSV |
stop_go |
SPMG |
|
integral_gain |
ICOF |
s_revolutions |
SREV |
|
jog_accel |
JAR |
stop |
STOP |
|
jog_forward |
JOGF |
t_direction |
TDIR |
|
jog_reverse |
JOGR |
tweak_forward |
TWF |
|
jog_speed |
JVEL |
tweak_reverse |
TWR |
|
last_dial_val |
LDVL |
tweak_val |
TWV |
|
low_limit |
LLM |
use_encoder |
UEIP |
|
low_limit_set |
LLS |
u_revolutions |
UREV |
|
lo_severity |
LLSV |
use_rdbl |
URIP |
|
lolo_alarm |
LOLO |
drive |
VAL |
|
low_op_range |
LOPR |
base_speed |
VBAS |
|
low_alarm |
LOW |
slew_speed |
VELO |
|
last_rel_val |
LRLV |
version |
VERS |
|
last_dial_drive |
LRVL |
max_speed |
VMAX |
|
last_SPMG |
LSPG |
use_home |
ATHM |
|
low_severity |
LSV |
deriv_gain |
DCOF |
用于epics.Motor的方法
motor.get(attr[,as_string=False]):为电机设置一个字段attribute
参数:
- attr(来自以上表格):attribute名称
- as_string(True/False):是否返回字符串值
注意:get()返回字符串值,而获取而获取attribute不能做这件事:
>>> m = epics.Motor('XXX:m1')
>>> print m.device_type
0
>>> print m.get('device_type', as_string=True)
'asynMotor'
motor.put(attr, value[,wait=False[,timeout=30]])
为这个电机设置一个字段attribute。
参数:
- attr((来自以上表格的字符串)):attribute名称
- value:对应attribute的值
- wait(True/False):是否等待结束
- timeout(float):在放弃尝试前要等待的时间(秒)
motor.check_limits():检查当前电机位置是否引起一个电机越限,并且如果它是产生一个MotorLimitExceptioin。如果没有越限,返回None。
motor.within_limits(value[,limits='user']):检查一个目标值会是一个越限。
参数:
- value:目标值
- limits(string):对应要考虑哪一个,'user','dial'或'raw'之一。
返回类型:True/False
motor.move(val=None[,relative=None[,wait=False[,timeout=300.0[,dial=False[,raw=False[,ignore_limit=False[,confirm_move=False]]]]]]])
移动电机到指定的驱动位置。
参数:
- val:移动到的值(float)[必须提供]
- relative:相对于当前位置移动(T/F)[F]
- wait:是否等待移动结束(T/F)[F]
- timeout:等待移动结束的最长时间(秒为单位)[300]。
- dial:使用dial坐标系(T/F)[F]
- raw:使用raw坐标系(T/F)[F]
- ignore_limits:不考虑限位,尝试移动(T/F)[F]
- confirm_move:尝试确定移动开始了(当wait=False)(T/F)[F]
返回类型:整数
根据以下表格,返回一个整数值。注意:一个用wait=False的0返回值不确保一次成功移动,只是发出了一个启动请求。如果你对检查一个请求的移动确实开始而不等待这次移动结束感兴趣,你可能想要使用confirm_move=True选项。
来自move()的返回值表格
return value |
meaning |
---|---|
-13 |
无效值(不能转成浮点)。不尝试移动。 |
-12 |
超出软限位的目标值。不尝试移动。 |
-11 |
未连接drive PV:不尝试移动。 |
-8 |
启动开始,但超时了。 |
-7 |
移动开始,超时了,但似乎结束了。 |
-5 |
移动开始,来自put()的无预计的返回值。 |
-4 |
带等待的移动结束了,见到软限位了。 |
-3 |
带等待的移动结束了,见到硬限位了。 |
0 |
带等待的移动正常结束。 |
0 |
不带等待的移动执行了,未被确认 |
1 |
不带等待的移动执行了,移动确认了。 |
3 |
不带等待的移动结束了,见到硬限位了。 |
4 |
不带等待的移动结束了,见到软限位了。 |
motor.tweak(direction='forward'[wait=False[,timeout=300]])
通过当前tweak值移动电机。
参数:
- direction(字符串:'forward'(默认)或'reverse') 移动方向
- wait(True/False):是否等待结束
- timeout(float):用于移动到结束的最长时间(秒为单位)[default=300]
motor.get_position(readback=False[,dial=False[,raw=False]])
按user,dial或raw坐标返回电机位置。
参数:
- readback:是否按所需坐标系返回回读值。默认是发货电机的驱动位置。
- dial:是否按dial坐标系返回位置。默认是user坐标。
- raw:是否返回raw位置。默认是user坐标。
"raw"和"dial"关键字是相互排斥的。"readback"关键字可以在user, dial或raw坐标中使用。
motor.set_position(position[dial=False[,raw=False]])
参数:
- position:新的电机位置。
- dial:是否在dial坐标中设置。默认是在用户坐标中。
- raw:是否在raw坐标中设置。默认是在user坐标中。
"raw"和"dial"关键字是相互排斥的。
motor.get_pv(attr)
返回对应这个attribute的PV。
motor.set_callback(attr='drive'[,callback=None[,kw=None]])
在PV上为一个特定attribute设置一个回调。
motor.get_callback(attr='drive')
在PV上清除对应一个特定attribute的回调。
motor.show_info()
输出一个attributes和它们的当前值的表格。
其它Device示例
一个EPICS Device提供把一个PV集合组成一起的一种通用方式。以下示例显示了如何在这种普遍性上构建,并且激发你构建你自己的设备类。
一个没有有前缀的基本Device
我们在这里定义一个非常简单的设备,其甚至没有定义一个前缀。这不比一个PVs集合多多少。由于没有指定前缀,在设备中的所有PVs必须完全合格。注意:在这样的PVs集合中不需要共享一个公共的前缀:
from epics import Device
dev = Device()
p1 = dev.PV('13IDC:m1.VAL')
p2 = dev.PV('13IDC:m2.VAL')
dev.put('13IDC:m1.VAL', 2.8)
dev.put('13IDC:m2.VAL', 3.0)
print dev.PV('13IDC:m3.DIR').get(as_string=True)
注意:这个device不能使用基于字段名称的attributes。
这看起来非常有趣--为什么不就使用一群PVs?如果通过子类化Device并且添加专用方法,你考虑Device作为构建更复杂对象的开始,接着你可以开始有兴趣。
EPICS ai记录作为Device
一个稍微有用并且代表性示例,pyepics发行版包含了对应一个EPICS ai的Device。这个设备的完整实现是:
#!/usr/bin/env python
"""Epics analog input record"""
from .. import Deviceclass ai(Device):"Simple analog input device"attrs = ('VAL', 'EGU', 'HOPR', 'LOPR', 'PREC', 'NAME', 'DESC','DTYP', 'INP', 'LINR', 'RVAL', 'ROFF', 'EGUF', 'EGUL','AOFF', 'ASLO', 'ESLO', 'EOFF', 'SMOO', 'HIHI', 'LOLO','HIGH', 'LOW', 'HHSV', 'LLSV', 'HSV', 'LSV', 'HYST')def __init__(self, prefix, **kwargs):if prefix.endswith('.'):prefix = prefix[:-1]Device.__init__(self, prefix, delim='.', attrs=self.attrs, **kwargs)
此代码仅预定义了作为一个EPICS ai输入记录的后缀的字段,并且用这些字段子类化Device来创建相应的PVs。对于大部分记录后缀,这些将作为这个Device对象的attributes被获取。例如,可以简明地使用以上ai类:
from epics.devices import ai
This_ai = ai('XXX.PRES')
print 'Value: ', This_ai.VAL
print 'Units: ', This_ai.EGU
当然,你也可以使用对应一个基本Device地get(),put()方法:
This_ai.put('DESC', 'My Pump')
用这种方法可以简单地展示其它标准的EPICS记录为Devices,并且pyepics发行包包含对EPICS ao,bi和bo记录以及来自synApps的若干更复杂记录的这样简单的包装。
EPICS Scaler记录作为Device
对于一个稍微复杂的示例:一个来自synApps Scaler记录的未完成但非常有用的映射,包括用于更改模式,以及读写数据的方法。
#!/usr/bin/env python
"""Epics Scaler"""
from .. import Device, pollclass Scaler(Device):""" Simple implementation of SynApps Scaler Record. """attrs = ('CNT', 'CONT', 'TP', 'T', 'VAL')attr_kws = {'calc_enable': '%s_calcEnable.VAL'}chan_attrs = ('NM%i', 'S%i')calc_attrs = {'calc%i': '%s_calc%i.VAL', 'expr%i': '%s_calc%i.CALC'}_nonpvs = ('_prefix', '_pvs', '_delim', '_nchan', '_chans')def __init__(self, prefix, nchan=8):self._nchan = nchanself._chans = range(1, nchan+1)attrs = list(self.attrs)for i in self._chans:for att in self.chan_attrs:attrs.append(att % i)Device.__init__(self, prefix, delim='.', attrs=attrs)for key, val in self.attr_kws.items():self.add_pv(val % prefix, attr= key)for i in self._chans:for key, val in self.calc_attrs.items():self.add_pv(val % (prefix, i), attr = key % i)self._mutable = Falsedef AutoCountMode(self):"set to autocount mode"self.put('CONT', 1)def OneShotMode(self):"set to one shot mode" self.put('CONT', 0)def CountTime(self, ctime):"set count time"self.put('TP', ctime)def Count(self, ctime=None, wait=False):"set count, with optional counttime"if ctime is not None:self.CountTime(ctime)self.put('CNT', 1, wait=wait)poll()def EnableCalcs(self):" enable calculations"self.put('calc_enable', 1)def setCalc(self, i, calc):"set the calculation for scaler i"attr = 'expr%i' % iself.put(attr, calc)def getNames(self):"get all names"return [self.get('NM%i' % i) for i in self._chans]def Read(self, use_calc=False):"read all values"attr = 'S%i'if use_calc:attr = 'calc%i'return [self.get(attr % i) for i in self._chans]
注意:我们接着从它额base PV前缀创建一个scaler对象,并且使用像Count()和Read()的方法,而不用直接调用epics调用:
s1 = Scaler('XXX:scaler1')
s1.setCalc(2, '(B-2000*A/10000000.)')
s1.enableCalcs()
s1.OneShotMode()
s1.Count(t=5.0, wait=True)
print 'Names: ', s1.getNames()
print 'Raw values: ', s1.Read(use_calc=False)
print 'Calc values: ', s1.Read(use_calc=True)
包含在PyEpics中的其它Devices
若干其它EPICS记录已经被展示位Devices,并且在PyEpics发行包中被包含。这些在多完整以及功能丰富中有些区别,并且的确倾向于在同步辐射线站数据采集。一个当前Device的表格被列在Table of included Epics Devices中,进一步讨论,咨询这些模块的源代码。
在PyEpics发行包中包含了EPICS Devices表格。对于那些被描述为"pretty basic"的,只有PV后缀映射到attribute。很多其它包含一个或多个用于专门使用哪个Device的方法。
module |
class |
description |
---|---|---|
ad_base |
AD_Camera |
areaDetector Camera, pretty basic |
ad_fileplugin |
AD_FilePlugin |
areaDetector File Plugin, many methods |
ad_image |
AD_ImagePlugin |
areaDetector Image, with ArrayData attribute |
ad_overlay |
AD_OverlayPlugin |
areaDetector Overlay, pretty basic |
ad_perkinelmer |
AD_PerkinElmer |
PerkinElmer(xrd1600) detector, several methods |
ai |
ai |
analog input, pretty basic (as above) |
ao |
ao |
analog output, pretty basic |
bi |
bi |
binary input, pretty basic |
bo |
bo |
binary output, pretty basic |
mca |
MCA |
epics DXP record, pretty basic |
mca |
DXP |
epics MCA record, get_rois()/get_calib() |
mca |
MultiXMAP |
Multiple XIA XMaps, several methods |
scaler |
Scaler |
epics Scaler record, many methods |
scan |
Scan |
epics SScan record, some methods |
srs570 |
SRS570 |
SRS570 Amplifier |
struck |
Struck |
SIS Multichannel Scaler, many methods |
transform |
Transform |
epics userTransform record |
xspress3 |
Xspress3 |
Quantum Electronics Xspress3 Multi-MCA |
pyepics Device:PVs的集合相关推荐
- pyEpics概要---1
python epics包提供了若干函数,模块和类用于与EPICS通道访问交互.最简单的方法是使用在顶层epics模块内的caget(), caput()和cainfo()来读写EPICS过程变量的值 ...
- 中型企业VDI实现方案
一. 背景描述 XX公司是一家国内大型零售企业,IT信息建设方面,数据中心则位于北京,在全国各地有30多家分支机构,每个分支机构有30到50个PC机,如果数据中心的员工要到每个分支机构维护当地的PC机 ...
- EPICS -- synApps -- Autosave
内容表 概要 Autosave自动保存EPICS过程变量(PVs)到一个服务器上文件,并且在IOC(输入输出控制器,EPICS业务端)被重启时恢复这些值. Autosave是一个两部分操作:运行时保存 ...
- 章鱼体验第一天:思杰VDI之7.14.1
前言:因工作原因,也泡了一两年的桌面虚拟化,公有云等等,思杰和VmVare两个老大哥产品自然不在话下,当然价格也是让人接受不了.所以我们这些小众的VDI厂商还是有生存空间的(我们不可否认,我们国内厂商 ...
- 【Android】SerialPortFinder学习笔记,显示串口列表
显示串口列表这个操作还不涉及底层的东西,因为Android与Linux相似,有串口设备就会在/dev目录下生成一个文件,比如/dev/ttyS0之类的,在谷歌的ndroid-serialport-ap ...
- 原创Citrix XenDesktop7.15长期稳定版本虚拟桌面-实施手册
下面列出来的是目录大纲,里面包含了Citrix完整搭建的教程,此次实验环境是利用Citrix XenDesktop 7.15 CU3长期稳定版虚拟桌面详细安装教程, 含PVS及UPM相关配置,期待视频 ...
- Linux LCD驱动程序
LCD操作原理 在Linux系统中通过Framebuffer(简称为fb,又叫显存)驱动程序来控制LCD. Frame是帧的意思,buffer是缓冲的意思,这意味着Framebuffer就是一块内存, ...
- zutuanxue.com-linux磁盘管理基本管理
linux磁盘管理基本管理 开课 本章我们将学习到磁盘管理的相关知识,这部分知识在我们以后的工作中非常重要,它可以让我们知道如何去规划磁盘,如何去使用磁盘,如何去提高磁盘的利用率,这些都会影响服务 ...
- 百战RHCE(第十四战:Linux进阶命令十一-nmcli 配置网络极简管理)
哈喽哈喽哈喽,大家好啊,很高兴大家能看到这篇文章! 首先,本人目前是计算机专业的大一学生,基于对Linux操作系统的爱好,参与了RHCE的培训班,而我这次编写的 <百战RHCE>文章,是基 ...
最新文章
- matlab绘制三维图形现状,MATLAB绘制三维图形
- linux电脑系统投到电视,教你如何在Linux操作系统下观看电视节目
- 安装 PHP Memcache 扩展
- cf1561D Up the Strip(D1D2)
- ad19pcb设置恢复默认_条码打印机-斑马产品常用恢复出厂设置
- 程序员面试金典 - 面试题 04.02. 最小高度树(二叉搜索树中序遍历)
- PHP开发框架[国内框架]
- HBase使用场景和成功案例 (转)
- magento2 checkout totals添加产品属性
- 【转】opencv 配置
- Redis常见配置文件详解
- 微信开放平台错误码大全
- 手机号码归属地查询API
- 清空html输入框,jquery清空textarea等输入框
- 01336软件项目管理复习
- 基于访客的网络(VBN)
- 计算机毕业设计JAVA企业售后服务管理系统mybatis+源码+调试部署+系统+数据库+lw
- 【数学建模】基于matlab武汉地铁2号线路线地图动态模拟【含Matlab源码 1092期】
- floyed 4.9
- CRM(客户关系管理系统)项目框架搭建