1 | #!/usr/bin/env python |
---|
2 | |
---|
3 | ########### SVN repository information ################### |
---|
4 | # $Date: 2012-04-26 15:30:26 +0000 (Thu, 26 Apr 2012) $ |
---|
5 | # $Author: jemian $ |
---|
6 | # $Revision: 833 $ |
---|
7 | # $URL$ |
---|
8 | # $Id: m_axis.py 833 2012-04-26 15:30:26Z jemian $ |
---|
9 | ########### SVN repository information ################### |
---|
10 | |
---|
11 | ''' |
---|
12 | details about a model single axis |
---|
13 | |
---|
14 | Copyright (c) 2009 - 2011, UChicago Argonne, LLC. |
---|
15 | See LICENSE file for details. |
---|
16 | ''' |
---|
17 | |
---|
18 | |
---|
19 | # - - - - - - - - - - - - - - - - - - Imports |
---|
20 | |
---|
21 | |
---|
22 | import m_pv |
---|
23 | import paxis |
---|
24 | |
---|
25 | |
---|
26 | # - - - - - - - - - - - - - - - - - - Global |
---|
27 | |
---|
28 | |
---|
29 | __svnid__ = "$Id: m_axis.py 833 2012-04-26 15:30:26Z jemian $" |
---|
30 | |
---|
31 | |
---|
32 | # - - - - - - - - - - - - - - - - - - class |
---|
33 | |
---|
34 | class SingleAxis: |
---|
35 | ''' |
---|
36 | A single axis connects to several EPICS PVs. |
---|
37 | Since the axis may not be an EPICS motor record, |
---|
38 | we allow them to be completely separate. |
---|
39 | |
---|
40 | :param str name: short name for this axis |
---|
41 | :param obj axis: Either a Motor object or a PAxis object |
---|
42 | ''' |
---|
43 | |
---|
44 | def __init__(self, name, val, isMotorRecord = True, |
---|
45 | desc = '', dmov = '', egu = '', rbv = '', stop = ''): |
---|
46 | ''' |
---|
47 | Constructor |
---|
48 | |
---|
49 | :param str name: short name for this axis |
---|
50 | :param str val: EPICS PV name of the target position of this axis |
---|
51 | :param bool isMotorRecord: True if val refers to an EPICS motor record |
---|
52 | :param str rbv: EPICS PV name of the readback position of this axis |
---|
53 | :param str stop: EPICS PV name of the stop field of this axis, writing 1 to this PV will stop the axis if it is moving |
---|
54 | :param str dmov: EPICS PV name of the done-moving field of this axis, 1 if axis is not moving, 0 if axis is moving |
---|
55 | :param str desc: EPICS PV name of the description field of this axis |
---|
56 | :param str egu: EPICS PV name of the engineering units field of this axis |
---|
57 | ''' |
---|
58 | self.name = name |
---|
59 | self.isMotorRecord = isMotorRecord |
---|
60 | self.axis = None |
---|
61 | if isMotorRecord: |
---|
62 | pv = m_pv.GetBasePv(val) |
---|
63 | if not m_pv.pvIsAvailable(pv, timeout = 0.5): |
---|
64 | raise Exception, "Could not connect with PV: " + pv |
---|
65 | if not m_pv.pvIsMotorRec(pv): |
---|
66 | raise Exception, "%s.RTYP = %s, must be 'motor'" % (pv, m_pv.GetRTYP(pv)) |
---|
67 | self.axis = paxis.Motor(val) |
---|
68 | else: |
---|
69 | # elegant, but hard to read, need better feedback if PV not found |
---|
70 | #status = map(m_pv.pvIsAvailable, (val, rbv, desc, egu, dmov, stop)) |
---|
71 | #ready = reduce(lambda x, y: x and y, status) |
---|
72 | for pv in (val, rbv, desc, egu, dmov, stop): |
---|
73 | if not m_pv.pvIsAvailable(pv): |
---|
74 | raise Exception, "Could not connect with PV: " + pv |
---|
75 | self.axis = paxis.PAxis(val, rbv, desc, egu, dmov, stop) |
---|
76 | if self.axis is None: |
---|
77 | raise Exception, "Did not connect axis: " + name |
---|
78 | self.callback_ids = {} |
---|
79 | |
---|
80 | def move(self, position): |
---|
81 | '''tell EPICS to move this axis''' |
---|
82 | self.axis.VAL = position |
---|
83 | |
---|
84 | def stopMotion(self): |
---|
85 | '''tell EPICS to stop moving this axis''' |
---|
86 | self.axis.stop() |
---|
87 | |
---|
88 | def connect(self, handler = None): |
---|
89 | '''connect the callbacks''' |
---|
90 | if len(self.callback_ids) > 0: |
---|
91 | self.disconnect() |
---|
92 | for field in ('VAL', 'RBV', 'DESC', 'EGU', 'DMOV', 'STOP'): |
---|
93 | # remember the callback id |
---|
94 | cb = self.axis.start_callback(field, handler, {'field': field}) |
---|
95 | self.callback_ids[field] = cb |
---|
96 | self._connected = True |
---|
97 | |
---|
98 | def disconnect(self): |
---|
99 | '''disconnect all the PVs with EPICS''' |
---|
100 | for field in self.callback_ids.keys(): |
---|
101 | self.axis.stop_callback(field, self.callback_ids[field]) |
---|
102 | self.callback_ids = {} |
---|
103 | self._connected = False |
---|
104 | |
---|
105 | |
---|
106 | # - - - - - - - - - - - - - - - - - - methods |
---|
107 | |
---|
108 | |
---|
109 | def __demo_waitmove(axis, position, seconds): |
---|
110 | '''move this axis and wait for a fixed time (showing EPICS CA monitors)''' |
---|
111 | from time import sleep |
---|
112 | print "moving", axis._pvs['VAL'], " to ", position |
---|
113 | axis.move(position) |
---|
114 | for i in range(seconds, 0, -1): |
---|
115 | print i, " seconds remain" |
---|
116 | sleep(1) |
---|
117 | print "done waiting" |
---|
118 | |
---|
119 | |
---|
120 | def handler(**kw): |
---|
121 | '''trivial example callback handler''' |
---|
122 | print kw['pvname'], kw['field'], kw['value'] |
---|
123 | |
---|
124 | |
---|
125 | def _demo_(): |
---|
126 | '''demonstrate use of this module''' |
---|
127 | from time import sleep |
---|
128 | pv = "prj:m1" |
---|
129 | |
---|
130 | motor = SingleAxis( name = "test axis", val = pv, isMotorRecord = True, ) |
---|
131 | motor.connect(handler=handler) |
---|
132 | name = motor.axis.DESC |
---|
133 | motor.axis.DESC = "new name" |
---|
134 | sleep(1) |
---|
135 | motor.axis.DESC = name |
---|
136 | sleep(1) |
---|
137 | |
---|
138 | # now try a couple moves |
---|
139 | __demo_waitmove(motor.axis, position=5.5, seconds=5) |
---|
140 | __demo_waitmove(motor.axis, position=1.1, seconds=5) |
---|
141 | motor.disconnect() |
---|
142 | del motor |
---|
143 | |
---|
144 | # - - - - |
---|
145 | |
---|
146 | non_motor = SingleAxis( name = "second axis", isMotorRecord = False, |
---|
147 | val = pv + '.VAL', |
---|
148 | rbv = pv + '.RBV', |
---|
149 | desc = pv + '.DESC', |
---|
150 | egu = pv + '.EGU', |
---|
151 | dmov = pv + '.DMOV', |
---|
152 | stop = pv + '.STOP', |
---|
153 | ) |
---|
154 | non_motor.connect(handler=handler) |
---|
155 | __demo_waitmove(non_motor.axis, position=5.5, seconds=5) |
---|
156 | __demo_waitmove(non_motor.axis, position=1.1, seconds=5) |
---|
157 | non_motor.disconnect() |
---|
158 | |
---|
159 | # - - - - - - - - - - - - - - - - - - main |
---|
160 | |
---|
161 | |
---|
162 | if __name__ == '__main__': |
---|
163 | _demo_() |
---|