4. 状态机建模基础
在CNC设备联动控制中,PLC程序经常需要处理“设备当前处于什么工况、什么条件下允许切换、切换时执行什么输出”这类问题。如果只用梯形图的置位/复位线圈堆叠逻辑,程序很快会变得难以维护。状态机建模提供了一种结构化表达方式:把设备行为拆分为有限个状态,用迁移描述状态之间的切换,用事件触发迁移,用动作定义状态或迁移期间输出什么,用守卫条件约束迁移是否允许发生。
一、五个核心概念
状态(State)是设备在某一时刻所处的稳定工况。例如一台加工单元可划分为:Idle(待机)、Homing(回零)、Ready(就绪)、Processing(加工中)、Paused(暂停)、Fault(故障)。状态必须是互斥的,同一时刻设备只能处于一个状态,这是状态机与普通标志位最本质的区别。
事件(Event)是引发状态迁移的外部或内部信号,例如操作员按下启动按钮、伺服到位信号上升沿、定时器超时、报警输入触发。事件通常是瞬时发生的,PLC中常用上升沿检测捕捉。
迁移(Transition)表示从一个源状态到目标状态的切换。一条迁移由“源状态 + 事件 + 守卫条件 + 动作 + 目标状态”构成。迁移是状态机的骨架,它决定了设备行为的合法路径。
守卫条件(Guard)是迁移上的布尔表达式,只有为真时迁移才被允许。例如从Ready迁移到Processing,守卫条件可能是气压正常 AND 安全门关闭 AND 工件已夹紧。守卫条件与事件的区别在于:事件回答“什么时候考虑切换”,守卫回答“现在允许不允许切换”。
动作(Action)是迁移发生时或状态驻留期间执行的输出操作,例如启动主轴、打开冷却液、置位完成标志、记录时间戳。动作可以绑定在迁移上(进入/退出时执行一次),也可以绑定在状态上(驻留期间持续执行)。
二、Moore模型与Mealy模型的区别
根据动作绑定位置的不同,状态机分为两种经典模型。
Moore模型:输出只由当前状态决定。即“处于什么状态,就输出什么”。例如只要进入Processing状态,主轴使能M3就为ON,与迁移路径无关。Moore模型的输出稳定、易于预测,适合表达设备持续性的工况输出,如指示灯、使能信号、模式标志。
Mealy模型:输出由当前状态和输入事件共同决定。即“在某个状态下,收到某个事件并满足守卫时,才输出某个动作”。例如在Ready状态下检测到Start事件且守卫满足,才输出“启动进给”脉冲。Mealy模型的响应更快、状态数量更少,适合表达瞬时动作、握手信号、脉冲输出。
在CNC设备联动中,两者往往混合使用:用Moore表达状态驻留输出(如“加工中”指示灯、伺服使能),用Mealy表达迁移瞬间动作(如“启动完成”脉冲、换刀请求)。
三、在PLC中如何落地
在西门子S7-1200/1500或三菱FX系列PLC中,状态机通常用整数或枚举变量表示当前状态,用CASE语句或状态寄存器实现。以下是一个简化的SCL风格伪代码示例,展示Moore与Mealy的混合表达:
// 状态定义
// 0=Idle, 1=Homing, 2=Ready, 3=Processing, 4=Paused, 5=Fault
CASE state OF
0: // Idle
IF PowerOn AND NOT Alarm THEN
state := 1; // 迁移到Homing
END_IF;
1: // Homing
HomeCmd := TRUE; // Moore输出:回零期间持续输出
IF HomeDone THEN
HomeCmd := FALSE;
state := 2; // 迁移到Ready
END_IF;
2: // Ready
ReadyLamp := TRUE; // Moore输出:就绪指示灯
IF StartBtn AND DoorClosed AND Clamped THEN
StartPulse := TRUE; // Mealy输出:迁移瞬间脉冲
state := 3;
END_IF;
3: // Processing
SpindleEnable := TRUE; // Moore输出:加工中主轴使能
IF ServoAlarm THEN
state := 5; // 迁移到Fault
ELSIF PauseBtn AND NOT EStop THEN
state := 4; // 迁移到Paused
END_IF;
4: // Paused
SpindleEnable := FALSE;
IF ResumeBtn AND AlarmReset THEN
state := 3; // 恢复加工
END_IF;
5: // Fault
SpindleEnable := FALSE;
FaultLamp := TRUE;
IF ResetBtn AND NOT Alarm THEN
state := 0; // 复位回Idle
END_IF;
END_CASE;
这段代码中,HomeCmd、ReadyLamp、SpindleEnable、FaultLamp是Moore输出,只要处于对应状态就持续为真;StartPulse是Mealy输出,只在Ready→Processing迁移的那一个扫描周期内为真,适合触发后续的启动握手或记录事件。
四、建模时的关键约定
第一,状态必须互斥且完备。互斥指任意时刻只有一个状态有效;完备指所有可能的工况都被覆盖,不能出现“没有状态匹配”的悬空情况。建议在CASE末尾加ELSE分支,将未知状态强制导向Fault或Idle。
第二,守卫条件要显式写出。不要把守卫条件隐含在事件里,例如“StartBtn AND DoorClosed”应拆分为事件StartBtn和守卫DoorClosed,这样在调试时能清楚区分“没按按钮”和“按了但门没关”两种不同原因。
第三,迁移动作要区分进入/退出。进入Processing时置位主轴使能,退出Processing时复位主轴使能,这种成对操作建议用状态进入/退出动作统一管理,避免在多个迁移分支中重复写复位逻辑。
第四,事件用上升沿。PLC扫描周期远快于按钮动作,若用电平判断,一个按钮按下可能触发多次迁移。建议对StartBtn、PauseBtn、ResetBtn等事件信号做上升沿检测后再送入状态机。
五、常见错误与排查
实际调试中,状态机最常出现三类问题。一是状态卡死:某个迁移的守卫条件永远为假,例如DoorClosed信号因传感器接线错误始终为OFF,导致Ready无法进入Processing。排查时可在PLC变量表中强制该信号,观察状态是否迁移。二是状态抖动:事件未做上升沿处理,或守卫条件在临界值附近波动,导致状态在两个值之间快速跳变。可用状态变化沿触发一个计数器,观察单位时间内的迁移次数。三是输出残留:退出某状态时忘记复位Moore输出,例如退出Processing后SpindleEnable仍为ON。建议在状态机的每个CASE分支开头统一复位所有输出,再按当前状态置位需要输出的信号。