西门子PLC状态机初浅设计
记录一次应用plc所牵连的应用设计其中主体学习参考isa-88的框架模型。西门子官方架构博大精深依据我实际使用做了适当拆解。1. 文档概述1.1 目的本文档规定基于ST 编程语言实现的设备状态机软件架构、状态定义、状态转换、控制逻辑、异常处理、复位机制及程序接口。状态机用于实现设备在不同运行阶段之间的有序切换并对设备的启动、运行、停止、完成、故障及复位过程进行统一管理。状态机设计应满足以下目标状态定义清晰状态转换条件明确状态转换具有唯一性正常流程与异常流程分离支持自动、手动及维护模式支持 HMI 状态显示及操作支持运行超时检测支持故障锁定及复位支持状态机复用支持在线调试和故障诊断避免业务逻辑直接依赖物理 IO 地址。2. 设计原则状态机采用“状态 事件 条件 动作”的基本模型。状态机的基本逻辑为当前状态 ↓ 判断当前状态允许的事件/条件 ↓ 执行状态动作 ↓ 满足状态转换条件 ↓ 进入下一状态状态机不直接控制物理 IO而是通过设备控制层实现设备动作。推荐的软件层级关系如下┌────────────────────────────┐ │ HMI / SCADA │ └─────────────┬──────────────┘ ↓ ┌────────────────────────────┐ │ Sequence Layer │ │ FB_MainSequence │ └─────────────┬──────────────┘ ↓ ┌────────────────────────────┐ │ Application Layer │ │ FB_Target / FB_AGV / ... │ └─────────────┬──────────────┘ ↓ ┌────────────────────────────┐ │ Device Layer │ │ Motor / Valve / Pump / ... │ └────────────────────────────┘状态机只负责当前处于什么状态当前状态是否允许执行下一状态是什么状态转换是否超时是否发生故障是否允许复位。状态机不负责直接操作Q0.0直接读取I0.0直接执行具体阀门驱动直接处理 Modbus 报文直接实现复杂设备控制算法。3. 状态机软件架构3.1 状态机组成一个完整的状态机由以下模块组成FB_xxxSequence │ ├── Command │ ├── xStart │ ├── xStop │ ├── xReset │ └── xAbort │ ├── State │ ├── eState │ ├── eLastState │ └── eNextState │ ├── Control │ ├── xEnable │ ├── xRunning │ ├── xComplete │ ├── xFault │ └── xBusy │ ├── Permit │ ├── xStartPermit │ ├── xRunPermit │ └── xResetPermit │ ├── Timer │ ├── tStateTimeout │ └── tStepTime │ ├── Diagnostic │ ├── uiStateCode │ ├── uiErrorCode │ └── xTimeout │ └── Sequence Logic └── CASE eState OF4. 状态类型定义推荐使用 PLC 数据类型ENUM定义状态。不推荐iState : 0; iState : 10; iState : 20;推荐TYPE eTargetState : ( Idle, Init, Check, Ready, Start, Running, Stop, Complete, Fault, Reset ); END_TYPE状态变量eState : eTargetState;这样可以避免大量“魔法数字”。5. 标准状态定义对于通用设备推荐建立以下基础状态。状态名称状态说明Idle空闲设备未执行任务Init初始化初始化内部变量和设备Check条件检查检查启动条件Ready就绪启动条件满足Start启动执行启动动作Running运行正常执行任务Stop停止执行正常停止Complete完成当前任务完成Fault故障当前流程发生故障Reset复位执行故障或流程复位状态流程┌──────────────┐ │ Idle │ └──────┬───────┘ ↓ ┌──────────────┐ │ Init │ └──────┬───────┘ ↓ ┌──────────────┐ │ Check │ └──────┬───────┘ ↓ ┌──────────────┐ │ Ready │ └──────┬───────┘ ↓ ┌──────────────┐ │ Start │ └──────┬───────┘ ↓ ┌──────────────┐ │ Running │ └───┬──────┬───┘ │ │ Stop Fault │ │ ↓ ↓ ┌──────┐ ┌───────┐ │ Stop │ │ Fault │ └──┬───┘ └───┬───┘ ↓ ↓ Complete Reset ↓ ↓ Idle Idle6. 状态定义的工程规则每个状态必须定义以下内容项目要求状态名称唯一状态编号唯一状态进入条件明确状态执行动作明确状态完成条件明确状态超时时间必要时定义状态失败条件明确下一状态明确故障状态明确HMI显示文本明确例如Start状态状态 Start 进入条件 Ready 状态收到 Start 命令 执行动作 启动目标设备 完成条件 设备反馈 Running TRUE 超时 5 s 超时处理 进入 Fault 下一状态 Running7. 状态转换设计状态转换应采用明确的“当前状态 条件 → 下一状态”模型。例如Idle │ │ xStart ↓ Init │ │ xInitDone ↓ Check │ │ xCheckOK ↓ Ready │ │ xStart ↓ Start │ │ xRunning ↓ Running状态转换条件必须明确不允许一个状态同时存在多个相互冲突的转换条件。例如IF xReady THEN eState : Running; END_IF; IF xFault THEN eState : Fault; END_IF;虽然能够运行但可能造成多个条件同时成立时的状态覆盖问题。推荐使用明确优先级IF xFault THEN eState : Fault; ELSIF xReady THEN eState : Running; END_IF;安全相关条件应具有最高优先级。8. 状态转换优先级推荐状态转换优先级如下Priority 1安全条件 Priority 2故障条件 Priority 3停止/中止命令 Priority 4正常完成条件 Priority 5启动条件 Priority 6普通流程条件例如当前状态 Running ┌─ Safety Fault ─────→ Fault │ Running├─ Device Fault ─────→ Fault │ ├─ Stop Command ─────→ Stop │ ├─ Complete ─────────→ Complete │ └─ Otherwise ────────→ Running9. 状态机主程序结构推荐使用CASE实现状态机主体。CASE eState OF Idle: // Idle state logic Init: // Initialization logic Check: // Condition check Ready: // Ready logic Start: // Start logic Running: // Running logic Stop: // Stop logic Complete: // Complete logic Fault: // Fault logic Reset: // Reset logic END_CASE;禁止在多个程序块中同时修改状态变量。例如FB_MainSequence └── 唯一修改 eState其他 FB 只提供状态条件FB_Target └── xRunning └── xFault └── xReady10. 状态进入与状态保持建议区分xStateEnterxStateActivexStateExit定义xStateEnter : eState eLastState; xStateActive : TRUE;状态发生变化时IF eState eLastState THEN xStateEnter : TRUE; ELSE xStateEnter : FALSE; END_IF;然后eLastState : eState;这样可以实现“进入状态时执行一次”。例如IF xStateEnter THEN xStartCommand : TRUE; END_IF;避免xStartCommand : TRUE;在整个状态周期内持续执行。11. 推荐的状态机模板标准 FB 建议结构如下// // State Change Detection // #xStateEnter : #eState #eLastState; IF #xStateEnter THEN #tStateStart : TIME_TCK(); END_IF; // // Global Fault Check // IF #xSafetyFault THEN #eState : eSequenceState.Fault; END_IF; // // State Machine // CASE #eState OF eSequenceState.Idle: #xBusy : FALSE; #xComplete : FALSE; IF #xStart THEN #eState : eSequenceState.Init; END_IF; eSequenceState.Init: #xBusy : TRUE; IF #xInitDone THEN #eState : eSequenceState.Check; END_IF; eSequenceState.Check: IF #xCheckOK THEN #eState : eSequenceState.Ready; ELSIF #xCheckFault THEN #eState : eSequenceState.Fault; END_IF; eSequenceState.Ready: #xReady : TRUE; IF #xStart THEN #eState : eSequenceState.Start; END_IF; eSequenceState.Start: #xBusy : TRUE; IF #xRunning THEN #eState : eSequenceState.Running; ELSIF #xStartTimeout THEN #eState : eSequenceState.Fault; END_IF; eSequenceState.Running: #xBusy : TRUE; IF #xFault THEN #eState : eSequenceState.Fault; ELSIF #xStop THEN #eState : eSequenceState.Stop; ELSIF #xComplete THEN #eState : eSequenceState.Complete; END_IF; eSequenceState.Stop: IF #xStopped THEN #eState : eSequenceState.Complete; END_IF; eSequenceState.Complete: #xComplete : TRUE; IF NOT #xStart THEN #eState : eSequenceState.Idle; END_IF; eSequenceState.Fault: #xFault : TRUE; IF #xReset THEN #eState : eSequenceState.Reset; END_IF; eSequenceState.Reset: IF #xResetDone THEN #eState : eSequenceState.Idle; END_IF; ELSE: #eState : eSequenceState.Fault; END_CASE; // // Last State // #eLastState : #eState;12. 状态超时机制所有可能等待设备反馈的状态均建议增加超时保护。例如Start ↓ 等待 Motor.xRunning ↓ 最大等待 5 s ↓ 未收到反馈 ↓ Fault推荐TON_StartTimeout( IN : (#eState eSequenceState.Start), PT : T#5s );然后IF #TON_StartTimeout.Q THEN #eErrorCode : 1001; #eState : eSequenceState.Fault; END_IF;13. 超时错误码建议每一种状态超时具有独立错误码。例如错误码状态故障1001Init初始化超时1002Check条件检查超时1003Start启动超时1004Running运行超时1005Stop停止超时1006Reset复位超时错误码建议采用模块 状态 故障类型进行统一规划。14. 状态机命令设计状态机不建议直接使用多个散乱 BOOL 作为命令。建议统一Command │ ├── xStart ├── xStop ├── xReset ├── xAbort └── xPause例如Start 启动当前流程 Stop 正常停止当前流程 Abort 立即中止当前流程 Reset 复位故障 Pause 暂停当前流程15. Start / Stop / Abort 的区别这三个命令必须明确区分。Start正常启动Ready → Start → RunningStop正常停止Running → Stop → Complete/IdleAbort异常中止Running → Abort → Safe Stop例如Running │ ├── Stop ───→ Stop │ ├── Abort ──→ Abort │ └── Fault ──→ Fault16. 自动模式与手动模式状态机与设备手动控制应进行隔离。推荐eMode │ ├── Manual ├── Auto ├── Maintenance └── Simulation自动状态机只在IF #eMode eMode.Auto THEN条件下运行。手动模式HMI ↓ Device Cmd ↓ Device FB而不是HMI ↓ State Machine这样手动操作不会破坏自动流程状态。17. 状态机与设备控制关系推荐FB_TargetSequence │ ├── Start Target │ ↓ FB_Target │ ├── Motor ├── Valve └── Sensor状态机只提出要求xMoveTarget : TRUE设备 FB 决定电机如何启动 电机如何停止 反馈如何判断 故障如何判断18. 状态机与联锁关系状态机启动前必须检查xStartPermit例如xStartPermit xSafetyOK AND xCoolingOK AND xVacuumOK AND xTargetReady AND xAGVReady状态机IF #xStart AND #xStartPermit THEN #eState : eSequenceState.Init; END_IF;如果xStart TRUE xStartPermit FALSE则保持 Ready而不是直接进入 Fault。这是一个很重要的设计原则“不满足启动条件”和“发生故障”必须区分。19. 状态机故障分类建议至少区分A类安全故障例如急停 安全门打开 安全回路断开处理→ FaultB类设备故障例如电机故障 阀门故障 传感器故障处理→ FaultC类流程超时例如阀门打开超时 AGV到位超时 电机启动超时处理→ FaultD类条件未满足例如水冷未准备 真空未达到 设备未回原点通常不进入 Fault而是保持 Check / Ready20. Fault 状态设计进入 Fault 后状态机不得自动退出。Fault │ │ xReset ↓ Reset │ │ xResetDone ↓ Idle推荐Fault: #xBusy : FALSE; #xFault : TRUE; IF #xReset THEN IF #xResetPermit THEN #eState : eSequenceState.Reset; END_IF; END_IF;故障复位必须满足故障原因消失 设备允许复位 收到 Reset 命令21. Reset 状态Reset 不建议简单eState : Idle;应执行停止输出 清除临时命令 复位设备 清除状态机内部变量 清除流程计时器 确认设备安全流程Fault ↓ Reset ↓ Device Reset ↓ Clear Command ↓ Check Device ↓ Idle22. 状态机数据结构推荐定义UDT_Sequence │ ├── Cmd │ ├── xStart │ ├── xStop │ ├── xAbort │ └── xReset │ ├── State │ ├── eCurrent │ ├── eLast │ └── eNext │ ├── Status │ ├── xReady │ ├── xBusy │ ├── xRunning │ ├── xComplete │ └── xFault │ ├── Permit │ ├── xStart │ ├── xStop │ └── xReset │ └── Diagnostic ├── uiStateCode ├── uiErrorCode ├── tStateTime └── xTimeout23. HMI接口设计HMI不直接修改状态。禁止HMI ↓ eState : Running推荐HMI ↓ Cmd.xStart ↓ State Machine ↓ eState ↓ HMI显示HMI可以读取State.eCurrent Status.xReady Status.xBusy Status.xRunning Status.xComplete Status.xFault Diagnostic.uiErrorCodeHMI只允许写Cmd.xStart Cmd.xStop Cmd.xReset Cmd.xAbort24. HMI状态显示建议建立统一状态代码StateCodeHMI显示Idle0空闲Init10初始化Check20条件检查Ready30就绪Start40启动Running50运行Stop60停止Complete70完成Fault80故障Reset90复位PLC内部使用 ENUM。HMI显示可以通过状态代码进行映射。25. 状态机调用规范建议每个状态机只允许一个 FB 负责状态管理。例如FB_TargetSequence内部CASE eState OF而其他程序FB_Target FB_AGV FB_Cooling FB_Vacuum只能提供状态信息。禁止FB_Target → 修改 FB_TargetSequence.eState26. 多状态机之间的关系复杂系统不建议建立一个巨大的状态机。例如整个系统可以拆分FB_MainSequence │ ├── FB_TargetSequence ├── FB_AGVSequence ├── FB_CoolingSequence └── FB_TreatmentSequence系统状态机Main ↓ Check ↓ Target Ready ↓ AGV Ready ↓ Cooling Ready ↓ Treatment Ready ↓ Running各子系统独立运行自己的状态机。27. 状态机层级关系推荐Level 1 System Sequence ↓ Level 2 Process Sequence ↓ Level 3 Equipment Sequence ↓ Level 4 Device Control例如MainSequence ↓ TargetReplaceSequence ↓ TargetSequence ↓ Motor / Valve / Sensor这样可以避免一个 FB 里面出现数千行程序。28. 状态机程序规模控制建议程序类型推荐规模Device FB100~500 行Service FB100~500 行Equipment FB300~800 行Sequence FB300~1000 行Main Sequence≤1000 行如果一个状态机超过约 1000 行应考虑拆分子状态机。29. 状态机禁止事项以下写法不建议使用// 直接跳转多个状态 #eState : Running;如果没有明确转换条件不允许直接跳转。禁止#eState : 10;禁止IF HMI_Button THEN #eState : Running; END_IF;禁止Q0.0 : TRUE;禁止多个 FB 同时修改#eState禁止通过多个 BOOL 隐式表达复杂状态xInit xCheck xReady xStart xRun xStop xComplete这些信号可以作为状态输出但不能替代主状态变量。30. 状态机标准模板最终建议项目所有 Sequence FB 统一采用以下结构FB_xxxSequence │ ├── 01 Interface │ ├── 02 Initialization │ ├── 03 Command │ ├── 04 Permit │ ├── 05 State Change │ ├── 06 Timeout │ ├── 07 State Machine │ ├── 08 Fault │ ├── 09 Status │ └── 10 Diagnostic程序顺序固定后后续人员查看任何一个 Sequence FB都能够快速找到状态机。31. 状态机标准执行周期每个 PLC 扫描周期执行① 读取输入 ↓ ② 更新设备状态 ↓ ③ 计算安全条件 ↓ ④ 计算联锁条件 ↓ ⑤ 读取 HMI Command ↓ ⑥ 状态机执行 ↓ ⑦ 计算设备 Command ↓ ⑧ 更新报警 ↓ ⑨ 更新 HMI Status ↓ ⑩ 输出 IO推荐状态机处于⑤⑦之间。32. 状态机时序示例以设备启动为例HMI Start │ ↓ Cmd.xStart │ ↓ Check Start Permit │ ├── FALSE → 保持 Ready │ └── TRUE ↓ Start ↓ Device Start ↓ 等待 Running / \ / \ 反馈成功 超时 ↓ ↓ Running Fault33. 状态转换表推荐每个实际状态机都建立一张状态转换表。例如当前状态事件/条件下一状态备注IdleStartInit收到启动命令InitInitDoneCheck初始化完成InitFaultFault初始化故障CheckPermitOKReady启动条件满足CheckFaultFault检查发现故障ReadyStartStart收到启动命令StartRunningRunning设备启动成功StartTimeoutFault启动超时RunningCompleteComplete任务完成RunningStopStop正常停止RunningFaultFault设备故障StopStoppedComplete停止完成CompleteReset/IdleIdle流程结束FaultResetReset收到复位命令ResetResetDoneIdle复位完成34. 状态机设计检查项每一个状态机在设计完成后必须检查状态完整性是否定义 Idle是否定义 Init是否定义 Check是否定义 Ready是否定义 Running是否定义 Complete是否定义 Fault是否定义 Reset状态转换每个状态是否存在明确退出条件是否存在无法退出的状态是否存在循环跳转是否存在状态死锁是否存在多个条件同时成立是否定义转换优先级故障是否存在故障状态是否存在超时检测是否有错误码故障是否锁定是否需要人工复位复位条件是否明确安全急停是否具有最高优先级安全门是否纳入状态转换条件安全条件失效时是否进入安全状态复位是否需要重新检查安全条件HMIHMI是否只能发送CommandHMI是否能够读取Current State是否显示State Code是否显示Error Code是否显示State Time35. 状态机测试要求状态机测试至少包括以下内容测试项目测试内容预期结果正常启动Idle→Running状态正确正常停止Running→Stop正常停止正常完成Running→Complete流程完成启动条件不足Check保持不启动启动超时Start→Fault产生超时报警运行故障Running→Fault进入故障急停任意运行状态→安全状态输出安全复位Fault→Reset→Idle正常复位重复StartRunning期间Start不改变状态重复ResetIdle期间Reset不产生异常HMI断开状态机继续运行PLC不受影响PLC重新启动Startup状态恢复至安全初始状态36. 推荐的最终状态机架构本项目最终推荐采用HMI │ ┌────────────▼────────────┐ │ Command Layer │ │ Start / Stop / Reset │ └────────────┬────────────┘ │ ┌────────────▼────────────┐ │ Permit Layer │ │ Safety / Interlock │ └────────────┬────────────┘ │ ┌────────────▼────────────┐ │ Sequence FB │ │ │ │ Idle │ │ ↓ │ │ Init │ │ ↓ │ │ Check │ │ ↓ │ │ Ready │ │ ↓ │ │ Start │ │ ↓ │ │ Running │ │ ↓ │ │ Complete │ │ │ │ Fault ← Any Fault │ │ ↓ │ │ Reset │ └────────────┬────────────┘ │ ┌────────────▼────────────┐ │ Device Layer │ │ Motor / Valve / Pump │ │ Sensor / AGV / Drive │ └─────────────────────────┘37. 设计结论本项目状态机采用S7-1500 TIA Portal V19 SCL ENUM CASE的实现方式。核心设计原则为ENUM CASE Command Permit State Timeout Fault Reset形成统一状态机框架。对于大型设备系统不建议建立一个包含所有工艺步骤的超大状态机而应采用系统状态机 ↓ 工艺状态机 ↓ 设备状态机 ↓ 设备控制FB通过层级化状态机实现流程解耦。最终形成FB_MainSequence │ ├── FB_TargetSequence │ ├── FB_Target │ ├── FB_Motor │ └── FB_Valve │ ├── FB_AGVSequence │ ├── FB_CoolingSequence │ └── FB_TreatmentSequence所有状态机均遵循统一的Idle → Init → Check → Ready → Start → Running → Stop/Complete → Fault → Reset基础框架并允许根据具体工艺增加专用状态。该架构可作为后续所有设备 Sequence FB 的统一开发模板。

相关新闻

最新新闻

日新闻

周新闻

月新闻