首页 / 资讯中心 / 文章详情

LabVIEW与FX5U通讯:不装插件用SLMP协议直接TCP读写D寄存器

LabVIEW与FX5U通讯:不装插件用SLMP协议直接TCP读写D寄存器 ★ FEATURED ARTICLE
写上位机跟FX5U通讯这事我算是被各种插件折腾出心理阴影的人。之前做一个产线数据采集的小改造上位机要25毫秒轮询一次PLC里的温度、压力和几个设备状态位。同事张口就是“装个官方组件包吧配置一下就行”我一听就头大装插件、配DLL、对版本号、32位64位坑一堆现场电脑还不能随便重启。后来我干脆不绕弯子直接查了FX5U内置以太网口支持的SLMP协议也就是MC协议的以太网版用LabVIEW自带的TCP节点怼着PLC网口干报文自己组、响应自己拆半天就把轮询跑通了。这篇文章就把这套“不装插件不调DLL、直接怼网口”的玩法完整写出来给做上位机、做LabVIEW和PLC通讯的兄弟们做个参考。这套方案爽在哪一是LabVIEW只需要用到它自带的TCP函数不需要任何第三方库二是SLMP协议本身是开放的、报文格式公开PLC端只要在参数里把SLMP连接打开LabVIEW这边就能以TCP客户端身份直接读写D寄存器、M继电器这些软元件。适合什么人用主要是两类一类是刚接触LabVIEW和PLC通讯、被各种中间件配置搞得头大的电气工程师另一类是已经在用官方插件但觉得太重、想自己掌控底层报文的工控开发者。下面我就按“协议原理—PLC端配置—LabVIEW报文收发—批量读写模板—踩坑经验”这个顺序逐步说清楚。1. 为什么我决定不装MX组件直接用SLMP协议怼网口1.1 先搞明白SLMP协议到底是个什么东西SLMPSeamless Message Protocol可以理解成FX5U这类带以太网口的PLC对外提供的一种“明文敲门协议”。PLC在以太网口上监听一个TCP端口上位机按规定的报文格式把读写指令发过去PLC处理完再按格式把数据回过来。它跟Modbus TCP的思路有点像区别在于软元件的编址体系是PLC厂家自己的D区、M点、X/Y这些概念都直接体现在报文里。对LabVIEW来说这意味着你根本不需要经过OPC、不需要调用DLL、不需要开.NET节点只要会用TCP函数就能跟PLC对话。LabVIEW的TCP节点在函数面板里一直都有处理字节流和字符串也顺手报文里那些十六进制字节用U8数组一拼转成字符串往TCP Write里一塞剩下的就是等响应。类比一下官方中间件相当于你请了个管家管家帮你把饭端到桌上但你要为管家安排房间、给管家发工资而SLMP报文更像你自己去食堂窗口点菜菜单是固定的你按格式报菜名窗口师傅就把菜打给你。前期学菜单要花点时间但一旦会了以后换菜、换窗口都灵活。1.2 直接怼协议的适用边界别什么需求都往上套我必须先泼盆冷水不是所有场景都适合裸写SLMP报文。我推荐直接怼网口的情况是上位机只是做数据采集、状态监控、产线看板需要周期性读D区、M点、少量写入。现场电脑软件环境受限不让随便装组件、不能随意动系统Path。你希望报文可控出问题能从字节级定位不被中间件“黑盒”卡住。不太适合的情况也有如果项目要求读取PLC特殊智能模块的高层数据、需要走厂家私有加密通道、或者要跨三层网络做复杂路由那老老实实用官方中间件或专用网关更省事。另外如果你们团队后续维护的人对底层协议完全不熟也要慎重——裸写报文的上手门槛确实比配置组件高。这就跟开车一样手动挡学会了哪儿都能开但只图省事的人还是开自动挡合适。2. FX5U端先别急着写LabVIEWPLC侧要配置的事2.1 在GX Works3里打开SLMP连接固定IP和端口很多人上来就写LabVIEW程序结果TCP连接死活不通最后发现是PLC参数里压根没开SLMP连接。FX5U的CPU内置以太网口默认并不一定开放这个服务你需要用GX Works3连上PLC在导航窗口里找到CPU参数进入以太网端口设置把SLMP连接相关的选项打开。实际操作中不同固件版本界面位置略有差异但思路一致启用SLMP连接、设置本机端口号、保存并写入PLC、重启生效。端口号这块我给你个建议别用小于1024的端口容易跟系统服务冲突也别用那种一眼就能猜到的值。我在项目里测试的时候用的是5000多的高端口稳定没冲突。还有IP地址强烈建议在PLC参数里给CPU模块设定固定IP别用DHCP随机分配。上位机和PLC必须在同一网段这个不用我多说了但测试前务必用ping确认物理链路是通的。有一个很容易忽略的点SLMP连接参数里通常可以限制允许访问的IP地址。调试阶段为了方便可以先不限制流程跑通后一定要把白名单加上不然车间里任何一台电脑都能读写你的PLC等于把现场设备的命门全敞开了。2.2 软元件编号换算与协议基础字段搞错一个字节就白干SLMP报文里的软元件不是你在梯形图里直接看到的“D100”“M50”那种带字母的地址而是被编码成“软元件代码起始编号”的组合。比如D寄存器软元件代码固定为十六进制 A8起始编号就是寄存器号本身D100对应0x0064。M继电器软元件代码固定为十六进制 90M100同样对应0x0064。X输入软元件代码为 9CY输出为 9D但它们的编号不是简单的BCD转十六进制而是按位编号映射格式比较绕初学建议先拿D和M练手X/Y等把报文跑通再去研究。再强调一下字节序三菱系PLC在以太网报文里默认是小端Little-endian。所谓起始软元件编号在报文中是4字节低2字节放编号高2字节是软元件偏移值大多数D/M场景高2位就是0x0000。还是拿D100举例编号部分在报文里应该是“64 00 00 00”很多人在这一步把顺序写反变成“00 00 00 64”结果PLC直接回一个错误码。报文的另一个关键字段是“点数”。读D区时点数指的是“读多少个字”每个字是2字节读M点时点数指的是“读多少个点”返回的数据按位打包成字节。这里单位很容易混后面实操模板里我会再演示。3. LabVIEW侧搭一个最小读D区模板TCP四件套3.1 组帧把读D100的请求报文按字节拼出来先看一个最常用的例子读D100开始的两个寄存器也就是4个字节我后面打算把它当一个32位浮点数来用。请求报文用十六进制写出来是这样50 00 00 FF FF 03 00 00 00 04 01 00 00 64 00 00 00 02 A8逐段拆开看50 003E帧二进制模式的帧头只要是请求帧就是这个。00网络号单PLC直连时固定为0。FFPC号上位机请求时通常固定为FF。FF 03 00请求目标模块的I/O编号对CPU内置以太网口一般固定这么填不同固件可能有差异以实际抓包或手册为准。00站号单机场景填0。04 01批量读取命令。00 00子命令固定为0。64 00 00 00起始软元件编号D100的0x0064小端排列。02点数表示读两个字。A8软元件代码表示D寄存器。在LabVIEW里组这个报文很简单用“Build Array”把一个个U8常量拼成数组中间可以用输入控件控制起始编号和点数然后“String From Byte Array”转成字符串发给TCP。我自己的习惯是把“构建请求报文”做成一个子VI输入软元件代码、起始编号、点数、读写命令输出完整的Byte数组后续所有读写都复用这一个子VI。3.2 发帧与收帧TCP函数的正确打开方式LabVIEW里的TCP节点位置在函数面板的“数据通信协议TCP”下面核心就四个TCP Open Connection、TCP Write、TCP Read、TCP Close。一个最小读取流程是这样用“TCP Open Connection”连接PLC的IP和端口得到一个连接引用。把上一步组好的请求字符串交给“TCP Write”发给PLC。用“TCP Read”读取响应。这里有个关键点TCP Read要读多少字节响应长度其实是可以提前算出来的。还是读D100两个字的例子响应长度固定等于响应帧的固定头部长度加上数据区长度2个字乘以2字节等于4字节。我实测局域网环境下直接按理论长度读很稳定不会出现半包问题。如果不放心可以把超时设成2秒读不到就报错重发。处理完用“TCP Close”关掉连接或者为了效率不关留着下一轮继续用后面轮询部分会说。这里有个新手常踩的坑TCP Open 成功只是表示TCP握手通了并不代表PLC认为你的报文合法。如果PLC返回的结束代码不是0000说明请求报文里有字段不对比如点数太多、软元件代码错、编号越界要从协议层去排别只盯着网络层。3.3 解帧从字符串里抠出数值对应的响应帧格式大致是这样D0 00 00 FF FF 03 00 00 00 04 01 00 00 00 00 60 41前半部分和请求对得上是帧头D0加一堆回显字段最后的“00 00”是结束代码为0表示成功。结束代码后面才是真正的数据区。读回来的数据字符串怎么变成LabVIEW能用的数值用“Unflatten from String”节点格式字符串根据数据类型填比如读16位无符号整数填U16读32位浮点数填SGL最关键的一步是把字节序改成Little-endian。LabVIEW默认是大端不改的话数值直接乱套明明读回来的电阻值是12.5解析出来可能是5.4e-42这种鬼数字。举个例子如果我读D100和D101两个字把它们组合成一个单精度浮点数。程序框图的处理是先跳过响应头部和结束代码把数据区那4个字节单独截出来连到Unflatten from String格式字符串填SGL字节序选Little-endian输出就是PLC里的那个浮点了。这里我需要多说一句不要想当然地把响应从头到尾整个拿去解析一定要先把前面那一长串回显字段跳过去否则字节对不齐。4. 批量读写模板从单点读升级到产线轮询4.1 批量读M点状态位打包解析产线监控里最常用的除了D区数值就是M点的设备状态。读M点和读D区的报文结构基本一样差异只在中后段。比如读M100开始的8个点请求报文的起始编号是64 00 00 00M100点数改成08软元件代码改成9050 00 00 FF FF 03 00 00 00 04 01 00 00 64 00 00 00 08 90响应数据区的长度不是8字节而是1字节。因为8个M点刚好打包成一个字节最低位对应M100依次往上排。如果读M100开始的9个点数据区就是2字节最后一个字节只用到1个位其余位补0。解析时把对应字节拿过来用“Integer to Boolean Array”或者位运算把每一位拆出来再赋值给面板上的状态指示灯。这个位打包逻辑是SLMP协议里比较绕的地方你要心里有数读M点不是每个点一个字节而是8个点一个字节。点数越多返回字节数等于“点数除以8向上取整”。知道了这个规则批量读几百个M点也不怕你只要把返回的字节数组循环解包就行。4.2 写入D区单个写与批量写报文差异写操作比读操作多一个数据区命令代码也从“04 01”变成“14 01”。拿“写D200为12345”举例请求报文是50 00 00 FF FF 03 00 00 00 14 01 00 00 C8 00 00 00 01 A8 39 30C8 00 00 00是D200的十六进制0x00C8小端排列01是写入字数A8是D寄存器代码最后的“39 30”是12345的十六进制0x3039按小端排列低字节在前。批量写就是把后面的数据区加长比如写D200和D201两个寄存器就在软元件代码后面依次放两个字的字节。记住一个原则写入数据的排列顺序永远是“起始编号对应的寄存器先写”编号递增的寄存器依次往后排每个寄存器内部又是小端字节序。这个双重顺序搞反了轻则数据错乱重则把设备状态位改错现场出事故不是闹着玩的。我在调试批量写的时候习惯先用一组不会影响设备的测试寄存器验证顺序比如写D1000-D1003确认无误再把地址改成实际控制字。写M点的话数据区同样是位打包写8个M点就是1字节每个位对应一个点。这里要特别小心写M点是有可能直接改变设备动作的联调前必须把设备切到手动模式或者摘掉执行机构工业现场的安全第一别问我怎么知道的。4.3 轮询节奏与连接复用很多初学者把“发一次请求、关一次连接”用在循环里结果发现25毫秒周期根本跑不动。原因很简单TCP每次建立连接要握手断开还要挥手来回的网络开销就把周期吃掉了。正确的做法是在While循环外面Open一次连接循环体里只做“发送请求—读取响应—解析”一直复用同一个连接引用。PLC那边SLMP连接本身也支持长连接你只要不发关闭指令它的状态就是一直保持的。轮询周期建议留余量。比如产线要求25毫秒刷新一次你PLC扫描周期如果是5毫秒网络来回占1到2毫秒理论上是够的但现场有交换机、可能有线缆干扰我一般把周期设定在15到20毫秒留出余量。真遇到偶发超时不要盲目缩短周期先抓包看是谁慢。另外我会用“生产者/消费者”结构把通讯和UI分开一个循环专门负责TCP收发和报文解析把结果放进队列另一个循环从队列取数据刷新显示。这样即使UI某帧卡了一下通讯循环也不会被拖累数据不会积压到断开。5. 实测最容易翻车的五个细节个人经验5.1 端口没通先查PLC参数别急着敲代码连接不上时我按这个顺序排查先ping通PLC的IP不通就是网线、IP地址、VLAN问题通了之后用简单的TCP测试工具比如各类网络调试助手连一下PLC端口连不上多半是PLC的SLMP连接没启用或者端口号填错。别在LabVIEW程序里反复改来改去用第三方工具先验证端口可达能省下一半调试时间。5.2 超时但TCP又是通的八成是报文长度不对如果TCP能连上发请求后一直超时最常见原因是报文字节数不对。SLMP对报文长度是敏感的多一个字节少一个字节都可能被PLC当成非法报文丢弃。我踩过一次我把起始编号写成4字节但忘了交换字节序结果PLC直接不响应。这时候可以打开Wireshark或者用PLC侧的在线监视去对照把你发出的报文和PLC接收到的报文字节数做对比别靠肉眼硬猜。5.3 结束代码非0要对表查别慌响应帧里结束代码如果不是“00 00”PLC已经把错误原因用代码告诉你了。我遇到最多的两种一种是点数和软元件代码组合超过上限另一种是写入数据长度和点数不匹配。手里最好备一份协议文档的错误代码表对号入座改起来很快。5.4 字节序与高低字组合数据翻车重灾区前面反复强调小端实际中还有一个容易漏的点FX5U里两个相邻D字组成32位数据时低地址那个字是低16位。比如D100里放的是32位数据低半部分D101里是高半部分。用Unflatten from String解析时格式字符串选U32或SGL字节序选小端结果就是对的。要是你把格式字符串选成U16再手动拼接就很容易把高低字搞反。我的建议是凡是32位数据直接用U32/SGL解析不要手动拆两个16位再拼。5.5 轮询和UI刷新混在一起永远在卡顿不少人喜欢在同一个While循环里又收数据又刷新波形图表结果通讯周期一短图表刷新慢整个循环被拖住TCP读响应就跟着超时。正确的做法就四个字解耦。通讯循环只做收发和解析UI循环只管显示中间拿队列或者通知传递数据。这样做完之后你会发现即使前面板刷新掉帧采集数据也不会断。最后再分享一个小经验这套“LabVIEWSLMP裸报文”的玩法学会之后很多带以太网口的PLC都能套用区别只在软元件代码和报文头字段。我后来索性把这套报文组帧和解析逻辑封装成了一个内部库换PLC型号就只改参数表。从一开始排斥中间件、到研究协议、再到自己封装最大的体会是底层东西掌握在自己手里调试时的底气和效率是完全不一样的。如果你现在正卡在插件配置的泥潭里不妨试试我说的这条路直接怼PLC网口真的爽。
阅读完成 · 觉得有帮助?
咨询建站