
做工业自动化的朋友应该都遇到过这种场景现场一堆设备PLC是各个品牌混着来的上位机要采集数据MES要要数据云平台也要数据。早期我折腾Modbus TCP轮询、OPC DA还得配DCOM烦得要命。后来项目里切到Codesys平台开始认真研究OPC UA才发现这玩意儿确实能把这些乱七八糟的通信需求捋顺。这篇就把我在实际项目里配置Codesys OPC UA通信的完整经验写出来从服务端怎么开、符号表怎么弄到客户端怎么连、常见坑怎么踩一次讲透适合正在做Codesys项目或者准备用OPC UA打通上层系统的工程师参考。1. 一上来先弄明白Codesys里那么多通信协议为什么偏偏OPC UA地位特殊1.1 Codesys的通信矩阵从Modbus到OPC UA各自在什么层级干活Codesys本身是个软PLC平台但它跟传统硬PLC最大的区别在于整个运行环境跑在通用硬件上通信协议栈也是以库和组件的形式叠加。你这会儿打开一个Codesys工程往设备树里拖几个以太网主站、串口主站能看到Modbus TCP、Modbus RTU、EtherCAT、PROFINET、EtherNet/IP一堆选项每个协议解决的是不同层级的问题。Modbus TCP和EtherCAT这类协议本质上是PLC和现场设备之间的“车间语言”承担的是I/O扫描、伺服运动控制、现场仪表采集这些实时性要求高的任务。一旦数据要往上走交给MES、SCADA、数据库、云平台再用Modbus去轮询就吃力了一方面数据模型太扁平只有寄存器地址和线圈没有语义另一方面安全机制基本为零跨网段、跨防火墙折腾起来特别痛苦。OPC UA在Codesys里的定位是“上位机信息集成层”的通信协议它不抢实时控制那部分活而是把PLC内部的结构体、数组、变量、诊断信息打包成一个带语义的地址空间让外部系统可以按名字、按结构去读。所以我的项目里通常是这样分工设备层用EtherCAT车间层用OPC UA两者各管一段互不冲突。1.2 OPC UA到底解决了什么痛点语义、安全、双向通信先说语义。以前用OPC DA客户端读到的是Variant数据你得自己心里记住寄存器40001是温度、40002是压力OPC UA直接给你一套信息模型变量的名字、数据类型、单位、工程范围、描述都是编码在地址空间里的客户端浏览节点树就跟看XML一样清晰。数据可视化、报警、历史归档都方便很多。其次是安全。OPC UA内置了证书机制支持Basic256Sha256等安全策略客户端和服务端要互相验证身份才能建立会话这比Modbus那种裸奔的明文通信强太多。碰到工厂网络的IT部门做安全审计拿OPC UA出来解释对方基本能接受。第三是双向通信不光是上位机读PLCPLC也可以主动往客户端推数据、调用客户端的方法、读客户端的变量。这在以前很难实现现在做设备远程诊断、反向写参数都顺手多了。另外OPC UA自带历史数据模型虽然Codesys自带的OPC UA历史功能不如专业历史库强但配合第三方软采网关也能做出不错的效果。2. Codesys侧OPC UA服务器配置全流程从项目设置到变量开放2.1 环境准备版本、授权和运行时选型我的习惯是新项目一律用Codesys V3.5 SP19以上的版本。OPC UA服务器这个功能在Codesys里不是免费午餐它属于运行时组件不同的设备厂商做OEM时可能内置了授权也可能单独卖授权。你打开Codesys Control Win V3或者Linux版本在设备树里找“OPC UA”这个子项如果能看到节点说明运行时自带了OPC UA组件但能不能跑还要看授权没授权的情况下服务端能起来但可能只允许短时间连接或者限制变量数量。如果你是搭测试环境我建议用Codesys Control Win V3加笔记本自带网卡跑软PLC模拟调试OPC UA完全够用。如果是现场工控机优先考虑Linux版本或者加固过的Windows版本稳定性和资源占用都更好。另外要提醒一句OPC UA服务端是跑在Codesys Runtime里的跟编程环境不是一回事所以调试时要保证PC和运行PLC的IP网络互通而不是只开着编程软件就能连。2.2 符号配置是成败关键让外部客户端看得到你的变量这是整篇里最让我踩坑的地方。很多新手把OPC UA服务器启动了UaExpert也能连上但节点树里空荡荡的什么都看不到原因就是符号配置没做。Codesys的变量默认对OPC UA是“不公开”的你必须显式告诉系统哪些变量要对外暴露。在工程树的“Application”上右键进“项目设置”找到“符号和映射”然后勾选“构建时创建符号表”再把需要暴露的变量或结构体的“符号”属性设为“仅显示或者可读写”。如果你的变量很多我推荐在“符号和映射”里统一管理按命名空间分组导出成XML检查一遍再确认是否包含POU、全局变量、I/O映射。有个细节符号配置里“支持无符号访问”和“支持用户管理”这两个选项要分别理解。无符号访问是指客户端可以不带用户名密码直连但安全策略一般还是要求有证书用户管理则是指是否启用Codesys内部的用户权限系统。我的建议是测试阶段可以把两者都打开简化调试生产环境务必关闭匿名访问给外部客户端分配独立用户并严格限制权限。2.3 启用OPC UA服务器端口、安全策略和证书信任完成符号配置后在设备树中找到“OPC UA”组件右键选择“激活”或直接把它拖到运行设备上。然后进入它的参数属性这里有几个关键参数。端口号默认是4840如果现场工业网里有多个OPC UA服务器可以给每台设备单独分配端口避免冲突但客户端连接时URL也要跟着改。安全策略方面我强烈建议生产环境至少使用Basic256Sha256签名和加密都打开不要图方便选None。测试环境可以先用None把链路跑通但不代表可以保持到上线。证书这块是前期最折磨人的Codesys运行时会自动生成一个自签名证书客户端第一次发起连接时双方会交换证书客户端那边会提示是否信任服务端证书同样服务端也可能提示是否信任客户端证书。如果你用的是UaExpert第一次连接时一定要在证书对话框里勾选“信任服务器”否则即使URL正确也进不了会话。在Codesys侧偶尔需要到证书存储目录下手动添加客户端证书特别是客户端用C#、Node-RED这类库时不会自动弹出信任提示你要把客户端证书导出通过OPC UA组件属性里的“证书”标签页导入。3. 客户端对接的几种实用姿势UaExpert、C#、Qt、Node-RED全试过3.1 用UaExpert快速验证通信链路5分钟定位问题我几乎每个项目调试的第一步都是打开UaExpert。这是OPC基金会官方出的免费客户端功能很强。连接时填好URL形如opc.tcp://192.168.1.10:4840然后选好安全策略和消息模式再选择客户端证书点击连接。如果一切正常左边能看到地址空间浏览到“Objects”下的“DeviceSet”就能看到你的程序按命名空间展开的变量树。如果用UaExpert能读到变量就说明Codesys侧的符号配置、安全策略、端口都没有大问题后面换其他客户端对接基本就是抄公式。如果用UaExpert都连不上就别急着去怀疑C#代码或者Node-RED节点先把网络、证书、服务端状态这一层排查清楚这是效率最高的排查路径。我见过太多人一上来就用代码连结果连错误是证书不信任还是命名空间不对都分不清。3.2 C#上位机连接Codesys用官方库写一个最简轮询器C#是上位机开发里最常见的语言推荐用OPC Foundation官方的UA-.NETStandard库NuGet包名是OPCFoundation.NetStandard.Opc.Ua这是跨平台的实现.NET 6、.NET Framework 4.7.2都能用。核心流程是配置ApplicationConfiguration指定应用名称、证书路径、安全策略然后创建Session连接服务器之后用ReadValuesAsync或订阅方式读取指定节点的值。这里有个很重要的经验节点ID的确定。最稳妥的方式不是手写字符串而是在UaExpert里把节点树中你要的变量右键“Copy NodeId”粘贴到C#代码里比如ns4;sMyApplication.PLC_PRG.Temperature。命名空间的索引数字在不同工程里可能不一样手拼容易出错直接复制能省很多事。写订阅时要创建订阅对象和监控项采样间隔建议设在100ms以上读得太频繁对Codesys运行时负载不友好尤其是变量多的时候。下面是核心代码骨架基于官方库var config new ApplicationConfiguration { ApplicationName CSharpOpcUaClient, ApplicationUri urn:CSharpOpcUaClient, SecurityConfiguration new SecurityConfiguration { ApplicationCertificate new CertificateIdentifier { StoreType Directory, StorePath %LocalApplicationData%\OPC Foundation\CSharpOpcUaClient\pki\own, SubjectName CNCSharpOpcUaClient } }, TransportConfigurations new TransportConfigurationCollection(), TransportQuotas new TransportQuotas { OperationTimeout 10000 }, ClientConfiguration new ClientConfiguration { DefaultSessionTimeout 60000 }, TraceConfiguration new TraceConfiguration() }; await config.Validate(ApplicationType.Client); using var session await Session.Create( config, new ConfiguredEndpoint(null, new Uri(opc.tcp://192.168.1.10:4840), EndpointConfiguration.Create(config)), false, CSharp Session, 60000, null, null ); var nodeId new NodeId(sApplication.PLC_PRG.Temperature, 4); var value await session.ReadValueAsync(null, nodeId, CancellationToken.None); Console.WriteLine($温度: {value.Value});这个库封装得很干净读一个值就这么几行。但要注意证书路径要先创建目录Windows下的%LocalApplicationData%会自动展开Linux下要用环境变量的写法。3.3 从C#到Qt用open62541把Codesys变量接入上位机界面Qt项目一般用C连OPC UA主要靠open62541。这个库是C语言写的但有C封装。如果你用QML做界面可以把open62541客户端封装成QObject暴露signal给QML调用。流程跟C#类似初始化UA_Client设置ClientConfig填写ServerURL调UA_Client_connect连接然后UA_Client_readValueAttribute读变量返回的UA_Variant里装着值。不过公平地讲Qt的OPC UA集成比C#麻烦不少open62541虽然好用但内存管理要非常小心比如读取的Variant要记得UA_Variant_clear不然跑久了内存泄漏很难查。我在一个HMI项目里试过直接调open62541后来还是改成了用C写一个独立的OPC UA采集线程把数据丢到QAbstractTableModel里UI层只做展示这样结构清晰很多。如果你不是一定要桌面端也可以考虑用Node-RED把OPC UA转成MQTT再用Web页面消费开发效率更高。3.4 Node-RED实现OPC UA转MQTT迈向云平台的关键一跳Node-RED在边缘网关场景用得很多特别是需要把现场PLC数据转成MQTT送到IoT平台或数据库的场景。实现起来也不复杂主要用到两个节点node-red-contrib-opcua-client负责从Codesys的OPC UA服务器读数据mqtt out负责发布。先说OPC UA节点的配置它跟UaExpert一样要点“Discover”浏览服务器端节点确认命名空间和节点路径。安全策略一样要选如果Codesys侧禁用了匿名访问要在节点配置里填用户名密码。连接成功后可以用OpcUa-Item这个节点订阅指定的变量也可以写function节点从Msg里解析出NodeId和Value。举个例子我要把PLC_PRG.Temperature每分钟往MQTT Broker发一次流程就是inject(每60秒触发)-OpcUa-Item(读节点)-function(拼JSON)-mqtt out(主题为factory/line1/temperature)。这个流程我实际用在好几个数据采集项目里稳定跑过几个月不用管。如果vars数量多一个很实用的技巧是在Codesys侧把所有需要采集的变量放进一个结构体数组比如DataBlock[100]然后用一个function节点循环读取100个节点批处理。千万别用100个OpcUa-Item节点去订阅那样既乱又容易触发服务器连接上限。4. 打通老牌SCADA和网关工具WinCC和KEPServerEX怎么配合Codesys4.1 WinCC做OPC UA客户端组态里直连Codesys变量西门子的WinCC跟Codesys属于不同生态但OPC UA把两边拉平了。我的做法是在WinCC项目里新建一个“OPC UA”连接通道单位选“SIMATIC OPC UA”然后在变量管理里新建变量地址直接填opc.tcp://192.168.1.10:4840下的节点路径类型跟Codesys保持一致。有些版本还需要单独装SIMATIC OPC UA Scout做证书管理把Codesys运行时的证书导入到Windows证书库否则WinCC连不上。这里提醒一句WinCC做OPC UA客户端时对安全策略的兼容性比UaExpert抗拒一些有时候Codesys侧选了Basic256Sha256WinCC连不上改成Basic128Rsa15甚至None却能连上这是因为WinCC旧版本的安全策略库不够新。解决办法是升级WinCC版本或者确保两边选同一策略。我做某汽车零部件项目时WinCC 7.5处理不了新密钥长度最终统一到Basic128Rsa15才稳定。4.2 WinCC做OPC UA服务器KEPServerEX做网关异构网络的常见架构有些工厂WinCC这边各条产线已经有数据了但更上层的MES想统一采集可以让WinCC把自己做成的OPC UA服务器对外暴露画面变量或归档变量。这样Codesys的数据先到WinCC再由WinCC统一通过OPC UA向上走相当于多了一层中转。这个架构对老产线改造特别友好不用去动原有组态但代价是数据链路过长实时性会下降。KEPServerEX这个软件也值得一提。它是很经典的多协议网关可以通过Modbus、EtherNet/IP等协议把底层的设备数据采上来再通过自带的OPC UA Server接口对外发布。如果你现场既有Codesys PLC又有别的品牌PLC用KEPServerEX就能统一成一个OPC UA地址空间。它的思路是“设备驱动协议转发”跟Codesys里直接开OPC UA服务器本质上不一个逻辑但对外部系统来说一模一样的接口。我通常这样分工Codesys本身开OPC UA管自己的数据如果有第三方老设备需要接入通通扔给KEPServerEX不污染PLC程序。5. 数据采集和数据库集成从PLC到MES的最后一公里5.1 PLC-Recorder怎么读Codesys变量轻量数据采集的一种选择PLC-Recorder是一款国产的软采软件支持通过OPC UA读取Codesys的变量它的特点是配置简单、占资源少还能把数据按周期存成CSV或写入数据库。我试用过一段时间在Codesys侧不需要做额外配置软件填好服务器URL和用户名密码就能看到节点树然后勾选要采集的变量设置采集周期比如100ms就能开始录制。不过有一点要注意PLC-Recorder内部也是OPC UA客户端如果Codesys侧的证书是自签的你要在PLC-Recorder的证书配置里信任服务端证书。而且它的采样周期不能无限快OPC UA通信有网络开销通常采集周期大于50ms比较合理再快就不如直接用EtherCAT或ADS了。相比自写程序这类工具适合快速出数据、重数据存储的场景但要做复杂的逻辑控制和报警处理还是得用面向工程的语言。5.2 Codesys数据怎么落库MySQL第三方库与OPC UA转发两种路径的选择看到热词里有“MySQL的alongwu第三方库”和“Codesys数据库类库”这个我确实折腾过分享一点经验。路径一是直接在Codesys里用数据库库函数直连MySQL比如alongwu大神写的那套第三方库支持连接、查询、插入操作优点是实时性好数据不经过中间层缺点是占PLC运行内存、写库逻辑会耦合进控制程序、数据库宕机还要处理重连我个人不喜欢把它放在核心工艺里。路径二是OPC UA转发到Node-RED或C#中间层再由中间层写入数据库这是数据采集项目的主流做法。Codesys只管把数据暴露给OPC UA客户端中间层负责缓存、断线重连、批量写入。丢失数据可以补采不会干扰控制。如果数据库是MySQL或MariaDBNode-RED里装个node-red-contrib-mysql就能完成插入配合OPC UA节点一个流程就搞定。我个人的经验是涉及工艺参数归档、质量追溯的数据尽量走路径二如果要记录设备自诊断信息且网络不频繁变动走路径一也行。大部分设备数据采集链路的稳定性重要性远超毫秒级延迟。6. 常见问题与排查技巧实录连接不上时的自救手册6.1 客户端连不上Codesys OPC UA服务器的排查清单我先整理一个排查顺序按这个走基本能把问题快速定位到层排查项操作常见原因网络层ping PLC主机的IP检查端口4840通不通IP不在同一网段、防火墙拦截服务端状态Codesys运行时是否启动设备树OPC UA组件是否激活运行时没跑、未激活OPC UA组件安全策略客户端选的安全策略必须与服务端一致服务端强制加密客户端选了None证书信任UaExpert或代码库的证书目录是否信任对方自签证书没导入双向信任未建立符号配置节点树里能否看到变量没生成符号表、变量符号属性未勾选用户权限启用用户管理后用的账号是否有效匿名被禁、密码过期、权限不够从我的经验看项目里八成以上的“OPC UA连接超时”问题出在“防火墙端口”和“证书信任”这两块。工控机上的Windows防火墙默认会拦外部连接你要么开放4840入站规则要么直接关掉专用网络的防火墙。现场的网闸、路由ACL也要提前跟IT确认放开。有些人老觉得是自己程序写错了其实用抓包软件看一眼TCP三次握手通不通就有答案了。第二个高发点是节点树里变量不全。你找了半天只看到Objects - DeviceSet - Device - Program但Program下是空的十有八九是“符号配置”没点“构建时创建符号表”或者构建后没有下载到运行时。记住一个口诀改了变量符号属性必须重新build并下载只改在线值不重下是无效的。6.2 通信性能与安全实践从能连到好用还差哪几步如果只是连上、能读一个值其实离“好用的系统”还远得很。OPC UA通信性能的瓶颈通常在订阅数量和数据批次大小上。订阅时采样间隔设太短、监控项太多会让Codesys运行时每秒处理大量请求导致扫描周期抖动。我建议一次读取的变量控制在500个以内采样间隔不低于100ms变量太多就分多个订阅组或者从被动读取改成服务器端的DataChange订阅让Codesys只在数值变化时推数据显著降低无意义流量。安全这块刚刚说了证书生产环境一定要禁匿名并且建议把用户分配到对应的访问级别。Codesys里“用户管理”可以做权限配置比如只允许读、允许写工艺参数、允许配置通信等。有一回客户要求做产线防错只允许MES系统写特定配方节点其他上位机一律只读我就是靠用户权限实现的。还有一点是监控报警。OPC UA连接断掉的时候很多现场是没感知的数据一动不动你还在看着旧值。建议在采集层加心跳监控比如定时读一个Heartbeat变量超过N秒读不到就置报警或者利用Codesys侧的ChangeDetection事件断线时往消息队列里发一条通知。这个“看着像连上了其实早断了”的坑是数据采集项目里最容易让人背锅的点。最后分享一个经验性的建议如果OPC UA通信动不动就断、延迟不稳先别急着优化客户端代码去查一下Codesys运行时所在设备的CPU占用和网络负载。软PLC跑在通用工控机上如果CPU占用超过50%OPC UA服务器的响应就会出现明显的抖动。我做过一台老工控机CPU常年跑在90%OPC UA连接每几分钟断一次后来把程序里的冗余IO扫描减掉、升级了双网卡分流问题才彻底解决。我在很多项目里都把OPC UA当成PLC对外沟通的“普通话”不管上层是SCADA、云平台还是MES只要对方会说普通话咱们就能对接。选型时也不必死守单一协议现场总线上该用EtherCAT还是用EtherCAT信息层该用OPC UA就用OPC UA两层错开了复杂度反而是最低的。如果你现在还卡在“UaExpert连不上”“节点树看不到变量”这种问题上照着上面的排查清单过一遍十有八九能解决。