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
7272_Clarity__SETSVCMODE1 = 0xe0 #1 byte for service mode. SLEEP activates service mode. RUN returns to normal mode.
7373
7474
75+
7576class 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