Intelligent Part-Presence

Filed under: Robot Happiness Workflow TP Programming

Good material handling applications typically include many part-presence sensors: proximity switches on fixtures or machine tools, photo eyes or gripper open/closed/overtravel switches on end-of-arm tools, etc. How and when do you use them most effectively?

I check part-presence liberally. If something has gone awry with your automation, you want to realize it as soon as possible to minimize damage. Take a simple pick routine as an example:

  1. Make sure the part is present at the fixture
    It doesn’t make much sense to pick a part that isn’t there.
  2. Make sure the gripper is open and empty
    The robot will probably crash if the gripper is not open and will almost certainly crash if’s it already gripping a part. If the gripper IO is not functional here, you’ll hopefully detect it before it becomes a bigger problem (e.g. after you’ve picked up a 100lb part).
  3. Move to the part
  4. Grip the part
  5. Make sure the gripper is closed and the part is present within the gripper
    If you have the IO, use it.
  6. Retreat from the fixture
  7. Make sure the gripper is still closed and the part is still there
    Even if the gripper IO was satisfied at the fixture, it could be a bad grip that lets go as soon as you leave.
  8. Make sure the fixture is now empty If a sensor fails, you want to know about it as soon as possible. It’s more important to make this check when loading, but it’s worthwhile checking here too. On the load side, you’ll want to know that a part is incorrectly seated before you bash into that “empty” fixture at 2000mm/s on the next load cycle.

Of the 8 steps in that sequence, 5 involve part part-presence IO. Skipping any one of those checks could be a dangerous oversight.

Programming

Since these checks are so common, I usually write small routines for them. Since I may want to intelligently recover or simply throw up an error, I usually separate these rooutines into two separate types: “checks” and “ensures.”

Checks

Almost all of my applications use a status register (e.g. R[1:Status]). See my post on using conventions to save time.

A “check” program simply checks the status and returns a 0 if the status was expeted or something else depending on the condition. I usually use one or two arguments: AR[1] for the expectation (e.g. present or not present), and sometimes AR[2] for the ‘station’ within the fixture if the robot makes use of multiple stations within the same general fixture.

For example:


  ! CHECK_PP_STAGING.LS            ;
  ! ============================== ;
  ! AR[1] - expectation            ;
  !         0 for not present      ;
  !         1 for present          ;
  ! AR[2] - station                ;
  !                                ;
  ! Examples:                      ;
  !   CALL CHECK_PP_STAGING(1,2)   ;
  !   # => returns 0 in R[1] if    ;
  !        part present at station ;
  !        2, 1 otherwise.         ;
  !   CALL CHECK_PP_STAGING(0,2)   ;
  !   # => returns 0 in R[1] if    ;
  !        part NOT present at     ;
  !        station 2, 1 otherwise. ;
  ! ------------------------------ ;
  IF AR[2]=1,JMP LBL[100] ;
  IF AR[2]=2,JMP LBL[200] ;
  JMP LBL[404] ;
   ;
  LBL[100] ;
  ! Fixture 1 ;
  IF (AR[1]=1 AND DI[1]=ON),JMP LBL[600] ;
  IF (AR[1]=0 AND DI[1]=OFF),JMP LBL[600] ;
  JMP LBL[500] ;
   ;
  LBL[200] ;
  ! Fixture 2 ;
  IF (AR[1]=1 AND DI[2]=ON),JMP LBL[600] ;
  IF (AR[1]=0 AND DI[2]=OFF),JMP LBL[600] ;
  JMP LBL[500] ;
   ;
  LBL[500] ;
  R[1:Status]=1 ;
  JMP LBL[999] ;
   ;
  LBL[600] ;
  R[1:Status]=0 ;
  JMP LBL[999] ;
   ;
  LBL[999] ;

Utilizing two arguments allows you to use one routine for any part presence checking within a multi-fixture station.

Ensures

When I want to actually stop the robot and throw up an error message when the part-present state is not what I expect, I sometimes create an additional “ensure” routine that wraps the “check” function with an error message if the status is unexpected.

  ! ENSURE_PP_STAGING.LS                   ;
  ! ====================================== ;
  ! Throws an error if the part-presence   ;
  ! state (AR[1]) is not what was expected ;
  ! at the provided station (AR[2])        ;
  ! -------------------------------------- ;
  LBL[1] ;
  CALL CHECK_PP_STAGING(AR[1],AR[2]) ;
  IF R[1:Status]=0,JMP LBL[999] ;
   ;
  ! display error on HMI ;
  UALM[1] ;
  JMP LBL[1] ;
   ;
  LBL[999] ;

The routine also “traps” the robot within the subroutine until the expected condition is met. This ensures that a button-happy operator doesn’t simply ignore an error message without fixing the condition.

Usage

Let’s go back to the pick routine and actually write a little code:


  ! UNLOAD_STAGING_1 ;
  ! ================ ;
  CALL ENSURE_UNGRIP ;
  ! ensure part IS present at fixture ;
  CALL ENSURE_PP_STAGING(1,1) ;
   ;
  L P[1:Unload] 2000mm/sec CNT100 Offset,PR[1:Approach OF] ;
  L P[1:Unload] 500mm/sec CNT0 ;
  CALL GRIP ;
  CALL ENSURE_GRIP ;
  L P[1:Unload] 2000mm/sec CNT100 Offset,PR[2:Retreat] ;
   ;
  CALL ENSURE_GRIP ;
  ! ensure part NOT present at fixture ;
  CALL ENSURE_PP_STAGING(0,1) ;

If you want the robot to be a bit more intelligent, you can easily just use your check macro instead of the ensure to try to pick the part again:


  ! UNLOAD_STAGING_1 ;
  ! ---------------- ;
  LBL[1] ;
  CALL ENSURE_UNGRIP ;
  ! ensure part IS present at fixture ;
  CALL ENSURE_PP_STAGING(1,1) ;
   ;
  L P[1:Unload] 2000mm/sec CNT100 Offset,PR[1:Approach OF] ;
  L P[1:Unload] 500mm/sec CNT0 ;
  CALL GRIP ;
  CALL ENSURE_GRIP ;
  L P[1:Unload] 2000mm/sec CNT100 Offset,PR[2:Retreat] ;
   ;
  CALL CHECK_GRIP ;
  IF R[1:Status]=0,JMP LBL[999] ;
   ;
  ! missed the part, check to make sure it's still there ;
  CALL ENSURE_PP_STAGING(1,1) ;
  CALL UNGRIP ;
  ! maybe add a limit to retries here ;
  JMP LBL[1] ;
   ;
  LBL[999] ;
  CALL ENSURE_PP_STAGING(0,1) ;

I use routines like these all the time to catch any issues before they cause damage to the cell or the robot. Hopefully you will too.


Want posts like this delivered right to your inbox?

If you liked this post, please sign up for my mailing list!