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

资讯详情

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

欧姆龙NJ/NX PLC的FINS通信与Node-RED可视化实战指南

欧姆龙NJ/NX PLC的FINS通信与Node-RED可视化实战指南 搞工业自动化的朋友应该都有过这种经历设备装好了、程序跑通了老板突然甩过来一句“把这个PLC的数据弄到电脑上做个界面我看看”。如果你用的是欧姆龙NJ/NX系列PLC那么FINS通信就是绕不开的一条路。不夸张地说只要把FINS这套机制搞明白从PLC里读数据、写数据再到用Node-RED做可视化大屏基本就是一条龙的事。先说说这篇文章适合谁看。如果你正在做产线数据采集或者想把NJ/NX的数据接到MES、SCADA、物联网平台又或者单纯想在电脑上写个小工具监控PLC状态这篇文章都适用。我会从硬件侧的网络配置开始讲到Sysmac Studio里的参数设置再到上位机通过FINS/TCP读写数据的实际代码最后在Node-RED里把数据变成仪表盘和实时曲线。整个过程我踩过的坑、绕过的弯都会一并写出来。1. 内容整体设计与思路拆解1.1 FINS协议的本质与选型逻辑FINS是欧姆龙自家定义的工业以太网协议全称是Factory Interface Network Service。它不是欧姆龙拍脑袋发明的私有黑盒而是一套结构非常清晰、层级分明的报文协议。简单理解FINS就是欧姆龙设备之间“对话”的语法规范——谁发给谁、读什么地址、读几个字、数据是什么都规定得明明白白。这套协议的好处在于它不依赖特定品牌的软件包只要你按报文格式把请求发到PLC的端口上PLC就会按同样的格式应答。所以无论你用的是C#、Python、Java还是Node-RED只要学会构造FINS帧就能和PLC通信。这也是我为什么推荐NJ/NX用户优先学FINS而不是一上来就上OPC UA——FINS的报文结构直观、排错容易而且不依赖额外授权。选型时要考虑的另一件事是通信载体。NJ/NX系列支持EtherNet/IP也支持FINS over UDP和FINS over TCP。如果你的系统里全是欧姆龙设备EtherNet/IP当然也能用但如果上位机是自己写的工具或者接的是Node-RED这类开源平台FINS/TCP往往是兼容性最好的方案——Node-RED社区里现成的欧姆龙节点底层走的就是FINS/UDP或FINS/TCP。这篇文章里我以FINS/TCP为主原因后面会展开。1.2 整个链路的架构拆分动手配置之前建议先在心里画一张数据链路图。整套系统分四层第一层是PLC本体NJ/NX系列通过内置网口接入工业交换机第二层是上位机或边缘网关运行采集程序或Node-RED第三层是通信协议也就是FINS报文在TCP 9600端口上跑第四层是数据呈现Node-RED负责把从PLC读到的数据转成JSON、存库、画图表。为什么要这么拆因为排错时每一层都能单独验证。网络通不通用ping测PLC的FINS服务有没有开启看Sysmac Studio的通信设置报文格式对不对用网络调试助手发一帧试试Node-RED能不能解析数据看调试窗口的 payload。分层拆解的好处是任何一个环节出了问题你都能快速定位而不是对着满屏报错一头雾水。2. 硬件准备与Sysmac Studio通信配置2.1 硬件接线与IP地址规划硬件层面的东西其实不复杂但恰恰是最容易被忽略的一环。NJ/NX系列CPU本体自带一个EtherNet/IP端口用的就是普通的RJ45网口。如果你只是单台PLC和电脑通信一根网线直连就行如果现场有多台设备建议老老实实接个工业交换机方便后续扩展。IP地址规划是有讲究的。PLC的IP地址和电脑/Node-RED所在设备的IP地址必须在同一个网段比如PLC设为192.168.250.1电脑就设为192.168.250.10。为什么强调这个因为我见过太多人栽在IP网段不一致上PLC配置了地址但电脑还在自动获取IP结果两边永远ping不通。工业现场如果网络环境复杂建议单独拉一根管理网线给PLC通信用别和办公网混在一起。还有一点要注意NJ/NX的CPU上有两个网口的情况并不少见比如NX102系列自带EtherNet/IP和EtherCAT做FINS通信时务必确认你插的是EtherNet/IP口而不是EtherCAT工业总线的口。插错口的症状很经典——电脑显示网线已连接但网络调试助手发送FINS请求永远没响应。2.2 Sysmac Studio里的通信参数设置硬件接好后打开Sysmac Studio连上PLC在“配置和设置”里找到CPU的以太网设置。这里需要配置几个关键参数IP地址、子网掩码还有FINS通信服务的使能选项。NX系列默认情况下FINS服务通常是启用的但NJ系列有些型号需要手动确认。最稳妥的做法是在CPU的以太网端口设置里找到“FINS服务”确保“FINS/TCP”和“FINS/UDP”都是启用状态。FINS/TCP的默认端口是9600最好不要改除非现场有特殊的端口映射需求。Sysmac Studio里有一个参数容易忽略FINS节点号。这个节点号不是IP地址而是FINS协议内部用来识别设备的编号。NJ/NX系列的CPU本体节点号默认和IP地址的最后一位保持一致比如IP是192.168.250.1节点号就是1。如果这个值被改过上位机请求帧里的DA1字段填错PLC会直接丢弃报文。所以配置完IP后记得进“FINS节点设置”里看一眼实际节点号。2.3 用网络调试助手先验证通道这一步强烈建议不要跳过。在正式写程序或者配置Node-RED之前先用电脑上的TCP调试工具比如NetAssist或者Hercules手动发一帧FINS报文验证通信链路是否通畅。方法很简单TCP客户端连上PLC的IP和9600端口然后发送一条FINS读取命令。一条最基础的FINS报文长这样十六进制46494E5300000000000000000000000000C00000AC000000000001000100018200000000020001前面十几个字节是FINS/TCP的帧头46494E53表示FINS中间的C00000AC000000000001是指令头后面的0001是命令码读0001是响应标识82000000是内存区代码和起始地址0002是读取字数0001表示读1个字。具体字段含义下面会细说这里你只需要确认发送后能收到PLC的响应就说明FINS/TCP通道已经打通。我自己的习惯是每配置一台PLC都先用这个方法发一帧读取命令验证再进入下一阶段。因为一旦确认报文有响应后面所有的问题都被限定在了程序解析和Node-RED配置层面范围小了很多。3. 上位机通信协议实现与代码示例3.1 FINS/TCP帧结构逐字段拆解要真正掌握FINS通信不能只会调现成的库还得懂报文本身。FINS/TCP的报文分为三部分FINS/TCP帧头、FINS指令帧头、FINS指令本体。先说FINS/TCP帧头固定占用16个字节。前4个字节是ASCII字符“FINS”紧接着4个字节是保留字段再后面4个字节是本次会话的数据长度最后4个字节是命令码00000000表示正常数据帧。这部分看起来复杂但你用现成库的时候它基本是自动生成的只有手动构造报文才需要关心。FINS指令帧头是10个字节依次是ICF、RSV、GCT、DNA、DA1、DA2、SNA、SA1、SA2、SID。家用计算机和PLC通信时常用的设置是ICF0x80表示需要响应RSV0x00GCT0x02DNA和SNA都等于0x00表示本地网络DA1填PLC的FINS节点号DA2填PLC的单元号CPU本体为0x00SA1填电脑的FINS节点号SA2填上位机的单元号没有就填0x00SID是序列号每次请求自增就行。后面的指令本体就是具体的操作了。FINS协议里读内存区的命令码是0101写内存区是0102。读指令的格式是命令码2字节 内存区代码1字节 起始地址3字节 读取长度2字节。写指令则在后面继续追加要写入的数据。3.2 用C#实现FINS/TCP读写理论说完了上代码。以下是一段用C#写的FINS/TCP读取示例核心逻辑是构造请求报文、发送、接收响应并解析数据。using System; using System.Net.Sockets; using System.Text; public class FinsTcpClient { private TcpClient _tcpClient; private NetworkStream _stream; private byte _sid 0; public void Connect(string ip, int port 9600) { _tcpClient new TcpClient(); _tcpClient.Connect(ip, port); _stream _tcpClient.GetStream(); byte[] header new byte[] { 0x46, 0x49, 0x4E, 0x53, // FINS 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00 }; _stream.Write(header, 0, header.Length); } public short ReadWord(int dmAddress) { byte[] command BuildReadCommand(dmAddress, 1); _stream.Write(command, 0, command.Length); byte[] response new byte[256]; int len _stream.Read(response, 0, response.Length); // 响应数据的第20字节开始才是有效数据 short value (short)((response[20] 8) | response[21]); return value; } private byte[] BuildReadCommand(int dmAddress, int wordCount) { byte[] frame new byte[28]; // FINS/TCP帧头 Encoding.ASCII.GetBytes(FINS).CopyTo(frame, 0); BitConverter.GetBytes(0).CopyTo(frame, 4); BitConverter.GetBytes(18).CopyTo(frame, 8); BitConverter.GetBytes(0).CopyTo(frame, 12); // FINS指令帧头 frame[16] 0x80; frame[17] 0x00; frame[18] 0x02; frame[19] 0x00; frame[20] 0x01; // PLC节点号 frame[21] 0x00; frame[22] 0x00; frame[23] 0x0A; // 电脑节点号 frame[24] 0x00; frame[25] _sid; // 指令体 frame[26] 0x01; frame[27] 0x01; // 这里只写了核心部分实际还要追加内存区代码和地址 return frame; } }上面代码只展示了框架实际项目中还需要处理内存区代码、地址高低字节转换、响应校验等。C#里常见的坑是大小端问题——FINS协议规定高字节在前而Windows系统默认是小端存储直接用BitConverter一定要记得反转字节序。3.3 FINS内存区地址映射规则FINS协议里不同内存区用不同的代码标识这一点新手最容易糊涂。NJ/NX系列常用的几个区CIO区是0xB0WR区是0xB1HR区是0xB2DM区是0x82。其中DM区在梯形图里写作D100在FINS报文里就是内存区代码0x82 地址100。要注意的是地址的编码方式。FINS报文里的地址是3个字节其中前两个字节表示字地址第三个字节表示位地址。对于DM区这种按字访问的区域位地址填0即可。假如你要读D100到D109这10个字报文里就是0x82, 0x00, 0x64, 0x00, 0x00, 0x0A——注意十进制100要转成十六进制0x64。我在实际项目中还踩过一个坑在Sysmac Studio里定义变量时如果变量类型是INT16位有符号通过FINS读出来的是原始二进制值但如果变量类型是DINT32位一次读一个字的长度就不够了需要连续读两个字再拼成32位整数。所以做上位机时一定要先和PLC工程师确认好变量类型否则读出来的数据会因为位数错位而完全对不上。4. Node-RED可视化配置与实战4.1 Node-RED环境的搭建与节点安装Node-RED的安装有好几种方式最省事的是用npm全局安装npm install -g node-red node-red装完以后浏览器访问http://localhost:1880就能打开编辑界面。如果你是在Linux工控机上跑建议用systemd把它注册成服务这样开机自启、异常重启都能自动处理不用每次手动敲命令。和欧姆龙PLC通信需要装一个社区节点node-red-contrib-omron-fins。在Node-RED右上角的菜单里选择“节点管理”搜索“omron”就能找到。安装完毕后左侧节点面板的“网络”分类下会出现一个FINS节点用它就能直接读写PLC。有一点提醒一下node-red-contrib-omron-fins这个节点底层走的是FINS/UDP协议所以PLC侧的FINS/UDP服务必须启用Node-RED所在设备和PLC之间UDP 9600端口要保持通畅。4.2 用Dashboard节点搭一个实时监控面板数据从PLC读到以后怎么展示是关键。Node-RED里最常用的可视化方式是Dashboard节点。可以通过节点管理安装node-red-dashboard它提供仪表盘、实时曲线、按钮、开关等组件。我的做法是FINS节点按固定周期比如500ms读一次PLC的D区数据输出一个包含多个数值的payload然后让这个payload通过Function节点拆分成独立的topic分别接到不同的gauge节点和chart节点上。这样界面上就能看到转速、温度、产量等多个仪表盘实时刷新。具体配置时要注意node-red-contrib-omron-fins节点的输出是Buffer类型还是解析后的数值取决于你选择的数据类型。如果你读的是“16位有符号整数”节点会自动帮你解析成JavaScript的number类型如果你用“原始Buffer”就得自己调DataView来解析。为了省事建议在节点属性里直接选择数据类型让节点自己解析。4.3 在Node-RED里实现写入操作可视化不光是看还得能操作。比如界面上放一个“开启/停止”按钮点击后要把一个布尔值写到PLC的W区。这个需求用node-red-contrib-omron-fins节点就能实现区别只是指令从“读”换成“写”。从Dashboard的按钮节点输出msg.payload经过一个Function节点把按钮状态映射成PLC要写的值再把映射后的值传给FINS写节点配置好要写的内存区、地址和数据类型即可。这里有个细节按钮节点的输出是“true”或“false”但PLC的W区布尔值对应的可能是1或0你需要在Function节点里做一层转换。我自己的习惯是在写操作前后各加一个调试节点输出写入的结果。这样界面上点击按钮后能在调试窗口立刻看到PLC返回的响应状态。如果响应里出现错误码也能第一时间发现是地址写错还是权限不允许。另外对生产设备做写入操作时界面上务必加确认弹窗别让操作工一不小心就误触了按钮造成设备动作——这个我在实际项目里吃过亏。4.4 进阶把数据推送到EMQX和IoTDB如果你的项目不只是本地可视化还要把数据上云或者存历史库Node-RED的生态就派上大用场了。通过MQTT节点可以把PLC数据发布到EMQX Broker再由后端服务订阅入库。Dashboard只是实时展示数据落到时序数据库里才能做报表分析和历史追溯。我的推荐组合是Node-RED读PLC数据 → Function节点整理成JSON → MQTT节点发布到EMQX → EMQX通过规则引擎把数据写入IoTDB。这套组合的好处是解耦——PLC采集和云端存储之间的逻辑互不干扰哪一段挂了都不影响其他段。Node-RED里只需要再装两个节点node-red-contrib-mqtt和node-red-contrib-iotdb-node按节点说明填好Broker地址和IoTDB连接信息就行。如果你第一次搞这套建议先用MQTT X这个桌面工具订阅Node-RED发布的消息确认JSON格式没问题再配置EMQX到IoTDB的转发规则。数据流这个东西只要格式定了后边就是填地址的事。5. 常见问题与排查技巧实录5.1 通信连不上先排查这五处我做过不少欧姆龙项目的技术支持总结下来FINS通信连不上时80%是下面几个原因。把这五处检查完基本能解决绝大多数问题。第一IP地址是否在同一网段。这个最简单也最容易犯先把PLC和电脑的IP、掩码列出来对比。第二FINS服务是否启用。去Sysmac Studio里看CPU的以太网设置确认FINS服务没有Disabled。第三FINS节点号是否匹配。PLC侧的节点号和上位机请求帧里的DA1必须一致。第四端口是否被防火墙拦了。Windows防火墙默认会拦UDP和TCP的非标端口FINS常用的9600端口往往不在放行列表里。第五PLC型号对FINS的支持范围。NJ/NJ501系列基本没问题但老款CS/CJ系列部分型号默认不开放FINS/TCP需要在PLC系统设置里手动开放。5.2 响应错误码的含义速查FINS协议的响应帧里如果命令没执行成功会返回一个错误码。我刚接触FINS时经常被这串错误码搞得焦头烂额后来把常用的几个整理成了速查表排查的时候对照着看就快多了。错误码含义常见原因0x0101本地节点错误请求帧的网络地址DNA填错0x0201目标节点错误DA1节点号填错PLC不在线0x0301中继节点错误多级网络的路由配置有问题0x1101内存区代码错误指定的内存区代码不存在0x1102起始地址错误地址超出了PLC允许范围0x1103读取长度错误读取的字数超过上限0x2003数据被保护PLC开启了数据写入保护0x2101数据格式错误写入数据的长度和类型不匹配这张表建议收藏。实际做项目时把错误码和错误描述贴到代码注释里后面维护的人会感谢你。5.3 Node-RED读不到数据时的排查思路Node-RED的FINS节点如果读不到数据往往不是协议问题而是数据格式和解析的问题。我的排查顺序是先在FINS节点后面加一个调试节点看输出的payload是什么。如果输出是Buffer类型说明数据读到了但没解析成功检查数据类型设置如果输出显示为0检查PLC地址是否真的有数据如果节点直接报超时错误回到网络层排查——ping PLC能否通UDP端口是否被防火墙拦截。还有一个容易忽略的点node-red-contrib-omron-fins节点有些版本对PLC型号的适配有差异。如果你用的是NX102系列而节点版本比较老可能会遇到请求超时的问题。这时候先确认Node-RED和节点的版本都是最新的再检查节点配置里的“UDP端口”“9600”或“9601”都有可能在用实际以Sysmac Studio里的设置为准。5.4 数据类型转换常踩的坑FINS读上来的数据PLC侧怎么定义类型上位机就怎么解析两边必须严格一致。我这里整理几个常见的坑第一INT和UINT的区别。PLC里定义INT是有符号数如果值是50000FINS报文的两个字节是0xC3 0x50上位机如果按无符号解析就是50000按有符号解析就是-15536。第二实数REAL的读取。REAL是32位浮点数需要连续读两个字然后按IEEE 754标准解析内存中的4个字节。Node-RED里用Buffer.readFloatBE就能读出来。第三字符串的读取。FINS字符串是ASCII码按字节读出来再转字符串就行但注意PLC侧字符串的存放方式是从高位字节开始还是低位字节开始欧姆龙默认是高位字节在前。所以做数据字典的时候一定要把PLC变量名、数据类型、FINS地址、转换公式写清楚。这不是可有可无的文档而是后续排查问题的地图。6. 上手建议与我的个人体会这套从PLC到Node-RED的链路我前前后后在不同的项目里搭过好多次每次都有新问题但每次解决完都能对整个系统的理解更深一层。最后分享两个我自己的实操习惯。第一个习惯是分阶段验证。拿到项目别急着写完整的上位机程序先用网络调试助手手动发几帧FINS报文确认PLC的地址、节点号、数据类型都对得上然后在Node-RED里用Inject节点手动触发一次读取确认数据解析正确最后才去搭Dashboard、配MQTT、接IoTDB。每一步都验证通过再往下走整个项目的调试时间能缩短至少三分之一。第二个习惯是给所有节点加上明确的中文备注。Node-RED的流程图一旦复杂起来节点多了以后光靠默认的节点名根本分不清哪个是读温度、哪个是写风机。每个FINS节点、每个Function节点都命名成“读D100-当前温度”“转换温度单位”这样直白的名字过一个月再回来维护你能省非常多事。如果你只是想快速跑通一个Demo那按这篇文章的顺序操作一个下午就能把数据从PLC里读出来并显示在网页上。但如果你想把它做成一个长期稳定运行的产线数据采集系统我建议你在每一个环节都多花一点时间理解原理——网络层次怎么分、报文结构怎么解析、数据字典怎么建、异常怎么排查。这些东西搞明白了换一个PLC品牌、换一个可视化平台你也能很快上手。欧姆龙的FINS协议并不难难的是你不知道自己不知道什么。希望这篇教程能帮你把“不知道”的部分变成“知道”后面的一切就顺理成章了。
返回列表