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 } { 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 }  
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 }  )
297363        else :
298364            ui .print_header (f"CURRENT: { test_current }  )
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 }  )
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