尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

三菱CNC数据采集实战:FOCAS库连接、参数配置与C#开发全流程

三菱CNC数据采集实战:FOCAS库连接、参数配置与C#开发全流程 1. 为什么用FOCAS方案三菱CNC数据采集的选型逻辑做机床数据采集这件事我在车间里摸爬滚打了几年先说个结论三菱CNC的数据采集FOCAS基本是绕不开的标准方案。所谓的三菱CNC数据采集本质上就是把机床内部的坐标、转速、报警、程序号、倍率这些状态数据从控制系统里安全地取出来交给上位机软件去处理。如果你只打算做产量统计可以用PLC外挂传感器的方式在机床主电路上加电流检测但那只能判断开机关机拿不到主轴转速、当前坐标这类系统级数据。想要拿到真正的系统内部数据就必须和CNC的通信端口打交道。三菱官方提供的通信方式主要有这么几条路串口RS-232文本输出老设备常见速度慢只能输出有限格式的数据解析麻烦。以太网板卡直连需要额外买三菱的以太网模块走专用协议开发资料开放程度低。FOCAS库NC Server/N C Explorer这是三菱官方提供的API库通过以太网直接访问CNC内部数据区读取速度快、支持功能多也是目前工厂数采项目里最主流的做法。FOCAS这个名字展开是FA Open Connection API Standard说白了就是三菱给第三方开发者开的一扇窗。你通过C#调用FOCAS库向CNC发起连接然后像查字典一样去读你关心的数据项。这个方案的好处是稳定、官方维护、不依赖第三方驱动而且C#做上位机开发本来就方便无论是做WebAPI接口还是做WinForm看板都能很快落地。这一篇我会带你走完整条链路从SDK在哪里下载、怎么安装到NC端参数设置再到C#代码从连接、读取、调试到排错每一步都交代清楚最后附一个我整理好的可直接运行的资源包说明代码结构、引用方法都会讲。2. 环境准备与SDK安装版本搭配和路径规划直接决定后面能不能跑通2.1 资源包获取与文件结构先说资源。三菱FOCAS库可以在三菱电机FA官方网站的e-Manual或开发者支持板块找到。你搜索关键词NC CLL或者FOCAS Library就能定位到。完整的开发包通常包含这几个东西组件用途Fwlib32.dll32位核心API动态库Fwlib64.dll64位核心API动态库mcfwlib.dllC#调用时的P/Invoke声明库也包含API函数声明头文件.hC/C开发时引用示例代码C/C/VB/C#官方Demo包括坐标读取、程序上传下载等手册PDF函数参考手册部分版本为英文或日文现在这套库最新版本已经支持到M800系列和M80系列控制器老的700系列也兼容。你需要根据自己的控制器年代选择版本一般下载最新的就可以向下兼容大多数型号。2.2 安装时最容易踩的坑位数版本不一致这里我踩过一个大坑必须单独拿出来说32位和64位的dll不能混用而且C#工程的目标位数配置必须在项目一开始就确定。FOCAS库虽然提供了32位和64位两个版本的dll但实际项目中你的上位机软件是跑在Windows 10/11的工控机上系统是64位的可如果你在Visual Studio里创建的是Any CPU首选项Prefer 32-bit打勾的工程程序会在运行时以32位模式运行这时候必须加载Fwlib32.dll。如果你把Fwlib64.dll拷进去调用时会直接报试图加载格式不正确的程序BadImageFormatException。我的建议是新项目一律用x64平台。在VS的解决方案管理器里右键项目→属性→生成→平台目标选x64然后把Fwlib64.dll放到生成目录bin\x64\Debug\下面。这样最稳也避免了某些功能在32位模式下表现不稳定的情况。2.3 NC端参数设置不打勾的采集都是白做很多新手把SDK装好、代码写好一运行发现连接失败卡在这里。大概率不是代码问题而是机床NC参数没有开权限。三菱CNC默认是不允许外部设备随便连的你必须先在机床面板上把以太网相关的参数配好。需要检查的几个关键位置参数#9491以太网有效设定通常设置为0以外的值表示以太网通信有效。IP地址设定在I/O Link或者以太网参数画面里设置给CNC分配一个固定IP例如192.168.1.10。端口号FOCAS默认端口是8193TCP一般不用改。操作权限部分系列需要设置从外部计算机访问时是否需要密码如果机床设置了密码保护你就得让现场人员把对应权限打开。这里提醒一句改NC参数之前先拍照留档并且把原始值记下来。有些老设备的参数之间互相牵连改完回不去就只能叫维修了。3. 最小的C#连接案例从创建工程到读出第一个坐标值3.1 创建工程与引用FOCAS库的方式对比在Visual Studio里新建一个控制台应用.NET Framework 4.8或者.NET Core 3.1以上都可以我推荐.NET Framework 4.8兼容性和工业现场的老工控机最合拍。引用FOCAS库的方式有两种方式一直接DllImport。在C#代码里手写声明。这是我最早用的方式也是官方示例给的方式。优点是控制力强缺点是函数声明太多容易写错参数类型。方式二引入官方封装好的mcfwlib.dll。这个文件里已经包含了所有API的C#声明你只需要在项目里添加引用就能直接使用。我实际用过之后感觉效率高很多推荐用这种方式。3.2 最小可运行代码连接CNC并读取主轴转速以方式二为例注释部分就是整个流程的核心逻辑。using System; using mcFwlib; // 引用FOCAS的C#封装 class Program { static void Main(string[] args) { // 1. 建立连接句柄 // 三菱FOCAS最多支持同时连接4个设备句柄必须唯一用0就够了 ushort handle 0; // 2. 配置连接参数 // 这里用TCP连接IP是机床IP端口默认为8193超时时间设为10秒10000毫秒 short ret mcFwlib.mcFwlib.cnc_allclibhndl3(192.168.1.10, 8193, 10, out handle); if (ret ! 0) { Console.WriteLine(连接失败错误码: ret); return; } // 3. 读取主轴转速单位rpm // S值是主轴实际转速数据读出来是以0.1rpm为单位 short sValue 0; ret mcFwlib.mcFwlib.cnc_rdspindle(handle, out sValue); if (ret 0) { Console.WriteLine(当前主轴转速: (sValue / 10.0) rpm); } else { Console.WriteLine(读取主轴转速失败错误码: ret); } // 4. 断开连接 mcFwlib.mcFwlib.cnc_freelibhndl(handle); } }这段代码的意图很简单建立一个到CNC的TCP连接读当前主轴实际转速然后断开。但里面有两个细节值得注意cnc_allclibhndl3的第三个参数是超时时间单位毫秒。在现场网络环境较差的情况下10秒可能不够我实际用的比较多的是30秒30000毫秒因为有些老机床在长时间待机后第一次响应会慢。cnc_rdspindle读出来的S值乘以0.1才是真实转速这是最常见的坑——如果你没看手册直接用整数去显示转速会差10倍。比如程序显示1200实际是120rpm放在面板上操作员一眼就会觉得你这套系统不准。3.3 如何验证连接是否成功错误码速查FOCAS函数返回的short类型值就是错误码0表示成功。我整理了几个在调试中最高频出现的错误码排错时直接对着查错误码含义处理方向0成功无需处理-17连接超时EW_TIMEOUT检查IP、网线、NC以太网参数-16无法连接到伺服EW_NOTREADYCNC处于报警或紧急停止状态-13参数错误EW_PARAM检查函数参数类型、IP字符串格式-10硬件错误EW_HARD通讯模块故障或网线物理断开-6无设备EW_MASTER句柄未建立先检查连接步骤-1初始化失败EW_INIT缺少dll或dll位数不匹配这些错误码会伴随你整个调试过程尤其在现场联调的时候几乎每一条都能碰上。我的做法是把错误码表写成一个静态类放在项目里打印日志的时候直接显示含义不然现场的人看不懂一串负数排查起来效率低。4. 核心API坐标系我把真正用过的函数按功能分了个类4.1 坐标读取机床位置数据的正确打开方式采集坐标是数据采集项目的核心需求之一。FOCAS里读取坐标主要用两个函数cnc_rdposition读取机床的绝对坐标、相对坐标、机械坐标、剩余移动量等信息最全推荐首选。cnc_rdmachine只读取机械坐标。来看一个读取绝对坐标和机械坐标的完整例子// 定义位置数据结构体 // 三菱FOCAS的位置数据以脉冲为单位或者以µm为单位具体看函数的输出标志 // 这里用cnc_rdposition获取输出单位默认为µm取决于参数设定 // 实际项目中坐标显示一般保留3位小数 short ret; ushort handle; mmc.FocasPosition pos new mmc.FocasPosition(); ret mcFwlib.mcFwlib.cnc_allclibhndl3(192.168.1.10, 8193, 30000, out handle); if (ret ! 0) return; ret mcFwlib.mcFwlib.cnc_rdposition(handle, 0, ref pos); // 第二参数0表示读取绝对坐标 if (ret 0) { Console.WriteLine(X轴绝对坐标: pos.abs.data[0] µm); Console.WriteLine(Y轴绝对坐标: pos.abs.data[1] µm); Console.WriteLine(Z轴绝对坐标: pos.abs.data[2] µm); // 第三、四、五轴铣床一般为A/B/C轴车床则可能为第二主轴 Console.WriteLine(第4轴坐标: pos.abs.data[3] µm); }注意这个函数读出来的是µm微米如果你需要毫米显示记得除以1000。官方手册里写的是坐标系中各轴数据以µm为单位很多刚上手的人在这里容易忽略直接展示出来的数值大得离谱还会被机床操作员怀疑是乱写的。4.2 运行状态读取程序号、进给倍率、主轴倍率、运行模式做完坐标读取第二重要的就是机床运行状态。cnc_rdstat能一次性读出运行状态的所有标志位包括自动运行中、暂停中、紧急停止、报警中、程序启动状态等。而cnc_rdprgnum可以读取当前正在执行的主程序和子程序号。把这几样组合起来你就基本能还原机床当前在干什么了。我实际用过的典型应用是做一个实时的机台状态看板绿点表示运行中自动且没有报警黄点表示暂停暂停中且没有报警红点表示报警中。这个看板逻辑的数据来源就是这几个API。// 读取当前程序号 ncPrgNum prgInfo new ncPrgNum(); ret mcFwlib.mcFwlib.cnc_rdprgnum(handle, ref prgInfo); if (ret 0) { Console.WriteLine(主程序号: prgInfo.data); // prgInfo.mdata 为主程序/子程序嵌套时的信息按需使用 } // 读取运行状态标志位 short runStat 0; ret mcFwlib.mcFwlib.cnc_rdstat(handle, ref runStat); if (ret 0) { // runStat是16位bitmap各个bit表示不同的状态自动、暂停、报警等 // bit0: 自动运行中 bit1: 暂停 bit2: 紧急停止 bool isAuto (runStat 1) 1; bool isHold (runStat 2) 2; }runStat这个位图的具体bit含义在不同系列控制器上大同小异但为了保险我还是建议读一下对应型号的手册章节别只看示例代码的注释就以为万事大吉。我之前在一台M70的老机床上就碰到过bit定义和M80不一致的情况最后是用试错的方式确定的。4.3 报警历史的读写这是机床数据采集的增值点报警信息这往往是客户最关心的数据之一。FOCAS提供cnc_rdalm读报警信息和cnc_rdalmhist读报警历史。// 读取当前报警信息 public static void ReadAlarm(ushort handle) { AlarmInfo alarm new AlarmInfo(); short ret mcFwlib.mcFwlib.cnc_rdalm(handle, ref alarm); if (ret 0) { for (int axis 0; axis 10; axis) { if (alarm.data[axis].alm_no ! 0) { Console.WriteLine(报警号: alarm.data[axis].alm_no 轴: alarm.data[axis].axis 内容: alarm.data[axis].alm_msg); } } } }报警信息读出来后能直接给MES系统用来做设备OEE分析。这块的实际价值比你想象的大很多工厂上数采第一步就是要搞清楚每台机到底什么时候报警、报的什么警。数据的准确性取决于轮询频率——如果你5秒轮询一次报警信息那么5秒内短暂出现的报警可能会被漏掉这个在方案评审阶段就得跟客户说清楚不然后续验收会扯皮。4.4 程序传输双向上传下载NC程序除了状态监控另一个常见需求是程序管理。FOCAS里传输程序用的是cnc_download从CNC下载程序到PC和cnc_upload从PC上传程序到CNC这两个函数用的不是普通数组那么简单是带文件头的数据流。因为程序传输涉及的内容比较多文件头格式、传输长度、缓冲区管理这一块单独拎出来又是一篇文章这次先不展开。但在资源包里我放了完整的上传下载示例代码来自官方Demo稍加改造就能直接用于DNC传输系统。5. 完整数据采集框架设计多线程轮询、断线重连与数据落地5.1 架构选型为什么轮询而不是用事件推送三菱FOCAS本身不是事件驱动的它没有CNC主动往上位机上报数据这种机制。所以你只能选择轮询。轮询频率怎么定是个具体问题。我用的经验值是坐标、转速、倍率500ms ~ 1s轮询一次太频繁会占用CNC的CPU时间影响加工稳定性。对三菱系统来说50ms一次的极限轮询是完全支持的但实际生产中没必要500ms足够用了。报警、状态、程序号1s ~ 3s轮询一次这些数据变化不频繁短间隔反而容易漏。坐标高精度轨迹采集如果用于加工轨迹分析可能需要100ms甚至更短。但这时候你要评估上位机的处理能力以及网络负载。轮询方案的处理逻辑开一个后台线程循环读取数据每次读出来放到一个共享缓存区或写入数据库UI线程只从缓存区取最后一条数据显示。这能避免UI线程阻塞也能避免数据库写入太频繁导致的性能问题。5.2 一个稳定的循环采集线程核心逻辑示例这里给出一个骨架代码你拿去改改就能用public class CncCollector { private ushort _handle; private bool _isRunning; private Thread _collectThread; private readonly object _lockObj new object(); public void Start(string ip, int port) { // 建立连接带超时重试 short ret mcFwlib.mcFwlib.cnc_allclibhndl3(ip, port, 30000, out _handle); if (ret ! 0) { // 连接失败记录日志等待下一次重试 return; } _isRunning true; _collectThread new Thread(CollectLoop); _collectThread.IsBackground true; _collectThread.Start(); } private void CollectLoop() { while (_isRunning) { try { // 读取坐标、转速、状态 // 组装成数据对象 // 写入数据库或发送到MQTT / WebAPI // 如果返回值异常处理错误并判断是否需要重连 if (ret ! 0) { // 错误码为-17表示超时需要重连 ReleaseHandle(); // 重连退避比如10秒后重新连接 Thread.Sleep(10000); continue; } } catch (Exception ex) { // 记录异常 } Thread.Sleep(500); // 轮询间隔按需调整 } } }这个骨架里有两个动作值得注意第一Thread.Sleep放在每次读取循环的末尾保证读取频率是上次读取结束后500ms而不是严格500ms周期。如果设备响应慢读一次要300ms那实际周期就是800ms这种非严格周期在某些对时间敏感的应用里要提前跟需求方确认。第二重连必须带上退避机制否则机床断电恢复的瞬间你的程序可能在1秒内发起几十次连接请求反而把机床的通信模块拖垮。5.3 数据落地数据库写入与WebAPI对接的实践建议数据落地通常有两种路径写入本地数据库SQLite/SQL Server或者通过HTTP把数据推送给第三方系统。我的建议是中间加一层消息队列或者缓存区不要每次读取都直接发HTTP请求。原因很简单轮询500ms一次一台机床一小时产生7200条数据10台机床就是72000条。如果每一条都实时POST到WebAPI一旦接口抖动你的采集线程就会被阻塞在HTTP等待上累积起来的延迟最后会导致数据严重滞后。我在实际项目里的做法是后台线程只把数据放进ConcurrentQueue另开一个独立的发送线程批量打包后每2秒POST一次。这样即使WebAPI暂时不可用数据也只是在队列里积压不会丢失。数据库写入同样走这个思路批量插入比逐条插入快得多数据量大的时候差别非常明显。6. 踩坑记录连接失败与数据异常问题的完整排查链路6.1 问题一总是报错-17连接超时之前有个项目在客户现场连接三菱M80系统代码反复报-17。排查思路一步步走下来第一步Ping机床IP通。说明物理链路没问题。第二步检查NC参数#9491的以太网有效设定显示已经开启。第三步停掉了我自己的程序用FOCAS自带的调试工具如果开发包里有Example工具测了一遍也是超时。第四步检查端口用netstat命令在PC端看TCP 8193端口有没有建立连接的迹象。第五步把机床面板打开看NC侧的以太网参数细节发现IP地址段和PC不在同一网段——机床是192.168.1.10PC是192.168.2.30中间没有路由器自然连不通。这个问题看起来很基础但在实际现场非常容易发生尤其是一些老设备机床IP不是网络管理员统一规划的而是设备厂安装时随手设置的。我后来在代码里加了一个跳板启动时先探测一下CNC IP是否可达不可达就给出中文提示无法访问机床IP请检查网线连接和IP设置现场人员看到提示心里就有数了不用打电话把我叫过去远程瞎猜。6.2 问题二数据读出来了但坐标值大了1000倍还有一个高频问题坐标值读出来不对。比如机床面板显示X轴100.000mm我程序读出来是100000。原因之前提过——单位是µm不是mm。这种错误其实不是bug而是手册没仔细读。但有一种更隐蔽的情况有些型号的控制器可以设置坐标单位是µm还是脉冲数一旦机床参数里设置成脉冲输出读出来的值还需要乘以每脉冲对应的微米数取决于光栅尺或编码器的分辨率这个数值不是固定的得看机床参数。我的建议是程序里不要写死单位换算的系数而是做一个配置文件现场调试的时候根据实际显示值调整系数调到一致为止。6.3 问题三长时间运行后偶发性读取失败这类问题是最麻烦的因为不稳定复现。我遇到过的情况是程序连续采集三天三夜偶尔出现一次-13参数错误但过几秒又恢复了。排查过程检查代码中是否存在内存泄漏连接句柄建立后没有释放FOCAS句柄是有限资源建立一次连接占用一个句柄反复建立不释放最终CNC端不再接受新连接。检查超时设置是否合理长时间运行后CNC侧有时会因为通信空闲进入省电模式第一个唤醒连接需要更长的超时时间。我的做法是每次读取失败时不要立即报错而是重试2次如果连续3次失败再判定为断线并重连。检查网络交换机端口是否出现CRC错误包工业现场电磁环境复杂网线质量差会导致偶发的数据包损坏。这类问题最不好查因为你的程序看不出任何规律只能通过交换机的计数器看到错误包在涨。6.4 排查工具组合拳日志、抓包、模拟器最后分享一套排查组合拳日志记录每次调用API都把返回值记录下来配合时间戳出了问题能回头看当时的现场环境。网络抓包用Wireshark抓TCP 8193端口的数据包能很直观看到三次握手是否成功、数据响应是否正常。这个方法在排查对方服务器主动断开连接这类问题上特别有效。模拟器验证三菱的FOCAS开发包中有时会包含一个NC Server Simulator模拟器可以在没有实体机床的时候模拟CNC方便先跑通上位机代码。这个我在出差路上经常用手机热点加笔记本就能提前把代码跑起来等到现场只需要改IP就能联机调试。7. 完整资源包结构与后续扩展建议7.1 资源包内容清单与使用步骤我把这套全流程整理成了一个资源包里面包含文件/目录内容说明FocasDll/Fwlib32.dll / Fwlib64.dll / mcfwlib.dllDoc/FOCAS函数手册英文/日文PDFExample/官方示例代码含C#、C、VBMyDemo/我封装好的C#完整采集Demo含UI界面Tools/错误码速查表、NC参数检查清单README.md完整的安装部署步骤说明使用步骤也一并在资源包里写清楚了解压后先把FocasDll/下的dll复制到你的bin目录注意根据你的平台目标选32位还是64位。用记事本打开MyDemo/App.config填上你的CNC IP地址和端口。运行看左下角连接状态是否变成绿色。如果连接失败对着Tools/错误码速查表排查。7.2 从这套基础框架还能扩出哪些玩法基础的数据采集跑通之后扩展方向非常多。我实际做过或见过的几个方向设备OEE分析采集运行信号、报警信号、程序号结合排产计划算出OEE。这是工厂上数采最直接的诉求。远程监控和预测性维护通过采集主轴负载电流分析负载曲线的异常波动提前发现刀具磨损或主轴轴承问题。FOCAS的cnc_rdspdl可以读主轴负载值。与MES/ERP系统打通把产量、工时、报警数据实时推送到MES形成车间级的数字看板。程序版本管理通过程序上传下载功能统一管理机床里的NC程序版本避免操作员用了错误版本的程序导致工件报废。我个人实际在做的项目是把三菱FOCAS采集上来的数据统一转换成OPC UA格式这样不管是MES、SCADA还是自己写的可视化看板都能用统一的标准接口取数后续接什么系统都不用再改采集层了。7.3 最后再给两个实用经验一个是关于dll分发如果要把程序部署到客户的电脑上记得把Microsoft Visual C Redistributable装一下。FOCAS库底层依赖VC运行库没有这个库程序一加载dll就报错无法定位程序输入点。这个问题在纯净版Windows工控机上特别常见。另一个是安全提醒FOCAS连接是可以读写参数的CNC参数一旦写错机床动作会异常。所以我强烈建议程序中涉及参数写入的功能要么不做要么加上双层确认和操作日志。工业安全无小事采集层做好只读就够了写操作留给现场专业工程师手工完成。数据采集这个事看起来简单——连上就收数嘛——但真正做扎实每一层都有细节。从SDK选型、NC参数配置、代码编写到现场排查每一步都有前人踩出来的坑。希望这篇文章能把你的起步阶段缩短几天如果你在部署中遇到其他奇怪的问题欢迎带着现象和数据来交流。
返回列表