3232
3333# Test Parameters
3434FORCE_SPEED = 10
35- FORCE_MARGIN = 15 # Percentage
36- FORCE_TEST_SETTINGS = [
37- {"CURRENT" : 0.15 , "F_MAX" : 50 },
38- {"CURRENT" : 0.2 , "F_MAX" : 73 },
39- {"CURRENT" : 0.3 , "F_MAX" : 120 },
40- {"CURRENT" : 0.4 , "F_MAX" : 160 },
41- {"CURRENT" : 0.5 , "F_MAX" : 200 },
42- {"CURRENT" : 0.6 , "F_MAX" : 230 },
43- {"CURRENT" : 0.7 , "F_MAX" : 260 },
44- {"CURRENT" : 1.4 , "F_MAX" : 480 },
45- {"CURRENT" : 1.5 , "F_MAX" : 520 },
35+ FORCE_MARGIN = 35 # Percentage
36+ FORCE_TEST_LEFT_SETTINGS = [
37+ {"CURRENT" : 0.15 , "F_MAX" : 39 },
38+ {"CURRENT" : 0.2 , "F_MAX" : 63 },
39+ {"CURRENT" : 0.3 , "F_MAX" : 107 },
40+ {"CURRENT" : 0.4 , "F_MAX" : 148 },
41+ {"CURRENT" : 0.5 , "F_MAX" : 189 },
42+ {"CURRENT" : 0.6 , "F_MAX" : 226 },
43+ {"CURRENT" : 0.7 , "F_MAX" : 259 },
44+ {"CURRENT" : 1.4 , "F_MAX" : 498 },
45+ {"CURRENT" : 1.5 , "F_MAX" : 528 },
4646]
47+ FORCE_TEST_RIGHT_SETTINGS = [
48+ {"CURRENT" : 0.15 , "F_MAX" : 35 },
49+ {"CURRENT" : 0.2 , "F_MAX" : 57 },
50+ {"CURRENT" : 0.3 , "F_MAX" : 98 },
51+ {"CURRENT" : 0.4 , "F_MAX" : 129 },
52+ {"CURRENT" : 0.5 , "F_MAX" : 168 },
53+ {"CURRENT" : 0.6 , "F_MAX" : 196 },
54+ {"CURRENT" : 0.7 , "F_MAX" : 228 },
55+ {"CURRENT" : 1.4 , "F_MAX" : 410 },
56+ {"CURRENT" : 1.5 , "F_MAX" : 448 },
57+ ]
58+
59+ ONLY_COUNT_USING_CURRENT_YIELD = True
4760CYCLES_CURRENT = 5
4861
49- TEST_PARAMETERS : Dict [str , float ] = {
62+ TEST_LEFT_PARAMETERS : Dict [str , float ] = {
63+ "SPEED" : FORCE_SPEED ,
64+ "FORCE_MARGIN" : FORCE_MARGIN ,
65+ "CYCLES" : CYCLES_CURRENT ,
66+ }
67+
68+ TEST_RIGHT_PARAMETERS : Dict [str , float ] = {
5069 "SPEED" : FORCE_SPEED ,
5170 "FORCE_MARGIN" : FORCE_MARGIN ,
5271 "CYCLES" : CYCLES_CURRENT ,
5372}
54- for i in FORCE_TEST_SETTINGS :
55- TEST_PARAMETERS [str (i ["CURRENT" ])] = i ["F_MAX" ]
5673
74+ for i in FORCE_TEST_LEFT_SETTINGS :
75+ TEST_LEFT_PARAMETERS [str (i ["CURRENT" ])] = i ["F_MAX" ]
76+
77+ for i in FORCE_TEST_RIGHT_SETTINGS :
78+ TEST_RIGHT_PARAMETERS [str (i ["CURRENT" ])] = i ["F_MAX" ]
5779
5880# Global variables
5981thread_sensor = False
6082force_output = []
83+ valid_fail = []
6184
6285
6386def _connect_to_mark10_fixture (simulate : bool ) -> Union [Mark10 , SimMark10 ]:
@@ -81,7 +104,7 @@ def build_test_lines() -> List[Union[CSVLine, CSVLineRepeating]]:
81104 mount_data_line : List [Union [CSVLine , CSVLineRepeating ]] = [
82105 CSVLine ("TEST_CURRENTS" , [str , str , str , str , str ])
83106 ]
84- for setting in FORCE_TEST_SETTINGS :
107+ for setting in FORCE_TEST_LEFT_SETTINGS :
85108 mount_data_line .append (
86109 CSVLine (
87110 _get_test_tag (setting ["CURRENT" ]),
@@ -98,8 +121,18 @@ def _build_csv_report() -> CSVReport:
98121 test_name = "z-stage-test-qc-ot3" ,
99122 sections = [
100123 CSVSection (
101- title = "TEST_PARAMETERS" ,
102- lines = [CSVLine (parameter , [int ]) for parameter in TEST_PARAMETERS ],
124+ title = "TEST_LEFT_PARAMETERS" ,
125+ lines = [
126+ CSVLine (parameter , [int , CSVResult ])
127+ for parameter in TEST_LEFT_PARAMETERS
128+ ],
129+ ),
130+ CSVSection (
131+ title = "TEST_RIGHT_PARAMETERS" ,
132+ lines = [
133+ CSVLine (parameter , [int , CSVResult ])
134+ for parameter in TEST_RIGHT_PARAMETERS
135+ ],
103136 ),
104137 CSVSection (
105138 title = OT3Mount .LEFT .name ,
@@ -190,7 +223,6 @@ def check_force(
190223 qc_pass = True
191224 else :
192225 qc_pass = False
193-
194226 _tag = _get_test_tag (current )
195227 report (
196228 mount .name ,
@@ -203,12 +235,15 @@ def check_force(
203235 CSVResult .from_bool (qc_pass ),
204236 ],
205237 )
206-
207238 return qc_pass
208239
209240
210241async def _force_gauge (
211- api : OT3API , mount : OT3Mount , report : CSVReport , simulate : bool
242+ api : OT3API ,
243+ mount : OT3Mount ,
244+ report : CSVReport ,
245+ simulate : bool ,
246+ arguments : argparse .Namespace ,
212247) -> bool :
213248 """Apply force to the gague and log."""
214249 global thread_sensor
@@ -235,11 +270,40 @@ async def _force_gauge(
235270 ["MAX" , "MAX_RANGE" , "AVERAGE" , "AVERAGE_RANGE" , "RESULT" ],
236271 )
237272 # Test each current setting
238- for test in FORCE_TEST_SETTINGS :
273+ if mount == OT3Mount .LEFT :
274+ force_test_setting = FORCE_TEST_LEFT_SETTINGS
275+ else :
276+ force_test_setting = FORCE_TEST_RIGHT_SETTINGS
277+ for test in force_test_setting :
239278 # Test each current setting several times and average the results
240279 max_results = []
241280 avg_results = []
242281 test_current = test ["CURRENT" ]
282+ if arguments .user_current == "None" :
283+ pass
284+ else :
285+ if test_current != float (arguments .user_current ):
286+ continue
287+ else :
288+ for i in range (100 ):
289+ await api .move_to (mount = mount , abs_position = pre_test_pos )
290+ ui .print_header (f"Cycle { i + 1 } : Testing Current = { test_current } " )
291+ try :
292+ async with api ._backend .motor_current ():
293+ await api ._backend .set_active_current ({z_ax : test_current })
294+ await api .move_to (
295+ mount = mount ,
296+ abs_position = press_pos ,
297+ speed = FORCE_SPEED ,
298+ expect_stalls = True ,
299+ )
300+ finally :
301+ pass
302+ await api ._update_position_estimation ([Axis .by_mount (mount )])
303+ await api .refresh_positions ()
304+
305+ await api .move_to (mount = mount , abs_position = pre_test_pos )
306+
243307 for i in range (CYCLES_CURRENT ):
244308 # Move to just above force gauge
245309 await api .move_to (mount = mount , abs_position = pre_test_pos )
@@ -272,10 +336,12 @@ async def _force_gauge(
272336 avg_results .append (round (analyzed_avg , 1 ))
273337 else :
274338 ui .print_error (
275- "DATA INVALID - z-stage did not contact or guage not zeroed"
339+ "DATA INVALID - z-stage did not contact or guage not zeroed \n "
340+ f"Mount { mount .name } fail !"
276341 )
342+ valid_fail .append (mount .name )
277343 qc_pass = False
278- break
344+ return False
279345
280346 # we expect a stall has happened during pick up, so we want to
281347 # update the motor estimation
@@ -296,7 +362,12 @@ async def _force_gauge(
296362 ui .print_header (f"CURRENT: { test_current } - PASS" )
297363 else :
298364 ui .print_header (f"CURRENT: { test_current } - FAIL" )
299- qc_pass = qc_pass and res
365+ # only calculate 0.2 & 0.5
366+ if ONLY_COUNT_USING_CURRENT_YIELD :
367+ if test_current == 0.2 or test_current == 0.5 :
368+ qc_pass = qc_pass and res
369+ else :
370+ qc_pass = qc_pass and res
300371
301372 return qc_pass
302373
@@ -306,11 +377,15 @@ async def _run(api: OT3API, arguments: argparse.Namespace, report: CSVReport) ->
306377 qc_pass = True
307378
308379 if not arguments .skip_left :
309- res = await _force_gauge (api , OT3Mount .LEFT , report , arguments .simulate )
380+ res = await _force_gauge (
381+ api , OT3Mount .LEFT , report , arguments .simulate , arguments
382+ )
310383 qc_pass = res and qc_pass
311384
312385 if not arguments .skip_right :
313- res = await _force_gauge (api , OT3Mount .RIGHT , report , arguments .simulate )
386+ res = await _force_gauge (
387+ api , OT3Mount .RIGHT , report , arguments .simulate , arguments
388+ )
314389 qc_pass = res and qc_pass
315390
316391 return qc_pass
@@ -327,8 +402,12 @@ async def _main(arguments: argparse.Namespace) -> None:
327402 dut = helpers_ot3 .DeviceUnderTest .OTHER
328403 helpers_ot3 .set_csv_report_meta_data_ot3 (api , report , dut = dut )
329404
330- for k , v in TEST_PARAMETERS .items ():
331- report ("TEST_PARAMETERS" , k , [v ])
405+ # NOTE: We submit an automatic "PASS" result for these parameter lists.
406+ # They do not test any logic but only add the list of parameters used to the CSV
407+ for k , v in TEST_LEFT_PARAMETERS .items ():
408+ report ("TEST_LEFT_PARAMETERS" , k , [v , CSVResult .PASS ])
409+ for k , v in TEST_RIGHT_PARAMETERS .items ():
410+ report ("TEST_RIGHT_PARAMETERS" , k , [v , CSVResult .PASS ])
332411
333412 # Attempt to home if first homing fails because of OT-3 in box Y axis issue
334413 try :
@@ -354,6 +433,14 @@ async def _main(arguments: argparse.Namespace) -> None:
354433
355434 try :
356435 qc_pass = await _run (api , arguments , report )
436+ await api .home (
437+ [
438+ Axis .X ,
439+ Axis .Y ,
440+ Axis .by_mount (OT3Mount .LEFT ),
441+ Axis .by_mount (OT3Mount .RIGHT ),
442+ ]
443+ )
357444 except KeyboardInterrupt :
358445 print ("Cancelled" )
359446 except Exception as e :
@@ -364,6 +451,12 @@ async def _main(arguments: argparse.Namespace) -> None:
364451 ui .print_title ("Test Done - PASSED" )
365452 else :
366453 ui .print_title ("Test Done - FAILED" )
454+ if len (valid_fail ) == 0 :
455+ pass
456+ else :
457+ print ("Data Invalid, Please Re-Test This Unit (数据验证失败, 请复测当前Z轴) !" )
458+ for item in valid_fail :
459+ print (f"Mount { item } Fail" )
367460 report .save_to_disk ()
368461 report .print_results ()
369462
@@ -373,6 +466,7 @@ async def _main(arguments: argparse.Namespace) -> None:
373466 arg_parser .add_argument ("--simulate" , action = "store_true" )
374467 arg_parser .add_argument ("--skip_left" , action = "store_true" )
375468 arg_parser .add_argument ("--skip_right" , action = "store_true" )
469+ arg_parser .add_argument ("--user_current" , type = str , default = "None" )
376470 old_stall_setting = get_adv_setting ("disableStallDetection" , RobotTypeEnum .FLEX )
377471 try :
378472 asyncio .run (set_adv_setting ("disableStallDetection" , True ))
0 commit comments