TP Programming
Simplifying Robotics: Mastering FANUC CRX Plugins and Timeline Editor
FANUC CRX Robots and the Timeline Editor
I contend that programming FANUC robots is easy and can be learned quickly. But what if the idea of writing code is too intimidating or you just don’t have time?
Wouldn’t it be great if you could make the robot do a job without writing a single line of code?
That’s the idea behind FANUC’s new(ish) timeline editor for CRX robots. You basically program the robot by dropping functional blocks onto a timeline. My two-year old could figure it out.
Asynchronous Part-Presence Checking (When the Robots are Too Fast)
I’ve spent a lot of time working on high-speed line tracking (iRPickTool) applications. When I first started working on them back in 2008, throughputs around 100 cycles per minute were really pushing the envelope (but this was when FANUC’s flagship high-speed picking robot was the M-430iA).
Since then FANUC has introduced a number of Delta robots: the M-1iA in 2009, the M-3iA in 2010, the M-2iA in 2013(?) and the DR-3iB in 2019. These robots are much better suited for high-speed picking applications than the articulated M-430iA arm: lighter, faster, better work envelope– great robots.
Named Variables & Constants for FANUC TP (with Fexcel)
When I first learned to program FANUC robots, I was bothered by the TP programming language. At the time I was using Ruby primarily, which, according to the official website, “has an elegant syntax that is natural to read and easy to write.”
I was annoyed that I had to manage my own memory locations for numbers, positions, I/O, etc.
Wouldn’t it be nice if I could program FANUC robots with Ruby? …or at least something Ruby-esque?
How to Diagnose FANUC Alarm Codes and Error Codes
It’s inevitable. You’re setting up your robot, programming it or running production, and you come across an alarm code that you don’t recognize. What do you do? Call tech support? Google? Read the manuals?
Based on some of the questions I’ve seen, I think a lot of people are unaware of the troubleshooting resources available at their fingertips.
Your robot probably has a ton of help files and documentation available right on the teach pendant. That eDoc CD that came with your robot is also packed with documentation gold, and there are also a couple of ways to lookup alarms online.
Four Ways to Control FANUC Robots' Speed Override
Imagine this: you have a robot that easily keeps up with its task (trust me, these applications do exist!). Like a considerate parent, you allow the robot to run at 70% which still gives it a little time to rest between cycles.
But every time you walk by the cell, the teach pendant shows a glaring 100% override. The robot works its ass off for a few seconds and then sits there motionless, waiting for the next part to come down the line.
Refactoring Skip Conditions
In my last article we talked about FANUC’s Skip Conditions: how they work, where you might use them and why they can be confusing. We also discussed the SkipJump option which may have better semantics.
Today I want to use the Skip Condition syntax as an opportunity for refactoring. We’ll work with TP parameters and their corresponding argument registers (
AR[]), side-step some argument register limitations, discuss return values and eventually create a pretty powerful two-stage search algorithm that has high accuracy without sacrificing cycle time.How to Search with a FANUC Robot Using Skip Conditions
Have you ever needed your FANUC robot to search for something and stop when it “sees” it with some sort of sensor?
There are probably 100 ways you could pull this off (macros, background logic, manipulating UOP signals, etc.), but if you’ve been programming FANUC robots for a while, your first thought is probably “SKIP CONDITIONS!” followed almost immediately by “How exactly do those work again? I remember them being kinda weird.”
How to RUN FANUC Programs Concurrently with the RUN statement
I get emails from time to time about programming FANUC robots. (Please feel free to reach out!) 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.
TP Programming With Interfaces
I worked on a palletizing project recently that required serialization. In effect, the product must be tracked through every stop of the process:
- Product picked
- Inspection passed
- Inspection failed
- Product moving to pallet
- Product placed on pallet
- Product dropped
- Product rejected
The robot simply sends a Digital Output signal to the PLC when any of these events takes place, and the PLC is responsible for sending signals on to the customer’s serialization service.
Teaching Points Backwards
I was with a customer earlier this week who needed a little help with one of their robots. It was a simple pick and place application, but for one reason or another, one of its placements had drifted and now the robot was fumbling that drop at overrides over 70%.
Pretty simple fix, right? Put the robot in teach, pick up a part and then step it through the place routine. Touch up the drop position when you get there.
Embrace the END Statement
What do you think this line of code does?
JMP LBL[9999] ;If you’ve been programming FANUC robots for a while, you probably guessed that this statement jumps to the end of the program. It comes in many variants:
JMP LBL[999],JMP LBL[10000], etc., but the intent is almost always the same: end this routine.The problem is that there’s no guarantee that
LBL[9999]orLBL[10000]or whatever actually ends the routine. That label may not even exist. You may be reasonably sure as to what will happen if you wrote the program, but I’m willing to bet that someday yourLBL[10000]won’t be the last line of your routine.Isolate Your Wait Statements
Have you ever looked at a TP program and gotten lost following all the
LBLs andJMPs? Have you ever gotten lazy handling yourWAIT-statementTIMEOUTs because you didn’t want to bother adding the extra stuff to your main routine?If you’re nodding “yes” right now, you should try isolating your
WAIT-statements into their own small programs.In my eight-plus years of programming robots and troubleshooting other people’s code, I’ve found that a mess of labels and lack of refactoring large programs into smaller routines is the single biggest cause of issues.
Smart Payloads
My last project was a machine load/unload application where the robot had two basically identical grippers. Either gripper could be used to load or unload any station. Here’s how I handled the payload switching and grip/ungrip logic in the load/unload programs.Small Programs
FANUC’s TP programming environment is great for creating simple programs quickly. From the comfort of your teach pendant, you can record a few points, turn a few bits on and off and have a fully functional demo within a few minutes. However, as soon as you have to add some real intelligence to your robot, you’ll quickly find the editor to be cumbersome and slow.
I’ve already written about how I write my TP programs by hand, but here’s a quick trick I’ve been using to make my development faster and my programs a little easier to understand: tiny programs. I’m talking really small, like one or two lines.
Programming Multiple Robot Systems Effectively
When dealing with multiple robot systems, I usually find that maintaining consistency from robot-to-robot is usually the most difficult part. Simply getting backups of all your robots can be a pain if you don’t have the right tool for the job. If you’re using Windows (you probably are), just a little knowledge of the command line and the
ftputility will make your life a lot easier.The Command Prompt
If you’ve never used the Windows command prompt before, read this quick intro from the Princeton CS department.
How to Use BG Logic to Simplify Your TP Programs
TP programs should be readable. If an operator can step through the code and understand it, you might be able to avoid a phone call when the robot inevitably misbehaves. Lately I’ve been simplifying complex conditionals into unique flags to keep my programs short and simple.
Let’s say you have an application where the robot needs to unload one machine and then load another machine. The part out of machine 1 is hot so you want to wait until both machines are ready before unloading the first machine. You might have a line of code that looks like this:
Polish
Programming FANUC robots is easy. Giving the robots enough intelligence to run safely and reliably in just about any failure scenario is the hard part.
This is where many integrators get into trouble. They don’t plan enough programming time on the front-end so that they are forced to add polish on the production floor. If your FAT is just a day or two away and your code isn’t sprinkled with all sorts of (hopefully rarely used but thoroughly tested) error recovery routines, you’re in trouble.
When to use Tool Offsets vs. Frame Offsets
I used to be a frame offset (PR Offset) guy almost 100% of the time. Assuming you are using accurate UFRAMEs and UTOOLs, this should get you pretty far in material handling. However, once things stop being perfect and your tolerances start getting really tight, you might be better off using tool offsets in your pick and place situations.
UTOOL_NUM=1 ; ; ! pick product from fixture 1 ; UFRAME_NUM=1 ; L P[1:pick] 1000mm/s CNT100 Offset,PR[1:pick approach] ; L P[1:pick] 250mm/s CNT0 ; CALL GRIP ; L P[1:pick] 500mm/s CNT100 Offset,PR[2:pick retreat] ; ; ! place product on fixture 2 ; UFRAME_NUM=2 ; L P[2:place] 1000mm/s CNT100 Offset, PR[3:place approach] ; L P[2:place] 250mm/s CNT0 ; CALL UNGRIP ; L P[2:place] 500mm/s CNT100 Offset,PR[4:place retreat] ;This works great when you can approach and retreat from your fixtures in an orthogonal or parallel direction, but what happens when your part doesn’t sit quite perfectly in the fixture? What if your user frame isn’t perfectly accurate? Time to use a tool offset.
Writing TP Programs by Hand - Pros and Cons
FANUC’s TP programming language and the teach pendant’s built-in editor are great tools. They allow relatively novice programmers to get up and running very quickly. Teach a couple points, throw in a couple labels andIFstatements, and you’re off to the races. However, anyone who’s tried to do anything a bit more complex quickly realizes how cumbersome programming on the teach pendant is. Navigating through multiple levels of menus to find thePAYLOADinstruction or creating an extensive mixed-logic conditional is really painful. At this point many programmers switch to programming.LSfiles by hand.Visual Line Tracking is Hard
I spent last week helping an end-user with their two-robot visual line tracking system. As far as systems like these go, this one’s pretty simple: just two robots, one backlit conveyor, one camera and basically one product. The entire codebase comes in well under a thousand lines. We had issues that were hard to solve despite the simplicity. What follows is my process while debugging several common visual tracking errors.Simulating TP Programs in the Browser with tp.js
Last week I wrote about Testing TP Programs with Ruby, but you had to trust that I wasn’t just making things up. Over the past few days I’ve ported most of my work into a JavaScript library so you can actually see TP programs running directly in your web browser.
Let’s cut to the chase and do an example. I’ve written a simple TP program below that performs a few basic functions like numeric register assignment, conditional evaluation, jumping to a label and linear motion. Next to the program, I’ve created a simple debugger which gives you some insight into how the program is running and what’s happening to the numeric register.
Testing FANUC TP Programs with Ruby
I’ve written about testing before, but I still can’t get over the fact that the state of the art method for testing multi-million dollar industrial robot cells is trial and error. That’s why I’ve started working on an environment for reliably testing FANUC TP code.
I’ve basically written a Ruby gem to correctly parse, interpret and execute TP programs within a simulated runtime. With this environment I can use any of Ruby’s great testing tools to make sure the robot does what it’s supposed to do.
Never Trust an Operator
Programming robots can seem easy. You can get a robot moving around for a quick video demo in minutes. Even a tradeshow cell that needs to run perfectly for a day at a time isn’t too bad because the environment is controlled. Once you give up that control and hit the factory floor, however, the game changes. Here we have to validate everything, double-check it all and keep the robot safe when it gets misinformation.Intelligent Traversing
I’ve been working on several machine-tending applications lately. These projects tend to get complicated quickly as the robot decides where to go next based on the state of the peripheral equipment. The decision-making logic is hard enough, but getting the robot to and from each station safely can be tricky. This is how I handle it.
I start off by defining a list of stations:
- Home
- Inbound parts
- Regrip station
- Machine 1
- Machine 2
- Reject station
- Inspection station
- Outbound parts
I then define a register for saving the robot’s current location. I’ll typically also add another register for saving the previous station, just in case I need it.
Writing Maintainable TP Code
Continuing with last week’s theme of best-practices, I’d like to discuss what makes certain programs maintainable and others impossible to work with. Eliminating as much jumping as possible is a good start, but there are a few other rules I always try to follow when working on a project.
1. Keep Programs Short and Focused
FANUC’s Teach Pendant doesn’t have much screen real estate. The default editor can only display 11 lines of code (LOC), and you only get 20 in the Double or Single Wide modes. That means that if you need to troubleshoot a 200 LOC routine on the floor, you can at best only see 10% of the program at any given time.
TP Syntax Highlighting with Pygments
You have noticed that the snippets of TP code in my previous posts now have pretty colors. I created a custom fork of GitHub’s pygments.rb that adds a lexer for FANUC TP. I’m going to maintain and improve this custom fork for a while until the lexer is a bit more complete, then I will see about submitting the patch to the official Pygments project.
Here’s an example:
/PROG EXAMPLE /ATTR OWNER = ASCBIN; COMMENT = "Example TP file"; PROG_SIZE = 2651; CREATE = DATE 14-01-02 TIME 10:12:44; MODIFIED = DATE 14-01-02 TIME 10:12:44; FILE_NAME = ; VERSION = 0; LINE_COUNT = 21; MEMORY_SIZE = 3195; PROTECT = READ_WRITE; TCD: STACK_SIZE = 0, TASK_PRIORITY = 50, TIME_SLICE = 0, BUSY_LAMP_OFF = 0, ABORT_REQUEST = 0, PAUSE_REQUEST = 0; DEFAULT_GROUP = 1,*,*,*,*; CONTROL_CODE = 00000000 00000000; /APPLLINE_TRACK; LINE_TRACK_SCHEDULE_NUMBER : 1; LINE_TRACK_BOUNDARY_NUMBER : 1; CONTINUE_TRACK_AT_PROG_END : TRUE;
/MN 1: ! Example comment ; 2: ; 3: LBL[1] ; 4: R[1:Some Register]=1 ; 5: DO[1:Some Output]=ON ; 6: ; 7: CALL MY_SUBROUTINE ; 8: ; 9: IF R[2:Another register]>=3,JMP LBL[999] ; 10: ; 11:L PR[1:Some PR] max_speed CNT20 VOFFSET,VR[1] ACC R[100] ; 12: ; 13: UTOOL_NUM=5 ; 14: //PAYLOAD[2] ; 15: ; 16: F[1]=(OFF) ; 17: ; 18: WAIT .20(sec) ; 19: JMP LBL[1] ; 20: ; 21: LBL[999] ; /POS /END
Don't Jump Around
I hate to disagree with the wise words of House of Pain, but excessive jumping around is the most common issue I see when reviewing others’ TP code. Labels and jump-statements come natural in a language that doesn’t support actual code-blocks for simple if-statements. Within just a few minutes of programming, a beginner sees an
IF (...),JMP LBL[X]and decides that this is how FANUC programming is done.Randall Munroe from xkcd sums up the potential for catastrophe when using GOTO statements (TP’s JMP) in this comic:
FANUC TP Syntax Highlighting for Vim
Vim is my favorite text editor. It may take an hour or two to get over the initial learning curve (and probably years to master it), but it’s worth it. The ability to cruise through your code and change it quickly without ever touching a mouse saves a ton of time, and there are plenty of good resources for learning it.
You can grab my syntax highlighting file on GitHub. Pull requests appreciated.
Intro to FANUC Background Logic
FANUC’s Background Logic feature is basically the ladder-logic you know and love in TP Program form. These programs only consist of Mixed Logic statements (e.g. F[1]=(DI[1] AND DI[2])), and the programs are constantly scanned in the background while your robot is online, ignoring all E-Stops, alarms, etc. Depending on the complexity of your system, you may be able to skip the PLC and simply use BG Logic to control everything.Testing FANUC TP and KAREL Code
UPDATE 2014/02/27:
If you're looking for a how-to guide on FANUC KAREL programming, you're probably better off reading my Introduction to KAREL Programming article.
One of the things I love about the Ruby community is its dedication and support for testing. Having very little formal computer science education, concepts like unit testing and integration testing were completely foreign to me. After first ignoring everyone’s advice to test now and test often, I eventually forced myself to learn out of necessity and now advocate the practice to anyone who will listen. Having confidence in your code is very important, especially when your code is the only thing keeping a $100k robot from crashing through a $500k machine tool. By testing thoroughly, it’s much easier to have confidence in your code and gives you the freedom to perform large refactorings while still maintaining essential functionality.
Intelligent Part-Presence
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:
- Make sure the part is present at the fixture
It doesn’t make much sense to pick a part that isn’t there. - 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). - Move to the part
- Grip the part
- Make sure the gripper is closed and the part is present within the
gripper
If you have the IO, use it. - Retreat from the fixture
- 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. - 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.
- Make sure the part is present at the fixture
Clean Code
We’ve all been there: asked to work on a project where some or all of the programming has already been done. You pick up the teach pendant to find a program called MAIN which contains 1000 LOC with a mess of labels, old sections of code that are jumped out and may even be controlling other parts of the machine at the same time. If you’re lucky, there might be some comments or thoughtfully-labeled sections, but it’s still going to be a nightmare to work on. If only the original programmer had put some more thought into the architecture of his programming you wouldn’t have to sift through 1000 lines to fix a bug.AP_LD and RT_LD Functions
If you’ve ever worked on a robot with the Constant Path option, you’ve probably seen these funny motion segment modifiers and wondered what they were for.
AP_LD and RT_LD stand for “Approach Linear Distance” and “Retreat Linear Distance.” They guarantee the last (or first on a retreat) Xmm of a given motion segment to be linear. This can be very useful when you need to avoid an obstacle or make sure your motions are not rounding off too soon.
To ACC or not to ACC
That is the question. And the answer is “probably not.”
Once a programmer learns that the ACC instruction exists (and figures out how to make it go over 100) this is often the first place they go to make the robot faster. It’s such an easy change to make with immediate results, but there are serious consequences. I’d argue that going over ACC100 should only be done as a last resort.
