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.
|Background Logic||Setup (can run TP
||TP (can run TP or KAREL programs)|
||System Config (can run TP or KAREL programs)|
|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
AUTOEXECprograms, 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 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
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.)
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
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
ABORT each one individually from this screen.
NOTE: You can also see the program status (but not the source code) from the
Menu > Status > Programmenu. Hit
NEXTto 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.$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.
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.
LBL ; CALL TASK_STATUS(‘ASYNC_TASK’,1) ; IF R[1:TASK STATUS]<>2,JMP LBL ; ! task is aborted ; RUN ASYNC_TASK ; END ; ; LBL ; ! task is still doing something or hung up ; JMP LBL ;
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)|
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:
RUN BG ; WAIT 2.00(sec) ; CALL TASK_STATUS(‘BG’,1) ; IF R[1:TASK_STATUS]<>1,JMP LBL ; ! bg is paused ; RUN BG ; CALL TASK_STATUS(‘BG’,1) ; IF R[1:TASK_STATUS]<>0,JMP LBL ;
PAUSE ; LBL ; JMP LBL ;
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