ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

SCL标准化编程:UDT、状态机与多重实例的阀门函数块

SCL标准化编程:UDT、状态机与多重实例的阀门函数块 简介这份资源面向工业自动化领域的PLC编程人员聚焦SCL标准化编程中的多功能阀门控制函数帮助解决电磁阀、气动阀、电动阀等不同驱动类型阀门在编程中接口不统一、逻辑重复、复用性差的问题。资源包内含1个docx文档压缩包约101KB文档结构完整按目录划分为阀门驱动类型、控制开关位置与方式、状态输入点、控制输出点等基础说明以及SFC_SCL_Vavle函数的接口定义、参数含义与函数逻辑等核心内容。在函数部分文档详细列出输入参数io_STW状态字、io_CTW控制字、i_Mode模式控制字、输出状态字o_Status以及input、output、inout、本地变量与临时变量的划分并逐条说明各参数在阀门位置反馈、动作命令、手动自动远程模式切换中的作用函数逻辑则覆盖LCC信号、MCC信号、阀体信号、开关到位延时、开关超时、综合故障、综合报警、故障复位与开关就绪等处理环节。该资料已有427人学习适合希望统一阀门控制接口、提升代码可读性与可维护性的自动化工程师参考。1. 从 32 个阀门复制粘贴说起SCL 标准化编程到底标准在哪现场有 32 台气动球阀梯形图里每个阀都是“开输出、关输出、开限位、关限位、故障延时”五段逻辑改一个延时参数要改 32 次。SCL 标准化编程要解决的正是这种重复把阀门控制封装成一个带明确接口的函数块用 UDT 统一信号类型用状态机描述动作顺序。多功能阀门函数不是把梯形图翻译成 SCL而是让同一套代码适配单电控、双电控、常开、常闭、带反馈和不带反馈的阀门。只要接口不变换阀门型号、换 PLC 平台调用层几乎不用动。读者如果是做产线改造、水处理、暖通或汽车焊装的电气工程师这套写法能把调试时间从“逐个改点”压到“改参数、看状态字”。2. 用 UDT 定义阀门接口SCL 标准化函数的数据底座2.1 阀门 UDT把限位、反馈、故障打包成结构体在博途里先建一个 UDT命名如UDT_Valve。不要小看这一步UDT 是 SCL 标准化函数的地基。如果每个阀门都用零散的 Bool 变量函数接口会有二十多个引脚调用时容易接错位。UDT 把同一类信号归到一个结构里调用时只传一个变量。常见做法是把阀门拆成三组命令组开、关、停、反馈组开限位、关限位、故障、状态组状态码、报警字、超时时间。这样 HMI 面板、报警系统和诊断逻辑都能共用同一份数据。表UDT_Valve 成员建议成员名数据类型方向说明EnableBool输入阀门使能来自设备层AutoModeBool输入自动/手动切换Cmd_OpenBool输入自动命令开Cmd_CloseBool输入自动命令关Cmd_StopBool输入停止/保持InterlockBool输入互锁条件TRUE 允许动作FB_OpenedBool输入开到位反馈FB_ClosedBool输入关到位反馈Out_OpenBool输出开阀输出Out_CloseBool输出关阀输出FaultBool输出综合故障StateInt输出当前状态码AlarmCodeWord输出报警位TimeoutTime参数动作超时时间这张表就是接口契约。以后无论阀门是气动、电动还是液压只要信号能映射到这些成员函数块就不用改。UDT 的另一个好处是支持多重实例32 个阀门只需要一个Array[1..32] of UDT_Valve配合 FB 的多重实例数组代码量线性下降。2.2 命令字与状态字的位定义为什么不用一堆 Bool有人喜欢把报警做成十几个 Bool超时报警、限位冲突、反馈丢失、互锁未满足。在小型项目里没问题但到了标准化函数里Bool 会让接口膨胀。更常见的做法是用一个 Word 做报警字一个 Int 做状态码再用常量定义位含义。状态码用于描述阀门生命周期报警字用于记录具体原因。两者分开的好处是HMI 显示“阀门故障”时工程师可以进一步看到“超时 关反馈丢失”。表报警字位定义示例位名称含义触发条件0ALM_TIMEOUT动作超时输出动作后超过 Timeout 未到位1ALM_LIMIT限位冲突开限位与关限位同时为 TRUE2ALM_FB_LOST反馈丢失输出断开后限位仍保持3ALM_INTERLOCK互锁未满足动作命令存在但 Interlock 为 FALSE4ALM_CMD命令冲突同时收到开和关命令5ALM_ENABLE使能丢失运行中 Enable 变为 FALSE状态字则用 Int 枚举0空闲10正在开20已开30正在关40已关99故障。这样写状态机时CASE 分支清晰在线监控也直观。2.3 在博途 SCL 中声明 UDT 类型变量与多重实例建立 UDT 之后在 DB 或 FB 的静态变量里声明。SCL 中引用 UDT 成员用点号。例如// 在全局 DB 中声明阀门数组 VAR_GLOBAL Valve : ARRAY[1..32] OF UDT_Valve; END_VAR // 在 FB 内部声明多重实例 VAR ValveFB : ARRAY[1..32] OF FB_Valve; END_VAR // 调用时把 UDT 传进去 FOR #i : 1 TO 32 DO #ValveFB[#i](Valve : #Valve[#i]); END_FOR;这段代码的逻辑是UDT 只描述数据结构FB 负责逻辑。全局 DB 保存 32 个阀门的数据FB 的多重实例数组保存每个阀门的状态机内部变量。参数说明Valve : #Valve[#i]是 InOut 传递FB 内部可以直接修改 UDT 的 Out 和 State 成员FOR 循环批量调用新增阀门只需改数组上限。注意如果阀门数量在编译期不确定可以用可变数组或分开声明但多数产线项目固定数量数组最省事。博途中使用优化访问的 DB 时多重实例效率更高也支持在线修改单个成员而不下载整个 DB。3. 多功能阀门函数 FB 的 SCL 实现开、关、停、超时与互锁3.1 函数接口设计In、InOut、Static 各放什么接口设计决定函数能不能复用。我的习惯是外部命令和配置放VAR_INPUTUDT 数据放VAR_IN_OUT输出镜像放VAR_OUTPUT状态机和定时器放VAR静态。不要把 HMI 命令直接连到输出也不要让 FB 内部直接访问全局 DB否则换项目时拖泥带水。下面是一个最小接口版本。表FB_Valve 接口参数区域参数类型说明InputEnableBool使能FALSE 时复位输出InputAutoModeBoolTRUE 自动FALSE 手动InputCmd_OpenBool自动开命令InputCmd_CloseBool自动关命令InputCmd_StopBool停止命令InputInterlockBool互锁允许InputTimeoutTime动作超时InOutValveUDT_Valve阀门数据OutputOut_OpenBool开输出OutputOut_CloseBool关输出OutputFaultBool故障OutputStateInt状态码StaticstatStateInt内部状态StatictonTimeoutTON超时定时器StatictonDebounceTON反馈防抖注意Fault和AlarmCode最好通过 UDT 输出而不是单独引脚这样 HMI 可以批量映射。接口固定后不同阀门类型只改 UDT 里的配置位不改 FB。3.2 用 CASE 写阀门状态机从 IDLE 到 FAULT状态机是阀门函数的心脏。常见做法是用 Int 定义状态用 CASE 分支写动作每个扫描周期只执行一个分支。这样不会出现多个 IF 同时置位输出导致短路。下面是一段可运行的 SCL 骨架。CASE #statState OF 0: // IDLE #Valve.Out_Open : FALSE; #Valve.Out_Close : FALSE; #Valve.Fault : FALSE; #Valve.AlarmCode : 0; IF #Enable AND #Interlock THEN IF #Cmd_Open THEN #statState : 10; ELSIF #Cmd_Close THEN #statState : 30; END_IF; END_IF; 10: // OPENING #Valve.Out_Open : TRUE; #Valve.Out_Close : FALSE; #tonTimeout(IN : TRUE, PT : #Timeout); IF #Valve.FB_Opened THEN #statState : 20; ELSIF #tonTimeout.Q THEN #Valve.AlarmCode : 16#0001; #statState : 99; END_IF; 20: // OPENED #Valve.Out_Open : FALSE; #Valve.Out_Close : FALSE; IF #Cmd_Close THEN #statState : 30; ELSIF NOT #Enable THEN #statState : 0; END_IF; 30: // CLOSING #Valve.Out_Open : FALSE; #Valve.Out_Close : TRUE; #tonTimeout(IN : TRUE, PT : #Timeout); IF #Valve.FB_Closed THEN #statState : 40; ELSIF #tonTimeout.Q THEN #Valve.AlarmCode : 16#0001; #statState : 99; END_IF; 40: // CLOSED #Valve.Out_Open : FALSE; #Valve.Out_Close : FALSE; IF #Cmd_Open THEN #statState : 10; ELSIF NOT #Enable THEN #statState : 0; END_IF; 99: // FAULT #Valve.Out_Open : FALSE; #Valve.Out_Close : FALSE; #Valve.Fault : TRUE; IF #Enable AND NOT #Cmd_Open AND NOT #Cmd_Close THEN #statState : 0; // 复位条件 END_IF; END_CASE;逻辑说明IDLE 等待命令OPENING 置开输出并启动超时到位后进入 OPENED 并切断输出CLOSING 类似FAULT 锁存故障。参数说明#tonTimeout(IN : TRUE, PT : #Timeout)每个扫描周期调用PT使用接口传入的超时时间16#0001对应报警字第 0 位超时。注意状态切换要加互锁判断不能只靠命令。状态码与报警字分开HMI 只读状态码就能画动画报警字用于诊断。3.3 超时、限位冲突与故障锁存超时用 TON 实现但要注意进入动作状态时启动离开动作状态时复位。如果只在 CASE 分支里写TON(IN : TRUE)离开分支后 TON 不再被调用输出可能保持。稳妥做法是在 CASE 之前统一调用定时器或者显式复位。限位冲突检测开限位和关限位同时为 TRUE 超过防抖时间直接置报警位。故障锁存则用状态 99 实现只有使能且无命令时才允许复位避免故障自动消失。表常见故障与处理故障现象报警位检测条件处理方式动作超时bit0TON.Q 且未到位停输出进入 FAULT限位冲突bit1FB_Opened AND FB_Closed 持续停输出报警反馈丢失bit2输出断开后限位仍为 TRUE报警但可继续互锁未满足bit3命令存在且 InterlockFALSE不动作报警命令冲突bit4Cmd_Open AND Cmd_Close不动作报警使能丢失bit5Enable 下降沿且正在动作停输出回 IDLE这些报警位可以合并成一个 Word 写入Valve.AlarmCodeHMI 用位映射显示详细文本。注意故障锁存后必须满足使能且无命令才允许复位否则现场会出现“复位后马上又报故障”的循环。3.4 手自动切换与互锁链的标准化写法手自动切换不要散落在各个阀门逻辑里。标准做法是在 FB 内部统一处理AutoModeTRUE时使用 Cmd_Open/Cmd_CloseAutoModeFALSE时使用 HMI 手动命令。手动命令建议加脉冲或长按判断避免误碰。互锁链则通过 InOut 或 Input 传入一个已经汇总好的 Interlock 信号FB 不关心具体工艺只判断允许不允许。这样工艺互锁在上一层做阀门函数只负责执行。// 手自动命令选择 IF #AutoMode THEN #statCmdOpen : #Cmd_Open; #statCmdClose : #Cmd_Close; ELSE #statCmdOpen : #Valve.ManualOpen; #statCmdClose : #Valve.ManualClose; END_IF; // 互锁未满足报警 IF (#statCmdOpen OR #statCmdClose) AND NOT #Interlock THEN #Valve.AlarmCode : #Valve.AlarmCode OR 16#0008; END_IF;逻辑说明手动命令放到 UDT 里HMI 可以直接写互锁不满足只报警不动作。参数说明ManualOpen、ManualClose需要在 UDT 中增加16#0008是 bit3。这样写的好处是自动程序调试时不受 HMI 影响手动模式也能单独测试阀门。4. 多实例、HMI 与批量调用把阀门函数接进真实 PLC 项目4.1 多重实例与数组调用一台 PLC 带 32 个阀门的写法32 个阀门如果每个都建一个背景 DB项目树会臃肿跨版本复制也容易错。西门子 PLC 的多重实例数组可以把 32 个 FB 实例塞进一个数组配合全局 UDT 数组调用代码只有几行。这是 SCL 标准化编程最舒服的地方代码量不随设备数量增长而是随设备类型增长。表单实例与多重实例数组对比项目单实例背景 DB多重实例数组DB 数量每阀一个32 个一个数组实例调用方式逐个调用FOR 循环新增阀门新建 DB 拖拽块改数组上限在线监控分散一个表格看全部移植容易漏整块拷贝调用示例// 全局 DBValveData // 静态变量ValveFB : ARRAY[1..32] OF FB_Valve FOR #i : 1 TO 32 DO #ValveFB[#i]( Enable : #Enable[#i], AutoMode : #AutoMode[#i], Cmd_Open : #CmdOpen[#i], Cmd_Close : #CmdClose[#i], Interlock : #Interlock[#i], Timeout : #Timeout[#i], Valve : #ValveData.Valve[#i] ); #ValveData.Valve[#i].Out_Open : #ValveFB[#i].Out_Open; #ValveData.Valve[#i].Out_Close : #ValveFB[#i].Out_Close; #ValveData.Valve[#i].Fault : #ValveFB[#i].Fault; #ValveData.Valve[#i].State : #ValveFB[#i].State; END_FOR;逻辑说明循环调用同一个 FB把每个阀门的 UDT 传进去输出再回写到 UDT方便 HMI 读取。参数说明#Enable、#AutoMode等是每个阀门的输入数组可以来自工艺逻辑#ValveData.Valve[#i]是全局数据。注意 FB 的 InOut 参数必须在调用时提供实际变量不能为空。如果 32 个阀门的命令来自不同的设备模块可以把输入数组也做成 UDT进一步减少接口。提示多重实例数组的索引最好与阀门编号一致现场调试时不容易对错。4.2 HMI 面板映射与报警文本标准化标准化函数的好处是 HMI 也可以标准化。WinCC 或精智面板里建一个阀门面板接口连接Valve.State、Valve.Fault、Valve.AlarmCode三个变量。面板内部根据状态码显示颜色0 灰、10/30 闪烁、20/40 绿、99 红。报警文本用报警字位映射避免每个阀门写一套。常见做法是建立一个报警文本库文本内容与 bit0~bit5 一一对应。表HMI 状态码映射State显示颜色文本0空闲灰待命10正在开绿闪开阀中20已开绿开到位30正在关黄闪关阀中40已关黄关到位99故障红故障查看报警字这样一套面板可以复制到所有阀门只改变量连接。报警字在 HMI 脚本里做位判断或者在 PLC 里把 Word 拆成 Bool 数组供 HMI 直接使用。博途的 HMI 支持数组变量连接配合 UDT 可以一次连接 32 个阀门调试时非常省时间。4.3 用 PLCSIM 做阀门函数仿真与在线调试写完 SCL 不要直接上机先在 PLCSIM 里跑。仿真能验证状态机跳转、超时时间和报警锁存。常见的调试步骤强制 Enable 和 Interlock 为 TRUE给 Cmd_Open 一个脉冲观察 State 从 0 到 10手动置 FB_Opened 为 TRUE观察 State 到 20去掉 FB_Opened等超时观察是否进入 99。PLC 在线时可以用监控表把 Valve 数组展开看每个阀的状态和报警字。// 仿真用测试代码在 OB1 中临时调用一个测试阀 #TestValve( Enable : TRUE, AutoMode : TRUE, Cmd_Open : #TestOpen, Cmd_Close : #TestClose, Interlock : TRUE, Timeout : T#5S, Valve : #TestValveData );逻辑说明测试代码只用于仿真正式项目应放在设备控制层。参数说明T#5S缩短超时便于观察#TestOpen、#TestClose可以在监控表里手动修改。注意PLCSIM 里 TON 的计时依赖扫描周期仿真时间可能与实际 PLC 有偏差但逻辑验证足够。用状态码和报警字做断点比在梯形图里逐行找故障快得多。5. 进阶让阀门函数可配置、可诊断、可移植5.1 参数化配置常开/常闭、单/双电控、反馈类型多功能阀门函数要适配不同执行机构靠的是配置位而不是改代码。在 UDT 里增加Config字bit0 表示常开阀bit1 表示双电控bit2 表示无反馈。常开阀在输出逻辑上取反双电控需要开/关两个输出无反馈阀则用输出状态加超时判断。配置位在 FB 初始化时读取运行时只判断一次。// 配置位解析 #statNO : #Valve.Config.0; // 常开阀 #statDouble : #Valve.Config.1; // 双电控 #statNoFB : #Valve.Config.2; // 无反馈 // 输出逻辑 IF #statDouble THEN #Valve.Out_Open : #statOpenCmd; #Valve.Out_Close : #statCloseCmd; ELSE // 单电控开输出和关输出互斥 #Valve.Out_Open : #statOpenCmd AND NOT #statCloseCmd; #Valve.Out_Close : #statCloseCmd AND NOT #statOpenCmd; END_IF;逻辑说明双电控允许两个输出同时存在单电控必须互斥。参数说明Config位在 HMI 参数页设置statOpenCmd来自状态机。注意常开阀的限位逻辑要反过来用否则状态机会误判。5.2 首故障记录与状态字诊断标准化函数除了控制还要能诊断。首故障记录的实现方式在报警触发时如果 AlarmCode 还是 0就记录当前状态码和报警位后续故障不再覆盖。这样现场看到的是最先发生的原因而不是连锁反应。可以用一个FirstFault结构保存。表首故障记录字段字段类型说明FaultCodeWord第一个报警位FaultStateInt故障发生时的状态码FaultTimeTime故障发生时间戳FaultCountInt故障次数5.3 移植到不同 SCL 平台的注意事项不同 PLC 的 SCL 语法有差异。博途的 SCL 支持 UDT、多重实例、优化访问代码可以写得很结构化CODESYS 系 PLC 也支持类似写法但 UDT 声明和定时器调用略有不同三菱的 ST 语言不支持西门子的多重实例数组需要用结构体数组加功能块调用。移植时把 UDT 定义和 FB 逻辑分开先改数据类型再改定时器接口最后调整调用方式。只要接口表不变阀门函数的逻辑可以复用八成以上。移植后先在 PLCSIM 里跑一遍 32 个阀门的循环调用确认状态码和报警位没有偏移再下载到目标 PLC。本文还有配套的精品资源点击获取
返回列表