1 from mechanism import mechanism
2 import math
3 import ConfigParserRT
4
6 """Class representing a 4 position filter-wheel type mechanism,
7 based on the generic mechanism class in mechanism.py. It adds
8 attributes for motor steps per rotation and preferred direction
9 of movement. There is optional position feedback checking from
10 grey code microswitches."""
11
12
13 statusDict = {4:0, 6:0.5, 2:1, 3:1.5, 7:2, 5:2.5, 1:3, 0:3.5}
14
15 - def __init__(self, names, cortex, icu_num, axis_num, \
16 base_speed, max_speed, acceleration, deceleration, \
17 position, steps_per_rev, direction, \
18 name='filterwheel'):
19 """
20 Initialiser for filterwheel class.
21
22 Arguments:
23 names: String containing a comma seperated list of
24 names for the filters.
25 cortex: String containing the name of the cortex based
26 ICU daisy chain instance that this mechanism is a
27 part of.
28 icuNum: Which ICU in the chain this mechanism is connected
29 to.
30 axisNum: Which axis of the ICU the mechansism is connected
31 to.
32 baseSpeed: Starting speed (steps/half steps per sec)
33 maxSpeed: Peak speed (steps/half steps per sec)
34 acceleration: Acceleration (steps/half steps per sec^2)
35 deceleration: Deceleration (steps/half steps per sec^2)
36 position: Initial position of the mechanism (steps)
37 steps_per_rev: Number of motor steps per revolution of the wheel
38 direction: +1 or -1, specifies the direction for rotation
39 name: Label used for logging purposes.
40 """
41
42 mechanism.__init__(self, cortex, icu_num, axis_num, \
43 base_speed, max_speed, acceleration, deceleration, \
44 position, name)
45
46
47 self.names = names.split(',')
48 self.stepsPerRev = int(steps_per_rev)
49 direction = int(direction)
50 if direction > 0:
51 self.direction = +1
52 elif direction < 0:
53 self.direction = -1
54 else:
55 self.logger.critical('Invalid direction "%s" passed to __init__' \
56 % direction)
57 self.logger.critical('Assuming direction = +1')
58 self.direction = +1
59
61 """
62 Should be called by the parent instrument object's destructor
63 to enable status information to be saved to file on exit.
64
65 Takes a ConfigParserRT.SafeConfigParser object as argument.
66 """
67 self.logger.debug("updateConfig() called.")
68 if isinstance(config, ConfigParserRT.SafeConfigParser):
69 config.set(self.name, 'steps_per_rev', str(self.stepsPerRev))
70 config.set(self.name, 'direction', str(self.direction))
71
72 mechanism.updateConfig(self, config)
73 else:
74 self.logger.critical("Invalid argument to updateConfig(%s)" \
75 % repr(config))
76 self.logger.critical("Unable to save status data")
77
79 """
80 Runs through an 'auto-fettling procedure'.
81 """
82 self.logger.debug('setupWheel() called.')
83 OK = [False, False, False, False]
84
85 while not OK[0] or not OK[1] or not OK[2] or not OK[3]:
86 status = self.getStatus()
87
88
89 if status % 1:
90 self.logger.debug('Position not found, searching...')
91 OK = [False, False, False, False]
92 search_count = 0
93
94 while status % 1:
95 if search_count > 1200:
96 self.logger.critical(\
97 'Moved over 90 degrees without finding position!')
98 self.logger.critical('setupWheel() failed!')
99 return
100 self.moveBy(self.direction * 3)
101 search_count += 3
102 status = self.getStatus()
103
104
105 self.setPosition(1200 * status * self.direction)
106
107
108 self.logger.debug('Located position %i.' % status)
109 OK[status] = True
110
111 self.moveBy(self.direction * 1200)
112
113 self.logger.info('Filter wheel setup complete.')
114
116 """
117 Returns 0, 1, 2 or 3 if the wheel in position, 0.5, 1.5, 2.5 or 3.5
118 if between positions.
119 """
120 self.logger.debug('getStatus() called')
121
122 if self.cortex.isActive(self.icuNum):
123 self.logger.warning('Attempt to getStatus() while active, ignored')
124 else:
125 self.cortex.setOutput(self.axisNum, self.icuNum)
126 status = self.statusDict[self.cortex.getInput(self.icuNum)]
127 self.cortex.setOutput(7, self.icuNum)
128 return status
129
130 - def goTo(self, filter):
131 """
132 Moves the wheel to the correct position for the given filter number
133 (0, 1, 2 or 3) or filter name (pass a string) .
134 """
135 self.logger.debug('goTo(%s) called' % filter)
136 if isinstance(filter, int) and filter in (0, 1, 2, 3):
137 self.moveTo(self.direction * self.stepsPerRev * filter / 4.0, \
138 blocking = True)
139 status = self.getStatus()
140 if status == filter:
141 self.logger.info('goTo(%i) successful' % filter)
142 else:
143 self.logger.warning('goTo(%i) resulted in status %s' \
144 % (filter, str(status)))
145 elif isinstance(filter, str) and filter in self.names:
146 number = self.names.index(filter)
147 self.moveTo(self.direction * self.stepsPerRev * number / 4.0, \
148 blocking = True)
149 status = self.getStatus()
150 if status == number:
151 self.logger.info('goTo(%s) successful' % filter)
152 else:
153 self.logger.warning('goTo(%s) resulted in status %s' \
154 % (filter, str(status)))
155 else:
156 self.logger.critical('Invalid argument to goTo(%s), ignored' \
157 % filter)
158
159 - def moveBy(self, steps, blocking=True):
160 """
161 Moves the filter wheel position by a given number of motor steps.
162 Modifies the move to ensure it's in the correct direction and
163 is of magnitude less than a full rotation.
164 """
165 self.logger.debug('moveBy(%i, %i) called' % (steps, blocking))
166
167
168 steps = int(math.fmod(steps, self.stepsPerRev))
169 if steps * self.direction < 0:
170 steps = self.direction * (self.stepsPerRev - abs(steps))
171 mechanism.moveBy(self, steps, blocking)
172
173 self.position = int(math.fmod(self.position, self.stepsPerRev))
174 if self.position < 0:
175 self.position = self.stepsPerRev - abs(self.position)
176
177 - def moveTo(self, position, blocking=True):
178 self.logger.debug('moveTo(%i, %i) called' % (position, blocking))
179 self.moveBy(position - self.position, blocking)
180
182 self.logger.debug('setPosition(%i) called' % new_position)
183
184 new_position = int(math.fmod(new_position, self.stepsPerRev))
185 if new_position < 0:
186 new_position = self.stepsPerRev - abs(new_position)
187 self.position = new_position
188