How to RUN FANUC Programs Concurrently with the RUN statement

Filed under: FANUC TP Programming

Every once in a while I get asked about FANUC’s multitasking capabilities:

“Can I do multitasking with a FANUC robot?”
“How do I run a background task with FANUC?”
“How do I run an aux axis independently while the robot is doing other stuff?”

The short answer is yes, but there are a number of options. Which one’s appropriate depends on your use-case.

Option Environment
Background Logic Setup (can run TP or KAREL programs)
The RUN statement TP (can run TP or KAREL programs)
AUTOEXEC programs System Config (can run TP or KAREL programs)
Condition Monitors TP
Condition Handlers KAREL
PMC (Programmable Machine Control)* Ladder logic

*NOTE: PMC requires a robot software option and the FANUC Ladder PC software. Only recommended for budget systems that don’t have a separate PLC.

I use Background Logic most often, and I’ve written about it before with an Intro to FANUC Background Logic and How to use BG Logic to to simplify your TP programs. If you don’t need motion, you can probably do it with Background Logic. For almost all other cases, I will generally use the RUN statement to spawn another task.

NOTE: I almost never use AUTOEXEC programs, Condition Monitors or PMC, so let’s skip over those for now. Let me know if you want to know more about them.

Today I want to talk about the RUN statement — the basics, potential use-cases and some things to watch for. I’ll wrap things up with a simple KAREL utility that should help with one of the most annoying issues you might see when using the RUN statement.

RUN statement basics

You can add a RUN statement in the TP editor via INST > Multiple Control > RUN.

On the surface it looks just like a program CALL. You simply provide the program name and any (optional) parameters:

CALL FOO ;
RUN FOO ;
CALL FOO_WITH_ARGS(1,2,3) ;
RUN FOO_WITH_ARGS(1,2,3) ;

You’re probably aware that process control is immediately given to a called program and returned to the calling program when the called program ends.

! main task ;
CALL FOO ;
    ! we are in FOO now ;
    ! FOO ends ;
! back to main task ;

RUN statements work differently. The main program proceeds immediately after the RUN statement is executed, and both programs will now execute concurrently.

! main task ;
RUN FOO ;
! both the main task AND foo are both running now ;

NOTE: The details of how the controller handles task-scheduling are outside the scope of this post, but scheduling itself is a really interesting computer science problem. I learned a lot by taking this free course on operating systems, and I would highly recommend it if you are interested in learning more about how computers and operating systems (like the FANUC robot controller) actually work.

Some potential use-cases

I’ve generally only RUN a concurrent task when I am controlling an external device or independent axis.

You may also want to spin off a separate task when you need to signal something that takes a little while, but you don’t want the robot to wait for a response.

I generally use Flags (F[]) to communicate between tasks. Flags are just boolean I/O bits that are completely local to the robot — perfect for interprocess communication.

Say you wanted to spin off a concurrent task, let the robot do some other stuff without waiting but then you wanted the robot to make sure the task completed before moving on:

! main task ;
F[1:TASK DONE]=(OFF) ;
RUN ASYNC_TASK ;
! do some stuff ;
WAIT (F[1:TASK DONE]) ;

! async_task ;
! do some concurrent stuff ;
F[1:TASK DONE]=(ON) ;

Sometimes it’s safe to just fire these tasks off and forget, but it’s usually helpful to have some sort of signaling to make sure your concurrent tasks don’t hang or create race conditions.

Some things to watch out for

Motion control

Only one task can have motion control for any group at one time. Have you ever noticed that GROUP_MASK header in your TP programs? That specifies which, if any, motion groups your program will lock when it is executed.

A FANUC robot can have up to 8 motion groups (a group of axes or a single axis), but most robots are probably just a single group. That’s why the GROUP_MASK header is usually set to 1,*,*,*,*,*,*,*. This indicates that the program will lock motion for group 1 and no other groups.

BGLOGIC programs must not lock any motion groups, so that GROUP_MASK header will be *,*,*,*,*,*,*,*.

In general, it may be a good idea to only lock motion when necessary (e.g. use a GROUP_MASK of *,*,*,*,*,*,*,* for your gripper macros, etc.)

Setting the IGNORE PAUSE header

Sometimes you want your concurrent task to continue running even if a fault occurs. If this is the case, set the IGNORE PAUSE header from the program DETAIL screen.

Debugging and monitoring concurrent tasks

When your robot is running, the TP editor will typically show the main task’s status.

The best way to see what your other tasks are doing is to bring up the SELECT screen and then press the F4 (MONITOR) softkey. Press ENTER to view the task in an editor, and you can also PAUSE and ABORT each one individually from this screen.

NOTE: You can also see the program status (but not the source code) from the Menu > Status > Program menu. Hit NEXT to cycle through the current running tasks.

Making sure all tasks abort

You can configure the UOP cycle stop bit to abort all tasks by going to Menu > System > Config and setting CSTOPI for ABORT and Abort all Programs by CSTOPI to true. (You could also just set the $SHELL_CFG.$USE_ABORT and $SHELL_CFG.$CSTOPI_ALL system variables.)

I generally always set these bits. I can’t think of any instances where I wouldn’t want a single bit to be able to abort everything in an error condition. It’s like giving the PLC access to the TP’s Function > ABORT ALL button.

Attempting to RUN the task when it’s already running

Ah the dreaded INTP-267 RUN stmt failed error caused by PROG-007 Program is already running. This error is always annoying, typically requires an abort, and I’ve seen a lot of people (including myself) throw some nasty hacks in to try and avoid this. (I’ve even seen this occur while running FANUC’s PalletTool and iRPickTool… maybe it’s fixed now!)

This could simply be a programming bug (e.g. you did not have appropriate checks in place to ensure that your task completed before running it again), but it could also be a case where your concurrent task hung up for some reason (e.g. IGNORE PAUSE header was not set) and did not get resumed properly. Maybe you are not using the Abort all Program by CSTOPI option.

Wouldn’t it be nice if there was a way to check if a task is running before you attempt to RUN it? I’m looking for something a bit more reliable than a F[1:TASK RUNNING] flag.

TASK_STATUS KAREL utility

I should have written this years ago, but here’s a little KAREL utility that provides just that. You give it the name of a program and a status register id, and it will tell you what the task is doing.

Example:

LBL[1] ;
CALL TASK_STATUS(‘ASYNC_TASK’,1) ;
IF R[1:TASK STATUS]<>2,JMP LBL[501] ;
! task is aborted ;
RUN ASYNC_TASK ;
END ;
 ;
LBL[501] ;
! task is still doing something or hung up ;
JMP LBL[1] ;

The possible return values are:

-2 Run request has been accepted
-1 Abortrequest has been accepted
0 Task is running
1 Task is paused
2 Task is aborted
Other Refer to the Error Code manual… probably a usage issue (e.g. misspelled program name)

I’ll write another article about the KAREL internals of TASK_STATUS, but for now you can check out the source code and download the latest binary release on GitHub.

NOTE: You’ll need the R632 KAREL software option on your robot in order to load and use this utility.

As a parting note (and I actually did not know this until I was working on writing this post) you can actually use the RUN statement to resume a paused task by name. This pairs nicely with the TASK_STATUS KAREL program.

Here’s a contrived example:

Parent Task

RUN BG ;
WAIT 2.00(sec) ;
CALL TASK_STATUS(‘BG’,1) ;
IF R[1:TASK_STATUS]<>1,JMP LBL[500] ;
! bg is paused ;
RUN BG ;
CALL TASK_STATUS(‘BG’,1) ;
IF R[1:TASK_STATUS]<>0,JMP LBL[500] ;

BG Task

PAUSE ;
LBL[1] ;
JMP LBL[1] ;

Traditionally I’ve avoided pausing concurrent tasks, preferring to use WAIT statement to keep things in sync instead, but maybe there are cases when you would legitimately want to use the PAUSE statement. Paired with TASK_STATUS, you can be sure to avoid those pesky INTP-267 and PROG-007 errors.


There's more where that came from.

I email (almost) every Tuesday with the latest insights, tools and techniques for programming FANUC robots. Drop your email in the box below, and I'll send new articles straight to your inbox!

No spam, just robot programming. Unsubscribe any time. No hard feelings!