西门子PLC结构化编程_水处理系统水泵多备多投

文章目录

  • 前言
  • 一、功能概述
  • 二、程序编写
    • 1. 需求分析
    • 2. 编写运行时间累计功能块
    • 3. 创建自定义数据类型
      • 1. 时间排序数据类型
      • 2. 多备多投数据类型
      • 3. 多备多投切换数据类型
    • 4. 编程
      • 1. 创建DB数据块
        • 1. 多备多投数据块
        • 2. 多备多投切换数据块
      • 2. 创建FB功能块
  • 三、程序调用
  • 总结


前言

在之前的文章中,我们讨论了通过SCL语言实现电机主备互投《西门子PLC常用底层逻辑块分享_电机主备互投》,和多台电机按时间排序均衡运行《电机主备互投功能优化_多台设备均衡运行》的方法。
但实际现场中,经常会遇见4用1备、3用2备、2用2备、2用3备等复杂情况,如果对每种情况分别编程,会使程序过于冗杂,故本文提供一种多备多投的实现方法,假设现场有5台水泵,可根据现场要求,自由选择主动泵数量和备用泵数量,实现主备泵自由切换。


一、功能概述

假设有5台水泵,5台水泵的运行逻辑如下:

  1. 具有以下几种情况:4用1备、2用2备、2用3备、3用2备、1用1备、1用4备等任意组合;
  2. 主泵同时启动,触发切换命令后,按照运行时间由小到大的顺序切换备用泵或主泵;
  3. 每台水泵都有故障信号,当某台泵出现故障或运行信号丢失时,能自动切换到其它泵;
  4. 故障出现后,水泵的运行时间需要保持不变,不能丢失;
  5. 每台水泵有3种状态:1. 作为主泵;2. 作为备用泵;3. 不投用;
  6. 有故障的水泵自动停止,并且不允许启动,直到故障解除;
  7. 可选择投用或不投用“多备多投”功能。

二、程序编写

1. 需求分析

  1. 参考文章《电机主备互投功能优化_多台设备均衡运行》的思路,根据5台电机的运行时间,计算出由小到大对应的序号,遍历1-5,每次启动都启动序号1对应的电机;
  2. 当水泵处于故障状态、不投用状态、运行状态时,可将该水泵的运行时间设置为最大值,即可跳过该水泵,启动下一台。

2. 编写运行时间累计功能块

可参考文章西门子PLC常用底层逻辑块分享_设备运行时间统计。
根据该文章可编写FC块“运行时间累计”,并新建数据类型“时钟”。具体步骤这里不再赘述。

3. 创建自定义数据类型

1. 时间排序数据类型

在这里插入图片描述
图1

2. 多备多投数据类型

在这里插入图片描述
图2

3. 多备多投切换数据类型

在这里插入图片描述
图3

4. 编程

1. 创建DB数据块

1. 多备多投数据块

在这里插入图片描述

图4

2. 多备多投切换数据块

在这里插入图片描述
图5

2. 创建FB功能块

新建FB块“水泵多备多投”,添加如下变量。
在这里插入图片描述
图6
编写如下程序:

REGION 功能已启用、已停止IF #PumpSwitch.StaCmd THEN#PumpSwitch.Running := 1;ELSIF#PumpSwitch.StpCmd THEN#PumpSwitch.Running := 0;END_IF;END_REGIONREGION 调用程序"运行时间累计"(Start := #PumpControl[1].Run,Clock_1Hz := #Clock_1Hz,"Time" := #PumpControl[1].RunTime);"运行时间累计"(Start := #PumpControl[2].Run,Clock_1Hz := #Clock_1Hz,"Time" := #PumpControl[2].RunTime);"运行时间累计"(Start := #PumpControl[3].Run,Clock_1Hz := #Clock_1Hz,"Time" := #PumpControl[3].RunTime);"运行时间累计"(Start := #PumpControl[4].Run,Clock_1Hz := #Clock_1Hz,"Time" := #PumpControl[4].RunTime);"运行时间累计"(Start := #PumpControl[5].Run,Clock_1Hz := #Clock_1Hz,"Time" := #PumpControl[5].RunTime);END_REGIONREGION 计算运行时间FOR #PumpSwitch.N[0] := 1 TO 5 DO#PumpSwitch.Set[#PumpSwitch.N[0]]."Time" :=#PumpControl[#PumpSwitch.N[0]].RunTime.Day * 86400 +#PumpControl[#PumpSwitch.N[0]].RunTime.Hour * 60 * 60 +#PumpControl[#PumpSwitch.N[0]].RunTime.Min * 60 +#PumpControl[#PumpSwitch.N[0]].RunTime.Second; // 程序判断用时间#PumpSwitch.TimeOut[#PumpSwitch.N[0]] := #PumpSwitch.Set[#PumpSwitch.N[0]]."Time"; // 实际显示时间END_FOR;END_REGIONREGION 计算主泵、备泵、运行泵数量#NumMinPump := 0;FOR #PumpSwitch.N[1] := 1 TO 5 DOIF #PumpControl[#PumpSwitch.N[1]].ControlWord = 1 THEN#NumMinPump := #NumMinPump + 1;END_IF;END_FOR;#PumpSwitch.NumMinPump := #NumMinPump; // 计算主泵数量#NumBackupPump := 0;FOR #PumpSwitch.N[2] := 1 TO 5 DOIF #PumpControl[#PumpSwitch.N[2]].ControlWord = 2 THEN#NumBackupPump := #NumBackupPump + 1;END_IF;END_FOR;#PumpSwitch.NumBackupPump := #NumBackupPump; // 计算备泵数量#NumRun := 0;FOR #PumpSwitch.N[3] := 1 TO 5 DOIF #PumpControl[#PumpSwitch.N[3]].Run THEN#NumRun := #NumRun + 1;END_IF;END_FOR;REGION 泵切换命令IF #NumRun < #PumpSwitch.#NumRun THEN#SwitchPump := 1;ELSE#SwitchPump := 0;END_IF;#SwitchPumpR_TRIG(CLK := #SwitchPump); // 如果此刻运行泵数量小于上一时刻运行泵数量,则说明有泵停机,触发泵切换信号END_REGION#PumpSwitch.#NumRun := #NumRun; // 计算运行泵数量REGION 运行泵数量不足报警IF (#PumpSwitch.#NumRun < #PumpSwitch.NumMinPump) AND #PumpSwitch.Running THEN#PumpSwitch.NumFlt := 1;ELSE#PumpSwitch.NumFlt := 0;END_IF;END_REGIONEND_REGIONREGION 无设备运行时,复位启动命令IF #PumpSwitch.#NumRun = 0 THENFOR #PumpSwitch.N[6] := 1 TO 5 DO#PumpSwitch.Pump[#PumpSwitch.N[6]] := 0;END_FOR;END_IF;END_REGIONREGION 故障停机FOR #PumpSwitch.N[12] := 1 TO 5 DOIF #PumpControl[#PumpSwitch.N[12]].Flt OR(#PumpControl[#PumpSwitch.N[12]].ControlWord = 3)THEN#PumpSwitch.Pump[#PumpSwitch.N[12]] := 0;END_IF;END_FOR;END_REGIONREGION 按时间顺序计算序号REGION 故障处理FOR #PumpSwitch.N[8] := 1 TO 5 DOIF #PumpControl[#PumpSwitch.N[8]].Flt OR(#PumpControl[#PumpSwitch.N[8]].ControlWord = 3) OR#PumpControl[#PumpSwitch.N[8]].RunTHEN#PumpSwitch.Set[#PumpSwitch.N[8]]."Time" := 4294967295; // UDInt的最大值为4294967295END_IF;END_FOR; // 将故障泵和没有投用和正在运行的泵时间设为最大值END_REGION// 初始化序号数组FOR #PumpSwitch.I := 1 TO 5 DO#PumpSwitch.Set[#PumpSwitch.I].Sequence := 1; // 初始序号为1END_FOR;// 计算每个元素的序号FOR #PumpSwitch.I := 1 TO 5 DOFOR #PumpSwitch.J := 1 TO 5 DOIF #PumpSwitch.Set[#PumpSwitch.J]."Time" < #PumpSwitch.Set[#PumpSwitch.I]."Time" THEN#PumpSwitch.Set[#PumpSwitch.I].Sequence := #PumpSwitch.Set[#PumpSwitch.I].Sequence + 1; // 遇到更小的数,序号增加ELSIF(#PumpSwitch.Set[#PumpSwitch.J]."Time" = #PumpSwitch.Set[#PumpSwitch.I]."Time") AND (#PumpSwitch.J < #PumpSwitch.I) THEN#PumpSwitch.Set[#PumpSwitch.I].Sequence := #PumpSwitch.Set[#PumpSwitch.I].Sequence + 1; // 处理相同数值的情况,按顺序递增序号END_IF;END_FOR;END_FOR;FOR #PumpSwitch.N[13] := 1 TO 5 DO// 将启动顺序放入存储区,便于上位机显示#PumpSwitch.SequenceOut[#PumpSwitch.N[13]] := #PumpSwitch.Set[#PumpSwitch.N[13]].Sequence;END_FOR;END_REGIONREGION 根据时间顺序切换IF NOT #PumpSwitch.StpCmd THENCASE #PumpSwitch.Step OF0:IF #PumpSwitch.StaCmd AND #PumpSwitch.EnSwitch THEN#PumpSwitch.Step := 1;END_IF;#PumpSwitch.Pump[1] := 0;#PumpSwitch.Pump[2] := 0;#PumpSwitch.Pump[3] := 0;#PumpSwitch.Pump[4] := 0;#PumpSwitch.Pump[5] := 0;1:FOR #PumpSwitch.N[7] := 1 TO 5 DOIF #PumpControl[#PumpSwitch.N[7]].ControlWord = 1 THEN#PumpSwitch.Pump[#PumpSwitch.N[7]] := 1;END_IF;END_FOR; // 所有主泵同时启动#PumpSwitch.Step := 2;2:REGION 触发泵切换命令IF #SwitchPumpR_TRIG.Q AND #PumpSwitch.EnSwitch THENFOR #PumpSwitch.N[9] := 1 TO 5 DOIF (#PumpSwitch.SequenceOut[#PumpSwitch.N[9]] = 1) ANDNOT #PumpControl[#PumpSwitch.N[9]].Flt ANDNOT #PumpControl[#PumpSwitch.N[9]].Run ANDNOT (#PumpControl[#PumpSwitch.N[9]].ControlWord = 3) THENEXIT; // 找到启动顺序为1对应的泵的序号#PumpSwitch.N[9]END_IF;END_FOR;#PumpSwitch.Pump[#PumpSwitch.N[9]] := 1;END_IF;END_REGIONEND_CASE;ELSE#PumpSwitch.Pump[1] := 0;#PumpSwitch.Pump[2] := 0;#PumpSwitch.Pump[3] := 0;#PumpSwitch.Pump[4] := 0;#PumpSwitch.Pump[5] := 0;#PumpSwitch.N[9] := 0;#PumpSwitch.Step := 0;#PumpSwitch.EnSwitch := 0;END_IF;END_REGIONREGION 赋值FOR #PumpSwitch.N[11] := 1 TO 5 DOIF #PumpSwitch.Clear THEN#PumpControl[#PumpSwitch.N[11]].RunTime.Clear := 1;ELSE#PumpControl[#PumpSwitch.N[11]].RunTime.Clear := 0;END_IF;END_FOR;IF NOT "AlwaysFALSE" THEN#PumpSwitch.StaCmd := 0;#PumpSwitch.StpCmd := 0;#PumpSwitch.Clear := 0;END_IF;END_REGION

三、程序调用

在主程序中调用FB块“水泵多备多投”。
在这里插入图片描述
图7
程序分析:

  1. 实际应用时,#PumpControl[1].Run - #PumpControl[5].Run关联水泵1 - 5的运行反馈信号,#PumpSwitch.Pump[1] - #PumpSwitch.Pump[5]关联水泵1 - 5的启动命令,#PumpControl[1].Flt - #PumpControl[5].Flt关联水泵1 - 5的故障信号;
  2. 变量EnSwitch作为使能信号,只有EnSwitch置1时,功能才会正常投用,否则就算按下StaCmd启动按钮也不会实现主备互投;
  3. EnSwitch复位后,主备互投功能取消,此时可自由启停任意水泵;
  4. 按下StpCmd停止按钮后,所有水泵停止运行,EnSwitch自动复位;
  5. 当实际运行泵的数量小于应该运行的数量,会触发NumFlt运行泵数量不足报警,提醒操作员及时处理故障;
  6. 可在上位机画面中为每台泵添加“选择框控件”,关联ControlWord变量,ControlWord=1表示作为主泵,ControlWord=2表示作为备泵,ControlWord=3表示该泵不投用;
  7. 程序会根据选择的主泵数量和备泵数量,自动判断当前的主备互投模式。

总结

本文提供了一种结构化的水泵多备多投方法,可作为标准块应用于生产实际中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/78795.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QT:自定义ComboBox

实现效果: 实现combobox的下拉框区域与item区域分开做UI交互显示。 支持4种实现效果,如下 效果一: 效果二: 效果三: 效果四: 实现逻辑: ui由一个toolbutton和combobox上下组合成,重点在于combobox。 我设置了4种枚举,ButtonWithComboBox对应效果一;OnlyButt…

VS2022+OpenCasCade配置编译

一、Open CASCADE Technology介绍及安装&#xff08;windows10&#xff09; Open CASCADE Technology&#xff08;简称OCCT&#xff09;是一款开源的 3D CAD/CAM/CAE 软件开发平台&#xff0c;广泛应用于工业设计、工程仿真、制造等领域。开源OCC对象库是一个面向对象C类库&…

【OSG学习笔记】Day 12: 回调机制——动态更新场景

UpdateCallback 在OpenSceneGraph&#xff08;OSG&#xff09;里&#xff0c;UpdateCallback是用来动态更新场景的关键机制。 借助UpdateCallback&#xff0c;你能够实现节点的动画效果&#xff0c;像旋转、位移等。 NodeCallback osg::NodeCallback 是一个更通用的回调类&…

全新升级:BRAV-7601-T003高性能无风扇AI边缘计算系统,助力智能未来!

在数字化与智能化飞速发展的今天&#xff0c;AI边缘计算正成为各行各业的核心驱动力。BRAV-7601作为一款高性能无风扇AI边缘计算系统&#xff0c;凭借其强大的硬件配置与丰富的扩展能力&#xff0c;为车路协同、特种车辆车载、机器视觉、医疗影像等领域提供了卓越的解决方案。最…

删除 Git 远程记录并重新设置

删除 Git 远程记录并重新设置 以下是在 Windows 平台上删除当前项目的 Git 远程记录并重新设置远程存储库的步骤&#xff1a; 步骤一&#xff1a;查看当前远程仓库 首先&#xff0c;检查当前设置的远程仓库&#xff1a; git remote -v这会显示所有已配置的远程仓库及其 URL…

有哪些和PPT自动生成有关的MCP项目?

随着AI技术的快速发展, Model Context Protocol(MCP) 作为一种连接大型语言模型(LLMs)与外部工具的开放协议,正在重塑自动化办公领域。在PPT自动生成场景中,MCP通过标准化接口实现了AI模型与设计工具、数据源的无缝整合。以下从技术框架、项目案例、应用场景三个维度展开…

PostgreSQL psql 命令和常用的 SQL 语句整理

PostgreSQL psql 命令和常用的 SQL 语句整理 1、登录PostgreSQL数据库2、psql 命令3、数据库操作4、模式操作5、表操作6、数据操作7、索引操作8、视图操作9、权限操作 1、登录PostgreSQL数据库 在系统的命令行界面&#xff08;如 Windows 的 cmd 或者 PowerShell、Linux 的终端…

【unity游戏开发入门到精通——UGUI】文本输入控件 —— InputField旧控件

注意&#xff1a;考虑到UGUI的内容比较多&#xff0c;我将UGUI的内容分开&#xff0c;并全部整合放在【unity游戏开发——UGUI】专栏里&#xff0c;感兴趣的小伙伴可以前往逐一查看学习。 文章目录 前言1、文本输入控件2、InputField旧文本输入控件组成 一、InputField文本输入…

获得ecovadis徽章资格标准是什么?ecovadis评估失败的风险

EcoVadis徽章资格标准 EcoVadis徽章是对企业在可持续发展&#xff08;环境、劳工与人权、商业道德、可持续采购&#xff09;方面表现的认可。获得徽章需满足以下条件&#xff1a; 完成评估&#xff1a; 企业必须完成EcoVadis的问卷评估&#xff0c;并提交所有必要文件。 评分…

Python初学 有差异的知识点总结(一)

目录 一、基础语法规则 1.注释 2.代码编写 二、基础语法 1.变量 2.数据类型 3.数据类型的转换 &#xff08;1&#xff09;隐式转换 &#xff08;2&#xff09;显示转换 4.标识符 5.运算符 6.字符串 &#xff08;1&#xff09;定义 &#xff08;2&#xff09;拼接 …

Java面试场景深度解析

Java面试场景深度解析 在互联网大厂Java求职者的面试中&#xff0c;经常会被问到关于Java项目中的各种技术场景题。本文通过一个故事场景来展示这些问题的实际解决方案。 第一轮提问 面试官&#xff1a;马架构&#xff0c;欢迎来到我们公司的面试现场。请问您对Java内存模型…

【数据可视化艺术·应用篇】三维管线分析如何重构城市“生命线“管理?

在智慧城市、能源管理、工业4.0等领域的快速发展中&#xff0c;地下管线、工业管道、电力通信网络等“城市血管”的复杂性呈指数级增长。传统二维管理模式已难以应对跨层级、多维度、动态变化的管线管理需求。三维管线分析技术应运而生&#xff0c;成为破解这一难题的核心工具。…

Spring-全面详解(学习总结)

一&#xff1a;概述 1.1 为什么学 解决了两个主要问题 1. 2 学什么 1.3 怎么学 二&#xff1a;系统架构 作用&#xff1a;web开发、微服务开发、分布式系统开发 容器&#xff1a;用于管理对象 AOP:面向切面编程&#xff08;不惊动原始程序下对其进行加强&#xff09; 事…

企业架构之旅(2):解锁TOGAF ADM

文章目录 一、什么是 TOGAF ADM二、TOGAF ADM 的关键阶段架构愿景&#xff08;Phase A&#xff09;业务架构&#xff08;Phase B&#xff09;信息系统架构&#xff08;Phase C&#xff09;技术架构&#xff08;Phase D&#xff09;机会与解决方案&#xff08;Phase E&#xff0…

MySQL 中 SQL 语句的详细执行过程

MySQL 中 SQL 语句的详细执行过程 当一条 SQL 语句在 MySQL 中执行时&#xff0c;它会经历多个阶段的处理。下面我将详细描述整个执行流程&#xff1a; 1. 连接阶段 (Connection) 客户端与 MySQL 服务器建立连接服务器验证用户名、密码和权限连接器负责管理连接状态和权限验…

ETL架构、数据建模及性能优化实践

ETL&#xff08;Extract, Transform, Load&#xff09;和数据建模是构建高性能数据仓库的核心环节。下面从架构设计、详细设计、数据建模方法和最佳实践等方面系统阐述如何优化性能。 一、ETL架构设计优化 1. 分层架构设计 核心分层&#xff1a; 数据源层&#xff1a;对接O…

快速上手Prism WPF 工程

1、Prism 介绍 ​定位​&#xff1a; Prism 是 ​微软推出的框架&#xff0c;专为构建 ​模块化、可维护的复合式应用程序​ 设计&#xff0c;主要支持 WPF、Xamarin.Forms、UWP 等平台。​核心功能​&#xff1a; ​模块化开发​&#xff1a;将应用拆分为独立模块&#xff0c…

React 单一职责原则:优化组件设计与提高可维护性

单一职责原则&#xff08;SRP&#xff09; 在 React 中&#xff0c;组件是构建 UI 的核心单位&#xff0c;而良好的组件设计是保证应用质量和可维护性的关键。单一职责原则是一种设计原则&#xff0c;也适用于 React 组件的开发。它强调每个组件应该只关注一个职责&#xff0c…

css网格布局Grid

一、网格布局适应场景 当涉及到的布局是二维布局&#xff08;元素不止一行或者一列&#xff09;且比较复杂的时候&#xff0c;可以用网格布局&#xff0c;看下面的一个例子&#xff1a; 上图上一个四行三列的网格&#xff0c;布局相对比较复杂。如果你用别的布局方案&#xff…

利用Python生成Xilinx FPGA ROM IP核 .coe初始化文件

以下是一个 Python 脚本&#xff0c;用于生成 Xilinx IP ROM 的.coe 格式初始化文件&#xff0c;假设ROM 深度为 1024&#xff0c;数据位宽为 32bit&#xff0c;使用随机的 32 位无符号数进行初始化&#xff1a; import random# 定义ROM的深度和数据位宽 rom_depth 1024 data…