简介:Fanuc Focas 机床数据采集资料与演示代码合集,面向使用 C# 或通过 OPC UA 对接 FANUC 数控系统的开发人员、自动化工程师及工厂信息化项目团队。压缩包共 3768 个文件,整体 28.34MB,涵盖 C# 示例代码(cs)、动态链接库(dll)、C 头文件(h)、可执行程序(exe)、基础开发模块(bas),以及 XML/HTML/PDF/DOC 等多种格式的接口说明与帮助文档,可支持在 Windows 和 Linux 双平台下快速搭建 Focas 通信调试环境。已有 4159 人学习/下载。内含 Fwlib32 相关 .bas 源文件与 lib 链接库,配合示例程序和配置文档,能够帮助理解 Focas 函数调用、数据读取、报警处理、跨平台编译等关键环节;通过 demo 还可以掌握 CNC 状态读取、生产数据采集、远程监控等核心思路。资料按函数库、文档、示例、配置文件等目录组织,分类清晰,适合从入门到进阶的开发者按需查阅。 搞机床数据采集这些年,我接触最多的就是FANUC系统。不管你是要接MES、做OEE统计,还是给设备装一个远程监控大屏,只要机床是FANUC的,基本都绕不开FOCAS这套接口。我当初刚接触这个领域的时候,最头疼的不是写采集程序,而是东拼西凑找资料,官网文档全是英文且厚得像砖头,社区里能搜到的中文分享又零零散散。后来我自己攒了一套完整的东西,从开发包、编程手册到可运行的demo都整理齐了,而且实测下来Windows和Linux两个平台都能跑通。这篇就把它彻底摊开讲清楚,从原理到代码再到避坑,一次性说透。
FOCAS其实是Fanuc Open CNC API Specifications的缩写,简单理解就是FANUC官方提供给外部系统的数据访问接口。只要机床带有以太网功能,你就能通过FOCAS实时读取坐标、程序号、运行状态、报警信息、主轴负载、宏变量等等数据,甚至还能往PMC地址里写信号。相比早年靠RS232串口一个个字节去解析,FOCAS走网络、吞吐量大、稳定性好,是现在FANUC机床采集的主流方案。这篇内容适合工厂信息化工程师、设备维护人员、做机床联网项目的开发者,也适合刚入门想搞懂FOCAS是什么的人。
1. FOCAS是什么,以及为什么机床采集都绕不开它
1.1 FOCAS不是协议,是一套官方API库
很多人一听FOCAS,下意识以为它是一种通信协议。实际上它更像是一个封装好的开发工具包,官方把它发布成动态库,Windows下面叫fwlib32.dll/fwlib64.dll,Linux下面对应libfwlib32.so/libfwlib64.so。你的上位机程序调用里面的C语言函数,通过这些函数去跟CNC交互数据。底层通信细节、握手逻辑、报文封装这些,库里面已经处理好了,你不需要关心网络包长什么样。
这套库设计得很有年代感但非常稳定。函数命名有规律,cnc_开头的是CNC相关功能,pmc_开头的是PMC读写,ncl_是轮廓补偿相关,exe_是程序执行操作,nts_是网络传输服务。按前缀找功能基本不会迷路。我个人体会是这API跟Win32 API风格很像,哪怕你对机床内部结构不太懂,对着头文件里注释就能写起来。
1.2 FOCAS解决了传统采集方式的什么痛苦
早年采集FANUC机床数据,很多人用RS232串口,有的用宏输出功能,让梯形图编程人员把坐标、倍率这些数据拼成字符串往外发。这种方式不是不行,但痛点很明显:串口线距离短,抗干扰差,而且只能一对一连,速度也慢。车间里几十台机床,总不可能每台都拉一根串口线到服务器,布线都布到怀疑人生。
FOCAS走以太网之后,情况完全不一样了。一条网线进机床网卡,上位机通过交换机就能同时连几十台机床,采集周期可以做到几百毫秒甚至更低。而且能读的数据范围大了很多,除了标准坐标和程序名,PMC信号、系统参数、刀具数据、主轴负载都能通过同一个接口拿回来,这才让真正的设备数据采集成为可能。
1.3 FOCAS能采集哪些数据(一张表看全)
我列一个常用的采集项和对应函数,这对刚上手的人特别有用,你不用翻几十页英文文档去判断“这个数据能不能读”。
| 需要采集的数据 | 对应API函数 | 说明 |
|---|---|---|
| 绝对坐标、相对坐标、机械坐标 | cnc_rdposition | 返回当前各轴坐标值,数组按轴顺序排列 |
| 程序号、顺序号 | cnc_rdprgnum | 得到当前运行的程序号,也能读当前行号 |
| 运行状态(运行/暂停/停止) | cnc_rdprogstate | 状态码对应自动运行、进给保持、复位等 |
| 主轴转速与切削速度 | cnc_rdspindle | 主轴实际转速、倍率等参数都有定义 |
| 宏变量(如#500、#600等) | cnc_rdmacro | 很多机床厂把刀具寿命、工件计数存在宏变量里,靠它读 |
| 报警信息 | cnc_rdalm | 获取当前报警号和报警文本,做故障统计很方便 |
| 操作信息(倍率、进给轴方向等) | cnc_rdopmsg | 包含操作面板上的各种状态 |
| PMC地址读写 | pmc_rdpmcrng、pmc_rdpmcval | 按地址范围和数据类型读PMC寄存器,比如D地址、R地址 |
实际上FOCAS能做的事情比我表里列的多得多,光是函数就上百个,但平时做采集监控,上面这几类覆盖了90%以上的需求。剩下那些高级功能,等你真正需要了再去啃对应的章节就行。
2. 开发前的准备:拿到FOCAS开发包后这么搞才对路
2.1 一份合理的“FOCAS资料包”应该包含什么
我说的“看这个资料就够了”不是夸张,前提是资料结构要完整。一套够用的FOCAS开发包应该包含这么几块:动态库和头文件、编程手册(API参考)、demo示例代码,以及网络配置说明。有的还会附带NCGuide模拟器用于离线开发测试。
开发包里最关键的是两个目录:h目录放头文件,lib目录放库文件。Windows下打开看,一般有fwlib32.h和fwlib32.lib、fwlib32.dll,32位和64位分得清清楚楚。Linux下则是libfwlib32.so和对应32位的头文件。这里有个细节容易被忽略:头文件里定义了各种结构体,比如ODBST、ODBACT这些,它们对应不同功能函数的数据返回格式。写代码前最好把要用的结构体定义看一遍,因为不同版本的CNC系统对有些字段的填充情况不完全一样,尤其是老一点的系统,某些新字段并不会写入数据。
2.2 Windows环境下的库文件加载与工程配置
在Windows上写FOCAS程序,我一般用Visual Studio的C++控制台工程。步骤不复杂:
- 把解压出来的
fwlib32.h、fwlib32.lib、fwlib32.dll放到一个你找得到的公共目录,比如D:\focas。 - 在VS工程里配置附加包含目录为
D:\focas,附加库目录同为D:\focas。 - 在代码里加
#include "fwlib32.h",并在“链接器-输入-附加依赖项”里填fwlib32.lib。 - 编译生成exe之后,把
fwlib32.dll复制到exe同目录,否则运行时会提示找不到DLL。
这里有个最常见的坑,就是32位和64位错配。如果你的程序编译成32位,就必须挂32位的fwlib32.dll;编译64位,就必须用64位的库。混用会直接崩溃或者加载失败。另外很多老资料里的工程都是32位配置,如果你拿过来直接编译,会出现“无法解析的外部符号”这类链接错误,原因往往就是lib文件和编译目标位数不一致。
2.3 Linux环境下的编译链接与动态库路径
Linux下的做法和Windows类似,但有一个地方特别容易踩坑,就是动态库路径。头文件可以放在/usr/local/include下,库文件放到/usr/local/lib下,编译时这样来做:
gcc -o focas_demo focas_demo.c -lfwlib32 -lm如果系统找不到libfwlib32.so,你就得先执行:
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH或者把库路径写进/etc/ld.so.conf.d/focas.conf,然后运行ldconfig。我建议用ldconfig这种方式,因为如果你把程序部署成systemd服务,LD_LIBRARY_PATH不一定会被正确加载,而ldconfig只要配一次,后面就都正常了。还有一种情况是.so文件链接名带版本号,比如libfwlib32.so.1,这时需要确认libfwlib32.so这个软链是否存在,不存在就手动加一下。
写代码时,Linux和Windows的API使用方式几乎完全一致,唯一区别主要在库文件的加载路径和链接方式上,这个后面demo里我能体现得更清楚。
3. 网络配置与FOCAS连接建立
3.1 CNC端要做的几件事
写代码之前,得先保证机床那边的以太网功能是通的。FANUC的系统上,一般按SYSTEM键进入系统参数界面,里面有以太网设置菜单。要设的主要是这几项:
- IP地址:给你的CNC分配一个固定IP,比如192.168.0.10
- 子网掩码:和上位机保持一致,最常见的就是255.255.255.0
- 端口号:FOCAS默认走8193端口,特殊情况会改
- 以太网功能开关:有的系统还需要单独开启FOCAS通信许可
这里有个容易忽略的点:FOCAS连接端口和FANUC的FTP/数据服务器功能端口不是同一个。数据服务器一般是用FTP协议,跟FOCAS是两条路。你如果做机床采集,改完IP之后,最好在电脑上先ping一下CNC的IP,能ping通不代表FOCAS一定能连接(因为可能只是ICMP通了但服务没起来),但是ping不通一定连不上,排查顺序要记好。
3.2 连接代码怎么写:cnc_allclibhndl3的正确用法
FOCAS建立连接的核心函数是cnc_allclibhndl3,它有四个参数。
#include "fwlib32.h" ODBHND handle; short ret; ret = cnc_allclibhndl3("192.168.0.10", 8193, 5000, &handle); if (ret == EW_OK) { printf("连接成功\n"); } else { printf("连接失败,错误码: %d\n", ret); }第一个参数是CNC的IP,第二个是端口,第三个是超时时间,单位毫秒,第四个是返回的连接句柄。连接成功之后,所有其他函数都要用到这个handle作为第一个参数。用完记得释放连接:
cnc_freelibhndl(handle);超时时间建议不要设得太短,我第一次测试时设了1000毫秒,结果现场稍微有点网络波动就连不上;后来改成3000到5000毫秒就稳定多了。但也不要无限大,因为如果你批量连接几十台机床,某台机床关机了,你设置超时10秒,那这一轮扫描就要白白等上10秒。工程上建议用一个较长的超时做首次连接,之后采集中用短超时做重连判断,这样效果最好。
3.3 离线开发神器:NCGuide模拟器
平时开发采集程序时,最尴尬的事情就是不能一直占着车间的真机调试。FANUC官方有一个NCGuide,可以理解为CNC模拟器,它能在普通电脑上模拟0i-F等系统,而且完整支持FOCAS通信。很多人把NCGuide装在VMware虚拟机里,配好网络后,把模拟系统的IP设成固定的,你的采集程序直接对着这个虚拟机开发调试就行。
这个方案我用了很久,非常香。你可以程序改代码、断点调试、反复重连,完全不用担心影响车间生产。而且NCGuide模拟出来的数据和真机结构基本一致,等程序调通了再拿到现场部署,几乎不会出什么兼容问题。唯一注意的就是NCGuide的授权和安装包要找对版本,有些版本在Windows 10以上系统需要以兼容模式运行。
4. 双平台采集Demo:读取坐标、程序状态和宏变量
4.1 Demo想要达到的效果
我自己的这个demo当时写得很简单,但五脏俱全,完成了一个最小可用的采集链路:建立连接、循环读取数据、打印结果、断开连接。读取的数据我选了四个代表性的点:
- 绝对坐标,验证位置数据能不能读
- 程序号,验证程序管理数据能不能读
- 运行状态,验证状态类数据能不能读
- 宏变量#500,验证自定义变量能不能读
为什么选这四个?因为这四个字段基本代表了车间里最常见的采集诉求:坐标用于定位监控,程序号用于生产统计,运行状态用于报工和OEE计算,宏变量则往往藏着刀具寿命或者工件计数。把这四个学会了,其他数据照着函数名去找就行。
4.2 一段能同时跑在Windows和Linux的C代码
下面这段代码我在Windows和Linux上都编译运行过,关键地方我都加了注释。先把头文件和结构体准备好:
#include <stdio.h> #include <string.h> #include "fwlib32.h" int main(int argc, char *argv[]) { ODBHND handle; short ret; char *ip = "192.168.0.10"; long timeout = 5000; ret = cnc_allclibhndl3(ip, 8193, timeout, &handle); if (ret != EW_OK) { printf("连接失败,错误码: %d\n", ret); return -1; } printf("连接成功\n"); /* 1. 读取绝对坐标 */ ODBPOS pos; memset(&pos, 0, sizeof(pos)); ret = cnc_rdposition(handle, -1, &pos); if (ret == EW_OK) { printf("绝对坐标: "); for (int i = 0; i < pos.type; i++) { if (i < 3) { printf("%.3f ", pos.abs.data[i]); } } printf("\n"); } else { printf("读取坐标失败,错误码: %d\n", ret); } /* 2. 读取当前程序号 */ ODBPRG prg; memset(&prg, 0, sizeof(prg)); ret = cnc_rdprgnum(handle, &prg); if (ret == EW_OK) { printf("程序号: %d\n", prg.mdata); } else { printf("读取程序号失败,错误码: %d\n", ret); } /* 3. 读取运行状态 */ ODBPRO pro; memset(&pro, 0, sizeof(pro)); ret = cnc_rdprogstate(handle, &pro); if (ret == EW_OK) { printf("运行状态代码: %d\n", pro.prog_state); } else { printf("读取运行状态失败,错误码: %d\n", ret); } /* 4. 读取宏变量#500 */ ODBM acro; memset(&acro, 0, sizeof(acro)); ret = cnc_rdmacro(handle, 500, 0, &acro); if (ret == EW_OK) { printf("宏变量#500: %d\n", acro.cdata); } else { printf("读取宏变量失败,错误码: %d\n", ret); } cnc_freelibhndl(handle); return 0; }注意ODBPOS结构体里有一个type字段表示轴数,循环输出坐标时要以它为准,不要写死三轴。cnc_rdprgnum读出来的程序号,在有的系统上如果你没选程序,会返回0,这是正常的。运行状态代码的语义后面会列一张对照表。
4.3 编译运行与结果解读
在Windows下,用VS环境时把这段代码放进新建的控制台工程就行。如果命令行编译可以用cl命令,但需要提前把fwlib32.lib、头文件和dll路径配置好。推荐还是用VS工程管理,省心。
在Linux下,假设代码文件叫focas_demo.c,库和头文件都放到标准路径后:
gcc -o focas_demo focas_demo.c -lfwlib32 -lm如果编译时报找不到头文件或库,先确认头文件路径和库路径是否在/usr/include、/usr/local/lib下。
运行起来后的输出长这样:
连接成功 绝对坐标: 123.456 234.567 -89.012 程序号: 1234 运行状态代码: 3 宏变量#500: 18这里有个体验细节要提醒:坐标值的单位是毫米,但如果你机床用了公制英制切换,数值会跟着变,上位机最好加一个公制标识位来区分。程序号如果显示为0,可以先在机床面板上手动加载一个程序再测试。运行状态代码里面,常见的是0(停止)、1(运行)、3(进给保持)这些,具体对应关系可以查FOCAS头文件里的宏定义。
5. 实操期间最常踩的坑与排查技巧
5.1 连接层的问题,用一张速查表解决
开发FOCAS采集,最让人抓狂的不是代码写错,而是连接建立不起来。我在这个坑里爬过很多次,现在把典型的现象和对策整理成一张表,你遇到同样问题可以直接照着查。
| 现象 | 可能原因 | 解决办法 |
|---|---|---|
| ping不通CNC的IP | 网线没通、IP网段不一致、CNC网口是坏的 | 先查物理链路,再核对IP和掩码 |
ping通但cnc_allclibhndl3失败 | CNC以太网FOCAS功能未开启、端口被改 | 检查系统参数里是否有“以太网功能有效”选项 |
| 连接初始化报错为负值 | 端口号错误、CNC上装了防火墙策略 | 确认默认8193端口,联系现场电气查是否有安全软件 |
| 连接后偶发性断开 | 超时时间太短、交换机端口有STP隔离等 | 把超时加到3000ms以上,检查交换机端口模式 |
| Windows下运行提示找不到DLL | DLL没放对路径、位数不匹配 | 把fwlib32.dll放到exe同目录,按程序位数重新检查 |
5.2 读取函数返回错误码的排查思路
FOCAS的每个读取函数都会返回一个short类型的错误码,EW_OK代表0,表示成功。如果返回非0,不要急着改代码,先把错误码查一下。头文件里有详细的宏定义,常见的有EW_LENGTH表示数据长度错误,EW_PROT表示协议错误,EW_BUSY表示CNC忙。
产品环境里最常见的就是EW_BUSY,因为机床本身在做实时控制,你采样频率如果设得太高(比如50毫秒一次请求),CNC可能来不及响应。通常把采样周期放到200毫秒以上就很少遇到这个错误码了。如果读取的对象是宏变量,还要注意宏变量编号是否真的被机床厂启用了,像#500这种属于空变量时,读出来可能就是0,要对照机床PMC逻辑去确认才行。
5.3 Linux部署时的几个独有坑
Linux上的部署坑比Windows多一些,最常见的是:
.so库的软链接缺失。有的FANUC库发出来的时候文件名带版本号,比如libfwlib32.so.1,但编译时就缺一个libfwlib32.so软链。LD_LIBRARY_PATH没生效。如果你用systemd做开机自启,环境变量必须写进Environment=或者用ldconfig配置生效。- 32位库在64位系统上运行。如果你拿到的库是32位的,你的编译器和系统就得配置多架构支持,否则加载.so文件时直接失败。这个坑我在ARM工控机上踩过,当时折腾了一上午,最后才发现要装
lib32gcc之类的兼容库。 - 还有一种很特殊的情况,就是用了
dlopen延迟加载的方式。有的采集程序为了热插拔,不直接-lfwlib32链接,而是在运行时动态加载,这时必须自己管理句柄和函数指针,处理起来要复杂一些。如果你不是特别需要热更新,建议用常规链接别折腾。
5.4 一个经常被忽略的经验:不同系统版本的差异
最后说一个我在现场踩了多次才领悟到的经验。FANUC不同时期出的系统,比如0i-C、0i-D、0i-F,它们对FOCAS的API兼容性其实相当不错,大部分程序在真机上拿过去就能编译运行。但有一个地方不一样:各个机床厂家对宏变量和PMC地址的定义完全不自带,你需要跟电气工程师拿“PMC地址分配表”,对照表才能把#500到底对应什么含义搞明白。同型号的机床,只要来自两个不同厂家,逻辑几乎必然不同。有一次我在两台上看起来一样的机床上采集刀具寿命数据,结果一个藏在#501,一个藏在#531,完全对不上。
所以做FOCAS采集,不要一上来就写代码,先做两件事:确认机床FANUC系统版本,拿到该型号的宏变量和PMC地址规划表。这两样东西拿到手,你后面写采集程序的时间能省掉一大半。连不上、读不到、数据异常,大多数情况不是API不会用,而是现场信息没收集全。
我个人实际做下来的体会是,FOCAS这套东西本身是稳定的,它就是一层很薄的API封装,真正决定项目成功率的,是你对现场机床的了解程度和部署时的细心程度。写一个Hello World Demo半小时就能跑通,但做到几十台机床稳定运行,关键在于每一台机床的网络、系统版本、参数配置都要有专门的记录。做采集前,先把现场每一台机床的信息表建好,再动手写代码,这比我一开始那种“先跑通Demo再说”的做法靠谱太多了。希望这份整理能帮你少走几步弯路,如果后面遇到具体问题,再照着函数手册和它的返回值去定位,FOCAS没那么神秘。
本文还有配套的精品资源,点击获取