六层二部电梯是我近几年带仿真项目时觉得最有代表性的一类课题。表面看就是“按楼层、开开门”但一旦把两部电梯放在同一个控制系统里问题就彻底变了外呼该给谁、两部电梯同时闲着能不能一起出动、运行中的电梯要不要顺路捎带、反向召唤怎么处理。这些恰恰是电梯并梯调度里最值钱的部分。这篇文章就围绕“博途1200PLCHMI六层二部电梯控制系统仿真”这条主线把我从硬件选型、I/O分配、程序结构到HMI联调、踩坑复盘的全过程梳理出来。这个项目适合正在做类似课题的在校学生也适合刚接触S7-1200和触摸屏组态的自动化工程师。它的魅力在于不需要真实电梯井道和电机只靠博途里的PLCSIM仿真环境和HMI画面就能跑通“外呼—调度—运行—平层—开关门—待机”的完整闭环。你能在电脑前反复调逻辑、看趋势、改参数学习效率比直接上现场设备高不少。1. 项目拆解与总体设计思路1.1 为什么选“六层二部”作为仿真对象单部六层电梯核心逻辑就是“呼梯—确定方向—运行—平层—开门—关门—继续或待机”。这是一个非常典型的状态机理解起来不复杂写起来也顺。但加上第二部电梯之后问题立刻从顺序控制升级成了任务分配与冲突消解。每次有人在外面按了上行或下行按钮系统要回答一个关键问题这趟活到底该谁去两台电梯都闲着的时候不能让它们一起冲向同一层否则就是空跑和资源浪费。运行中的电梯如果方向顺路能不能把外呼截走这种“顺向截梯”逻辑是双梯控制里最容易写错、也最容易体现功底的地方。六层的高度也很适合做仿真。楼层太少分区调度体现不出来楼层太多I/O点数和程序量会快速膨胀反而模糊了核心逻辑。六层刚好能覆盖低区、中区、高区三类情况调度算法有足够的发挥空间又不至于把项目做成一个庞大的工程。再加上市面上大部分课程设计和毕业设计都围绕四到七层展开六层这个规模在资料参考和答辩讲解上都比较舒适。1.2 整体链路从硬件选型到仿真运行的思路这套仿真的完整链路是在博途TIA Portal里新建S7-1200项目完成硬件组态、编写控制程序然后把HMI画面挂到同一个项目里最终通过PLCSIM启动仿真PLC再配合HMI仿真运行实现“两套软件、一条数据通道、一块虚拟触摸屏”的效果。不需要下真硬件不需要接真实按钮和指示灯所有楼层信号、门状态、平层传感器全部抽象成PLC变量。PLCSIM里面通过手动修改变量值来模拟现场传感器的通断HMI上的按钮操作则直接写入到对应的PLC变量。这样做有一个优势你可以反复修改程序里的时序逻辑、延时参数、调度优先级甚至随时把一部的梯“切到检修状态”观察另外一部梯如何接管所有楼层召唤。真实设备上这种测试要付出时间和安全隐患仿真环境里只是点几下鼠标的事。不过也要清楚仿真永远不是真实现场的完全等价物。真实电梯必须考虑安全回路、限速器、门锁继电器这些硬逻辑仿真只能把这些外部条件简化成BOOL变量来模拟。这套项目的定位是跑通核心控制逻辑而不是替代真梯验收。1.3 关键选型单CPU控制双梯的可行性很多第一次做双梯的人会纠结两部电梯是不是应该用两台PLC然后组网通信答案是可以但没必要。在这个项目里我选择单台S7-1200同时控制两部电梯理由很直接两部电梯的调度任务需要在同一个逻辑平面里做决策数据共享越直接越好。用同一台PLC两部电梯的状态、呼叫登记、响应标志都存在全局数据块里调度函数读起来方便写起来也不绕。如果拆成两台PLC就必须考虑PROFINET通信、共享数据块的一致性、通信故障时的降级策略。这些内容虽然也很值钱但对于一个以“研究电梯控制逻辑”为核心目标的仿真项目来讲属于把精力花在了偏离主线的地方。单CPU方案的潜在瓶颈是I/O点数这个问题通过扩展模块来解决成本可控逻辑依旧集中在同一台设备上。实际上许多小型商用电梯的控制柜也是这种思路一台主控PLC加输出扩展同时管理轿厢和井道信号。2. 硬件组态与I/O分配方案2.1 CPU与模块配置I/O点数先算清楚再选型号在博途里新建项目、选PLC型号之前先估算I/O点数。这是最重要的一步直接决定你要不要扩展模块也决定后面变量表的结构。我先按常见的电梯信号做了个粗略统计。信号类别单梯输入数量两梯小计说明轿内指令按钮612每层一个各梯独立楼层位置传感器612每层一个井道内检测当前位置平层传感器12只采一个平层信号仿真够用开关门到位24开门到位、关门到位安全类信号36超载、急停、光幕保护外呼按钮10101楼只有上行6楼只有下行2~5楼上下各一其他模式信号24检修、消防各梯独立这样初步统计输入点数大约在48到50个左右。输出侧包括每梯的上下行接触器各1、开关门输出各1、轿内指令按钮指示灯各6、运行方向指示灯各2、外呼指示灯10个公共、蜂鸣器、到站钟等加起来大约35到40个点。S7-1200的常见CPU本体一般带14或16个数字量输入、10到16个数字量输出显然不够用。我的选择是CPU 1214C DC/DC/DC本体14DI/10DQ再扩展一到两个SM1221数字量输入模块和一个SM1222数字量输出模块。为什么用1214C而不是1215C1214C性价比更高扩展能力满足程序空间也足够。这类仿真项目如果选了1215C性能富余很多但用不上资源浪费。2.2 电梯I/O分配表命名规范决定程序整洁度I/O分配最忌讳的是“想到谁写谁”最后变量表乱七八糟程序里根本找不到信号。我当时写了这么一条命名规则输入信号前缀DI输出信号前缀DQ中间用“电梯号信号类型楼层/功能”区分。例如地址符号名数据类型备注I0.0DI_E1_InnerCall_1FBOOL1号梯轿内1楼按钮I0.1DI_E1_InnerCall_2FBOOL1号梯轿内2楼按钮I1.0DI_E1_PosSensor_1FBOOL1号梯1楼位置开关I1.1DI_E1_LevelSensorBOOL1号梯平层信号I2.0DI_E1_DoorOpenEndBOOL1号梯开门到位I2.1DI_E1_DoorCloseEndBOOL1号梯关门到位I3.0DI_E1_OverloadBOOL1号梯超载I3.1DI_E1_EStopBOOL1号梯急停Q0.0DQ_E1_UpContactBOOL1号梯上行输出Q0.1DQ_E1_DownContactBOOL1号梯下行输出这个表里我只列了1号梯的一部分2号梯完全对称地址继续往后排。外呼信号则单独放一个区域比如I4.0~I4.7、I5.0对应各层上行和下行按钮因为外呼是公共信号不属于任何单独一部电梯。命名规范这一步看似繁琐后面调试时会节省大量时间。尤其在HMI组态阶段如果PLC变量名清晰从HMI直接拖拽变量会非常顺畅不用再对照地址表猜来猜去。2.3 井道传感器与执行机构的仿真建模真实电梯的井道是一个很复杂的物理环境但仿真项目里我只需要保留信号层面的等价关系。楼层位置传感器我把它抽象成每个楼层一个BOOL量电梯到达哪一层哪一层的传感器变TRUE其余都变FALSE。平层传感器单独一个BOOL量用于触发精确停车。电梯运行时位置传感器的变化速度取决于程序里的运行计时器这和真实电梯的速度曲线不是一个概念但逻辑判据是等价的。执行机构这一侧主电机被简化成两组输出上行接触器和下行接触器。门电机简化成开门输出和关门输出。真实电梯可能有变频器多段速、抱闸控制、光幕串行通信但在仿真项目里每引入一个真实细节都会增加大量组态工作。我的原则是能用一个BOOL量表达的绝不拆成三个BOOL量能用一个INT楼层变量表达的位置就不挂一串传感器。保持模型精简核心逻辑才有机会被看清楚。3. PLC核心逻辑状态机与双梯调度3.1 程序结构设计为什么用FB而不是全部堆在OB1程序结构上我采用的是OB1 FC调度函数 FB电梯控制 全局DB数据块的结构。OB1是主循环里面按顺序调用两个FB实例分别控制1号梯和2号梯再调用一个FC函数专门处理双梯调度。为什么用FB而不用OB1里一大坨梯形图因为两部电梯的逻辑完全相同FB可以通过多重背景数据块的方式被复用两次。这样程序里只有一份电梯控制逻辑的代码1号梯和2号梯的区别仅仅体现在背景DB不同。以后修改开门延时、平层判定时间改一处就两梯同时生效。现场用这种方式维护比复制粘贴两份逻辑清爽太多。全局DB负责保存两部电梯共享的数据外呼登记数组、外呼给哪部梯的调度结果、当前电梯运行状态、报警标志。调度函数对这部共享数据做读写。FB电梯控制只处理单梯内部逻辑它不关心谁是调度者只负责执行“向上运行”“向3楼平层”“开门”这些动作。这样分层之后单梯逻辑和并梯调度彻底解耦排查问题时边界非常清晰。3.2 单梯控制的核心指令登记与运行方向决策单梯控制本质上是一个状态机。待机状态下只要有轿内指令或者被分配来的外呼召唤就根据目标楼层确定运行方向。运行状态下电梯需要不断检查是否到达目标楼层。到达目标楼层后进入平层延时然后开门、按开门保持时间计时、关门、关门到位后再次检查还有没有后续指令没有就回待机。方向决策是这里最常见的出错点。我采用了一个比较经典的规则先查上行方向是否有可响应目标如果有且当前电梯没有下行任务就定上行没有上行目标时查下行方向有则定下行两个方向都没有就待机。需要特别留意的是“不可响应”的过滤条件目标楼层等于当前楼层的不算已经在处理中的召唤不算反向召唤在顺路规则下也不一定算。这里宁可多写几行判断也别图省事把所有登记的楼层全部纳入方向决策。目标楼层检索不要用复杂的循环嵌套。因为楼层只有六层直接用六个BOOL组成的数组在程序中用FOR循环扫一遍扫到第一个有效的楼层记为目标即可。S7-1200对这么小的循环在毫秒级完成不会有性能压力。但要注意FOR循环里如果用SCL代码可读性会明显好于梯形图里的一堆比较器。3.3 双梯调度算法分区就近与顺向截梯双梯调度的核心任务只有一个每个新的外呼到来时判断该由哪部电梯响应。这里的决策优先级我按下述顺序实现。第一优先级是顺向截梯。如果某部电梯正在向上运行当前所在楼层低于外呼楼层且外呼方向也是上行那这趟活直接给这部电梯除非它已经有更靠前的目标。这个规则符合电梯搭乘者的直觉电梯已经顺路且会经过这一层没必要派第二部电梯再跑一趟。第二优先级是就近原则。两部电梯都空闲或者都不顺路时比较它们当前楼层与外呼楼层的距离距离近的去。第三优先级是均衡原则。距离一样的情况下选累计运行次数较少的电梯避免两梯长期一台忙一台闲。下面是我在博途里用SCL写的调度函数核心片段用于决策一个上行外呼应该分配给哪部电梯。// 调度函数简化示例: 新外呼到达时, 决定由哪部梯响应 IF NOT SharedDB.UpCall[CallFloor] THEN SharedDB.UpCall[CallFloor] : TRUE; // 结果ID: 11号梯, 22号梯, 3两部可协调 DispatchResult : 3; END_IF; // 先看哪部电梯顺向/空闲 IF Elevator1.Running AND Elevator1.Direction UP AND Elevator1.CurrentFloor CallFloor THEN DispatchResult : 1; ELSIF Elevator2.Running AND Elevator2.Direction UP AND Elevator2.CurrentFloor CallFloor THEN DispatchResult : 2; ELSE // 都没有顺路条件时, 比距离 Distance1 : ABS(Elevator1.CurrentFloor - CallFloor); Distance2 : ABS(Elevator2.CurrentFloor - CallFloor); IF Distance1 Distance2 THEN DispatchResult : 1; ELSIF Distance2 Distance1 THEN DispatchResult : 2; ELSE // 距离相同, 取累计运行次数较少的电梯 IF Elevator1.TotalTasks Elevator2.TotalTasks THEN DispatchResult : 1; ELSE DispatchResult : 2; END_IF; END_IF; END_IF;这只是调度决策的一部分实际代码还会有边缘处理外呼已经分配过、电梯检修中、电梯有故障等条件下会优先排除。SCL的好处是这类多条件判断的可读性远高于梯形图调试时对着普通逻辑语言一眼就能看出问题。调度锁定是另一个必须考虑的问题。一个外呼经过调度函数被分配给某部电梯后其他电梯对这个外呼就不能再响应。我的做法是每个外呼对应一个ResponseFlag数组调度时置位对应电梯的响应标志另一部电梯的响应标志保持FALSE。这样哪怕两部电梯同时空闲也只有先拿到调度结果的那部梯会往目标方向运行另一部不会盲目跟车。3.4 安全逻辑与故障处理实际项目中安全链是一票否决机制。我在程序里单独建了一个FC_Safety函数统一处理超载、急停、光幕、检修、消防这几个信号。任何一票否决有效电梯立即进入不可运行状态正在运行的话也会触发减速停车。仿真项目虽然没有真实硬件但安全逻辑的结构必须保留。将来换成真实设备时只需要把仿真变量换成真实输入点程序骨架可以直接沿用。检修模式专门说一下检修时电梯只允许点动运行且不通调度。我的做法是检修信号为TRUE时两梯都进入“手动模式”调度函数对这两部梯直接置为不可用外呼会全部分配给正常状态下的另一部梯。这个逻辑在真实维保场景里很关键也是答辩或面试时容易加分的细节。4. HMI画面设计与仿真联调4.1 画面整体布局与交互逻辑HMI画面我设计了两块主监控画面和调试画面。主监控画面采用左右分栏布局左边是1号梯的井道示意图右边是2号梯的井道示意图。每个电梯旁边有六层楼位置指示、当前楼层数字、方向箭头、开门状态和运行状态。井道示意图下面是外呼按钮区每个按钮旁边有一个状态指示灯用于表示召唤是否已登记。再往下是报警文本区显示超载、急停、光幕等故障状态。为什么会把外呼按钮放在两梯中间而不是分别放两边因为外呼按钮本来就是公共资源放在中间更符合“公共召唤”的语义操作时也直观你按了3楼上行判断哪部电梯响应看一眼哪部电梯的方向指示灯变亮就知道调度结果。这个布局我在第一次实际仿真时调整过一次最初是把外呼按钮放在了最底部结果操作时视线要在井道和最底栏之间来回跳很不舒服。挪到中间之后交互舒服很多。调试画面则单独放了一些手动操作按钮手动开门、手动关门、强制平层、清除报警、运行次数复位。仿真调试时这些按钮特别好用能快速把电梯恢复到某个状态验证特定场景。4.2 HMI变量连接与地址映射HMI画面里的所有按钮、指示灯、数值显示本质上都是PLC变量的镜像。我在博途里组态HMI时全部采用“从PLC拖拽变量”的方式完成连接。先在PLC符号表里把变量命名好然后在HMI画面设计器中直接开变量表从PLC变量列表里拖过去。这样避免手输地址出错也保证HMI侧变量类型和PLC侧一致。有几个容易忽略的小细节BOOL变量在HMI上如果要做“状态显示”通常是建两个文本列表TRUE和FALSE各对应一个文本颜色。INT类型的楼层显示只需要一个IO域数据格式选十进制禁止输入模式设为只读避免误操作。HMI按钮最好配置“按下置位、释放复位”事件对应外呼按钮的短脉冲触发。不要勾选按钮的保持功能否则一个外呼会一直占着按钮状态画面显示上会误导操作员。4.3 PLCSIMHMI仿真运行完整流程联调的第一步是启动PLCSIM。在博途项目树里选中S7-1200 CPU点击下载目标设备选择PLCSIM程序会下载到虚拟PLC里。接着在HMI文件夹里启动HMI仿真此时博途会再弹出一个HMI仿真窗口。HMI仿真窗口打开后需要在连接设置里指向正在运行的PLCSIM实例。完成之后HMI画面上的按钮操作会直接写入虚拟PLC的相应变量PLC程序扫描会做出响应HMI上的电梯位置指示、方向指示灯都会跟着变化。我按这个流程操作时踩过一个坑先启动了PLCSIM再启动HMI仿真HMI窗口提示连接失败反复查看才发现是HMI设备属性里的接口子网和PLC不在同一个PROFINET子网。解决办法是在设备组态里把HMI和PLC都挂在同一个子网上然后重新下载HMI画面。这个问题在真实触摸屏和真实PLC之间也会遇到养成“先建子网再下载”的习惯能少折腾半天。仿真联调的标准流程我习惯这样走。先用HMI按下一层某个外呼观察调度结果出现在哪部电梯的方向指示上。再点轿内目标楼层让电梯运行等平层停车后看开门和关门动作。接着把超载信号强制为TRUE检测电梯不能关门的逻辑。最后做一次双梯交叉往返的运行测试观察两部电梯是否按分区就近原则各自响应。每一步都记录下来便于后面发现问题时复盘。5. 调试中遇到的坑与解决实录5.1 平层过冲位置判断的时序问题第一次联调时遇到的现象很典型电梯明明已经到达目标楼层位置传感器也亮了但电梯显示还在运行中多跑了一个“假想楼层”才停下。原因出在平层判定和运行状态复位不在同一个周期里完成。位置传感器亮起后电梯的停车请求被置位了但上行输出还持续了一个扫描周期仿真计时器继续累加楼层位置就多跳了一段。解决办法是把平层判定做成“边沿触发 延时滤波”的组合。位置传感器从FALSE变TRUE的上升沿本身触发一次停车请求停车请求置位后立即复位运行输出再经过50毫秒的滤波确认位置稳定才更新当前楼层。这样即使传感器信号有轻微抖动楼层信息也不会乱跳。实际工程里位置信号的抖动问题比仿真更严重早早在程序里加入防抖习惯将来迁移到真实设备能省很多排查时间。5.2 双梯同时响应调度锁定的必要性调试时我故意让两部电梯都停在待机状态然后在HMI上按了一个4楼的上行外呼。结果两部电梯的方向指示灯几乎同时亮了都往4楼跑。这就是典型的“没有调度锁定”问题。两台空闲电梯看到同一个外呼各自都觉得该由自己响应于是全跑过去了。修复方式就是前面讲的ResponseFlag机制。调度函数在决策完成后要把这个外呼标记为“已分配给某梯”并且在同一个扫描周期内让另一部电梯对这个外呼的响应条件失效。具体实现是在FB电梯控制的启动逻辑里加上一个判断只有本梯的ResponseFlag为TRUE时外呼才进入本梯的任务队列。这样一锤定音谁响应谁执行不会出现两梯抢活。调试这类问题时我习惯在DB块里加一个调度日志数组数组每个元素记录一条完整调度信息时间戳、外呼楼层、外呼方向、被分配的梯号、当前两梯楼层。跑完一轮操作后直接查看日志数组立刻能看出调度逻辑有没有按预期执行。这个技巧看起来简单但排查双梯调度问题时的效率完全不一样。5.3 HMI连接不上与画面无响应HMI仿真连不上PLC这是仿真项目里最常见的卡壳点症状是画面能打开但所有按钮按了没反应状态显示全灰。排查步骤我总结成下面几点按顺序检查基本能定位问题。先看PLCSIM是否处于RUN模式如果停在STOP所有IO都不会刷新。再看HMI连接设置里的接口类型是不是选中了PROFINETIP地址和PLC是否在同一个网段。然后检查设备组态中HMI和PLC是否挂在同一个子网下。最后一步在博途项目属性里把HMI的“支持仿真”选项勾选上重新下载画面。很多时候问题就出在最后的这个“支持仿真”选项没开导致HMI仿真运行时无法与PLCSIM建立实时通讯。5.4 程序循环时间超时与扫描周期问题运行一段时间后博途诊断缓冲区突然弹出一个OB80报错随后仿真PLC进入STOP模式。原因是我的调度函数里有一处对日志数组的循环遍历数组长度过大再加上HMI画面大量刷新OB1的循环时间超过了S7-1200默认的150毫秒上限。解决办法有两步。第一步把日志数组的遍历频率降低用每秒执行一次的时间脉冲包住那段循环不让高频扫描拖累主循环。第二步在CPU属性中适当增加循环时间监视值从150毫秒调整到200毫秒。这里必须强调仿真项目里调循环监视时间没问题但真实项目中放宽循环时间通常是危险的。更稳妥的做法是优化程序结构把耗时任务分时执行。调试这类问题可以借助博途的“循环时间统计”诊断视图直接看每个OB块的执行耗时找到最消耗时间的逻辑块再优化。6. 写在最后这套仿真项目还能怎么扩展单梯到双梯的这套仿真框架跑通之后像积木一样可以继续往上搭。我目前在考虑三个方向的扩展。第一个方向是给电梯加变频器多段速。现在仿真里只有上行和下行两路输出电梯速度是恒定值。加了变频器之后可以模拟启动加速、稳定运行、减速爬行、精确平层四个阶段电梯运行的舒适度逻辑就能引入程序对位置控制的理解也会更深入。第二个方向是运行数据统计。利用全局DB记录每部电梯的总运行次数、总运行时间、各层呼叫次数、平均响应时长然后再通过HMI趋势视图展示。这些数据对于物业管理和电梯健康度评估都有实际意义学会用PLC做基础数据统计和分析对做大型项目也是一个很好的铺垫。第三个方向是把调度算法完善得更接近商用系统。比如加入高峰模式早高峰时电梯自动返回基站晚高峰时两梯分区运行再比如加入闲时节能策略外呼长时间无人响应的空驶电梯自动回到中间层待机。这些策略的核心原理和现在这套底层程序完全一致只是加了更精细的条件判断。回到初心这类项目最让我受益的地方其实不是记住了某个指令怎么用而是想明白了一个道理任何多任务系统的本质都是共享资源的管理问题。谁有权访问公共呼叫、如何避免资源冲突、如何设置优先级这套思想在电梯、物流分拣、自动仓储甚至操作系统调度里都通用。仿真项目给了你一个零成本试错的窗口把这里的逻辑彻底嚼透上了真机心里才有底。