每次听到有人说“全自动洗衣机控制程序不就是个顺序启动嘛”我都想拉他坐下来看看这套仿真工程的细节。说它难吧确实没到伺服运动控制那种程度说它简单吧等你做到水位传感器抖动、脱水时序打架、画面和PLC对不上号的时候就会明白那些“看得见的简单”背后全是“看不见的细节”。这套程序我用的环境是 GX Works2 编写梯形图逻辑GT Designer3 做触摸屏画面最后通过自带仿真器把 PLC 和 HMI 全套联动跑通。整个过程走下来最大的感受是洗衣机控制的关键根本不是“会不会写梯形图”而是能不能把一个生活常识准确地翻译成时序和互锁。下面我就按实际开发的顺序从需求拆解到仿真联调一段一段拆给你看顺便把那些仿真里才暴露出来的坑也一起说了。1. 需求拆解先别碰梯形图把“洗衣服”翻译成状态机1.1 顺序控制之外的三个隐藏需求洗衣机的自动流程教科书里都会写进水、洗涤、排水、脱水、结束。但真让你写PLC程序你会发现这几个词根本不够用因为中间还夹着很多“隐含动作”。最典型的是洗涤阶段。波轮洗衣机不是正转到底而是正转一会儿、停一会儿、反转一会儿、再停一会儿这样反复循环。如果只写一个“洗涤输出”那电机要么一直转要么停下来就再也起不来。所以洗涤这一个阶段实际上内部还要再拆成四个子状态正转、暂停、反转、暂停。第二个隐藏需求是水位判断。进水不能靠时间瞎猜要等水位开关到位排水也不能光靠时间要等水位确实降到安全点不然带着水强行脱水电机会过载。水位开关的反馈信号既是进水的结束条件也是排水结束和脱水启动的前置条件。第三个是门锁和安全联锁。洗涤和脱水过程中门必须锁死排水阀和进水阀不能同时打开脱水开始前必须确认水已经排完。这些条件看着不起眼但少写一个仿真的时候也许看不出来真机运行就可能出安全事故。所以第一步不是开软件而是在纸上把状态列出来。我一般直接画一个简单的状态表把每个阶段的进入条件、执行动作、退出条件写清楚。写完了再动程序后面基本不会乱。1.2 软元件规划从输入输出倒推写梯形图之前先把I/O分配定好。这个项目用的是一台模拟FX3U系列的PLC分配表如下类别软元件作用输入X0启动按钮输入X1停止按钮输入X2水位开关达到设定水位后ON输入X3模式选择OFF为标准、ON为轻柔输入X4门锁到位反馈输出Y0进水阀输出Y1洗涤电机正转输出Y2洗涤电机反转输出Y3排水阀输出Y4脱水电机含离合器输出Y5蜂鸣器输出Y6门锁电磁铁内部软元件这块我用M500做运行总标志M501到M504做洗涤四拍控制D0存放当前阶段代码D20做洗涤节拍索引D21做洗涤循环计数D100到D105存放各阶段的时间基准值D30存报警代码。定时器和计数器也要提前规划。FX3U的T0到T199是100ms时基定时器T200到T245是10ms时基定时器我这边统一用T0到T6具体用途后面代码里会体现。计数器用C0做洗涤循环计数。规划这一步很多人会跳过结果写一半发现软元件打架回来改程序改到怀疑人生。2. GX Works2落地梯形图从软元件规划到STL状态骨架2.1 工程创建和参数配置别默认一路下一步打开GX Works2新建工程选PLC系列时要注意和后面仿真器的匹配。如果选了FX3U对应的系列就是FX3U/FX3UC编程语言选“梯形图”就行。工程建好后先别急着写程序到“PLC参数”里看一眼软元件设置。仿真时有一个容易被忽略的点FX3U的默认输入输出点数、定时器范围够用但如果你在程序里用了比较指令、INC指令这类功能要注意PLC类型不能选太低端的FX3G不然指令集不支持。我这次因为要用比较触点和INC指令所以选了FX3U。参数配置里还要注意“注释”和“软元件内存”的设置。GX Works2支持给每个软元件写注释仿真联调时候注释会显示在软元件监视窗口里看起来一目了然。我这套程序的X0、Y0、D0这些都有注释调试时省了不少事。2.2 STL步进梯形图的搭建骨架洗衣机的核心流程用步进梯形图STL来实现这是三菱PLC里很适合顺序控制的写法。每个状态是一个STL触点状态内部写这个阶段要做的动作状态之间用SET指令转移。好处是结构清楚一个状态对应一坨逻辑改起来不会牵连其他状态。主流程我划分了这么几个状态S0待机S20进水S21洗涤S22排水S23脱水S24结束提示S30故障报警程序开头用M8002上电初始脉冲把S0置位然后从S0开始往下走。上电进入待机这段很多新手会漏掉M8002结果一上电PLC不知道自己在哪个状态直接乱跑。S0待机状态里的转移条件是这样处理的STL S0 LD X0 // 启动按钮 ANI X1 // 停止按钮没按 AND X4 // 门锁已经吸合 SET S20 // 进入进水状态这里把启动按钮、停止按钮、门锁反馈串在一起相当于一个启动总条件。X4门锁反馈必须为ON才能启动避免门没关好就开始进水。启动后程序进入S20进水状态。进水段的写法也简单但它带了一个保护定时器STL S20 OUT Y0 // 进水阀打开 OUT T4 K3000 // 进水超时保护5分钟 LD X2 // 水位到位 SET S21 // 进入洗涤状态 LD T4 // 如果5分钟还没到水位 SET S30 // 进入报警状态进水阀Y0在S20内直接OUT状态一旦转移Y0会自动断开。这个机制是STL的好处不用在下一个状态里手动去关上一个状态的输出。T4是保护逻辑防止水压不足或者水位开关坏了导致一直进水5分钟没到水位就直接报警。2.3 洗涤四拍定时器交替和循环计数洗涤是整个程序里最绕的部分因为一个S21状态内部还要跑四个子节拍。我处理方式是用D20做节拍索引0代表正转、1代表暂停、2代表反转、3代表暂停。进入S21时先确保D20为0然后靠定时器驱动D20不断变化。先看洗涤前的时间参数设定。因为标准模式和轻柔模式的时间不一样而且这个设定必须在启动瞬间锁存所以我用启动脉冲来做LD X0 PLS M0 // 启动脉冲 LD M0 ANI X3 // 标准模式 MOV K70 D100 // 正转7秒 MOV K20 D101 // 暂停2秒 MOV K70 D102 // 反转7秒 MOV K20 D103 // 暂停2秒 MOV K15 D104 // 循环15次 MOV K1800 D105 // 脱水3分钟 LD M0 AND X3 // 轻柔模式 MOV K40 D100 // 正转4秒 MOV K30 D101 // 暂停3秒 MOV K40 D102 // 反转4秒 MOV K30 D103 // 暂停3秒 MOV K10 D104 // 循环10次 MOV K900 D105 // 脱水1.5分钟这里用PLS M0取一个启动上升沿只在按启动按钮那一下把时间参数写到D100到D105。如果不用脉冲而是直接LD X0去MOV那运行过程中只要X0一直为ON模式切换就会实时改时间参数洗涤到一半突然变节奏这种问题排查起来特别隐蔽。洗涤主逻辑这样写STL S21 LD D20 K0 // 正转节拍 OUT T0 D100 // 正转时间 LD T0 MOV K1 D20 // 切到暂停节拍 LD D20 K1 // 暂停节拍 OUT T1 D101 // 暂停时间 LD T1 MOV K2 D20 // 切到反转节拍 LD D20 K2 // 反转节拍 OUT T2 D102 // 反转时间 LD T2 MOV K3 D20 // 切到暂停节拍 LD D20 K3 // 暂停节拍 OUT T3 D103 // 暂停时间 LD T3 MOV K0 D20 // 回到正转节拍这里要重点提醒一下定时器OUT T0 D100里的D100是定时器设定值单位是100ms一眼要看清。T0的输出条件LD D20 K0只有当前节拍是0时才为ON节拍一切走定时器条件断开才能在下一次重新计时。如果你把定时器放在一个一直为ON的常开触点后面那定时器只会计一次到点后触点一直ON再也回不去这是洗涤程序最常见的死循环原因。洗衣机的电机正转和反转输出实际上是在各自节拍里输出的。正转节拍时Y1为ON反转节拍时Y2为ON。我把Y1放在D20等于0的节拍里Y2放在D20等于2的节拍里。注意正转和反转绝对不能同时为ON这个由D20的互斥节拍索引天然保证了。循环次数计数交给C0。计数脉冲来自反转结束的T2LD T2 OUT C0 D104 // 每次反转结束计数一次 LD C0 // 循环次数到了 SET S22 // 进入排水 RST C0 // 复位计数器三菱计数器OUT C0 D104的计数条件是逻辑从OFF到ON的上升沿所以即使T2为ON保持几个扫描周期C0也只加一次。C0计满后触点ON转移去排水同时在S22状态里把C0复位。3. 排水、脱水与门锁互锁仿真最容易翻车的三个细节3.1 排水结束靠水位下降沿不是靠时间洗涤完成后进入S22排水状态我的处理是直接开排水阀Y3然后等水位开关X2从ON变成OFF。X2作为常开触点有水时ON排空了就OFF。所以转移条件用的是X2的常闭STL S22 OUT Y3 // 排水阀打开 OUT T5 K3000 // 排水超时保护5分钟 LDI X2 // 水位已经降下去 SET S23 // 进入脱水 LD T5 SET S30 // 超时报警有人觉得排水排个固定时间比如30秒就够了反正洗衣机一共就那点水。但仿真和真机不一样真机里水管高度、排水管堵塞程度都会影响排水速度。如果你用固定时间水没排完就直接脱水电机会带水启动轻则震动重则烧电机。所以排水结束条件必须是“水位信号消失”而不是“时间到了”。时间只做超时保护用这点在实际项目里是硬性要求。3.2 脱水启动必须先关进水、再开排水脱水阶段S23有个很容易犯的错排水阀Y3在S22里开了到了S23很多人就忘了继续开。因为STL切换后上一个状态输出自动OFF所以如果你在S23里不重新OUT Y3排水阀在脱水那一刻就关了剩下半管水在桶里脱水效果大打折扣。正确做法是在S23里同时保持排水阀打开并启动脱水输出STL S23 OUT Y3 // 排水阀继续开 OUT Y4 // 脱水电机启动 OUT T6 D105 // 脱水时间 LD T6 SET S24 // 进入结束状态这里还有一个顺序逻辑脱水电机Y4的启动必须发生在排水阀已经打开的前提下也就是S22已经运行过一段时间水位信号已经消失。如果程序里直接把进水、排水和脱水都塞在同一个状态里仿真时可能看不出来但真机一开脱水桶里还有水离合器硬接高速那个声音和震动能让隔壁邻居来敲门。另外注意脱水输出Y4算是一个高速输出仿真器里看不到实际旋转但可以通过监控Y4的通断状态判断时序是否正常。GT官方仿真器对高速脉冲这类功能支持有限但单纯的通断逻辑没问题。3.3 门锁联锁虽然仿真管得松程序不能松门锁电磁铁Y6我放在主逻辑里用运行标志M500控制LD M500 OUT Y6 // 门锁吸合M500在启动瞬间置位在停止或程序结束时复位。这么做意味着只要洗衣机在运行门锁就一直吸合不管当前是在进水、洗涤还是脱水。门锁电磁铁的复位时机也很关键必须在停止按钮按下或者结束状态完成后才断开。有人会把门锁逻辑也放进STL状态里结果状态一转移门锁就掉了。洗涤过程中门突然能打开这在真机里就是安全事故。仿真时可以偷懒但程序结构必须按真机标准写这是我认为做仿真项目最重要的心态。停止逻辑我单独拉了一段LD X1 // 停止按钮 ZRST S20 S24 // 复位所有工作状态 SET S0 // 回到待机 RST M500 // 关运行标志ZRST是区间复位指令一次把S20到S24全部复位。要注意如果当前正在S30报警状态停止按钮也需要能够退出报警所以复位区间要把S30也带上我实际程序里是ZRST S20 S30。这个细节很容易漏漏了之后一旦报警按停止键没反应只能断电复位体验非常糟糕。4. GT Designer3画面设计与HMI联动把程序搬上触摸屏4.1 画面工程的建立与GOT类型选择PLC程序写完开始做触摸屏画面。打开GT Designer3新建工程第一步选GOT类型。我用的是GT27系列这个系列在仿真器支持上比较完善字体和对象类型也丰富。通信设置这块PLC选FX3U系列接口选择“CPU直连”这样才能和GX Works2的仿真PLC建立通信。很多人建完工程直接画画面忘了设置系统区和通信参数导致后来GT Simulator3根本连不上GX Simulator。所以建完工程第一件事我建议先用“通信设置”向导走一遍确认控制器类型和连接方式正确。4.2 按钮、指示灯、阶段显示和报警的映射画面我做了几个核心区域启动停止区、状态指示灯区、阶段文字显示区、循环计数显示区、报警区。启动按钮在主画面上放一个“位开关”软元件设X0动作选点动也就是按下时X0为ON、松开为OFF。停止按钮同样用X1。模式选择开关用“位开关”的交替功能软元件X3按一次切换一次画面上可以用两个状态文本“标准”和“轻柔”来显示当前模式。状态指示灯直接对应Y0到Y6。进水阀亮绿色排水阀亮黄色脱水亮红色门锁合上亮蓝色。这种颜色区分在现场很实用仿真时也能一眼看出当前状态。阶段显示我用“字指示灯”对象软元件D0。程序里在各个状态里写入对应的阶段代码// 在S20里写 MOV K20 D0 // 在S21里写 MOV K21 D0 // 在S22里写 MOV K22 D0 // 在S23里写 MOV K23 D0 // 在S24里写 MOV K24 D0画面的字指示灯对象里设置多行文本D0等于20时显示“进水”等于21时显示“洗涤”以此类推。这样画面上能实时看到流程走到了哪一步。循环计数显示用“数值显示”对象软元件D21单位设个“次”看起来更直观。报警显示这一块我用D30存放报警代码。程序里如果进水超时或者排水超时就往D30里写一个1或2。画面上放一个“报警显示”对象关联D30再配置好报警文本。仿真时一旦D30被写入画面立刻弹出报警信息这个功能在真机上也非常好用。4.3 GT Simulator3与GX Simulator的联动流程画面工程做完进入最爽也最容易出问题的环节仿真联动。GX Works2这边的操作是菜单栏点“调试”里的“开始/停止模拟”启动GX Simulator2。模拟启动后梯形图会高亮显示当前执行中的触点比如S20正在运行进水阀Y0的状态会变成绿色高亮。打开“软元件监视”窗口可以强制ON/OFF一些输入点比如X2水位到位、X4门锁到位。确认PLC程序跑起来之后打开GT Designer3里的GT Simulator3。GT Simulator3启动后默认是以独立HMI的形式模拟。想要和PLC仿真联动需要在GT Simulator3的设置里选择连接GX Simulator2。具体的菜单位置一般在“模拟”或“通讯设置”里勾选“使用GX Simulator”或者“PLC仿真器联动”。联动成功之后你去点GT Simulator3画面上的启动按钮GX Works2里的梯形图会同步看到X0变成ONS0状态开始执行S20进水状态高亮。这感觉就像真机触摸屏连着PLC一样整个信号链路全部打通。5. 联调阶段我踩过的几个坑从定时器到画面数据不同步5.1 定时器编号和时基单位混搭第一个坑来自定时器时基。FX3U的T0到T199是100ms时基T200到T245是10ms时基。一开始我把正转7秒写成T0 K70这个没错K70意味着70个100ms也就是7秒。但同样的K70如果放到T200里就只剩0.7秒了。如果你一堆定时器混用画面上的节奏会突然变快或变慢还以为程序逻辑错了。排查这种问题我习惯在软元件监视窗口里同时看定时器的当前值和设定值。如果当前值从0一直涨到设定值然后触点动作那说明计时逻辑没问题如果设定值看起来不对先查K值的单位是不是100ms。还有一个附带问题定时器设定值可以用寄存器D来提供比如OUT T0 D100。我调试时遇到过D100被误写成0导致正转节拍瞬间跳过的诡异现象。所以用D做设定值时一定要在启动脉冲那段程序里确保MOV已经把值写进去了否则定时器拿到0基本等于常开。5.2 计数器不动作或提前动作的根因洗涤循环计数C0我最初接在T2的常开触点后面也就是反转节拍结束时计数。第一次仿真时发现C0到不了设定值或者有时候一下子加了好几次数动作看起来乱七八糟。后来用监视窗口盯着看发现问题出在反转结束那个瞬间T2触点在断开、导通的临界状态抖动。因为T2的ON状态不止持续一个扫描周期如果我又在T2后面串了别的触点导致OFF到ON的沿判断被干扰计数就变得不可靠。解决方法是给计数条件加一个脉冲整形或者直接用T2的边沿触发。三菱的PLS指令可以把一个窄脉冲提取出来我用一个辅助继电器M601来做计数脉冲T2一旦导通M601只ON一个扫描周期计数于是只加一次。这种沿处理思路在写任何计数器逻辑时都适用。5.3 仿真画面数据不刷新的真正原因GT Simulator3和GX Simulator2这俩协同工作的时候最容易出现的现象是画面上的按钮能点但PLC那边没有任何反应或者PLC程序一直在跑但画面上的指示灯和数据永远不变。我第一次遇到时以为是版本不兼容折腾了好久才发现是通信设置里选错了连接方式。GX Simulator2模拟出来的PLC默认提供一条虚拟通信通道GT Simulator3要指定走这条通道而不是走以太网或者串口。在GT Simulator3的通信目标设置里把连接目标选成“GX Simulator2”而不是某个具体的IP地址或COM口问题就解决了。还有一次是画面里把水位开关X2设成了“位开关”的动作模式误设成交替型结果按一下水位到位再按一下水位消失逻辑来回横跳。这个问题不在程序在画面配置。所以做画面映射时按钮是点动还是交替一定要分清启动按钮用点动模式选择才用交替别把逻辑搞混。5.4 双线圈输出和STL未配对程序做到后面最容易出现的是“双线圈”问题。比如排水阀Y3在S22里写了一次在S23里又写了一次。GX Works2编译时会有警告提示“双线圈”如果你忽略这个警告运行结果可能完全出乎意料。双线圈的机制是PLC扫描时同一个输出线圈如果在多处OUT最终以最后一次扫描为准。所以在S22里OUT Y3切到S23后S23里的OUT Y3覆盖了前面的结果。如果S23里忘记OUT Y3那个输出就一直保持S22最后一次的状态看起来像“排水阀不受控制”。这个现象仿真时特别能迷惑人因为画面上的Y3有时候亮有时候灭似乎没有规律。解决办法有两种要么每个输出在全局只写一次用中间继电器汇总要么干脆把排水阀的状态在所有相关STL块里都写全。我习惯用第二种简单直接只要保证所有可能激活排水阀的状态都写了OUT Y3就行。检查时在程序搜索里搜一遍Y3看看一共出现在几个地方每个地方是不是都符合预期。STL配对问题也是编译期常见的报错。STL开头必须和RET结尾配对程序末尾要写RET而且STL块内部不能用MC/MCR主控指令。如果编译直接报错程序根本进不了仿真所以这个坑其实是最容易发现的前提是你愿意看编译输出窗口。很多人编译报错后直接盯着梯形图找半天其实滚动条往下一拉错误行号和原因都写得很清楚。最后再分享一个小技巧不知道你们做仿真有没有一个习惯我反正在联调洗衣机这套程序时养成了每次改动程序后先把GX Simulator2停掉再重新启动而不是直接在线修改。因为GX Simulator2的在线修改对STL程序的支持偶尔会犯迷糊状态跑到一半你改程序容易产生“旧状态卡死、新状态进不去”的假故障。重启模拟把状态归零再按一次启动按钮重新走流程基本上能看到正确的结果。另外GT Designer3里给每个画面对象加注释时别偷懒一个按钮、一个指示灯注释都写清楚。仿真阶段看不出什么一旦真机调试现场的人对着画面问“这个绿灯是啥”的时候你会感谢当初多打的那几个字。洗衣机这套控制逻辑真正写下来其实不算长但每一段都有它该有的位置和理由。顺序控制项目最大的魅力就在这里程序本身不复杂复杂的是把常识、安全、时序这些“人的经验”翻译成PLC能执行、人能维护的逻辑。这篇先聊到这儿回头有时间我再把报警处理、手动调试模式这些进阶部分补一补。