11"""Test Pressure."""
22from asyncio import sleep
33from typing import List , Union , Literal
4+ from hardware_testing .drivers .sealed_pressure_fixture import SerialDriver as SealedPressureDriver
5+ from hardware_testing .opentrons_api import helpers_ot3
46
57from opentrons_hardware .firmware_bindings .constants import SensorId
68
79from opentrons .hardware_control .ot3api import OT3API
810from opentrons .hardware_control .backends .ot3utils import sensor_id_for_instrument
911from opentrons .hardware_control .types import InstrumentProbeType
1012
13+ from opentrons .hardware_control .motion_utilities import target_position_from_relative
14+
1115from hardware_testing .data import ui
1216from hardware_testing .opentrons_api import helpers_ot3
13- from hardware_testing .opentrons_api .types import OT3Mount
17+ from hardware_testing .opentrons_api .types import OT3Mount , Point , Axis
1418from hardware_testing .data .csv_report import (
1519 CSVReport ,
1620 CSVResult ,
1721 CSVLine ,
1822 CSVLineRepeating ,
1923)
2024
25+ USE_SEALED_FIXTURE = False
26+ USE_SEALED_BLOCK = True
27+ PRIMARY_SEALED_PRESSURE_FIXTURE_POS = Point (362.68 , 148.83 , 49.4 ) if USE_SEALED_BLOCK else Point (362.68 , 148.83 , 44.4 ) # attached tip
28+ SECOND_SEALED_PRESSURE_FIXTURE_POS = Point (264.71 , 212.81 , 49.4 ) if USE_SEALED_BLOCK else Point (264.71 , 212.81 , 44.4 ) # attached tip
29+ SET_PRESSURE_TARGET = 100 # read air pressure when the force pressure value is over 100
30+ REACHED_PRESSURE = 0
31+
2132SECONDS_BETWEEN_READINGS = 0.25
2233NUM_PRESSURE_READINGS = 10
2334TIP_VOLUME = 50
2435ASPIRATE_VOLUME = 2
2536PRESSURE_READINGS = ["open-pa" , "sealed-pa" , "aspirate-pa" , "dispense-pa" ]
2637
38+ SLOT_FOR_PICK_UP_TIP = 5
39+ TIP_RACK_FOR_PICK_UP_TIP = f"opentrons_flex_96_tiprack_{ TIP_VOLUME } ul"
40+ A1_OFFSET = Point (x = 9 * 11 , y = - 9 * 7 )
41+ H12_OFFSET = Point (x = - 9 * 11 , y = 9 * 7 )
42+ OFFSET_FOR_1_WELL_LABWARE = Point (x = 9 * - 11 * 0.5 , y = 9 * 7 * 0.5 )
43+
2744THRESHOLDS_1000 = {
2845 "open-pa" : (
29- 0 ,
30- 20 ,
46+ - 25 ,
47+ 25 ,
3148 ),
3249 "sealed-pa" : (
33- 5 ,
34- 50 ,
50+ - 30 ,
51+ 30 ,
3552 ),
3653 "aspirate-pa" : (
37- - 900 ,
38- - 500 ,
54+ - 750 ,
55+ - 400 ,
3956 ),
4057 "dispense-pa" : (
4158 2500 ,
6279 ),
6380}
6481
65- PROBE_POSITIONS = [InstrumentProbeType .PRIMARY , InstrumentProbeType .SECONDARY ]
6682
83+ PROBE_POSITIONS = [InstrumentProbeType .PRIMARY , InstrumentProbeType .SECONDARY ]
6784
6885def _get_test_tag (probe : InstrumentProbeType , reading : str ) -> str :
6986 assert reading in PRESSURE_READINGS , f"{ reading } not in PRESSURE_READINGS"
@@ -76,7 +93,10 @@ def build_csv_lines() -> List[Union[CSVLine, CSVLineRepeating]]:
7693 for p in PROBE_POSITIONS :
7794 for r in PRESSURE_READINGS :
7895 tag = _get_test_tag (p , r )
79- lines .append (CSVLine (tag , [float , CSVResult ]))
96+ if r == "sealed-pa" :
97+ lines .append (CSVLine (tag , [float , CSVResult , float ]))
98+ else :
99+ lines .append (CSVLine (tag , [float , CSVResult ]))
80100 return lines
81101
82102
@@ -104,9 +124,7 @@ async def _read_from_sensor(
104124 return sum (readings ) / num_readings
105125
106126
107- def check_value (
108- test_value : float , test_name : str , pipette : Literal [1000 , 200 ]
109- ) -> CSVResult :
127+ def check_value (test_value : float , test_name : str , pipette : Literal [1000 , 200 ]) -> CSVResult :
110128 """Determine if value is within pass limits."""
111129 if pipette == 1000 :
112130 THRESHOLDS = THRESHOLDS_1000
@@ -119,18 +137,77 @@ def check_value(
119137 return CSVResult .PASS
120138 else :
121139 return CSVResult .FAIL
140+
141+ async def calibrate_to_pressue_fixture (api : OT3API , sensor :SealedPressureDriver , fixture_pos :Point ):
142+ """move to suitable height for readding air pressure"""
143+ global REACHED_PRESSURE
144+ await api .move_to (OT3Mount .LEFT , fixture_pos )
145+ debug_target = input (f"Setting target pressure (default: { SET_PRESSURE_TARGET } g): " )
146+ if debug_target .strip () == "" :
147+ debug_target = f"{ SET_PRESSURE_TARGET } "
148+ while True :
149+ force_pressure = sensor .get_pressure ()
150+ # step = -0.06 if abs(float(force_pressure)) > 0.1 else -0.1
151+ step = - 0.06
152+ print ("Force pressure is: " , force_pressure )
153+ if force_pressure < float (debug_target .strip ()):
154+ await api .move_rel (OT3Mount .LEFT , Point (x = 0 , y = 0 , z = step ))
155+ await sleep (3 )
156+ else :
157+ REACHED_PRESSURE = sensor .get_pressure ()
158+ ui .print_info (f"Reaching force is { REACHED_PRESSURE } , exit calibration." )
159+ break
122160
123161
124- async def run (
125- api : OT3API , report : CSVReport , section : str , pipette : Literal [ 200 , 1000 ]
162+ async def _partial_pick_up_z_motion (
163+ api : OT3API , current : float , distance : float , speed : float
126164) -> None :
165+ async with api ._backend .motor_current (run_currents = {Axis .Z_L : current }):
166+ target_down = target_position_from_relative (
167+ OT3Mount .LEFT , Point (z = - distance ), api ._current_position
168+ )
169+ await api ._move (target_down , speed = speed )
170+ target_up = target_position_from_relative (
171+ OT3Mount .LEFT , Point (z = distance ), api ._current_position
172+ )
173+ await api ._move (target_up )
174+ await api ._update_position_estimation ([Axis .Z_L ])
175+
176+
177+ async def _partial_pick_up (api : OT3API , position : Point , current : float ) -> None :
178+ await helpers_ot3 .move_to_arched_ot3 (
179+ api ,
180+ OT3Mount .LEFT ,
181+ position ,
182+ safe_height = position .z + 10 ,
183+ )
184+ await _partial_pick_up_z_motion (api , current = current , distance = 12 , speed = 3 ) # change distance and speed, in case collision detected error
185+ await api .add_tip (OT3Mount .LEFT , helpers_ot3 .get_default_tip_length (TIP_VOLUME ))
186+ await api .prepare_for_aspirate (OT3Mount .LEFT )
187+ await api .home_z (OT3Mount .LEFT )
188+
189+ async def run (api : OT3API , report : CSVReport , section : str , pipette : Literal [200 , 1000 ]) -> None :
127190 """Run."""
128191 await api .home_z (OT3Mount .LEFT )
129192 slot_5 = helpers_ot3 .get_slot_calibration_square_position_ot3 (5 )
130193 home_pos = await api .gantry_position (OT3Mount .LEFT )
131194 await api .move_to (OT3Mount .LEFT , slot_5 ._replace (z = home_pos .z ))
195+ if USE_SEALED_FIXTURE :
196+ # init driver
197+ pressure_sensor = SealedPressureDriver ()
198+ pressure_sensor .init (9600 )
199+
200+ # move to slot
201+ ui .get_user_ready (f"Place tip tack 50ul at slot - { SLOT_FOR_PICK_UP_TIP } " )
202+ #await api.add_tip(OT3Mount.LEFT, helpers_ot3.get_default_tip_length(TIP_VOLUME))
132203
204+ tip_rack_pos = helpers_ot3 .get_theoretical_a1_position (SLOT_FOR_PICK_UP_TIP , TIP_RACK_FOR_PICK_UP_TIP )
205+ await helpers_ot3 .move_to_arched_ot3 (api , OT3Mount .LEFT , tip_rack_pos + Point (z = 30 ))
206+ await helpers_ot3 .jog_mount_ot3 (api , OT3Mount .LEFT )
207+ tip_rack_actual_pos = await api .gantry_position (OT3Mount .LEFT )
208+
133209 for probe in PROBE_POSITIONS :
210+ await helpers_ot3 .move_to_arched_ot3 (api , OT3Mount .LEFT , tip_rack_pos + Point (z = 50 ))
134211 sensor_id = sensor_id_for_instrument (probe )
135212 ui .print_header (f"Sensor: { probe } " )
136213
@@ -148,11 +225,33 @@ async def run(
148225
149226 # SEALED-Pa
150227 sealed_pa = 0.0
151- api .add_tip (OT3Mount .LEFT , helpers_ot3 .get_default_tip_length (TIP_VOLUME ))
152- await api .prepare_for_aspirate (OT3Mount .LEFT )
153228 if not api .is_simulator :
154- ui .get_user_ready (f"attach { TIP_VOLUME } uL TIP to { probe .name } sensor" )
155- ui .get_user_ready ("SEAL tip using your FINGER" )
229+
230+ # ui.get_user_ready(f"attach {TIP_VOLUME} uL TIP to {probe.name} sensor")
231+ if probe == InstrumentProbeType .PRIMARY :
232+ offset_pos = A1_OFFSET
233+ fixture_pos = PRIMARY_SEALED_PRESSURE_FIXTURE_POS
234+ elif probe == InstrumentProbeType .SECONDARY :
235+ offset_pos = H12_OFFSET
236+ fixture_pos = SECOND_SEALED_PRESSURE_FIXTURE_POS
237+ else :
238+ raise NameError ("offset position miss" )
239+
240+ tip_pos = tip_rack_actual_pos + offset_pos
241+ print (f"Tip pos: { tip_pos } " )
242+ ui .get_user_ready ("Pick up tip" )
243+ await _partial_pick_up (api , tip_pos , current = 0.1 )
244+ await api .prepare_for_aspirate (OT3Mount .LEFT )
245+ if not (USE_SEALED_FIXTURE or USE_SEALED_BLOCK ):
246+ ui .get_user_ready ("SEAL tip using your FINGER" )
247+ else :
248+ await helpers_ot3 .move_to_arched_ot3 (api , OT3Mount .LEFT , fixture_pos ._replace (z = fixture_pos .z + 50 ))
249+ ui .get_user_ready ("Ready for moving to sealed fixture" )
250+ if USE_SEALED_FIXTURE :
251+ await calibrate_to_pressue_fixture (api , pressure_sensor , fixture_pos )
252+ else :
253+ await helpers_ot3 .move_to_arched_ot3 (api , OT3Mount .LEFT , fixture_pos )
254+
156255 try :
157256 sealed_pa = await _read_from_sensor (
158257 api , sensor_id , NUM_PRESSURE_READINGS
@@ -162,7 +261,7 @@ async def run(
162261 break
163262 print (f"sealed-pa: { sealed_pa } " )
164263 sealed_result = check_value (sealed_pa , "sealed-pa" , pipette )
165- report (section , _get_test_tag (probe , "sealed-pa" ), [sealed_pa , sealed_result ])
264+ report (section , _get_test_tag (probe , "sealed-pa" ), [sealed_pa , sealed_result , REACHED_PRESSURE ])
166265
167266 # ASPIRATE-Pa
168267 aspirate_pa = 0.0
@@ -197,7 +296,18 @@ async def run(
197296 report (
198297 section , _get_test_tag (probe , "dispense-pa" ), [dispense_pa , dispense_result ]
199298 )
200-
299+ if USE_SEALED_FIXTURE or USE_SEALED_BLOCK :
300+ await helpers_ot3 .move_to_arched_ot3 (api , OT3Mount .LEFT , fixture_pos ._replace (z = fixture_pos .z + 50 ))
201301 if not api .is_simulator :
202302 ui .get_user_ready ("REMOVE tip" )
203- api .remove_tip (OT3Mount .LEFT )
303+
304+ trash_nominal = helpers_ot3 .get_slot_calibration_square_position_ot3 (12 ) + Point (z = 40 )
305+ # center the 96ch of the 1-well labware
306+ trash_nominal += OFFSET_FOR_1_WELL_LABWARE
307+ await helpers_ot3 .move_to_arched_ot3 (api , OT3Mount .LEFT , trash_nominal + Point (z = 20 ))
308+ await api .move_to (OT3Mount .LEFT , trash_nominal )
309+ await api .drop_tip (OT3Mount .LEFT )
310+ await api .remove_tip (OT3Mount .LEFT )
311+ await api .home ()
312+
313+
0 commit comments