搞电梯程序最带劲的就是逻辑设计,这话我做了这么多年工控依然举双手赞成。别不信,等真正动手搭一台四层电梯的时候,你会发现大学里《数字电路与逻辑设计》那门课才是最实用的——状态机那章终于从考试题变成了控制系统的骨架。
四层电梯这个项目,表面看不过就是"上下、停层、开门、关门",但把呼梯记忆、方向仲裁、顺路响应、平层消号、开关门互锁这一整套串起来,很多自称会PLC的同行都会卡壳。S7-1200是练这个项目最合适的主控制器,配合PLCSIM仿真和Factory IO可视化场景,你连一台真实电梯都不用掏钱,就能把逻辑设计能力刷上一个台阶。
这篇文章不是给你抄现成工程的搬运稿,更像是我反复调试过之后整理出的一套完整思路。从I/O分配讲到状态机设计,从SCL关键代码讲到仿真调试里踩过的三个坑,学完你至少能自己搭出一套可运行的四层电梯仿真程序,并且清楚每一行逻辑为什么必须存在。
1. 先想清楚:四层电梯到底在练什么逻辑
1.1 电梯程序的三件核心事
电梯程序看起来功能多得像棵圣诞树,指示灯、楼层显示、语音播报、消防归位,但剥掉这些花活,真正核心的逻辑就三件事。
第一件是呼梯登记。按下的按钮必须被 PLC 记住。轿厢里的楼层按钮是瞬动触点,你按一下松开,PLC 要把这个动作锁存成一个"目标层请求",直到电梯真正服务完这个楼层才消除。外呼按钮也一样:1楼只会有上行按钮,4楼只会有下行按钮,2楼和3楼各有一个上行一个下行。谁按了哪个按钮,PLC 都要记账,这是整个电梯逻辑的地基,地基不稳后面全白搭。
第二件是方向仲裁。电梯停在一个位置,面对一堆呼梯,先去哪、后去哪,必须有一条明确的规则。真实电梯用的是集选控制:同方向优先,同方向没有请求了才考虑反向。这句话看着就十二个字,展开成程序却能写几百行,是整个系统里最考验逻辑设计能力的部分,也是标题说的"最带劲"所在。
第三件是动作执行。确定了方向和目标层之后,电梯要关门、启动、运行、平层、停车、开门,每一步之间都有严格的互锁关系:门没关到位不能走,车没平层不能开门,运行中开门按钮直接无效,关门时有人挡光幕必须立刻重开。电梯的安全性一半在机械和电气回路,另一半就在这套动作互锁里。
这三件事不是独立的三个模块,而是互相咬合的:呼梯登记的结果决定方向仲裁,方向仲裁的结果驱动动作执行,动作执行跑到平层又反过来触发呼梯消除。这个循环一圈接一圈跑下来,状态机稳如老狗,这才是"逻辑设计带劲"的真正含义。
1.2 为什么用四层来练手最划算
楼层少不代表逻辑少。四层电梯该有的边界条件全都齐:最低层只有上行按钮、最高层只有下行按钮、中间层上下都有,电梯在1楼只能往上走,到4楼必须掉头。这些边界跟三十层楼宇电梯完全一致,程序架构可以直接平移。
但四层又足够简单。它不需要做分散厅外召唤的群控调度,不需要称重补偿,更不用碰复杂的安全冗余,单轿厢、四层楼,刚好把所有基础逻辑塞进一个 S7-1200 的 CPU 里。我见过不少人一上来就照着二十层大厦写,结果 I/O 表先把自己吓退,方向算法更是根本没法验证,最后烂尾。四层跑通了,本质逻辑全部成立,真到二十层你只是把数组边界从 4 改成 20,架构不用动。
另一个大优势是调试友好。楼层少,状态转移就少,你可以用 PLCSIM 手动强制每个平层信号,一步步验证每种呼梯组合。真搞二十层仿真,光是模拟各层呼梯的排列组合就够你调一周。写电梯逻辑本来就烧脑,别再给自己加戏。
2. 硬件选型和I/O分配:S7-1200怎么接这个局
2.1 为什么是S7-1200而不是S7-200 SMART、1500
选型这事我说句实在的:四层电梯的负载,200 SMART 能做,1500 也能做,但 S7-1200 是最舒服的中间点。
先说 200 SMART。价格确实低,做简单小设备顺风顺水,但复杂逻辑写起来真够呛。你要写一个几十行的状态机,在 200 SMART 里用梯形图拖线圈、置位复位,光是互锁条件就能把眼睛绕花,而且它的仿真调试能力很弱。咱们练逻辑设计,工具不能拖后腿。
再看 S7-1500。性能没得挑,SCL 写起来极其顺手,但贵,而且仿真门槛高,想跑得爽得上 PLCSIM Advanced。四层电梯根本用不到它的算力,我更愿意把 1500 留给真正的产线和大型项目。杀鸡用牛刀不是不行,是没必要。
S7-1200 正好卡在中间。典型型号 1214C DC/DC/DC,自带 14 路数字输入和 10 路数字输出,以太网下载、PLCSIM 全功能仿真、SCL 原生支持,写数组、FOR 循环、状态机非常顺手,对中小型设备开发和练手场景覆盖得死死的。
有一点必须提醒:1214C 的 14 路输入做四层电梯刚够用,但你要是把安全触板、超载、消防归位信号全拽进来,输入点会吃紧。我的习惯是配一块 SM 1223 扩展模块(8DI/8DQ),或者干脆把轿厢按钮做成矩阵扫描来省输入点。仿真阶段用变量表顶一顶没事,真接硬件时 I/O 规划一定要提前做,别等接线了再发现不够用。
2.2 I/O分配表与信号一览
我以 Factory IO 里常见的电梯场景为参考:平层用接近开关每层一个,外呼按钮 6 个,轿内按钮 4 个,开门、关门、安全光幕各一个。整理成一张表放在手边,动手前就画好,能省下后面一半找茬的功夫。
输入信号(数字量输入):
| 信号名称 | 地址 | 类型 | 说明 |
|---|---|---|---|
| 1楼平层 | I0.0 | 常开 | 接近开关,平层时导通 |
| 2楼平层 | I0.1 | 常开 | 接近开关,平层时导通 |
| 3楼平层 | I0.2 | 常开 | 接近开关,平层时导通 |
| 4楼平层 | I0.3 | 常开 | 接近开关,平层时导通 |
| 1楼上行外呼 | I0.4 | 瞬动 | 最低层只有上行按钮 |
| 2楼上行外呼 | I0.5 | 瞬动 | 2楼双按钮之一 |
| 2楼下行外呼 | I0.6 | 瞬动 | 2楼双按钮之一 |
| 3楼上行外呼 | I0.7 | 瞬动 | 3楼双按钮之一 |
| 3楼下行外呼 | I1.0 | 瞬动 | 3楼双按钮之一 |
| 4楼下行外呼 | I1.1 | 瞬动 | 最高层只有下行按钮 |
| 轿内1楼按钮 | I1.2 | 瞬动 | 轿厢内选层 |
| 轿内2楼按钮 | I1.3 | 瞬动 | 轿厢内选层 |
| 轿内3楼按钮 | I1.4 | 瞬动 | 轿厢内选层 |
| 轿内4楼按钮 | I1.5 | 瞬动 | 轿厢内选层 |
| 开门按钮 | I1.6 | 瞬动 | 轿厢内开门按钮 |
| 关门按钮 | I1.7 | 瞬动 | 轿厢内关门按钮 |
| 光幕/安全触板 | I2.0 | 常闭 | 有人遮挡时断开,按真实电梯习惯设定 |
输出信号(数字量输出):
| 信号名称 | 地址 | 类型 | 说明 |
|---|---|---|---|
| 上行运行 | Q0.0 | 继电器 | 驱动电梯上行 |
| 下行运行 | Q0.1 | 继电器 | 驱动电梯下行 |
| 开门继电器 | Q0.2 | 继电器 | 驱动门机开门 |
| 关门继电器 | Q0.3 | 继电器 | 驱动门机关门 |
| 上行指示灯 | Q0.4 | 指示灯 | 可选,显示运行方向 |
| 下行指示灯 | Q0.5 | 指示灯 | 可选,显示运行方向 |
这里有个细节很多人栽过:光幕和安全触板在真实电梯里必须是常闭输入。这样线断了或者传感器掉电,PLC 会认为"有遮挡",门就不会往死里关。仿真里你可能图省事设成常开,真接设备时一定要改回来,这是安全习惯问题,不是逻辑问题。
2.3 位置检测方案取舍:平层开关还是编码器
电梯怎么知道自己到哪一层了,工程上就两条路。
第一条,每层一个平层开关。电梯运行到楼层之间时所有平层信号都不通,到位时只有对应层导通。优点是完全不依赖运动学计算,只要传感器装得准,楼层判定永远正确;缺点是电梯在两个平层之间的具体位置你不知道,真要做精确爬行和停车,还得额外加逻辑。
第二条,旋转编码器加高速计数器。编码器装在曳引机或限速器上,每转一圈输出若干脉冲,S7-1200 内部的高速计数器累加脉冲数,结合运行方向做加减计数,推算出相对零点的高度值。这套方案能精确知道电梯在井道里的实际位置,变频器减速、爬行、平层都能靠坐标精细规划,更接近真实商用梯。缺点是代码复杂度明显上来了,要处理脉冲方向、零点校准、累计误差,对新手练逻辑不太友好。
我的建议很直接:做四层仿真练逻辑,用平层开关就够了。先让"停得准"不干扰你理解"该去哪、该停哪"。等把调度逻辑全跑通,再研究编码器版本,那个版本考验的是运动控制,跟电梯调度逻辑两码事。一上来就上编码器,很容易分不清到底是逻辑错了还是脉冲算错了,那才叫白忙活。
3. 电梯的灵魂:呼梯登记与方向仲裁算法
3.1 呼梯信号怎么记忆、怎么消除
按钮是瞬动的,PLC 扫描周期以毫秒计,你要是不做记忆,手一松请求就没了,电梯压根来不及反应。所以每路按钮信号必须对应一个锁存变量:按下置位,服务完成之前不许复位。
我习惯在 S7-1200 里用三个数组存呼梯:callUp[1..4] 存上行外呼,callDn[1..4] 存下行外呼,callCar[1..4] 存轿内目标。数组下标直接用楼层号 1 到 4,别用 0 起点,0 起点在电梯程序里特别容易把自己绕晕——1楼对应下标0,2楼对应下标1,满脑子偏移量,不出三行代码必出 bug。
呼梯消除是初学者最容易踩坑的地方。原则就一句话:这个楼层的需求被"实际服务完"才能消号。什么叫服务完?电梯平层、停稳、开门到位、乘客能进出,这时候消除这层的轿内呼梯和外呼信号都合理。
消号时机必须卡在开门状态确认之后,而不是平层信号的上升沿。为什么?平层信号通了只能说明电梯到了这层,万一程序卡在开门前的某个环节,乘客根本没机会进出,你先把呼梯消了,面板上的按钮灯灭了,门却不开,乘客第一反应就是电梯坏了。这种丢服务信号的事故,真梯上是要出投诉的。
再细一层:电梯上行到3楼停靠开门,3楼的上行外呼该消,那3楼的下行外呼要不要一起消?我的做法是消。既然电梯已经开门让乘客进出了,他要是真想去楼下,进了轿厢会重新按轿内按钮登记目标。所以开门到位后一次性清掉本层所有呼梯,是简单可行又符合乘客预期的方式,这也是很多小型电梯的默认策略。
3.2 方向仲裁:同向优先、换向判定
方向仲裁是整个电梯程序的灵魂,值得多花笔墨。
先说集选控制的核心原则:电梯按当前运行方向,优先服务方向前方的所有呼梯;当前方向前方没有呼梯了,才响应反方向的呼梯。翻译成大白话:电梯正在往上走,只要上面还有任何人按过电梯,它就不会掉头;上面没人等了,它才去看下面还有谁需要。
我推荐用"最远呼梯夹逼"这个思路落地,代码简洁,逻辑清晰。
上行时你需要知道两件事:本层以上有没有呼梯——有就继续上行;上行途中本层有没有可响应呼梯——有就停车开门。对应到工程实现,就是维护两个核心量:highCall(所有未消号呼梯里的最高层)和 lowCall(所有未消号呼梯里的最低层)。每个决策周期重新算一遍,然后按规则定方向:
- 如果 highCall 大于当前楼层,说明上方有请求,方向定为上行;
- 如果 lowCall 小于当前楼层,说明下方有请求,方向定为下行;
- 如果上下都有请求,优先与上一次运行方向一致的那一侧。
这个"关门后重新判向"的做法非常稳,它天然处理了一个隐蔽情况:电梯本来上行去4楼,结果在2楼停了,轿内有人按了1楼,此时上方已经没有任何呼梯。电梯门一关,上面这套算法立刻判定方向改为下行,直接送客,不会傻乎乎先冲到4楼再折回来。你要是沿用老思维"保持上一个方向",就会看到电梯对着空楼层白跑一趟。
顺路停靠的判断也是一句话:方向为上行时,如果当前层有上行外呼或者轿内呼梯,就停车开门;方向为下行时,只响应下行外呼和轿内呼梯,下行中遇到上行外呼不要停——那不是顺路,那叫绕路白跑。真实电梯里,下行电梯经过3楼时如果3楼有人按上行,电梯不会停,那个上行请求会一直保留到电梯掉头后再上来接人。这就是"反向不响应"的含义,写代码时千万别想偏。
3.3 状态机设计:把电梯动作拆成六个状态
逻辑设计真不用状态机,代码三天后你自己都看不下去。我习惯拆六个状态:
- IDLE:空闲待机,门关着,没有任何呼梯。
- MOVING_UP:上行途中。
- MOVING_DOWN:下行途中。
- DOOR_OPENING:正在开门。
- DOOR_OPENED:门已开,保持开门或等待关门条件。
- DOOR_CLOSING:正在关门。
状态迁移逻辑大致这样:IDLE 下发现任何呼梯,先看当前层有没有呼梯,有就直接切 DOOR_OPENING(省一趟白跑),没有就按方向仲裁结果切 MOVING_UP 或 MOVING_DOWN;运行中一旦到达目标平层,立刻切 DOOR_OPENING 开门;开门到位进 DOOR_OPENED,启动开门计时;计时到、无光幕遮挡、无安全信号,切 DOOR_CLOSING;关门到位后,没呼梯回 IDLE,有呼梯重新做方向仲裁再进 MOVING。
这条状态机最重要的纪律是:任意时刻只有一个状态为 TRUE,状态之间不允许跳步。S7-1200 里可以用枚举变量配 CASE 语句实现,比一堆互相置位复位的 BOOL 干净太多。调试的时候你在线看当前状态值,跟现场动作一比,bug 在哪个环节一目了然。
4. SCL代码实现:把逻辑翻译成PLC能跑的程序
4.1 输入滤波与楼层判定
仿真环境里平层信号通常挺干净,真机可不一定。接近开关在电梯快速经过时会抖动甚至闪断,这个毛病在 Factory IO 里也会以另一种形式冒出来。所以我从第一天就养成习惯:所有开关信号进程序先做防抖处理,平层信号用 50ms 的接通延时,光幕用 20ms。真机调试时这段代码不用大改。
SCL 里用 TON 做接通延时非常直接:
#tonLevel1(IN := #ioLevel1, PT := T#50MS); #level1 := #tonLevel1.Q;楼层判定也别偷懒直接拿平层信号当楼层号用。我是单独维护一个 curFloor 变量,专门存"最后确认的楼层位置":平层信号有效时刷新 curFloor,四层信号全部无效时保持原值,默认电梯还在最后一次确认的位置。这段逻辑在仿真里看着仿佛多余,但真机时能挡掉不少莫名其妙的幽灵 bug。
4.2 呼梯登记与目标层计算
呼梯登记很机械,核心就是每个瞬时按钮对应一个锁存变量。外呼6个、轿内4个,一行行写也就10行,不需要炫技。
IF #btnUp1 THEN #callUp[1] := TRUE; END_IF; IF #btnUp2 THEN #callUp[2] := TRUE; END_IF; IF #btnUp3 THEN #callUp[3] := TRUE; END_IF; IF #btnDn2 THEN #callDn[2] := TRUE; END_IF; IF #btnDn3 THEN #callDn[3] := TRUE; END_IF; IF #btnDn4 THEN #callDn[4] := TRUE; END_IF; IF #btnCar1 THEN #callCar[1] := TRUE; END_IF; IF #btnCar2 THEN #callCar[2] := TRUE; END_IF; IF #btnCar3 THEN #callCar[3] := TRUE; END_IF; IF #btnCar4 THEN #callCar[4] := TRUE; END_IF;目标层计算我把所有呼梯汇总后扫一遍,找出 highest 和 lowest:
#highCall := 0; #lowCall := 5; FOR #i := 1 TO 4 DO IF #callUp[#i] OR #callDn[#i] OR #callCar[#i] THEN IF #i > #highCall THEN #highCall := #i; END_IF; IF #i < #lowCall THEN #lowCall := #i; END_IF; END_IF; END_FOR;方向仲裁按前面讲的规则写。注意一个关键优化点:上下都有请求时,如果上次方向是上行且上方有呼梯,就继续上行;如果上次方向是下行且下方有呼梯,就继续下行。这段"同向优先"的修正逻辑,能让电梯减少折返次数,真实乘客也会觉得更聪明。对上文的例子:电梯在3楼,3楼有人要下1楼,4楼有人要下2楼,上下都有请求,程序会先往上送4楼那位,然后折返送1楼,而不是在3楼一股脑往下冲。
4.3 状态动作与开关门时序
状态机本体我用 CASE:
CASE #state OF IDLE: IF #anyCall THEN IF #callUp[#curFloor] OR #callDn[#curFloor] OR #callCar[#curFloor] THEN #state := DOOR_OPENING; ELSE #direction := 计算方向(); #state := DOOR_CLOSING; END_IF; END_IF; MOVING_UP: #qUp := TRUE; #qDown := FALSE; IF #levelX AND (#callUp[#curFloor] OR #callCar[#curFloor]) THEN #qUp := FALSE; #state := DOOR_OPENING; END_IF; MOVING_DOWN: #qUp := FALSE; #qDown := TRUE; IF #levelX AND (#callDn[#curFloor] OR #callCar[#curFloor]) THEN #qDown := FALSE; #state := DOOR_OPENING; END_IF; DOOR_OPENING: #qOpen := TRUE; IF #doorOpenLimit THEN #qOpen := FALSE; #state := DOOR_OPENED; END_IF; DOOR_OPENED: // 开门计时或关门按钮触发 IF #btnClose OR #doorOpenTimer.Q THEN #state := DOOR_CLOSING; END_IF; DOOR_CLOSING: #qClose := TRUE; IF #doorCloseLimit THEN #qClose := FALSE; // 关门到位后重新判向 ... ELSIF #safety THEN // 光幕触发,立即重新开门 #qClose := FALSE; #state := DOOR_OPENING; END_IF; END_CASE;这里 #levelX 是"当前楼层平层信号"的合并表达,实际代码里要按 curFloor 匹配对应的 #level1 到 #level4。DOOR_OPENED 状态下开门计时建议用 TON 定时器,比如默认保持 5 秒;但光幕如果一直被遮挡,计时要反复重启,别让门硬关。
还有个非常容易被忽略的互锁:电梯运行中,任何时候都不能执行开门输出。所以 MOVING_UP 和 MOVING_DOWN 状态里,开门继电器必须是 FALSE。很多新手把开门输出放在 DOOR_OPENING 里就以为没事了,结果状态机一旦因为 bug 跳错,运行中开门会直接放大事故。我在每个运行分支里都显式清了开门输出,这个习惯保了我好几年。
4.4 消号规则:什么时候消除呼梯信号
消号逻辑我集中在开门到位后的那个瞬间处理。DOOR_OPENING 状态里,开门限位信号一到位,先把本层所有呼梯清一遍:
IF #doorOpenLimit AND #state = DOOR_OPENING THEN #callUp[#curFloor] := FALSE; #callDn[#curFloor] := FALSE; #callCar[#curFloor] := FALSE; END_IF;特别提一个不算少见的情况:电梯下行经过3楼,3楼的人按的是上行。因为反向不响应,电梯不会停,这个上呼梯不会被消掉,只有电梯掉头后重新上行到3楼开门,它才会被清除。这个行为完全匹配乘客预期——他按的是上行,电梯刚才往下开根本没停,那这趟肯定坐不上,按钮灯必须保持亮着,等电梯回来接他。如果你在"经过层"就把反向呼梯清了,就是明显的逻辑硬伤,乘客会觉得按键失灵。
5. 仿真调试:从PLCSIM到Factory IO的完整过程
5.1 仿真环境搭建的两种路子
先说完整方案:TIA Portal + S7-PLCSIM + Factory IO。TIA 里把程序编译下载进 PLCSIM,Factory IO 加载电梯场景,通过官方驱动把仿真 PLC 的 I/O 挂接过来。驱动版本匹配的话,虚拟电梯就随着程序逻辑动起来,轿厢起停、开关门、平层都看得到,程序问题会立刻暴露成肉眼可见的动作异常。这套方案调试体验最好,也是我最推荐的。
如果没有 Factory IO,或者装驱动时被版本匹配恶心到了,直接在 PLCSIM 里手动仿真也完全够用:在线监视程序,用变量表强制输入信号,先强置 1 楼平层,再按下 1 楼外呼变量,观察 callUp 和状态的变化,然后按设定顺序挪平层信号模拟运行过程。这个过程慢,但也有个意想不到的好处——它逼着你看清每一个状态转换。我建议初学者至少完整手动跑一遍,再上 Factory IO 看连贯动作,理解深度完全不一样。
无论哪条路,我都建议先做离线自检:把状态机的每一条迁移路径列个清单,逐个场景推演一遍,而不是直接开仿真。我自己有个习惯,写大改之后先花十分钟在纸上把状态迁移表过一遍,很多 bug 是这么拦下来的。
5.2 坑一:方向死锁——换向判断不能只看外呼
我第一次写这套程序时犯过一个经典错误:只把"当前运行方向前方有没有外呼"作为换向依据,结果遇到一个很隐秘的死锁。
场景是这样的:电梯在2楼,3楼有人按上行要上4楼,4楼没人。电梯上行到3楼,开门,响应该层上行外呼。此时我程序里判断"上方没有更多外呼了,换向下行",于是关门,开始往下走。可问题是,3楼那个人进轿厢后按了4楼——轿内呼梯产生了,但我的程序压根没把 callCar 纳入换向判断。于是电梯明明应该继续往上送他,却掉头往下跑了。乘客懵了,我也懵了。
回头看根因:我的 highCall 和 lowCall 扫描逻辑里只包含了 callUp 和 callDn,漏了 callCar。这种"漏源"类 bug 超级隐蔽,因为普通场景跑两遍看着都是对的,只有呼梯组合凑到特定情况才会炸出来。这也是我为什么在第4章强调,目标层计算里三个数组必须全部参与扫描,缺一个都不行。电梯的呼梯来源一共有三种,任何一路都可能最后决定电梯方向,写代码时先把它们汇总成一个总的 anyCall 集合,再去做最高最低层的计算,别分头处理。
5.3 坑二:平层毛刺导致重复停车
仿真环境里的平层信号一般很干净,但接近开关真机经过楼层时会闪断,Factory IO 里如果场景参数设置不细心也会出现类似的毛刺。最直接的后果是:电梯经过一个不该停的楼层时,因为毛刺触发了停车判断,车瞬间停了一下又继续走,观感上就是"刹车点了一下头"。
根因是我直接用平层信号上升沿当停车条件,毛刺足以制造一个虚假上升沿。对策就是第4章写的三件套:平层信号先做 TON 延时滤波;状态机里停车判断要求"平层有效且本层有可响应呼梯"两者同时满足;维护 curFloor 变量确保毛刺不会刷新楼层号。这三条一起上,毛刺再凶也影响不到最终行为。
我后来在真机调试水泵设备时也遇到过完全一样的抖动问题,套路一模一样:输入滤波 + 条件 AND + 状态锁存。做 PLC 时间长了你会发现,天下的传感器毛刺都长一个样,防抖三板斧是通用技能。
5.4 坑三:消号过早导致乘客"被消失"
有一阵我把消号逻辑写在"平层信号导通"那一刻,结果出现一个经典怪象:电梯上行经过3楼时,3楼明明没人呼梯,程序却把3楼所有呼梯全清了。我当时的设计意图是"到达某层就清理该层",但没区分"途经"和"停靠服务"两个概念。于是后来3楼真有人按上行时,按钮信号被误清,电梯压根不再停,乘客看着自己按亮的按钮奇怪地灭掉。
教训很直白:消号只能发生在开门服务状态,绝不能发生在平层状态。平层只代表途经,开门才代表服务。我再补一刀:消号时刻我最终选在开门到位,而不是开门瞬间。因为万一门机卡住、限位没到,乘客没法进出,信号却已经清了,服务同样不完整。延迟几个扫描周期消号,成本几乎为零,但把"实际服务完成"和"信号清零"这两件事严格对齐了,这个原则以后做复杂项目一样适用。
6. 往后走:从四层仿真到真实电梯的几个进阶方向
6.1 双梯并联与MODBUS远程通信
单台四层电梯逻辑跑通之后,最自然的进阶是多梯并联。比如两台电梯共用前室外呼按钮,调度就升级成"派梯"问题:哪台离呼梯层最近、方向最顺,就派谁去。底层依然是呼梯登记和方向仲裁,只是多了"选谁去"这个分配层,这时候你前面打下的状态机功底会派上大用场。
真实项目还有通信需求。电梯的楼层显示器、远程监控、物联网盒子,很多走 MODBUS RTU 或以太网。S7-1200 G2 系列 CPU 上已经内置了 MODBUS 指令,用 modbus_comm_load 可以很方便地配置 RS485 模块或以太网端口做主站从站,把电梯当前楼层、运行状态、故障码定时上报。四层仿真跑通后,把数据通过 MODBUS 丢给 HMI 或上位机组态软件,控制系统和信息系统的链路就打通了,那时候你手里的就不再是一个练习,而是一个完整的小项目。
6.2 变频调速与平层精度
平层开关方案是"到了才停",真实电梯追求的是"快到的时候提前减速,再稳稳停准"。这就要上变频调速和位置闭环:编码器反馈位置,PLC 通过 PID 或变频器多段速端子控制,高速段跑 0.8m/s,接近目标层 1 米切爬行速度 0.1m/s,到平层瞬间抱闸停车。S7-1200 的高速计数器正好接编码器,PID 也是内置功能块。这套练完,你对运动控制的理解会和纯逻辑控制完全不同,而且你会发现,真正的电梯调试,一大半时间都在跟减速曲线较劲。
6.3 安全回路设计的底线思维
最后说一个跟逻辑设计同样重要、但很多人容易忽略的事:安全回路。真实电梯必须有独立的电气安全回路,限速器开关、安全钳开关、上下极限、抱闸检测、门锁回路,这些信号通常常闭串联,任何一个动作都直接切断主接触器,绝不依赖 PLC 程序。PLC 能做故障记录和显示,但不能替代硬件回路切断动力。我在仿真练习里也坚持把极限开关、超载信号接进状态机,让它们成为控制系统的一部分,而不是文档里一句话带过。这个底线思维,越早养成越好。
我的体会是,四层电梯这个题目难度设置得非常克制,刚好让你够得着,但每一步都得亲手想清楚。我用 S7-1200 跑通整个项目,最大的收获不是多会写几条 SCL 指令,而是真正理解了什么叫"状态即秩序"——所有逻辑围绕状态转移转,任何时刻都知道自己在哪一步,这在复杂的自动化项目里是救命的本事。如果你也准备上手练,我劝你别急着找现成程序抄,先自己憋两天写出一个笨版本,哪怕漏洞百出,再对照本文思路重写一遍。两遍下来,方向仲裁、消号时机这些核心逻辑基本就刻在脑子里了。