ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

欧姆龙PLC数据采集:虚拟机+Fins协议实战指南

欧姆龙PLC数据采集:虚拟机+Fins协议实战指南 欧姆龙PLC在产线设备层占有率极高尤其是CP/CJ/CS系列很多老产线跑了几十年还在稳定服役。但要把这些PLC里的数据实时抓出来接到上位机或者MES系统里很多人第一反应是装个组态软件不就行了。组态软件确实省事但授权费用高、点位受限、灵活性差遇到定制化需求就抓瞎。所以越来越多的工程师开始走自己写采集程序这条路——用一台虚拟机跑采集服务通过Fins协议直接跟PLC通信数据想怎么处理就怎么处理。这篇内容就是把我自己在项目里反复验证过的一套做法完整拆开讲。核心思路是在VMware虚拟机里搭一个干净的Windows环境装好欧姆龙官方通信组件用Fins协议走以太网跟PLC建立连接然后写代码读写DM区、CIO区数据。适合有一定网络基础和编程基础、想自己掌控数据采集链路的工程师也适合刚接触欧姆龙PLC通信、被各种驱动和配置搞得头大的朋友。下面从环境搭建到协议配置到代码实操一步步来。1. 为什么选虚拟机跑采集服务而不是直接上工控机1.1 虚拟机方案在产线环境里的真实优势先说清楚为什么要在VM里做这件事。直接在工控机上装采集软件当然可以但实际项目里会遇到几个很现实的问题。第一是环境隔离。采集程序往往需要装各种运行库、驱动、通信组件这些东西跟工控机上原有的组态软件、OPC服务很容易打架。我遇到过一次装完某个通信DLL之后原来的组态软件直接起不来了排查了一整天才发现是版本冲突。用虚拟机就完全没这个问题采集环境是独立的搞崩了直接快照回滚不影响主机上任何东西。第二是迁移和备份。虚拟机就是一个文件包换台机器直接拷过去就能跑不用重新配环境。产线上工控机坏了要换传统方式得重新装一遍所有软件虚拟机方案十分钟搞定。第三是多版本共存。有些项目要同时对接不同年代的欧姆龙PLC老设备可能只支持Fins/TCP新设备支持Fins/UDP甚至有些还要走串口。虚拟机可以开多个每个跑一套独立的通信环境互不干扰。当然虚拟机也有代价主要是网络延迟会比物理机略高一点点但对于PLC数据采集这种秒级、甚至百毫秒级的场景这点延迟完全可以忽略。实测下来VMware桥接模式下ping PLC的延迟跟物理机基本没差别。1.2 虚拟机网络模式的选择逻辑这是最容易踩坑的地方。VMware有三种主要网络模式桥接、NAT、仅主机。做PLC采集必须用桥接模式原因很简单——PLC和采集服务必须在同一个网段里直接通信。NAT模式下虚拟机的IP是VMware虚拟网卡分配的PLC根本看不到虚拟机通信必然失败。仅主机模式更不行虚拟机只能跟主机通信出不去。只有桥接模式虚拟机会像一台独立设备一样接入物理网络拿到跟主机同网段的IPPLC才能正常响应。具体操作虚拟机设置里网络适配器选桥接然后编辑虚拟网络编辑器桥接目标选主机实际连接PLC的那块物理网卡。如果主机有多块网卡比如一块连办公网、一块连设备网一定要选对选错了虚拟机就跑到办公网段去了跟PLC不在一个网里。提示桥接模式下如果虚拟机拿不到IP先检查物理网卡的网线是否插好、交换机端口是否正常。另外有些企业网络有MAC地址绑定或者端口安全策略虚拟机的虚拟MAC可能被拦截这种情况需要找网络管理员放行。1.3 虚拟机资源配置的合理区间采集服务本身不重但Windows系统加上欧姆龙通信组件资源给太少会卡。我的经验配置是CPU给2核内存给4GB硬盘给60GB。这个配置跑Windows 10或者Windows 7都够用采集几百个点位毫无压力。如果只是跑采集不需要图形界面其实用Windows Server Core或者精简版系统更省资源但欧姆龙的某些配置工具需要图形界面所以还是建议装完整版Windows。系统装好后第一件事是装VMware Tools这个直接影响虚拟机的网络性能和显示效果不装的话网卡驱动可能都不正常。硬盘建议用固定大小而不是动态扩展虽然占空间但性能稳定不会因为动态扩展导致采集过程中出现IO抖动。快照功能要善用装完系统打一个快照装完通信组件再打一个后面出问题随时回滚。2. Fins协议到底是怎么跟欧姆龙PLC对话的2.1 Fins协议的本质一套命令-响应机制Fins全称Factory Interface Network Service是欧姆龙自己的一套工业通信协议。理解它其实不难本质就是上位机发一条命令帧PLC回一条响应帧跟HTTP请求响应是一个道理只不过格式是二进制的更紧凑。命令帧里包含几个关键信息目标网络号、目标节点号、目标单元号这三个合起来叫目标地址用来定位具体是哪台PLC的哪个单元。然后是命令码比如读DM区是0101写DM区是0102读CIO区是0101但区域代码不同。最后是具体的地址和长度比如从D100开始读10个字。响应帧就是PLC把结果返回包含结束码判断成功失败和读到的数据。结束码00表示正常其他值对应各种错误比如0x40表示地址越界0x20表示命令不支持。2.2 Fins/TCP和Fins/UDP的区别与选型Fins协议可以跑在TCP上也可以跑在UDP上这是两个不同的封装方式。Fins/TCP是面向连接的通信前要先建立TCP连接默认端口9600。优点是可靠数据不会丢适合对数据完整性要求高的场景。缺点是连接维护有开销PLC那边能同时接受的TCP连接数有限一般就几个。Fins/UDP是无连接的直接发数据包默认端口也是9600。优点是轻量、快适合高频采集。缺点是不保证送达网络不好的时候可能丢包。实际项目里怎么选我的经验是采集频率低于100ms的用TCP高于100ms的用UDP。大部分产线数据采集是秒级或者几百毫秒级用TCP完全够而且省心。如果要做高速数据记录比如振动监测那种毫秒级的才考虑UDP但要在应用层自己做重传和校验。欧姆龙PLC默认两个都开着但需要在PLC的以太网单元设置里确认。有些老型号默认只开了一个这个后面配置章节会细说。2.3 欧姆龙PLC的地址体系DM区、CIO区、WR区怎么对应这是新手最容易晕的地方。欧姆龙PLC的地址分好几个区Fins协议里每个区有对应的区域代码区域名称区域代码地址范围典型用途CIO区0xB0CIO0~CIO6143输入输出继电器、内部继电器WR区0xB1W0~W511工作继电器HR区0xB2H0~H511保持继电器DM区0x82D0~D32767数据存储最常用EM区0x98~0x9DE0_0~E0_32767扩展数据存储采集最常用的是DM区因为它是纯数据存储不受程序逻辑影响适合放工艺参数、产量计数、配方数据这些。CIO区更多是跟实际IO和内部逻辑相关采集状态位的时候会用到。地址换算要注意Fins协议里地址是字节偏移而欧姆龙习惯说字。比如D100在Fins命令里要写成100*2200的字节偏移或者直接用字地址加区域代码。不同库的封装方式不一样用的时候要看清文档。3. 虚拟机里把欧姆龙通信环境搭起来3.1 系统准备与必要的运行库虚拟机装好Windows之后别急着装欧姆龙的东西先把基础运行库补齐。欧姆龙的通信组件很多是早年开发的依赖VC运行库和.NET Framework。需要装的Visual C Redistributable 2005/2008/2010/2013/2015-2022全套装上别嫌多.NET Framework 3.5和4.8Windows功能里勾选如果要用官方配置工具可能还需要装旧版的.NET 2.0这些库不装全后面装通信组件的时候会报各种找不到DLL的错误而且报错信息往往很模糊很难定位。我吃过这个亏后来养成习惯新系统先跑一遍运行库合集包。3.2 欧姆龙官方通信组件的安装与注册欧姆龙提供几个跟Fins通信相关的东西Sysmac Studio或者CX-One里带的通信驱动这是最正规的。CX-One是个大包装完会有FinsGateway或者类似的通信服务。但CX-One体积巨大几个G如果只是做采集没必要装全套。更轻量的方式是直接用FinsGateway或者Fins通信库。FinsGateway是欧姆龙早期的通信中间件装完之后会注册一个系统服务提供Fins/TCP和Fins/UDP的通信能力。装完后在服务里能看到FinsGateway相关的服务确保它是启动状态。还有一个方式是不装官方组件直接用第三方库。比如Python的fins库、C#的OmronFins库这些库自己实现了Fins协议不需要欧姆龙官方的东西。这种方式最干净虚拟机里只要有个运行环境就行。我现在的项目基本都走这条路省事。注意如果用官方FinsGateway安装时可能会提示要装驱动签名Windows 10以上系统对驱动签名要求严格可能需要临时关闭驱动签名强制。这个操作有安全风险建议只在测试环境做生产环境用第三方库更稳妥。3.3 网络连通性验证先ping通再谈协议装完环境第一件事是验证网络。虚拟机里打开cmdping一下PLC的IP。ping不通的话后面所有配置都是白搭。ping通了之后还要验证端口。Fins/TCP默认9600端口用telnet或者Test-NetConnection测一下Test-NetConnection -ComputerName 192.168.1.10 -Port 9600如果显示TcpTestSucceeded为True说明端口是通的。如果False可能是PLC那边没开Fins/TCP服务或者防火墙拦了。这一步看着简单但实际项目里至少三成的通信问题都出在这里。网络不通后面代码写得再对也没用。所以养成习惯先ping再测端口最后才写代码。4. Fins协议配置的完整实操链路4.1 PLC侧的以太网单元设置PLC那边要先配置好。以CJ系列配以太网单元为例用CX-Programmer或者Sysmac Studio连上PLC找到以太网单元的设置。关键参数IP地址给PLC设一个固定IP跟虚拟机同网段。比如虚拟机是192.168.1.100PLC设192.168.1.10子网掩码255.255.255.0Fins/TCP端口默认9600一般不改Fins/UDP端口默认9600Fins节点号这个很重要每台PLC在Fins网络里要有唯一节点号默认是根据IP最后一段自动算的也可以手动指定设置完要断电重启以太网单元有些参数改了不重启不生效。重启后用CX-Programmer的在线功能确认一下设置是否生效。4.2 上位机侧的Fins节点配置上位机虚拟机这边也要有个Fins节点号。如果用官方FinsGateway它会在安装时让你配一个本地节点号这个号不能跟PLC的节点号冲突。如果用第三方库节点号通常在代码里指定。比如Python的fins库建立连接的时候要传目标PLC的IP和节点号本地节点号有些库会自动处理有些需要手动指定。节点号冲突是隐蔽的坑。有一次我调试半天连不上最后发现虚拟机的节点号跟PLC设成一样的了Fins协议里节点号是网络内唯一的冲突了就通信异常。后来养成习惯虚拟机节点号统一用比PLC大很多的号比如PLC用10虚拟机用200避免冲突。4.3 用测试工具先跑通再写代码写代码之前强烈建议先用现成的测试工具验证Fins通信是否正常。欧姆龙官方有个Fins通信测试工具或者用第三方的Fins调试工具输入PLC的IP、节点号、区域、地址、长度点读取看能不能返回数据。这一步能排除掉大量配置问题。如果测试工具能读到数据说明PLC配置、网络、Fins服务都正常后面写代码只是把同样的参数用代码实现一遍。如果测试工具都读不到那问题一定在配置层面先解决配置再谈代码。我见过太多人跳过这一步直接写代码然后代码报错就开始怀疑代码有问题改来改去其实根子在PLC配置上。先用工具验证再写代码这个顺序能省大量时间。5. 代码实操从零写一个DM区数据采集程序5.1 Python方案用fins库快速实现Python是最快能跑通的方式。装库pip install fins然后写采集代码import fins from fins import FinsTCP # 建立连接 plc_ip 192.168.1.10 plc_port 9600 plc_node 10 local_node 200 client FinsTCP(plc_ip, plc_port, plc_node, local_node) client.connect() # 读DM区从D100开始读10个字 dm_address 100 read_count 10 data client.read_dm(dm_address, read_count) print(DM100-DM109:, data) # 写DM区把D200开始的值改成指定值 write_values [100, 200, 300] client.write_dm(200, write_values) client.close()这段代码的核心逻辑建立TCP连接发Fins命令帧解析响应帧。read_dm内部就是把区域代码0x82、地址100、长度10打包成Fins命令发出去然后把返回的字节流解析成整数列表。实际项目里不会这么简单要加异常处理、重连机制、数据缓存。但先跑通这个最小示例确认能读到数据再往上加功能。5.2 C#方案适合做Windows服务如果采集程序要长期跑在后台C#更合适可以做成Windows服务。用OmronFins或者HslCommunication这类库。using HslCommunication.Profinet.Omron; OmronFinsNet omron new OmronFinsNet(192.168.1.10, 9600); omron.DA1 10; // PLC节点号 omron.SA1 200; // 本地节点号 // 读DM区 var result omron.ReadInt16(D100, 10); if (result.IsSuccess) { short[] values result.Content; // 处理数据 } // 写DM区 omron.Write(D200, new short[] { 100, 200, 300 });HslCommunication这个库在国内工控圈用得很多封装得比较友好支持欧姆龙、三菱、西门子等主流PLC。它的地址格式直接用D100这种欧姆龙习惯的写法不用自己算字节偏移省事。5.3 采集频率与批量读取的优化采集频率不是越高越好。PLC的通信资源有限太频繁的请求会占用PLC的CPU时间影响控制逻辑。一般产线数据采集500ms到1s一次足够了。如果要采的点位多一定要批量读取不要一个点一个点读。比如要读D100到D199这100个字一次读100个比读100次每次读1个效率高几十倍。Fins协议单次最多能读960个字具体看PLC型号充分利用这个批量能力。批量读取的代码示例# 一次性读100个字 data client.read_dm(100, 100) # 然后按需解析 temperature data[0] / 10.0 # D100是温度放大10倍存的 pressure data[1] / 100.0 # D101是压力放大100倍 count data[2] # D102是产量计数这种批量读本地解析的方式是采集程序的标配。我做过一个项目采2000多个点位用批量读取一轮下来不到200ms完全满足秒级采集需求。6. 踩过的坑与排查思路6.1 连接超时但ping得通端口和节点号排查现象虚拟机ping PLC正常但Fins连接一直超时。排查顺序确认PLC的Fins/TCP服务是否开启。有些PLC默认只开UDPTCP要手动开确认端口号。默认9600但有些项目改过要跟PLC设置一致确认节点号。本地节点号和PLC节点号不能冲突确认目标网络号和单元号。跨网段或者多单元的情况下这两个参数不对也会连不上我遇到最隐蔽的一次是PLC的以太网单元设置了仅允许特定IP访问虚拟机的IP不在白名单里ping能通但Fins连接被拒。后来在PLC设置里把虚拟机IP加进去就好了。6.2 读到的数据全是0或者乱码地址和数据类型问题现象连接正常但读回来的数据不对。常见原因地址偏移算错。Fins协议用字节偏移欧姆龙习惯用字地址差2倍。D100在协议里是200字节偏移写成100就读到D50去了数据类型不匹配。PLC里存的是16位整数代码里按32位读就会把两个寄存器的值拼在一起字节序问题。欧姆龙是大端序有些库默认小端读出来高低字节反了排查方法先在PLC编程软件里确认D100的实际值然后用测试工具读同样的地址对比结果。如果测试工具读的对代码读的不对就是代码里的地址或类型处理有问题。6.3 长时间运行后连接断开心跳与重连机制采集程序跑几天后连接断了这是很常见的。原因可能是网络抖动、PLC重启、交换机端口老化等。解决办法是加心跳和重连。每隔一段时间比如30秒发一个轻量的读命令确认连接还活着。如果连续几次失败就关闭连接重新建立。import time def keep_alive(client): try: client.read_dm(0, 1) # 读一个点确认连接 return True except Exception: return False while True: if not keep_alive(client): client.close() time.sleep(5) client FinsTCP(plc_ip, plc_port, plc_node, local_node) client.connect() time.sleep(30)这个逻辑看着简单但能解决大部分跑一段时间就断的问题。生产环境的采集程序重连机制是必须的不能假设网络永远稳定。6.4 虚拟机快照回滚后网络异常的处理虚拟机用快照回滚之后有时候网络会出问题表现为拿不到IP或者网络适配器显示感叹号。这是因为快照回滚后虚拟网卡的状态跟主机侧对不上。解决办法虚拟机设置里把网络适配器先移除再重新添加编辑虚拟网络编辑器还原默认设置虚拟机里禁用再启用网卡实在不行删掉虚拟机目录下的.lck文件和网卡配置文件重启虚拟机这个问题在VMware Workstation和ESXi里都遇到过快照用多了就容易出。我的习惯是快照只保留最近两三个太老的删掉减少这类问题的概率。7. 采集程序上线前的检查清单程序写完了别急着扔到产线上跑。上线前过一遍这个清单能避免大部分现场问题。检查项检查内容常见问题网络虚拟机与PLC同网段ping通端口通桥接选错网卡PLC配置Fins/TCP开启节点号唯一IP白名单默认只开UDP节点号本地与PLC不冲突都设成10地址区域代码、字节偏移正确字/字节混淆数据类型16位/32位、字节序匹配大端小端反了异常处理超时、重连、日志断线不恢复资源占用CPU、内存、网络带宽采集频率过高持久化数据存储、断点续传重启丢数据这份清单是我从多个项目里总结出来的每次上线前对着过一遍基本能覆盖90%的现场问题。剩下的10%往往是现场环境特有的比如电磁干扰导致网络丢包、PLC固件版本差异导致某些命令不支持这些只能到现场再调。采集程序上线后前三天要重点观察。看日志有没有异常、数据有没有断档、PLC的通信负载是否正常。稳定跑一周之后基本就可以放心了。最后说一个实际体会Fins协议本身不复杂复杂的是现场环境。同样的代码在实验室跑得好好的到现场可能因为一根网线、一个交换机配置、一个PLC参数就卡住。所以做数据采集三分靠代码七分靠调试。把网络和PLC配置的基础打牢代码反而是最简单的一环。虚拟机方案的好处就在于它把环境问题隔离了让你能专注于通信本身出了问题也能快速回滚重来这在现场调试时特别有价值。
返回列表