发那科机床联网,官方路径只有一条:FOCAS 库(Fwlib32)。网上例子能跑通"连接 + 读一个程序号",但真到车间里,8 台机床同时连、要读主轴负载和件数、夜班还要不断线,坑全在例子之外。南京这家模具加工厂 8 台机床(6 台 0i-MF、2 台 31i-B),我们从拉网线到看板上线用了三周,这篇把项目档案、采集点表和四个实打实的坑都记下来。

项目档案:先摸清每台机床的"家底"

FOCAS 不是插上网线就能用。开干之前必须逐台确认三样东西:系统版本、以太网板卡、开放权限。这项目进场第一天我们就是拿着表逐台登记:

机床构成6 台 0i-MF(加工中心)+ 2 台 31i-B
通信方式以太网卡 FOCAS2,端口 8193
采集机车间工控机一台,C# .NET 4.8 轮询 8 台
采集点状态/转速/负载/件数/程序号/报警,共 14 点/台
刷新周期状态类 500ms,计数类 5s
FOCAS 版本Fwlib32 对应机床 CNC 版本向下兼容

有个前提容易被忽略:FOCAS 功能需要机床参数打开。0i-MF 上要让厂家或机修确认以太网嵌入板参数已设(IP、端口、FOCAS 有效),部分老机床这个选项是收费功能,没开通的话你 ping 得通、8193 端口就是连不上。我们项目里有一台二手机床,最后是发那科服务人员上门刷了参数才放开。

连接怎么建:一个句柄一台机,用完必须还

FOCAS 的调用模型很"C 语言":先 cnc_allclibhndl3 拿一个句柄(handle),之后所有读写都带这个句柄,程序退出前必须 cnc_freelibhndl 释放,否则句柄泄漏,机床侧连接数被占满,谁都连不上。C# 侧用官方 fwlib32.cs 的 P/Invoke 封装(或 Fwlib32.dll 自己 DllImport):

[DllImport("Fwlib32.dll", CallingConvention = CallingConvention.Cdecl)]
static extern short cnc_allclibhndl3(string ip, ushort port, int timeout, out ushort handle);

[DllImport("Fwlib32.dll", CallingConvention = CallingConvention.Cdecl)]
static extern short cnc_freelibhndl(ushort handle);

ushort h;
short ret = cnc_allclibhndl3("192.168.20.11", 8193, 3, out h);
if (ret != 0)   // EW_OK = 0 才算成功,非0全是错误码
    throw new Exception($"FOCAS连接失败, 错误码 {ret}");
try {
    // ……所有 cnc_xxx(h, ...) 读写都在这个生命周期里
}
finally { cnc_freelibhndl(h); }   // 必须释放,别等GC

▲ 8 台机床就是 8 个句柄,建议每台机床封装成一个 MachineSession,内部管自己的连接、轮询和重连。

到底能采到什么:四类数据各有各的读法

FOCAS 没有一个"读所有数据"的万能函数,你要的每类数据都有对应 API,而且同一种数据在不同系统版本上读法可能不一样。这是这个项目实际用的采集点表:

采集内容FOCAS API数据位置说明
系统/版本信息cnc_sysinfoODBSYS 结构开机时读一次,确认机型和版本
主轴实际转速cnc_actsODBACT实际 S 值,加工监控主用
主轴负载/伺服负载cnc_rdspdlname / cnc_modal窗口数据刀具磨损、断刀判断靠它,不同版本路径有差异,需现场对信号表
当前主程序号cnc_rdprgnumODBPRO正在跑的 O 号,对应工单/零件号
加工件数cnc_rdpmacro宏变量 #3901 / #500系件数在不同机床上宏号不同,常见 #3901(要求件数)和厂家自定义保持宏变量
运行/报警/进给保持状态cnc_statinfoODBSTaut/rst/run 等位,自动判定"运行/待机/报警"三态
报警号与报警文本cnc_alarm2 / cnc_rdalmmsgODBALMMSG报警代码+中文文本,直接进看板报警栏
PMC 内部信号cnc_pmc_rdmG/F/X/Y 地址F 地址是 CNC→PMC(机床输出给逻辑的状态),读润滑、气压、刀库信号走这里
件数这个点最磨人。它不是标准 API,而是存在宏变量里,宏号还因机床厂家而异——有两台机床加工程序里用 M30 结束时 #520=#520+1 自己计数,另外几台件数在系统的部件数计数器里。我们最后是每台机床让操机师傅调出计数器界面,对着宏变量表逐个试读确认宏号,再写进配置。这种活文档里查不到,必须到现场。

四个坑,个个都耽误过工期

坑 1:FOCAS 连接数有硬上限,多开程序直接互踢
0i 系列很多配置只允许 1~2 个 FOCAS 客户端连接。调试期我们两台电脑同时连着一台机床测试,后连的把先连的踢掉,症状是"随机断线",查了半天才发现是自己人踢自己人。
解法:全车间只部署一个采集服务(工控机上常驻),所有看板、MES 都从这个服务取数,杜绝多个客户端直连机床。
坑 2:64 位程序加载 32 位 Fwlib32 直接 BadImageFormatException
FOCAS 库分 32 位(Fwlib32.dll)和 64 位版本,跟项目编译平台必须严格一致。我们项目默认 Any CPU 在 64 位系统上跑 64 位,加载 32 位 DLL 直接起不来。
解法:项目显式编译成 x86 配 32 位库(最省事,老库资料也最全),或 x64 配 64 位 FOCAS 库,库的位数、生成平台、DLL 拷贝目录三者对齐
坑 3:夜班断连后再也不恢复——句柄没重建
机床夜班关机重启后,原来的句柄失效,API 开始返回 EW_RESET(-8)或 EW_SOCKET 错误。初期代码只做了"读失败跳过",结果机床早上开机了数据也不回来,要人工重启软件。
解法:封装健康检查——连续 3 次返回连接类错误码,先 cnc_freelibhndl 释放旧句柄,再 cnc_allclibhndl3 重新建连,重建成功前该机床状态显示"离线",不影响其他 7 台。
坑 4:轮询太勤,机床操作面板开始卡顿
调试时图新鲜 100ms 轮询全部 14 个点,老 0i-MF 的界面操作出现轻微迟钝——FOCAS 请求也要占 CNC 侧资源。
解法:按点分周期:状态/转速 500ms,件数/程序号 5s,系统信息开机读一次。8 台机床错峰轮询(每台错开 60ms 启动),实测对机床操作零影响。

上线节奏:三周是怎么排的

  • 第 1 周:通电联网布网线、逐台设 IP、确认 FOCAS 参数开通,8 台全部 8193 端口可连——比预想久,二手机床参数那台耗了两天。
  • 第 2 周:点表对齐逐 API 试读,重点是宏变量件数和 PMC 负载信号,每台机床出一张确认的点表,机修师傅签字。
  • 第 3 周:采集服务 + 看板8 个 MachineSession 常驻轮询、断连重建、数据入库,车间看板显示三态(运行/待机/报警)+ 当日件数 + 当前程序号。

上线后效果最直接的是稼动率:以前靠操作工填纸票统计,8 台机床一天实际切削时间没人说得清;现在状态位自动记录,一周数据出来,两台机床待机时间占了 40%,老板当场就排了排产整改。

给准备做发那科联网的两点建议

第一,进场前先远程确认机床系统版本和 FOCAS 授权,把 FOCAS 手册版本和 CNC 版本对上,别等网线拉完才发现端口没开;第二,件数、负载这类"活点"预留现场调试时间,它们不在标准 API 的舒适区,宏号和 PMC 地址一台一个样。先把"连接 + 状态三态 + 程序号"这条最稳的链路跑通给客户看到东西,再啃件数和负载,项目节奏会顺很多。