S7-1200以太网通信实现六部十层电梯群控调度系统
六部十层电梯单看题目很多人觉得“无非是把单部电梯的程序复制六份”。真正做完西门子智能制造挑战赛这个赛题才发现最大的坑根本不是电梯逻辑本身而是六部电梯在以太网通信下如何协调、如何响应外部召唤、如何在裁判系统随机请求下稳定运行。这篇文章把我从需求拆解、硬件组网、S7-1200程序架构到群控调度算法的完整开发过程写下来尤其侧重以太网通信下的PLC控制器逻辑设计思路给后面参赛的同学一条可以复现的路径。1. 竞赛项目的真实规模不是“电梯程序”而是“分布式控制系统”1.1 信号点位的数量级估算先算一笔账你就知道这个项目为什么不能用单梯思路硬套。十层楼六部电梯光轿厢内呼按钮就是每部10个、总共60个输入点每层厅外召唤按钮按真实电梯布置1层和10层各1个单方向按钮中间2到9层每层2个方向就是18个召唤输入点。再加上每部电梯的平层传感器、门区信号、开关门限位、上下极限位、超载信号、光幕信号一套系统下来离散量输入稳稳超过200点。这意味着什么如果用单台PLC的I/O硬接线方案选型直接往S7-1500大机架上靠成本高、接线复杂、比赛现场排查故障也麻烦。而比赛给的核心约束是“以太网通信”所以正确思路是把它当成一个分布式控制系统来做而不是一台中央控制器包揽所有I/O。1.2 评审眼中的“隐藏权重”竞赛评分不是只看电梯能不能动。我从赛后复盘和评委交流中总结出几个关键维度群控调度效率多部电梯同时响应召唤时派梯策略是否合理乘客平均候梯时间是否直观可见。通信稳定性在持续运行30分钟以上的压力测试中通信数据是否出现掉线、乱序、丢包。程序可读性与工程规范性OB块划分、FC/FB封装、变量命名、注释是否达到工程级标准。故障处理完备性困人、超时未响应、开关门故障等异常场景是否有明确逻辑。这些维度加起来其实是在模拟工业现场的“功能安全效率可维护性”三重评价体系。写程序之前心里就要有这张评分表否则后期返工非常痛苦。1.3 团队分工与开发节奏安排这个项目我一个人全包会非常吃力建议三人组队。我的分工方式是这样的一人负责硬件接线和网络组态完成PLC选型、交换机连接、IP规划。一人负责单梯控制逻辑把开关门、平层、运行状态机做扎实。一人负责群控调度算法和上位机监控界面把六台电梯的召唤分配逻辑跑通。开发节奏上我强烈建议前两周只做单梯逻辑和通信验证第三周才合并群控算法。很多队伍上来就直接写六梯联动结果单梯状态机还没调试稳定群控一跑就彻底乱套最后哪里有问题都定位不出来。2. S7-1200硬件选型与以太网组网方案的设计逻辑2.1 为什么选S7-1200而不是S7-1500或200 SMART这个赛题的硬件选型值得专门说。S7-1500性能当然更强但比赛场景用1200系列完全够而且有三个实打实的优势性价比与采购周期S7-1200系列CPU相比1500便宜不少比赛经费有限没必要把预算砸在冗余性能上。体积与安装灵活性如果采用分布式I/O方案1200配合ET200SP远程I/O模块安装空间和接线复杂度比一台大CPU加一堆I/O卡件友好得多。博途平台统一编程S7-1200和S7-1500共用TIA Portal代码几乎可以无缝迁移。用1200写好的FB块以后换1500直接拖过去就能用。具体型号我用的是CPU 1214C DC/DC/DC集成14路数字量输入和10路数字量输出再配合两个SM 1234模拟量模块和若干远程I/O。比赛模型电梯的传感器和执行器数量这个组合刚刚好。2.2 网络拓扑一台主站与五台智能从站的分布式架构我的整体拓扑是把六部电梯的控制器角色拆开一台S7-1200作为群控主站负责全局调度算法其余五台S7-1200作为智能从站各自控制一部电梯的现场逻辑。第六部电梯的逻辑直接集成在主站CPU里这样六台设备的通讯量相对均衡。为什么不干脆六台都独立再设一台单独的上位机做调度因为裁判系统直接通过以太网连接PLC读取数据如果调度逻辑放在PC上位机里一旦通信链路波动整个系统就失去调度能力。把调度下沉到PLC主站实时性更有保障。IP规划看似简单但特别重要比赛现场我看到不少队伍吃过亏。我的规划是这样的主站192.168.0.10智能从站1号至5号192.168.0.11到192.168.0.15裁判系统/监控上位机192.168.0.20子网掩码统一255.255.255.0所有设备接入同一个工业以太网交换机这里有个必须注意的细节PLC的PROFINET接口默认IP和电脑网卡IP要在一个网段否则博途在线诊断会一直报“无法访问设备”。比赛前一定要检查每台PLC的IP是否被占用或冲突。2.3 PUT/GET通信机制与数据一致性的取舍S7-1200之间做以太网通信有几种方式PROFINET IO、PUT/GET、TSEND_C/TRCV_C协议通信。比赛场景里我最推荐PUT/GET原因有两条配置简单直接在博途里填对方的IP地址、DB块号和偏移量就行。数据量不大每台从站向主站上报的状态字也就几十个字节PUT/GET完全扛得住。PUT/GET使用前有一个关键设置在博途里选中CPU属性在“防护与安全”里勾选“允许来自远程对象的PUT/GET通信访问”。不勾这个程序下载后通信死活不通这是我身边好几个队伍踩过的坑。数据块区域划分上我建立了一套通信规约每台从站PLC提供一个状态数据块和一个指令接收数据块。状态数据块从DB100开始指令数据块从DB200开始通过偏移地址区分不同电梯。主站定期调用PUT读取从站状态字用GET下发派梯指令。关于数据一致性PUT/GET本身是分块读取的如果读取一个结构体里的多个元素理论上存在数据不一致的窗口期。针对电梯这种控制场景我的做法是在每个从站的状态字里增加一个“数据有效”位只有这位为1时主站才解析整包数据。这样即使读取过程中刷新了数据也不会把中间状态当成有效输入。3. 群控调度算法核心逻辑与SCL实现3.1 两种调度策略的对比电梯群控调度算法我以前本科课程设计时只会做最简单的“固定分区”就是1号和2号梯管1到5层3号和4号梯管6到10层。这种方案在比赛模型下有两个致命问题固定分区不能响应跨区召唤乘客在1层想上10层分区管控的1号梯接到任务后往上跑如果2号梯刚好闲置系统不会重新分配。遇到考核场景集中召唤时某些区间的电梯排队其他区间电梯空跑。所以这次比赛我直接放弃了固定分区选用了动态派梯策略核心算法是最小预计到达时间Estimated Time of Arrival简称ETA。3.2 最小ETA算法的工程化设计最小ETA算法的思路并不复杂当一个新的厅外召唤产生时系统为每部电梯计算“如果派它去响应这个召唤预计需要多久能到达召唤楼层”然后选择ETA最小的电梯派去。ETA的计算需要考虑三个组成部分电梯当前所在楼层与目标楼层的距离电梯当前运行方向与目标方向是否顺路电梯已经登记的楼层任务数量如果电梯正忙响应新召唤的时间要增加公式简化后ETA 空闲时间基数 距离折算时间 方向惩罚系数 × 不顺路层数 任务排队惩罚 × 当前登记任务数距离折算时间每个楼层差折算1.5秒方向惩罚系数顺路取0不顺路取2.0秒/层任务排队惩罚每多一个登记任务增加1.0秒。这个公式本身不难难在参数整定。我一开始方向惩罚系数取太大导致系统总是派最近的一台电梯哪怕它已经满载后来把惩罚系数调小又出现多台电梯同时跑向同一楼层的情况。最终是通过连续几轮模拟测试把惩罚系数稳定在2.0左右并增加了“任务数超过4个则不再参与新派梯”的保护条件。3.3 上下行高峰模式的动态切换比赛场景里裁判系统会随机模拟高峰客流比如连续15个请求都集中在1层上行方向。如果这时候还用静态ETA参数电梯群会疲于奔命出现“大家都在跑但没有一台停在正确楼层”的混乱。我增加了一个高峰检测模块统计最近3分钟内上行召唤数量如果超过设定阈值系统自动切换到上行优先模式。在这个模式下所有空闲电梯自动向低楼层基站靠近而不是停留在任意楼层。下行高峰同理电梯群自动巡航到高层基站。这个设计在最终比赛演示时效果很明显评委随机灌入一组密集请求系统能在几秒钟内自动调整梯队布局候梯时间显著下降。3.4 SCL核心代码片段派梯决策下面给出我实现派梯决策的SCL核心代码。这段代码在OB30循环中断里执行每100毫秒扫描一次。FUNCTION_BLOCK FB_Dispatch VAR_INPUT newCallFloor : INT; newCallDirection : INT; // 1上行, -1下行 END_VAR VAR_IN_OUT liftStates : ARRAY[1..6] OF LiftStateType; END_VAR VAR i : INT; bestLift : INT; bestETA : REAL; tempETA : REAL; END_VAR bestLift : 0; bestETA : 9999.0; FOR i : 1 TO 6 DO // 跳过大故障或正在维修的电梯 IF liftStates[i].fault OR liftStates[i].maintenance THEN CONTINUE; END_IF; // 任务数过载的电梯不参与新派梯 IF liftStates[i].taskCount 4 THEN CONTINUE; END_IF; tempETA : CALC_ETA(liftState : liftStates[i], targetFloor : newCallFloor, direction : newCallDirection); IF tempETA bestETA THEN bestETA : tempETA; bestLift : i; END_IF; END_FOR; IF bestLift 0 THEN // 写入派梯指令触发从站执行 DispatchCmd[bestLift].targetFloor : newCallFloor; DispatchCmd[bestLift].commandValid : TRUE; DispatchCmd[bestLift].callDirection : newCallDirection; END_IF;这段逻辑的调用频率是100毫秒一次完全没有性能压力。真正需要关注的是liftStates数组的数据来源它由PUT/GET通信从各从站读入必须在读取更新周期内保证一致性。我的做法是OB30里先调用通信函数块刷新liftStates再执行派梯决策。顺序颠倒会导致派梯逻辑基于旧数据工作出现明显的逻辑滞后。4. 程序架构与PLC状态机设计让六部电梯共享一套逻辑4.1 用FB封装单梯控制逻辑避免六份重复代码很多初学者写多电梯程序时会把一个电梯的程序复制六份改成不同的DB号再改内部地址。这个做法非常糟糕后期想调整一个逻辑细节要重复改六次漏改一次就出现“1号梯正常但5号梯异常”的诡异现象。正确的做法是写一个通用功能块FB_Elevator把电梯控制的所有逻辑封装进去然后用多重背景的方式实例化六次。这样六部电梯共享完全相同的代码只是各自的数据块不同。后续修改一次FB编译下载后六部电梯全部生效。我的FB_Elevator接口包含了开关门控制、平层检测、运行方向切换、内呼登记、外呼响应、故障上报、急停逻辑、超时保护。内部使用一个状态机管理电梯的运行状态下面详细展开。4.2 电梯控制核心状态机状态机的设计我按照经典电梯控制方式拆成六个状态空闲、开门、关门、运行、平层停车、故障封锁。每个状态的事件和处理逻辑如下空闲电梯停在某层无任务。收到新任务后自动进入开关门流程。开门门正在打开等待门限位信号到位然后保持开门若干秒再触发关门。关门门正在关闭如果光幕被触发则立即重新开门。运行电梯根据目标方向选择上行或下行持续运行直到接近目标楼层。平层停车运行到目标楼层后减速平层传感器信号确认到位进入开门状态。故障封锁发生超速、门锁异常、急停等故障时封锁电梯停止响应一切召唤。状态机的实现用SCL的CASE语句最清晰。下面是个简化片段CASE liftState OF LiftState_Idle: IF newTask THEN liftState : LiftState_Opening; END_IF; LiftState_Opening: IF doorOpenLimit THEN openTimer(IN : TRUE); IF openTimer.Q THEN liftState : LiftState_Closing; END_IF; END_IF; LiftState_Closing: IF lightCurtain THEN // 光幕触发重新开门 liftState : LiftState_Opening; ELSIF doorCloseLimit THEN liftState : LiftState_Running; END_IF; LiftState_Running: IF floorSensor[targetFloor] THEN liftState : LiftState_Leveling; END_IF; LiftState_Leveling: IF levelSensor THEN liftState : LiftState_Opening; END_IF; LiftState_Fault: // 保持封锁直到人工复位 IF resetSignal THEN liftState : LiftState_Idle; END_IF; END_CASE;这个状态机看着简单但实际调起来有不少细节。比如关门限位和运行启动之间一定要加一个短暂延时否则门还没完全关严电机就启动模型电梯的机械结构会发出明显的撞击声。我的做法是关门限位到位后延时300毫秒再发运行指令。4.3 全局数据块与组内联锁逻辑六部电梯虽然共享FB但毕竟是独立执行机构组内联锁必须靠全局数据块配合。我建了一个全局DB保存六部电梯各自的当前位置、当前方向、当前状态、登记任务表以及每层的召唤请求状态。群控调度模块读这个DB修改这个DB单梯FB也扫描这个DB。联锁逻辑中比较重要的是“同一时间只允许一部电梯响应同一召唤”。具体实现是召唤信号在DB中有一个“assignedLift”字段一旦被某部电梯领取其他电梯扫描到该字段非0就自动忽略。这样可以避免两部电梯同时开向同一楼层。4.4 变量表命名规范这个说是规范其实是血泪教训。第一版程序里我的变量名随意起比如“a1”“b2”“temp”。到了联调阶段群控模块和单梯模块之间来回对地址对着对着就晕了。后来我按“楼层传感器”和“召唤按钮”统一命名楼层传感器FlrSns_L1到FlrSns_L10内呼按钮CabBtn_L1到CabBtn_L10厅外上行召唤HallUp_L2到HallUp_L9厅外下行召唤HallDn_L2到HallDn_L9这样变量表本身就是文档后期调试找点特别快。建议命名规范在项目第一天就定下来代码写多了再改命名等于重写。5. 调试方法论与现场排障从仿真到实物的沟沟坎坎5.1 仿真跑得通实物就一定会出问题我在博途里用PLCSIM仿真六部电梯的逻辑和调度算法在虚拟环境里跑得非常顺畅当时还挺得意。结果一接到实物模型上第一天就冒出三个问题通信掉线跑一段时间后某个从站的状态字不再更新主站一直读到旧数据。信号抖动平层传感器在接近感应位置时反复通断导致电梯在同一楼层反复开关门。机械卡顿模型电梯的抱闸释放和电机启动之间没有做好时序配合启动时出现明显抖动。先说通信掉线。排查过程是逐步缩小范围的先看交换机指示灯所有端口都亮说明物理链路没问题再看博途在线诊断里的通信连接状态发现掉线的从站连接确实处于中断状态。最后定位到问题根源是从站PLC的看门狗时间设置太短主站偶尔因为扫描周期波动通信间隔超过从站设定的监控时间从站自动断开了连接。解决办法是把通信监控时间从默认的1秒放宽到3秒同时保证主站侧PUT/GET调用周期稳定在100毫秒。5.2 平层信号抖动软件消抖与硬件滤波双管齐下平层信号抖动是电梯控制的经典问题。模型电梯用的是接近开关当金属挡片刚好处于开关检测边界时信号会快速抖动几毫秒。程序如果直接读取这个信号做状态切换就会出现电梯已经平层却反复开门关门的情况。我的处理分两层。硬件层面在博途的DI通道属性里启用数字量输入滤波设置成6.4毫秒能把大部分机械抖动滤掉。软件层面在FB里加了信号确认机制平层信号必须连续两次扫描都为1才认为平层有效。这个确认时间大约是20毫秒足够排除绝大多数干扰。另外还有一个隐蔽的坑六部电梯的平层传感器安装位置有细微差异有的偏高有的偏低。我在每部电梯的DB里加了一个“平层补偿偏移”参数通过现场逐层标定来修正每层停车位置的偏差。这个参数如果不加电梯在部分楼层会停得明显偏出平层区。5.3 一个需要重点处理的场景电梯长时间无响应竞赛压力测试中裁判系统会故意制造一些异常请求。最典型的是某部电梯收到派梯指令后由于机械卡阻或传感器丢失一直没有到达目标楼层。如果程序不对这种情况做处理整个调度系统会卡住后续所有请求都无法分配。我为每部电梯增加了一个“任务超时监控”功能块。当某部电梯领取任务后系统计算理论最大到达时间按电梯最大速度、楼层间距和额外冗余如果实际消耗时间超过理论值的1.5倍任务还未完成就判定“疑似卡梯”触发以下动作将该电梯状态标记为故障待检。清空该电梯的所有登记任务。把任务重新释放回全局召唤池由调度模块重新分派给其他电梯。释放任务的重分配逻辑要特别注意必须在“任务超时”状态确认后方可释放不能一超时就立即释放否则可能出现电梯其实马上要到达但任务已经被分配出去的情况造成两部电梯同时响应。我的做法是超时判定延迟2秒给电梯一个缓冲窗口。5.4 现场快速排障的调试工具选择调试阶段我强烈建议准备以下工具博途在线监控直接看FB内部变量和状态机当前状态。Wireshark抓包如果怀疑通信问题直接用Wireshark抓PROFINET数据包看PUT/GET数据是否正常往来。Excel记录脚本用PLC的Trace功能或者DataLog功能记录连续运行数据赛后复盘时把曲线拉出来看。特别是Wireshark很多同学只会用博途在线诊断遇到通信层面的问题就抓瞎。实际上Wireshark抓包能清晰看到每台PLC发送数据的周期性、数据包大小、是否存在重传。有一次排查一个偶尔掉线的bug博途诊断半天没结果用Wireshark一看发现有一台从站在每隔几秒重传同一个数据包顺藤摸瓜找到是网络线序压接问题。6. 竞赛评分与答辩准备的实战经验6.1 评分演示容易丢分的细节评委现场评分时不会只看你PPT上写得有多好而是现场跑系统的实际表现。我总结了几个容易丢分的细节电梯开关门逻辑不符合真实需求门开着的时间必须可调关门遇到阻挡必须立即开门。有些队伍为了赶进度门动作写得很快看起来“效率”很高但电梯模型的机械惯性会带来很大的顿挫感画面观感不好也会被评委质疑工程合理性。缺少数码管/指示灯状态显示模型电梯通常配了指示灯显示当前楼层、运行方向、开关门状态。如果程序没有把状态同步到这些指示输出上评委无法直观看到电梯正在做什么减分很直观。急停恢复逻辑不完整急停按下后电梯必须进入安全状态急停复位后必须从空闲状态重新开始不能直接继续原来的任务。比赛现场我见过有队伍急停复位后电梯自己乱跑这个场景非常影响评分。6.2 答辩时如何讲清楚调度算法答辩环节很多队伍栽在“只讲功能不讲设计理由”。评委问“为什么选择这个调度算法”时如果回答“因为大家都用这个”基本就告别高分了。我的答辩思路是把算法当成一个工程决策来讲述先列出候选方案固定分区、最小等待时间、能量优化调度。说明每种方案的优缺点和适用场景。结合竞赛模型的特点六部梯、十层、随机客流、通信实时性要求说明为什么选ETA以及ETA参数如何通过测试整定。另外一定要准备对比数据。我在演示前专门跑了两组测试一组用固定分区一组用ETA动态派梯各灌入100个随机召唤统计平均候梯时间。最终ETA方案平均候梯时间比固定分区缩短了约28%。这个数据放出来比任何口头描述都有说服力。6.3 一份能支撑长期维护的项目文档怎么写比赛结束后很多队伍的程序就烂在U盘里了但优秀的工程习惯应该是让程序具有可延续性。我的建议是项目文档至少包含三部分系统架构图、通信地址表、算法参数说明。通信地址表尤其重要。比赛里所有PLC的IP、通信DB块号、数据结构定义全部要整理成一张表。我记得决赛现场有一个队伍临时改IP改完之后有几台电梯通信不上主控老师过来帮忙排查结果他们自己都说不清楚哪些IP是哪些电梯现场非常混乱。提前做好地址表这种问题不存在。7. 最后补充想在这个赛题上拿高分的三个建议坦白说如果你现在刚开始接触这个赛题我建议你先不要急着写群控算法。先把单台S7-1200控制一部电梯的逻辑写透跑通再加上通信。一次通信连接调通再做第二台、第三台直到六台全部联网。群控调度再厉害底层单梯逻辑不稳定一切都是空中楼阁。第二点建议是亲自去现场看一次真实电梯的运行状态。我在参赛前专门去看了小区电梯的开关门时序、平层停车的位置感尤其是电梯到站时开门瞬间的减速手感。把这些真实体验映射到程序里参数设计会合理很多。比如关门后启动前的延时就是看了实物运行才意识到必须加的。最后一点关于算法不要追求花哨。比赛时间有限ETA动态派梯已经足够支撑你拿奖。我见过有队伍想把强化学习装到PLC上结果模型训练和部署都没跑通整个系统反而在基础功能上漏洞百出。根据实际需求选合适的算法把基础功能做到稳定可靠才是竞赛里更稳妥的策略。