
简介本资源是一套面向制造车间设备联网与数字化改造的异构数控机床数据采集系统适合设备工程师、信息化实施人员及中高级自动化开发者使用。系统针对车间内FANUC、西门子、海德汉等主流数控系统进行统一数据采集与集成能有效解决多品牌设备协议不统一、数据孤岛等典型问题后台支持写入Oracle数据库同时提供标准MQTT接口可将采集数据以消息形式推送至云端服务器便于上层MES或工业互联网平台对接。压缩包共0个文件大小25.46MB主要包含程序源码、配置文件及部署说明等类型可帮助读者快速理解采集架构、接口协议与存储方案。已有1720人学习浏览适合需要搭建车间级采集平台或进行异构系统数据整合的技术人员参考借鉴从整体架构到落地实现均有一定实用价值。1. 异构数控机床数据采集系统三个协议体系怎么汇进 Oracle在一家机加工车间做设备联网最头疼的不是设备多而是同一排厂房里躺着 FANUC、西门子和海德汉三套控制系统各自有各自的协议、各自的点位定义连时间基准都不一定一致。这套异构数控机床数据采集系统解决的就是一线车间联网工程师最常遇到的组合FANUC 走 FOCAS、西门子走 OPC UA/S7、海德汉走 TNC 通道统一把数据汇集进 Oracle 数据库供 MES、大屏和报表取数。它适合正在做数控机床集中监控、设备数据采集或 ERP/MES 对数项目的工程师尤其是机型杂、老设备多、数据口径还要统一的车间。2. 先定架构再做接入采集层、汇聚层到 Oracle这一条链路怎么搭做异构采集最大的教训是别一上来就写驱动。三个厂家的协议差异不是靠一个“万能驱动”能抹平的FANUC 的 FOCAS 库是 C 接口、西门子那边是 OPC UA 的地址空间、海德汉有的型号连 OPC UA 都没有。先把架构定下来后面接哪家设备都是往框架里填驱动的事不然每接一种新机床就要把整个采集程序翻一遍翻到最后自己都记不清哪个补丁是给谁打的。2.1 选型理由别在同一个驱动里硬揉三种协议采集层必须是一套“协议驱动”架构每种设备一个独立的 driverdriver 与 driver 之间不共享状态。FANUC 的官方对接方式是 FOCAS 开放接口库走以太网 TCP机床侧需要打开以太网功能并开放端口西门子 S7-1200/1500 自带 OPC UA 服务器S7-200 SMART 没有 OPC UA只能用 S7comm 或 Modbus TCP 兜底海德汉的情况最杂较新的 TNC 7xx 部分型号支持 OPC UA老的 iTNC 530 往往只有文本状态输出或远程桌面协议。这三家的接入深度、返回格式、刷新机制完全不同硬塞在一个循环里只会互相拖累。控制系统常规接入协议数据返回特点主要坑FANUCFOCAS 库TCP 以太网坐标、宏变量、报警、刀号均可读轮询太快会拉高 CNC 负载西门子OPC UA / S7comm结构化地址空间DB 块点表清晰S7-200 SMART 不支持 OPC UA海德汉OPC UA / 文本状态输出TNC 型号差异大通道选择依赖版本老型号只能解析文本协议层的设计原则就一句话driver 只管把设备侧的数据读回来不负责存储存储层只认归一化后的点位模型不关心底层是 FOCAS 还是 OPC UA。这套分层在做 MES 对点的时候尤其有价值——MES 关心的永远是“3 号机床主轴的当前转速”它不该知道你是在用cnc_rdaxisdata还是在用ReadValueAsync拿到的数据。2.2 数据链路设备侧到 Oracle 之间不是直连中间要有队列很多第一次做采集的同事会问既然都拿到数据了直接 INSERT 进 Oracle 不行吗这不是行不行的问题而是设备侧通信和数据库事务是两种完全不同的节奏。设备侧是 TCP 报文或协议轮询一秒钟可能有几百次状态变化Oracle 是事务型写入单独 INSERT 一条 2 毫秒一百台设备每 2 秒一轮直连入库瞬间把连接池塞满还没等写完下一轮数据又来了。我一般会在采集程序和数据库之间放一个前置队列本地内存或 Redis 都行采集端只负责往队列里丢入库端按批次批量写。collector: device: fanuc_01 protocol: focas host: 192.168.1.101 port: 8193 timeout_ms: 3000 poll_interval_ms: 2000 queue: type: memory capacity: 10000 low_water: 2000 high_water: 8000 writer: target: oracle conn_string: User Idmes;Passwordmes;Data Source//10.1.1.20:1521/MESDB batch_size: 500 flush_interval_ms: 1000 retry_count: 3这段配置的逻辑是采集端按poll_interval_ms的节奏轮询 FOCAS读到的数据进内存队列入库端每攒够batch_size条或者每隔flush_interval_ms就批量写一次 Oracle。队列设了高低水位超过high_water就暂停采集、防止内存被打爆低于low_water再恢复——这个机制在设备大批量入库失败时能起大作用。retry_count控制单批写失败的兜底重试次数超过以后把数据标记为失败并丢弃绝不好无休止地待在内存里。2.3 表设计普通点位、状态、报警分开存不要一张大表装所有东西存储层的数据模型我踩过坑一开始把所有数据往一张TA_DEVICE_DATA表里塞字段只有device_id、data_time、point_code、value跑了一个月表的行数到了千万级查询 MES 的追溯报表要十几秒。后来才把数据拆成三组点值表存连续变化的数据坐标、转速、进给状态表存开关量和运行状态开机、停机、报警状态报警表存稀疏但高价值的报警记录。三张表的写入频率和数据量级完全不同分开存既能控制单表行数也能让报警查询走独立的索引。CREATE TABLE TA_POINT_VALUE ( DEVICE_ID VARCHAR2(32) NOT NULL, POINT_CODE VARCHAR2(64) NOT NULL, CAPTURE_TIME TIMESTAMP(3) NOT NULL, VALUE NUMBER(18,6), QUALITY NUMBER(1) DEFAULT 1, CONSTRAINT PK_POINT_VALUE PRIMARY KEY (DEVICE_ID, POINT_CODE, CAPTURE_TIME) ) PARTITION BY RANGE (CAPTURE_TIME) INTERVAL (NUMTOYMINTERVAL(1, DAY)) (PARTITION P_INIT VALUES LESS THAN (DATE 2025-01-01));这张点值表有几个设计点直接关系到能不能扛住车间数据量。主键用了DEVICE_ID POINT_CODE CAPTURE_TIME这是为了配合 MES 侧“某个设备某个点在某个时间段的值”这种典型查询VALUE字段用NUMBER(18,6)留足小数精度FOCAS 返回的坐标值可能精确到微米级NUMBER(6,2)这种定义会把数据精度吃掉分区策略按天做范围分区因为一台机床 100 个点、每 2 秒采一次一天就是 432 万条不分区的表撑不过三个月。QUALITY字段标记数据质量0 表示无效、1 表示正常、2 表示可疑这个字段后面做数据校验时非常有用。3. FANUC 接入FOCAS 连接参数、读数映射与 C# 驱动封装FANUC 是这三家里“文档最全但上手最容易翻车”的。官方给的 FOCAS 库是 C 接口库本身不大难在连接参数要和机床侧严格对齐。很多同事卡在“代码照着写了一个小时就是连不上”其实多数不是代码问题而是机床侧以太网功能没打开或者安全参数没放行外部访问。3.1 FOCAS 连接握手IP、端口、超时和 DCS 安全参数FOCAS 连接是典型的 TCP 握手流程通过设备 IP 和固定端口建立连接成功后拿到一个句柄后续所有读写都基于这个句柄。协议端口在各版本里并不完全一致常见的端口配置是 8193但同一个车间里不同年代的 FANUC 系统端口可能不一样不能用一套参数通吃。连接前要去机床系统里确认以太网功能已激活、IP 与采集端在同一网段、端口没被机房防火墙拦掉。超时时间我一般设 3000 毫秒太短会误判太长会让采集程序卡死。连接失败的排障有一个血泪经验FANUC 机器人的控制柜上如果报syst-212这类错误多半和安全参数有关系。FOCAS 的外部访问会被 DCS 安全功能拦截需要在安全参数里把“外部通信访问”这一项放行不然代码怎么重试都是超时。机床侧和采集端两侧的 IP、掩码、网关必须逐一核对工业现场经常有网卡配了双 IP 导致路由漂移的问题用 ping 通不代表 FOCAS 端口通最好先在采集端用 TCP 工具直接测端口通断再做协议层调试。3.2 读数映射坐标、宏变量、报警返回值和单位要心里有数FOCAS 读数的函数并不少但真正在采集项目里高频用到的基本就三个方向轴数据、宏变量和报警。轴数据用的是轴坐标读取函数返回的是各轴的机床坐标或相对坐标宏变量读取函数负责读 FANUC 的用户宏变量很多车间把刀具寿命、工件计数、倍率这些工艺数据放在宏变量里不读这一层等于只拿到了一半数据报警读取函数返回报警号和报警文本这是做设备 OEE 和停机分析的关键输入。数据项典型 FOCAS 函数返回说明使用注意轴坐标cnc_rdaxisdata返回各轴位置值确认返回单位是毫米还是英寸宏变量cnc_rdmacro返回宏变量字符串低频读取频繁读会影响 CNC报警cnc_rdalarm返回报警号和文本报警文本可能是日文/英文倍率/进给cnc_rddynamic返回倍率与进给速度用于计算实际加工进度这里要强调一句FOCAS 的读写频率必须克制。官方建议轮询周期和 CNC 的插补周期错开实际项目中 500 毫秒到 2 秒一次的采样频率足够覆盖绝大多数监控需求我见过把轮询压到 100 毫秒的项目结果 CNC 系统负载明显升高加工出现卡顿。采集系统的价值在于长期稳定地拿数据不是短时间把机床逼到极限。3.3 用 C# 写一个可复用的 FANUC 采集驱动FOCAS 官方提供了 C 库C# 侧用 P/Invoke 调用核心就四步加载库、建立连接、循环读取、关闭连接。下面这段代码是我在实际项目里裁剪过的去掉了业务逻辑只保留驱动骨架新的 FANUC 设备接入直接改 IP 和轮询间隔就能跑。using System; using System.Runtime.InteropServices; public class FanucFocasDriver : IDisposable { // 加载 FOCAS 动态库注意 32 位/64 位要匹配采集程序目标平台 [DllImport(fwlib32.dll, EntryPoint cnc_allclibhndl3, CharSet CharSet.Ansi)] private static extern short cnc_allclibhndl3( string ip, ushort port, int timeout_ms, out IntPtr handle); [DllImport(fwlib32.dll, EntryPoint cnc_rdaxisdata, CharSet CharSet.Ansi)] private static extern short cnc_rdaxisdata(IntPtr handle, short axis, out ODBAXISDATA data); [DllImport(fwlib32.dll, EntryPoint cnc_rdmacro, CharSet CharSet.Ansi)] private static extern short cnc_rdmacro(IntPtr handle, ushort macroNum, int length, out string value); [DllImport(fwlib32.dll, EntryPoint cnc_freelibhndl, CharSet CharSet.Ansi)] private static extern short cnc_freelibhndl(IntPtr handle); private IntPtr _handle; public void Connect(string ip, ushort port, int timeoutMs) { short result cnc_allclibhndl3(ip, port, timeoutMs, out _handle); if (result ! 0) throw new Exception($FOCAS 连接失败错误码{result}); } public double ReadAxisPosition(short axis) { ODBAXISDATA data; short result cnc_rdaxisdata(_handle, axis, out data); if (result ! 0) throw new Exception($读取轴 {axis} 数据失败错误码{result}); // 返回的是机床坐标值不同机型可能带小数倍率按现场实测换算 return data.data * data.dec; } public void Disconnect() { if (_handle ! IntPtr.Zero) { cnc_freelibhndl(_handle); _handle IntPtr.Zero; } } [StructLayout(LayoutKind.Sequential)] public struct ODBAXISDATA { public short type; public short data; public short dec; public short flag; } public void Dispose() { Disconnect(); } }这段代码的运行逻辑是Connect负责建立 FOCAS 会话拿到句柄后所有读取操作都走_handleReadAxisPosition读单个轴的坐标值返回前把原始整值和小数倍率乘起来换算成真实坐标用完必须调Disconnect释放句柄驱动长期跑在边缘盒子上句柄泄漏会导致操作系统文件描述符耗尽。ODBAXISDATA这个结构体的字段顺序和大小必须和 FOCAS 头文件一致LayoutKind.Sequential就是强制按声明顺序对齐内存凡是 P/Invoke 结构体都建议加这个特性否则字段错位读出来的全是乱码。4. 西门子和海德汉OPC UA 配置、TNC 状态文件与数据归一化4.1 西门子从博途启用 OPC UA 到 C# 客户端读取西门子 S7-1200/1500 从较新的固件版本开始内置了 OPC UA 服务器这是目前接西门子最省事的通道不用去碰底层 S7comm 协议。配置分为两步第一步在博途TIA Portal里选中 PLC打开“OPC UA”设置激活服务器并设定安全策略把采集端的证书导进去第二步在 PLC 程序里把需要被读的变量放到 DB 块勾选“可访问”OPC UA 的地址空间就会自动生成对应的节点。博途版本不同菜单名称会有差异但“PLC 属性 → OPC UA → 激活服务器”这条路径基本一致。C# 客户端用 OPC Foundation 的 UA-.NETStandard 库读取逻辑本身不复杂无非是建立会话、浏览地址空间、订阅或读取节点值。和 FANUC 那套驱动相比OPC UA 最大的优势是地址空间自带语义变量的名称、数据类型、工程单位都在节点属性里MES 侧对点不用再翻机床手册。实际项目里 intouch 和西门子 1500 通讯、威纶通触摸屏导入 S7-1200 标签本质都是走同一套 OPC UA 机制标签表设计得越规整各种上位机对点就越省事。using Opc.Ua; using Opc.Ua.Client; public class SiemensOpcUaDriver { private Session _session; public void Connect(string endpointUrl) { var config new ApplicationConfiguration(); // 匿名连接用于测试现场环境建议配置用户名密码或证书认证 var endpoint CoreClientUtils.SelectEndpoint(endpointUrl, useSecurity: false); _session Session.Create( config, endpoint, updateBeforeRead: false, checkDomain: false, sessionName: cnc-collector, sessionTimeout: 60000, identity: new UserIdentity(), preferredLocales: null ).Result; } public DataValue ReadNode(string nodeId) { NodeId node new NodeId(nodeId); return _session.ReadValue(node); } }这段代码的核心参数有三个endpointUrl填 PLC 的 OPC UA 服务器地址格式是opc.tcp://192.168.1.10:4840useSecurity设为false是跳过安全握手适合车间内网调试生产环境建议打开证书校验sessionTimeout是会话超时时间西门子的 OPC UA 服务器默认有会话空闲回收策略采集端长时间不发请求会被踢掉采集程序要定期发心跳请求保持会话存活。ReadValue返回的DataValue里带SourceTimestamp这个时间戳是 PLC 侧的入库时不要直接拿它当采集时间后面避坑章节会细说。4.2 海德汉TNC 的采集通道、编码器信号对照与位置校验海德汉是三家里最“看版本说话”的。新一代 TNC 7xx 部分型号支持 OPC UA接法和西门子类似老一代 iTNC 530 和更早的系统没有现成的 OPC UA 接口只能走文本状态输出或者串口报文解析。文本解析的思路是让 TNC 周期性输出状态数据到指定端口采集端拿到以后按固定分隔符拆字段这种方案的代码不复杂但遇到系统版本升级输出格式可能微调解析逻辑就得多做一层容错。海德汉调试还有一个容易被忽略的点位置读数跳变。现象是采集端读回的坐标偶尔跳几个毫米但机床屏幕显示正常。这时候要查的不是协议而是编码器链路。海德汉编码器有正弦 1Vpp 和 TTL 方波两类信号接错信号类型、线数对不上、A/B 相序接反都会导致位置反馈异常。排查时先要一份编码器线数对照表把编码器线数和丝杠螺距做换算再让机床手动慢速移动一个固定距离比如 10mm对比采集端读数和实际移动量是否一致、方向是否正确。这一步在调试阶段花十分钟做一遍后面能省一整天的定位时间。4.3 数据归一化把三家的点变成一张标准表驱动层拿到三家数据后存储层不能直接入库要过一道归一化。不然 FANUC 的坐标轴名是X、Y、Z西门子的 DB 变量名可能是MachineData.Axis.ActualPos[0]海德汉那边又是另一套命名MES 侧根本没法统一对点。我一般在采集程序里维护一张点表映射把设备侧的点位映射成统一编码DEVICE_ID POINT_CODE CAPTURE_TIME为唯一键归一化后的数据长这样。CREATE VIEW V_NORMALIZED_DATA AS SELECT DEVICE_ID, POINT_CODE, CAPTURE_TIME, VALUE, QUALITY FROM TA_POINT_VALUE WHERE QUALITY 1;这类视图的作用是让上层应用只看到有效数据屏蔽底层的质量标记。实际项目中这张表还会加一个SOURCE_PROTOCOL字段标注这条数据来自 FOCAS、OPC UA 还是海德汉文本解析方便出问题时按协议维度排查。归一化这一步放在采集端和入库端都行我习惯放在采集端做因为这样入库 SQL 可以完全统一数据库端不需要关心三家的协议差异。5. 采集过程中的常见坑假在线、时标错位、缓存风暴和编码器跳变5.1 设备侧“假在线”连接还在数据已经死了现象采集程序运行正常FOCAS 句柄或 OPC UA 会话都没有报错但某一个点的数值连续半小时不动看着像数据正常实际上机床已经换刀换程序了读数却一直停留在旧值。原因CNC 系统负载过高时通信任务会被系统挂起TCP 连接不断但数据刷新已经停了西门子 OPC UA 偶尔也会出现节点值不更新的假死状态。简单的心跳超时检测对这些场景无效因为连接本身是活的。解决给每个点位加数据心跳判断——同一个点位连续多次采集值完全不变且持续超过业务阈值比如 10 分钟判定为假死强制重连设备并告警。判断时要把“机床真的没动”和“采集通道死了”区分开配合读取主轴负载或运行状态判断设备是否处于加工中。5.2 时标错位用了设备本地时间导致报表乱序现象同一台机床的坐标数据在 Oracle 里时间戳忽前忽后MES 的曲线图出现锯齿状回退追溯某个工件的加工参数时数据是乱的。原因每台数控机床的时钟和采集服务器存在几十秒甚至几分钟的偏差有些协议返回的时间基准还不统一FOCAS 返回的是机床本地时间OPC UA 的节点时间戳是 PLC 侧时间拿到哪边就用哪边早晚会错乱。解决统一以采集服务器时间为准。采集端在数据进入队列前就盖上服务器时间戳设备本地时间只作为原始字段存进RAW_TIMESTAMP不参与排序。采集服务器本身要做 NTP 校时车间里所有采集盒子连同一个 NTP 源保证多台盒子之间时间也一致。从那以后我每次上线新车间第一件事就是确认 NTP 配置。5.3 批量插入的缓存风暴停了十分钟恢复瞬间写崩数据库现象车间网络闪断十分钟恢复后 Oracle 的 CPU 瞬间打满INSERT 队列积压几万条把生产数据库搞到锁定。原因采集端把网络恢复前所有数据都装在队列里恢复后一次性回放Oracle 侧来不及刷盘重做日志暴增锁竞争加剧。解决队列加水位线超过高水位就丢旧数据并记录丢弃条数补传窗口限制在一个小时以内超过窗口的数据直接标记丢弃不再尝试入库。数据库端配合批量提交和按天分区把单次提交的控制权交给入库程序而不是让数据库端去扛。5.4 海德汉位置跳变读回来的坐标偶尔飘几个毫米现象海德汉机床的轴坐标采集值偶发跳变跳变幅度在毫米级持续几秒又恢复正常机床屏幕显示正常。原因编码器信号链路异常是主因比如正弦信号和方波信号接错、线数不匹配、屏蔽层接地不良也可能是采集端的解析频率和 TNC 的报文输出频率没对上把半包数据当完整报文解析了。解决先排查编码器线数和信号类型确认和机床丝杠螺距的换算关系再做慢速手轮移动测试移动 10mm 看采集端是否同步变化如果信号链路没问题检查采集解析代码增加报文完整性校验不完整的报文直接丢弃不要参与计算。5.5 Oracle 连接池死会话跑几天后入库失败重启才好现象采集服务刚上线一切正常跑三天后开始报 ORA-12505 或监听超时重启服务立刻恢复。原因采集程序与 Oracle 之间的会话被防火墙或数据库空闲超时机制断开连接池里的连接已经失效但程序不知道继续拿死连接去 INSERT。解决连接字符串开启连接有效性校验每次从连接池拿连接前做SELECT 1探活采集端定期重建连接池不要一个连接跑到底。数据库端清理空闲会话的阈值要留足余量至少大于采集端的轮询周期。6. 收尾技巧数据质量校验四步法和断线补传的时间窗数据采集系统上线后最怕的不是采不到数据而是采上来的数据没人敢信。我在这套系统上吃过一次大亏某个车间的 OEE 报表跑了一个月客户突然发现某台机床的开机率算错了查到最后是采集端把设备停机状态误判成了正常状态数据一路进了 Oracle报表一路错到底。从那以后我每次上线新车间都要强制走一遍数据质量校验四步法并用一套断线补传机制兜底避免类似的事故重演。第一步做完整性校验拿采集到的条数和理论条数对比比如一台机床 100 个点、2 秒一轮、一天应该采集 432 万条实际入库 380 万条少了 12%立刻检查是掉线还是点位漏采。第二步做范围校验坐标值、主轴转速、进给速度都有物理量程超出量程的数据直接标记QUALITY2不在报表里展示。第三步做跳变校验同一台机床同一轴相邻两次采集值突变超过阈值比如坐标跳动 50mm基本可以判定为噪声或解析错误。第四步做交叉核对拿采集数据和机床屏幕读数比或者和当天产量、加工工件数互相印证对不上就从头查。断线补传机制要和校验配合着用。补传窗口我控制在 60 分钟超过窗口的旧数据全部丢弃并记录丢弃数。这是因为补传的意义在于“尽量补齐短中断造成的数据空洞”而长时间断线后的历史数据价值极低疯狂补只会把数据库写爆。补传队列要按设备分开设备之间不能互相影响某一个设备的补传失败不能拖累其他设备的正常写入。这套“三层协议 Oracle 存储 四步校验”的采集架构就是从这个项目里磨出来的它解决的不只是采集协议的问题更是让最终报表数据能被人信任的问题。希望帮到你。本文还有配套的精品资源点击获取