简介:这份入门学习文档面向工业机器人工程师及自动化学习者,系统讲解FANUC机器人KAREL编程的基础知识,帮助读者从零理解KAREL与TP程序的差异、语言基本结构及程序执行流程。文档内容涵盖PROGRAM/END框架、变量声明规则、关键字限制,并详细演示了在ROBOGUIDE仿真环境中添加KAREL软件包、修改KAREL_ENB变量、创建源文件、编译生成.PC文件以及手动执行程序的完整操作。全包仅含1个docx文件,大小5.63MB,文字说明配合操作节点梳理,便于边看边练。目前已有2674人学习,适合刚接触FANUC机器人KAREL编程、希望快速搭建测试环境并掌握基础程序编写的读者,为后续进阶开发打下扎实基础。
1. 从TP程序到KAREL,为什么要学这门“看起来像Pascal”的语言
做FANUC机器人集成的朋友,应该都有这种体会:示教器上的TP(Teach Pendant)程序用久了,总觉得有点“憋屈”。IF判断、FOR循环、寄存器运算、位置偏移这些,TP指令里都有,但一旦逻辑复杂起来,程序的可读性和维护性就会直线下降。我自己接过的项目里,三四百行的TP程序见过太多了,到后面想去改一个分支逻辑,光是翻屏找跳转标签就要花半天。
而KAREL这门语言,恰恰是来解决这个问题的。它是FANUC机器人控制柜内置的一种高级编程语言,语法结构上有点接近Pascal——有类型声明、有函数、有结构化控制流,用起来比TP程序“像软件工程”得多。它能干很多TP程序不好干的事:
- 读写系统变量和执行后台逻辑,不需要靠TP里的后台指令硬撑;
- 处理字符串、文件读写、数组运算,TP写起来想砸示教器,KAREL用几十行代码就能搞定;
- 集成视觉、通讯、自定义界面、远程诊断,KAREL是绕不开的一环;
- 程序的可读性、模块化能力、复用性,都比TP程序高出一个量级。
标题里标注了“入门学习(1)”,所以这篇内容定位很明确:写给从未接触过KAREL的读者,但我默认你至少会用TP示教器编写过基础程序,知道什么是指令、什么是寄存器、什么是位置数据。如果你连TP都还不太熟,建议先去摸一遍基础操作再回来,否则有些对照关系体会不深。
这一篇我会从开发环境建起、程序骨架、变量与系统参数、编译下载运行、查错调试这条路走一遍,最后给你一套可以直接拿去试的示例程序结构。KAREL的资料在中文社区本来就不算多,大部分要靠啃英文手册,所以我会尽量用大白话把一些关键机制讲透。
2. 开发环境搭建:KAREL不是直接用记事本写完就完事的
先说结论:KAREL程序不能在示教器上直接编写(至少标准方式下不行),它需要在一台PC上用文本编辑器写好源代码,然后在RoboGuide里编译生成程序文件,再灌到控制器里运行。很多第一次接触KAREL的人都会卡在这一步——因为FANUC的官方手册默认你已经知道这个流程,实际跳过了不少细节。
2.1 必备软件与版本选择
你至少需要两样东西:
- RoboGuide:FANUC官方的离线仿真与编程软件。KAREL的编译器以插件形式集成在RoboGuide里面,没有它,源文件就是一堆没用的纯文本。
- 一个文本编辑器:Windows自带的记事本就能用,但我强烈建议用支持语法高亮的编辑器,比如VS Code、Notepad++。KAREL没有官方的高亮插件,网上能找到用户做的,聊胜于无,起码变量名和关键字能区分开。
RoboGuide版本上,我个人的经验是“能用新用新,但不追最新”。新版本对老控制柜的兼容性反而可能出问题,比如R-30iB柜子用V8.3左右的RoboGuide就很稳,R-30iB Plus和R-30iC则推荐V9.x以上。你手头项目用的是哪个控制柜固件版本,就选配套的RoboGuide版本,这是最省心的做法。
2.2 KAREL源文件的后缀名与编码问题
KAREL源程序的标准后缀是.kl(KAREL Language),这个没有商量的余地。编译后生成的是.pc文件(P-Code),扔到控制柜的FR存储区里直接执行。
编码上有个特别容易被坑的地方:KAREL编译器对源文件的编码格式很敏感。用记事本另存的时候,默认可能是带BOM的UTF-8,结果编译直接报错——有些版本就是认不得带BOM的UTF-8。我个人的建议是:全程使用纯ASCII字符写代码,字符串里也别放中文。
这一点真的很重要。我知道有人会想着“我注释里写点中文方便看代码”,但在KAREL这个环境下,中文注释在编译阶段大概率会变成乱码报错,不仅没方便,反而添乱。真要看注释,用拼音或者英文都能接受——反正KAREL的注释功能和TP程序里的注解其实是两回事,这点后面会细说。等你把逻辑跑通了,真想维护一份中文注释,就把注释单独放到项目维护文档里,别跟源码较劲。
2.3 RoboGuide中新建KAREL工程的路径
打开RoboGuide,创建或打开一个工作单元(Workcell)之后,KAREL相关操作集中在菜单栏中的“Utilities”一项里。新建KAREL源文件的入口是:Utilities -> KAREL,之后你会看到一个源文件管理对话框,在这里可以新建、编辑、编译、加载源文件。
需要注意,RoboGuide里新建的KAREL源文件会存放在工作单元的项目文件夹下,但编译器在编译时会有“当前工作目录”的概念,如果路径里有奇怪的特殊字符,个别版本会抽风。为了省事,我习惯把工作单元建在纯英文路径下,例如C:\Workcells\DemoCell,别用中文路径和空格,否则后面有你折腾的。
3. KAREL程序的标准骨架:从Hello World到看懂别人写的程序
KAREL程序看起来古板,但正因为古板,它的结构非常规整。只要你看过一次骨架,之后读其他KAREL源码就会轻松很多。
3.1 最典型的一段程序结构
下面这个例子是一个标准的带入口点的KAREL程序骨架:
PROGRAM hello_demo VAR msg_string : STRING[20] counter : INTEGER pos : XYZWPR BEGIN msg_string = 'Hello FANUC' counter = 0 WRITE('IR') FOR counter = 1 TO 3 WRITE(msg_string, CR) ENDFOR GET_POSITION(pos) WRITE('Current Position: ', pos.x:8:3, ', ', pos.y:8:3, ', ', pos.z:8:3, CR) END hello_demo程序名写在PROGRAM后面,并且END后面要再写一遍同样的名字,首尾呼应,这是KAREL的硬性语法要求。VAR和BEGIN之间的部分是变量声明区,类型包括字符串、整数、位置变量等。
WRITE指令在这里相当于TP程序里的“消息显示”,输出到示教器屏幕或日志里。CR是回车换行的常量,相当于写了一段内容后换行。GET_POSITION(pos)这个API调用能把机器人当前位置的坐标值读出来,存在位置变量pos里。注意输出格式pos.x:8:3的意思是:变量小数点前占8位,小数部分保留3位。这种格式化输出在TP程序里基本做不到,算是KAREL的实用功能之一。
3.2 注释和TP程序的巨大差别
用过TP程序的人都会在每条指令后面加中文注释,美其名曰“看代码方便”,这在TP的语境里没问题。但KAREL不是这么用的——KAREL里的注释是给编译器看的信息,写在两个特殊字符之间,不会显示在执行过程中:
WRITE('Hello', CR) -- 这是KAREL的注释KAREL的注释有块注释和行注释两种:块注释是/* ... */,行注释是--。注释里别放中文,原因前面说过了,编译不支持容易报错。更重要的是,KAREL的注释不能用来在程序执行时“弹提示给操作工”,如果你想要那种效果,得用WRITE指令主动输出,或者调UI相关的API,跟TP里的注解完全是两码事。
3.3 变量声明的几个硬性规定
KAREL里所有变量都要先声明后使用,这一点跟Pascal一脉相承。变量声明的位置在VAR区块内,程序执行期间不能随便新增变量。常见的类型有:
INTEGER:整数,做计数器、循环控制是最常用的;REAL:浮点数,注意在KAREL的写法里是REAL,不是FANUC TP里的R[];STRING[n]:定长字符串,方括号里是最大长度,这个长度要提前估好,太短会截断;BOOLEAN:布尔值,只有TRUE和FALSE;XYZWP、XYZWPR:位置变量,一个存姿态角、一个存姿态角加外部轴值;ARRAY[1..n] OF ...:数组,KAREL的数组起始下标可以自定义,例如ARRAY[0..9] OF INTEGER就是10个整数。
有个细节很多人会忽略:KAREL的字符串是定长的。你声明STRING[20],然后往里塞40个字符,超出的部分会直接截掉,而且不会给你任何警告。在写通讯解析、文件解析这类程序时,一定要先想清楚最长可能有多长,宁可多留余量也不要抠门。
4. 系统变量与$SBR[]:这门语言真正值钱的地方
如果只是写点简单的逻辑,TP程序其实也能凑合。KAREL真正不可替代的地方在于,它能直接访问控制器的系统变量(System Variables),读取和修改机器人系统的底层状态。
4.1 $PARAM、$SBR与自定义参数的存取
FANUC控制器的内部状态大量存储在系统变量里,它们以$开头,例如$SCR_GRP[1].$CART_POS(当前笛卡尔坐标)、$DI[1](数字输入信号)等等。
在KAREL里,我们可以通过GET_VAR和SET_VAR这两个API函数,读取和修改系统变量。更关键的是,FANUC提供了一个用户自定义参数区叫做$SBR[],下标从1开始。你在KAREL侧写入$SBR[1],在TP程序里通过系统变量界面也能看到同一个值,两边互通的,这个机制在工程上特别实用。
举个例子,我们可以定义一个程序,从$SBR读取配置参数,用于决定某段逻辑的开关:
VAR enable_flag : INTEGER GET_VAR(1, '$SBR[1]', enable_flag) IF enable_flag = 1 THEN WRITE('Feature enabled', CR) ELSE WRITE('Feature disabled', CR) ENDIF这里面的第一个参数1是任务号或组号,大多数情况下控制器里程序跑在任务1,但也有后台任务、前台任务等不同任务环境,后面聊到任务机制时会细说。
有个单独的实践点:TP程序里面同样可以读$SBR[n],这是系统变量访问的通路,完全无冲突。这给我留下一个很有价值的工程模式:用KAREL程序把复杂的逻辑计算结果写进$SBR,TP程序只做简单的条件判断和动作执行。这样两边的关卡各司其职,逻辑复杂度集中在KAREL侧,调试时更清晰。
4.2 $SBR[$PARAM[47]] 这种写法到底是啥意思
近期FANUC机器人相关社区里,$SBR[n].$PARAM[47]这个写法被反复提及,很多入门的朋友卡在这里。拆开说:
$SBR[n]:SBR数组的第n个子元素,每个SBR元素结构内部其实可以嵌套多个成员;.$PARAM[47]:是用户参数区里的第47号参数,也就是这个SBR结构体中的一个字段,按官方文档的描述,它通常被用于存放一些自定义的“工具编号”或“工艺编号”。
$PARAM[47]单独用来跨任务传消息很常见,它的访问权限已经开放给了TP指令,所以你会看到很多人的TP程序里直接有$SBR[1].$PARAM[47]这种指令——Source一侧读取,Destination一侧写入,达成“共享内存”的效果。
在KAREL里访问它同样没问题,格式稍有一点区别:
GET_VAR(1, '$SBR[1].$PARAM[47]', tool_num)如果你看到别人程序里有类似写法但不知道参数含义,最好的方式是进控制柜菜单看系统变量——菜单路径是MENU -> SYSTEM -> Variables,搜SBR,然后展开看成员结构和当前值,直观明了很多。自己项目里要定义跨程序的参数约定,尽量写好文档,不然半年之后你自己都忘了47号参数是干嘛用的。
4.3 GET_VAR与SET_VAR的实际用法
GET_VAR和SET_VAR这两个函数是KAREL访问外部变量的双通道,上至系统变量,下至机器人组的属性,都可以通过它们来读写。基本语法:
SET_VAR(task_id, var_name, value) GET_VAR(task_id, var_name, variable)其中task_id是任务编号,如果不确定,填1通常都能读到默认任务环境下的系统变量。var_name是变量名的字符串,要用单引号括起来。
工程上我最常用的几个场景:
- 把视觉系统算出的偏移量写进
$SBR,让TP程序判断是否执行抓取补偿; - 读取机器人伺服状态、操作模式、程序运行状态,用作上位机的状态映射;
- 修改某些允许在运行中调整的速度倍率参数,做成“软开关”效果;
- 跨KAREL任务传递数据,比如多任务里一个后台任务做数据采集,一个前台任务做逻辑动作。
这里必须强调一下:能读的变量很多,但可写的变量是有权限限制的。有些$开头的系统变量只读,强行去写会报错;有些变量虽然能写,但写完后立刻生效,可能带来安全隐患(比如修改速度倍率)。我建议你在正式写SET_VAR之前,先用GET_VAR读一遍确认变量存在性和类型,再决定怎么处理。
5. 在真实控制器上跑通第一个KAREL程序:从编译到下装
用RoboGuide写好代码、编译通过之后,还得把程序文件弄到真实控制器里才能跑。这个过程看起来简单,但有一点小陷阱值得花一节说清楚。
5.1 编译流程与编译输出
在RoboGuide的Utilities -> KAREL界面里,选择源文件后点“Compile”,编译器会生成对应的.pc文件。如果语法有错,信息区会给出错误行号和描述,提示通常比较直白,常见的有:
Missing END:忘记写结束关键字或者程序名不匹配;Undeclared variable:变量没声明就使用;Type mismatch:类型不匹配,比如把字符串赋给了整数变量;Expected ';':分号丢失。
KAREL的语句结尾不一定都加分号(它跟Pascal一样,有些语句不用),所以只看报错信息不一定马上知道问题在哪。我的调试习惯是:先检查所有关键行的ENDIF、ENDFOR这类块结束关键字是否成对,再检查程序名首尾是否一致。这两个地方出错概率极高。
5.2 下装到控制柜的两种常见路径
编译生成的.pc文件,最终要通过U盘、网络FTP或RoboGuide在线连接灌入控制柜。操作路径通常是:
- 把
.pc文件传到控制柜的FR分区(通常是FR:目录下,也有FR1:之类的不同分区)。 - 在示教器上进入文件管理界面,找到该文件并选中执行,或者在程序选择界面找到它直接运行。
注意一个机制:KAREL程序有两种运行模式。一是直接运行(相当于前台TP程序);二是被TP程序通过RUN指令调用,作为后台逻辑驻留执行。如果你是第一次下装KAREL,建议先直接运行最简单的Hello World,能从示教器屏幕上看到消息输出,再进阶玩别的。
5.3 一个高频报错:INTP-xxx状态码与恢复套路
KAREL程序运行过程中报错,屏幕上的状态码基本都是INTP-xxx的格式,一看是梯形结构“INTP”,多半就是程序运行类错误。常见的比如:
INTP-294:程序被暂停或中止,通常是人为停止了;INTP-334:试图访问不存在的变量或数组越界;INTP-384:程序执行了非法的算术操作;INTP-348:字符串长度溢出或格式错误。
恢复操作的通用套路是:在TP程序选择界面把报错的KAREL程序状态重置(选中它然后按FCTN -> 复位),或者直接在示教器上的程序报警清除按钮复位。如果反复报同样的错,大概率是你对变量和寄存器的使用范围判断错了,去查源码里所有数组下标和字符串操作的地方。
5.4 实机调试的一个实用技巧:用WRITE代替断点
很多人第一次调KAREL会找“断点”、“单步”功能,但RoboGuide的在线调试对KAREL的支持并不算完善,远不如通用IDE那么顺手。我的做法很土但很有效:在关键位置插入WRITE语句,把变量值打出来,以此代替断点。
WRITE('DEBUG counter=', counter:4, ' enable=', enable_flag:3, CR)这个输出会出现在示教器屏幕底部或日志区,虽然不如IDE的Watch窗口优雅,但在没有外设的情况下,这是最不挑环境也最好用的定位手段。调完逻辑呢?别忘了一句句删掉这些调试输出,干净生产版本不要带一堆调试打印,一是影响执行效率,二是屏幕刷屏干扰操作工。
6. KAREL语言的核心语法点:跟TP程序完全不同的思维方式
从TP转到KAREL,最难的不是语法本身,而是思维方式。TP程序写多了,脑子里全是“指令序列 + 跳转”,KAREL更重要的是“数据结构 + 控制流 + 模块化”。
6.1 条件分支、循环与控制流
KAREL支持IF...THEN...ELSE...ENDIF、FOR...ENDFOR、WHILE...ENDWHILE、REPEAT...UNTIL...ENDREPEAT这些结构。看起来不值一提,但跟TP程序相比这是质的飞跃。
一个典型的例子:TP里的“等待条件满足”,你通常会写一个等待指令配一个置位标志,但在KAREL里可以这样:
WHILE (counter < 10) AND (NOT abort_signal) DO counter = counter + 1 DELAY(100) ENDWHILE这种写法在TP里要跳转标签满天飞,在KAREL里就是一个逻辑块的事。更重要的是,KAREL支持EXIT跳出当前循环,支持RETURN从函数返回,这些结构化能力让复杂逻辑的代码量缩小一半以上,可读性却翻倍。
6.2 函数与过程的定义:写一次,到处用
TP程序没有“函数”的概念,子程序(TP里的Call)本质还是一段顺序指令,参数传递要靠寄存器约定。KAREL的ROUTINE(过程)和FUNCTION(函数)则正规得多。
定义一个函数计算两个数的平台均值?如下:
PROGRAM calc_demo VAR a : REAL b : REAL avg : REAL ROUTINE compute_avg(v1 : REAL; v2 : REAL) : REAL BEGIN RETURN (v1 + v2) / 2.0 END compute_avg BEGIN a = 10.0 b = 20.0 avg = compute_avg(a, b) WRITE('Average=', avg:8:2, CR) END calc_demo有些KAREL版本里,步带返回值的函数写法是ROUTINE compute_avg(...) : REAL,RETURN返回结果。参数名前面可以加IN、OUT、INOUT来声明输入输出方向,但默认不写就是输入参数,简单场景不用管方向修饰。
我建议你把项目中重复用到的数学运算、字符串处理、坐标换算这类代码封装成KAREL的ROUTINE或FUNCTION,这样长期积累下来的代码库,跨项目复用会越来越值钱。干过几个项目之后你会发现,KAREL程序的开发效率瓶颈往往就在“轮子太少”。
6.3 位置数据与运动控制的交互
KAREL程序本身不太适合做那些高频、实时的轨迹运动控制——那是TP程序和运动指令的强项。但KAREL可以读取当前位置、规划目标位置、调用位置寄存器,这些操作能辅助完成不少工作。
比较典型的用法是:KAREL程序计算出一个目标偏移量,然后把它写入位置寄存器(PR),再由TP程序去执行对应的运动指令。这个“计算在KAREL、运动在TP”的配合方式,是现场项目里被验证过无数次的稳妥架构。
GET_POSITION(current_pos) target_pos = current_pos target_pos.x = current_pos.x + 50.0 -- X方向偏移50毫米 SET_VAR(1, '$PR[1]', target_pos)从$PR[1]读取和写入位置数据,都可以通过GET_VAR、SET_VAR完成。前提是你在系统配置里把PR变量按XYZWPR格式定义好了,否则格式匹配不上会报类型错误。这种写法最大的价值是,偏移量的计算逻辑可以很复杂,但示教器端的TP程序就一行:L PR[1] 100mm/sec FINE,干净利落。
7. KAREL学习路线与资料检索经验:避坑比什么都重要
最后聊聊怎么继续往下学。FANUC官方的KAREL参考手册是英文原版,内容详尽但读起来很劝退。中文资料又少,而且很多是零散问答,质量参差不齐。结合我自己走过的弯路,给你一套省时间的路线。
7.1 第一优先级:官方Reference Guide,但别从头读到尾
FANUC的KAREL Reference Guide有几百页,从头读到尾既没效率也没必要。我建议把它当“字典”用。你要快速过一遍“变量类型”、“控制流”、“内置函数列表”,明白有哪些东西可用,然后用到什么查什么。
内置函数列表一定要通读一遍,很多人不知道KAREL内置了一堆字符串处理、数学计算、文件读取、通讯相关的API函数,导致他们用最笨的方法硬写功能。比如字符串转数字、数字格式化输出,内置函数里面有现成的,根本不用自己去造轮子。
7.2 利用示例程序和别人的源码反向学习
RoboGuide安装目录下自带不少KAREL示例程序,路径通常在你的RoboGuide安装目录下的Examples文件夹里。这些示例代码是官方工程师写的,整体风格规范、逻辑清晰,是绝佳的学习材料。
另外,如果你能在公司内部或行业社区里搞到别人已经调试通过的项目源码(脱敏过的),仔细读一遍比自己闷头写十个程序都管用。看别人怎么设计变量、怎么规划Routine、怎么处理异常,这些“行业惯例”是在手册里学不到的。
7.3 按“最小可用”思路做练习,别一上来就搞大工程
入门阶段,我建议你给自己定一串“最小可用”练习,每个都能在半小时内完成:
- 写一个程序,读取当前坐标并输出到屏幕;
- 写一个程序,用
FOR循环从1加到100,把结果写进$SBR[1]; - 写一个程序,定时读取某个数字输入信号,并把它映射到
$SBR[2]; - 写一个程序,从文件读取一行配置,根据内容执行不同的FLAG设置。
这些练习看着不起眼,但覆盖了变量、系统变量、循环、API调用、数据路由等核心能力。练完之后,你再看项目里的KAREL代码,基本不会再有“读天书”的感觉。
7.4 我踩过的最痛的一次坑:后台任务环境下的GET_VAR语义差异
单独把这个事拎出来说。KAREL程序如果作为后台任务运行(由TP指令RUN启动),它的任务 ID 跟前台任务不同。你在后台任务里调用GET_VAR时,如果还写GET_VAR(1, ...),在很多固件版本上读到的不是你想的那个前台变量,甚至可能读不到。
正确做法是,尽量用GET_VAR(TP_TASK, ...)或GET_VAR(0, ...)这类不受特定任务号限制的写法,或者提前确认后台任务上下文中的变量可见性。这个坑一次就能浪费你一下午,我摔过一次之后,写后台任务代码时第一件事就是确认任务ID语义。
8. 第一篇该收在哪:搭好这个骨架,后面就能往里填东西
写到这里,KAREL入门的第一块骨架就算搭起来了:环境装好了、写得出第一个程序、能编译下装、敢动系统变量了。说实话,第一篇在你真正写完那5个小练习之前,“看会了”和“会用了”之间还有一条大沟,跨过去的方式只有动手。
接下来有两个方向可以继续深入,你按自己的项目需求选。如果接下来要处理通讯、视觉数据对接这类偏“上位机交互”的活,下一篇你可以关注KAREL的文件读写和Socket通讯部分;如果要处理的是和TP程序的复杂协同、多任务调度,那重点可以放在任务机制和信号交互上。
我个人还是那句话:KAREL算不上你见过最现代的语言,写起来甚至有点老气,但在FANUC机器人这套封闭生态里,它是你从“会点程序”走向“真能搞定复杂功能”的最靠谱突破口。上手时多踩几个坑没关系,把前面那套调试流程跑熟了,后面的路就顺了。
本文还有配套的精品资源,点击获取