Skip to content

Commit ba42af9

Browse files
committed
Aurox changes made during first test with hardware.
1 parent e1bf310 commit ba42af9

File tree

1 file changed

+43
-19
lines changed

1 file changed

+43
-19
lines changed

microscope/filterwheels/aurox.py

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,14 @@
4040
_Clarity__SLDPOS2 = 0x02 #disk pos 2, mid sectioning
4141
_Clarity__SLDPOS3 = 0x03 #disk pos 3, high sectioning
4242
_Clarity__SLDERR = 0xff #An error has occurred in setting slide position (end stops not detected)
43-
_Clarity__SLDMID = 0x10 #slide in mid position (was =0x03 for SD62)
43+
_Clarity__SLDMID = 0x10 #slide between positions (was =0x03 for SD62)
4444
# Filter position/status
4545
_Clarity__FLTPOS1 = 0x01 #Filter in position 1
4646
_Clarity__FLTPOS2 = 0x02 #Filter in position 2
4747
_Clarity__FLTPOS3 = 0x03 #Filter in position 3
4848
_Clarity__FLTPOS4 = 0x04 #Filter in position 4
4949
_Clarity__FLTERR = 0xff #An error has been detected in the filter drive (eg filters not present)
50-
_Clarity__FLTMID = 0x10 #Filter in mid position
50+
_Clarity__FLTMID = 0x10 #Filter between positions
5151
# Calibration LED state
5252
_Clarity__CALON = 0x01 #CALibration led power on
5353
_Clarity__CALOFF = 0x02 #CALibration led power off
@@ -72,12 +72,12 @@
7272
_Clarity__SETSVCMODE1 = 0xe0 #1 byte for service mode. SLEEP activates service mode. RUN returns to normal mode.
7373

7474

75+
7576
class Clarity(microscope.devices.FilterWheelBase):
7677
_slide_to_sectioning = {__SLDPOS0: 'bypass',
7778
__SLDPOS1: 'low',
7879
__SLDPOS2: 'mid',
79-
__SLDPOS3: 'high',
80-
__SLDMID: 'mid',}
80+
__SLDPOS3: 'high',}
8181
_positions = 4
8282

8383
def __init__(self, *args, **kwargs):
@@ -91,18 +91,28 @@ def __init__(self, *args, **kwargs):
9191
self._slide_to_sectioning)
9292

9393
def _send_command(self, command, param=0, max_length=16, timeout_ms=100):
94+
"""Send a command to the Clarity and return its response"""
9495
if not self._hid:
95-
raise Exception("Not connected to device.")
96+
self.open()
9697
with self._lock:
97-
buffer = [0x00] * max_length
98-
buffer[0] = command
99-
buffer[1] = param
98+
# The device expects a list of 16 integers
99+
buffer = [0x00] * max_length # The 0th element must be 0.
100+
buffer[1] = command # The 1st element is the command
101+
buffer[2] = param # The 2nd element is any command argument.
100102
result = self._hid.write(buffer)
101-
response = self._hid.read(max_length, timeout_ms)
102-
if response[0] != command:
103+
if result == -1:
104+
# Nothing to read back
103105
return None
104-
else:
105-
return response[1:]
106+
while True:
107+
# Read responses until we see the response to our command.
108+
# (We should get the correct response on the first read.)
109+
response = self._hid.read(result - 1, timeout_ms)
110+
if not response:
111+
# No response
112+
return None
113+
elif response[0] == command:
114+
break
115+
return response[1:]
106116

107117
@property
108118
def is_connected(self):
@@ -129,7 +139,7 @@ def _on_enable(self):
129139
if not self.is_connected:
130140
self.open()
131141
self._send_command(__SETONOFF, __RUN)
132-
return self._send_command(__GETONOFF) == __RUN
142+
return self._send_command(__GETONOFF)[0] == __RUN
133143

134144
def _on_disable(self):
135145
self._send_command(__SETONOFF, __SLEEP)
@@ -143,16 +153,18 @@ def set_calibration(self, state):
143153

144154
def get_slide_position(self):
145155
"""Get the current slide position"""
146-
result = self._slide_to_sectioning.get(self._send_command(__GETSLIDE), None)
156+
result = self._send_command(__GETSLIDE)
147157
if result is None:
148158
raise Exception("Slide position error.")
149-
return result
159+
return result[0]
150160

151-
def set_slide_position(self, position):
161+
def set_slide_position(self, position, blocking=True):
152162
"""Set the slide position"""
153163
result = self._send_command(__SETSLIDE, position)
154164
if result is None:
155165
raise Exception("Slide position error.")
166+
while blocking and self.moving():
167+
pass
156168
return result
157169

158170
def get_slides(self):
@@ -166,23 +178,35 @@ def get_status(self):
166178
slide = result[4]
167179
status['slide'] = (slide, self._slide_to_sectioning.get(slide, None))
168180
status['filter'] = (result[6], self._filters.get(result[6], None))
169-
status['calibration'] == result[7] == __CALON
181+
status['calibration'] = result[7] == __CALON
170182
return status
171183

172184
# Implemented by FilterWheelBase
173185
#def get_filters(self):
174186
# pass
175187

188+
def moving(self):
189+
"""Report whether or not the device is between positions."""
190+
import time
191+
# Wait a short time to avoid false negatives when called
192+
# immediately after initiating a move. Trial and error
193+
# indicates a delay of 50ms is required.
194+
time.sleep(0.05)
195+
return any( (self.get_slide_position() == __SLDMID,
196+
self.get_position() == __FLTMID) )
197+
176198
def get_position(self):
177199
"""Return the current filter position"""
178200
result = self._send_command(__GETFILT)
179201
if result == __FLTERR:
180202
raise Exception("Filter position error.")
181-
return result
203+
return result[0]
182204

183-
def set_position(self, pos):
205+
def set_position(self, pos, blocking=True):
184206
"""Set the filter position"""
185207
result = self._send_command(__SETFILT, pos)
186208
if result is None:
187209
raise Exception("Filter position error.")
210+
while blocking and self.moving():
211+
pass
188212
return result

0 commit comments

Comments
 (0)