自动化控制逻辑建模方法

一、IEC-61131-3 支持的语言(PLC国际标准)

IEC-61131-3 是PLC编程的核心标准,它规定 5种官方语言(工业界通用):

① LD --- Ladder Diagram(梯形图)

电气继电器逻辑演化而来;最适合 IO、互锁、安全逻辑;可读性强,电气工程师友好;不适合复杂算法

👉 用途

IO逻辑;安全联锁;简单控制

② FBD --- Function Block Diagram(功能块图)

模块化数据流逻辑;类似 Simulink

👉 用途

PID;控制回路;信号处理

③ ST --- Structured Text(结构化文本)

类似 Pascal / C 的高级语言;支持函数、循环、复杂数据结构

👉 用途

复杂算法;数据处理;状态机实现

👉 现代 PLC 项目中 ST 使用比例越来越高

④ SFC --- Sequential Function Chart(顺序功能图)

专门用于 流程控制;本质就是 PLC 标准化流程状态机

👉 用途

自动流程;工艺步骤;工站控制

SFC(Sequential Function Chart)顺序功能图,是一种专门为 PLC 自动化流程设计的图形语言。

它用三种元素表达设备逻辑:

① Step(步骤)

② Transition(转换条件)

③ Action(动作)

⑤ IL --- Instruction List(指令表)

类似汇编语言;已被淘汰(IEC 标准已不推荐)

二、设计架构图

① 设备模式(Mode)------策略层

模式不属于流程,限制系统运行策略,它是运行规则系统。定义设备运行层级权限。定义系统权限与运行层级。

思考顺序:

1️⃣ 正常生产需要什么模式

2️⃣ 调试需要什么权限

3️⃣ 维护时要禁止什么

4 每个模式允许什么动作

模式决定:

是否允许自动

是否允许并行

是否允许人工干预

是否允许跳过工序

模式 是否允许轴运动 是否允许IO动作 是否允许自动流程 用途

Manual ✔ ✔ ✘ 调试

Auto ✔ ✔ ✔ 正常生产

Debug ✔ 部分 部分 开发调试

Maintenance ✘ 部分 ✘ 维护

👉 模式决定系统权限

👉 必须先设计,否则后期会混乱

设备全局状态(State)

↓ 反映系统运行阶段

② 全局状态(State)------系统生命状态

用于描述:

设备处于什么状态?

状态如何切换?

切换条件是什么?

控制大脑。它反映设备整体阶段,状态不是流程,设备始终处于某个状态。

状态 含义 允许动作 退出条件

Idle 空闲 等待启动 收到Start

Init 初始化 回零、加载参数 完成

Ready 就绪 等待自动运行 Start

Run 自动运行 执行流程 完成/错误

Pause 暂停 保持状态 继续/停止

Stop 停止 安全停机 Reset

Error 错误 停止所有动作 Reset

Alarm **** **** ****

EStop **** **** ****

Homing **** **** ****

Alarm **** **** ****

👉 状态机 = 整个系统骨架

进入条件;执行动作;退出条件

它决定:

是否允许工站执行

是否允许调度

是否允许恢复

问自己三个问题:

1️⃣ 设备"静态时"有哪些状态?

例如:

Idle / Ready / Error / Stop

2️⃣ 设备"运行时"有哪些状态?

Init / Run / Pause / Complete

3️⃣ 哪些条件会触发状态变化?

例如:

Start按钮;控制器完成反馈;报警信号;超时

👉 设计原则

✔ 状态少而清晰

✔ 转换条件明确

✔ 每个状态含义唯一

📌 状态机 = 整个系统的"骨架"

工站调度层(Station Manager)

↓ 控制并行工站

③ 工站管理层(Station Manager)

它负责:

多工站并行调度

工站互锁

资源冲突管理

同步点控制

这层是流程调度层。不是步骤。

例如:

工站A → 上料

工站B → 加工

工站C → 下料

它们可以:

并行运行

等待信号同步

互相触发

工站流程(Station Sequence)

↓ 大步序

④ 工站流程(大步序) 工艺流程设计(Process Flow)

自动流程骨架:每个工站都有自己的主流程:

上料工站:

Step1 等待物料

Step2 夹紧

Step3 完成

加工工站:

Step1 定位

Step2 加工

Step3 检测

这叫:

👉 Station Sequence

它们是:

独立执行单元

可以暂停

可以恢复

可以重跑

每一步需定义:

触发条件;执行动作;完成条件;超时策略

✔ 设计方法(工程思考顺序)

从工艺角度问:

1️⃣ 设备第一步做什么

2️⃣ 做完怎么判断完成

3️⃣ 下一步是什么

4️⃣ 哪些步骤可并行

得到流程:

回零 → 等待物料 → 定位 → 加工 → 检测 → 卸料

👉 工程原则

✔ 流程只描述顺序

✔ 不描述控制细节

✔ 不写程序逻辑

📌 流程 = 工艺视角

子流程(Sub Sequence)动作定义表(Action Table)

↓ 小步序

⑤ 子流程(小步序)

执行手脚。每个大步骤内部会有子流程,它们只是流程拆分,不是状态:

例如:

Step2 夹紧

├─ 打开气阀

├─ 等待压力

├─ 检查传感器

└─ 确认完成

这就是:

👉 Sub Sequence

这是最实用、最容易落地的部分。

动作ID 名称 执行对象 触发条件 完成条件 超时 失败处理

A01 回原点 轴控制器 Init进入 所有轴到位 30s 报警

A02 打开夹具 IO 流程步骤2 到位信号 5s 重试

A03 激光加工 控制器 定位完成 控制器反馈完成 120s 停机

👉 上位机实现时直接映射这些动作即可。

✔ 设计方法

把流程拆成:

👉 原子动作

例如:

MoveAxis;ClampOn;LaserFire;ReadSensor;

然后定义:

动作输入;动作输出;完成条件;超时策略;手动控制方式

📌 动作 = 软件接口层

这一步做好:

👉 上位机代码会非常清晰

原子操作(Action)

↓ 硬件控制接口

⑥ 原子操作(Action)

最底层:

MoveAxis()

SetIO()

ReadSensor()

LaserOn()

它们:

不知道流程

不知道状态

不知道模式

它们只是硬件接口。

另外有两条横向系统:

安全系统(Safety System)

异常系统(Alarm/Event System)

它们 不属于步骤,而是全局监控层。

三、异常处理和安全

保护底线。异常和安全不属于步骤

而是:

横向系统

也就是:

流程系统

异常系统(跨所有工站)

安全系统(最高优先级)

安全系统(最高级)

负责:

急停

门禁

光栅

超限

硬件互锁

它会直接:

强制停止所有工站

切断动作

进入安全状态

安全系统 永远在流程之上

恢复与安全策略(Recovery Model)

这是区分普通程序员和工程师的关键。

恢复策略模板

情况 是否允许继续 恢复动作

暂停恢复 ✔ 从当前步骤继续

IO异常恢复 ✔ 重试动作

轴错误恢复 部分 重新初始化

安全错误 ✘ 必须人工确认

异常系统(第二级)

负责:

报警分类

错误记录

UI提示

恢复策略

它会:

通知状态机进入 Error

通知工站停止

异常系统 管理状态

而不是步骤。

互锁与异常设计(Interlock Model)

工业系统最关键部分。

号 条件 禁止动作 原因

I01 安全门未关 禁止轴运动 安全

I02 真空未建立 禁止加工 工艺要求

I03 控制器报警 禁止所有动作 系统保护

异常分类模板

类型 例子 处理方式

设备报警 轴错误 停止流程

工艺报警 定位失败 重试/跳过

通信异常 控制器断开 进入Error

其它如:门开禁止启动;激光未关闭不能松夹;轴未回零禁止自动;气压低禁止运行

四、正确的系统控制流应该是

Mode

State

Station Manager

Station Sequence

Sub Sequence

Action

同时存在:

Safety System → 可中断一切

Alarm System → 可改变State

分三类思考:

1️⃣ 安全互锁

问:

👉 哪些情况必须禁止动作?

例如:

门未关;急停按下;控制器报警;

2️⃣ 工艺互锁

问:

👉 哪些条件不满足不能加工?

例如:

真空未建立;工件未检测到;温度未稳定

3️⃣ 故障恢复

问:

👉 出错后能否继续?

例如:

IO错误可恢复;轴错误需初始化;安全错误必须人工处理

📌 异常设计 = 系统稳定性核心

1、最重要的工程原则(请记住)

① 安全永远高于流程

安全不能写进步骤。

② 异常不属于步骤

步骤只能"发现异常",不能处理异常。

③ 工站是并行单元

不是步骤集合。

④ 状态是系统级

不是工艺级。

⑤ 模式是策略级

不是运行级。

2、一个真实设备的软件结构应该像这样

DeviceController

├─ ModeManager

├─ StateMachine

├─ SafetyManager

├─ AlarmManager

├─ StationManager

│ ├─ StationA

│ │ └─ Sequence

│ │ └─ SubSequence

│ ├─ StationB

│ └─ StationC

└─ HardwareInterface

如果你按这个结构设计:

✔ 并行可控

✔ 安全独立

✔ 异常统一

✔ 工站解耦

✔ 流程可维护

这就是工业级设备软件的骨架。

最后一句总结

模式决定策略

状态决定阶段

工站决定并行

步序决定流程

操作决定动作

安全决定底线

3、最终设计成果(你应得到这些文档)

1️⃣ 模式图

2️⃣ 状态机图

3️⃣ 流程图

4️⃣ 动作表

5️⃣ 互锁表

6️⃣ 异常恢复表

这就是完整自动化逻辑设计文档。实现技术(C++、PLC、控制器)都只是执行这些规则。

4、设计工具与方法对照表

步骤 推荐工具 设计思路

系统边界 draw.io 责任划分

模式设计 表格 + 状态图 权限管理

状态机 状态图 / Stateflow 系统骨架

流程设计 流程图 工艺顺序

动作定义 Excel 接口拆解

互锁异常 Excel/FMEA 稳定性保障

五、C++实现状态和步序跳转的核心

1.定义状态接口:状态自己决定跳转。线程不关心逻辑。

cpp 复制代码
class IState
{
public:
    virtual ~IState() = default;
    virtual void onEnter() {}
    virtual void onExit() {}
    // 返回下一个状态ID
    virtual int update() = 0;
};

2. 定义状态机

cpp 复制代码
class StateMachine
{
    std::unordered_map<int, std::unique_ptr<IState>> states;
    IState* current = nullptr;
    int currentId = -1;
public:
    void addState(int id, std::unique_ptr<IState> s)
    {
        states[id] = std::move(s);
    }

    void setInitial(int id)
    {
        currentId = id;
        current = states[id].get();
        current->onEnter();
    }

    void update()
    {
        int next = current->update();

        if (next != currentId)
        {
            current->onExit();
            currentId = next;
            current = states[currentId].get();
            current->onEnter();
        }
    }
};

3. 线程执行器

cpp 复制代码
void runMachine(StateMachine& sm)
{
    while (running)
    {
        sm.update();
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}
线程只调用 update()

👉 流程逻辑完全解耦

4、状态内部如何优雅跳转?

示例:加工流程状态

cpp 复制代码
class ProcessState : public IState
{
public:
    int update() override
    {
        if (emergencyStop())
            return STATE_ESTOP;

        if (!axisReady())
            return STATE_WAIT_AXIS;

        if (processFinished())
            return STATE_DONE;

        return STATE_PROCESS; // 保持当前
    }
};

状态自己决定跳哪里。

线程完全不知道。

5、优雅实现"异常跳转"

只需要在每个状态统一写:

cpp 复制代码
if (globalError())
    return STATE_ERROR;

👉 所有状态自动支持异常跳转

👉 不需要在线程中处理

6、优雅实现"回退"

状态返回目标即可

cpp 复制代码
if (retryCount < 3)
    return STATE_POSITION;
else
    return STATE_ERROR;

7、优雅实现"并行流程"

核心原则:

状态机不做耗时动作

动作交给任务线程

例如:

cpp 复制代码
class WaitAxisState : public IState
{
public:
    int update() override
    {
        if (axisDone.load())
            return STATE_NEXT;

        return STATE_WAIT_AXIS;
    }
};

轴线程独立:

cpp 复制代码
void axisThread()
{
    while (running)
    {
        if (needMove)
        {
            moveAxis();
            axisDone = true;
        }
    }
}

👉 状态机只判断事件

👉 不执行耗时动作

8、优雅实现"事件跳转"

只要事件是原子变量即可:

cpp 复制代码
std::atomic<bool> estop = false;
std::atomic<bool> manual = false;

状态里统一写:

cpp 复制代码
if (estop)
    return STATE_ESTOP;
if (manual)
    return STATE_MANUAL;

👉 任意状态都支持跳转

9、为什么这是工业最优结构?

因为它满足:

✔ 状态逻辑集中

✔ 线程职责单一

✔ 支持回退/跳转

✔ 支持异常

✔ 支持并行

✔ 支持调试日志

✔ 可测试

✔ 可扩展

10. 定义步骤接口

cpp 复制代码
class IStep
{
public:
    virtual ~IStep() = default;
    virtual void onEnter() {}
    virtual void onExit() {}

    // 返回下一步ID
    virtual int execute() = 0;
};

每个步骤自己决定跳转。线程不负责流程。

11. 步骤管理器(核心)

cpp 复制代码
class StepEngine
{
    std::unordered_map<int, std::unique_ptr<IStep>> steps;
    IStep* current = nullptr;
    int currentId = -1;
public:
    void addStep(int id, std::unique_ptr<IStep> s)
    {
        steps[id] = std::move(s);
    }

    void setStart(int id)
    {
        currentId = id;
        current = steps[id].get();
        current->onEnter();
    }

    void update()
    {
        int next = current->execute();

        if (next != currentId)
        {
            current->onExit();
            currentId = next;
            current = steps[currentId].get();
            current->onEnter();
        }
    }
};

12.线程执行器

cpp 复制代码
void runProcess(StepEngine& engine)
{
    while (running)
    {
        engine.update();
        std::this_thread::sleep_for(std::chrono::milliseconds(5));
    }
}

线程只是调度器。

13.步骤内部优雅跳转方式

示例1:顺序跳转

cpp 复制代码
class Step_Load : public IStep
{
public:
    int execute() override
    {
        if (!materialReady())
            return STEP_WAIT;

        startClamp();
        return STEP_MOVE;
    }
};

示例2:异常跳转

cpp 复制代码
class Step_Move : public IStep
{
public:
    int execute() override
    {
        if (estop)
            return STEP_ERROR;

        if (axisDone())
            return STEP_PROCESS;

        return STEP_MOVE;
    }
};

示例3:回退跳转

cpp 复制代码
class Step_Process : public IStep
{
    int retry = 0;

public:
    int execute() override
    {
        if (processOK())
            return STEP_UNLOAD;

        if (++retry < 3)
            return STEP_MOVE;   // 回退

        return STEP_ERROR;
    }
};

为什么这才叫"优雅跳转"

因为:

✔ 跳转逻辑写在步骤里

✔ 线程完全不知道流程

✔ 支持任意跳转

✔ 支持回退

✔ 支持异常

✔ 支持插入步骤

✔ 支持配置化流程

14.如何实现"动态流程" (更高级)

如果你不想写死:

cpp 复制代码
return STEP_MOVE;

可以用 流程表驱动:

cpp 复制代码
struct Transition
{
    int successNext;
    int failNext;
};

步骤只返回结果:

cpp 复制代码
enum StepResult
{
    STEP_OK,
    STEP_FAIL,
    STEP_BUSY
};

然后引擎决定跳转:

cpp 复制代码
int result = current->execute();
if (result == STEP_OK)
    next = trans[currentId].successNext;

👉 这就是 数据驱动流程引擎,工业 MES / 半导体设备常用。

15.如何避免线程阻塞(关键)

步骤不能做耗时动作:

❌ 错误:

cpp 复制代码
moveAxis();
while(!axisDone()) {}

✔ 正确:

cpp 复制代码
startMove();
if (axisDone())
    return NEXT;
else
    return CURRENT;

👉 步骤是"轮询判断器",不是执行器。

16、如果流程很复杂(并行步骤)

可以运行多个 StepEngine:

thread1 → 机械流程

thread2 → 激光流程

thread3 → 通讯流程

再用事件同步。

这就是:

👉 多流程引擎架构

很多半导体设备都这样做。

17、总结一句最关键的话

线程不控制流程,线程只是执行器。

步骤决定跳转

一旦做到这一点:

✔ 流程会变得极清晰

✔ 跳转完全自由

✔ 异常处理自然存在

✔ 代码结构像 PLC 一样稳定

这才是真正工业级实现。

18、状态跳转和步骤跳转的核心代码是一样的,其它驱动状态和步骤变换的方案

方案 优雅程度 工程难度 适合场景

状态机/步骤机 ⭐⭐ 低 小设备

数据驱动流程 ⭐⭐⭐ 中 可配置设备

协程流程 ⭐⭐⭐⭐⭐ 中 上位机控制(最推荐)

行为树 ⭐⭐⭐⭐⭐ 高 复杂机器人/多流程设备

六、核心的三张表:动作表,步骤表,异常表

1、① 动作表模板(Action Table)

👉 作用:定义设备"能做什么"

👉 上位机最终调用的就是这些动作

ActionID 动作名称 执行对象 输入参数 成功条件 失败条件 超时 是否可重试 备注

A01 回零 控制器 无 所有轴到位 控制器报警 30s 否 初始化

A02 打开夹具 IO 无 到位信号ON 信号异常 5s 是 装料

A03 定位工件 控制器 位置ID 控制器完成 定位失败 15s 是 加工前

A04 激光加工 控制器 程序号 控制器结束 报警 120s 否 主工艺

👉 原则:

一个动作 = 一个原子操作

不要写流程

只定义接口

📌 动作表 = 上位机接口层设计

二、② 步骤表模板(Step Table)

👉 作用:定义自动运行流程

👉 比流程图更清晰、更可实现

StepNo 步骤名称 执行动作 前置条件 完成条件 失败处理 超时处理 下一步 备注

1 初始化 A01 回零 Start命令 动作成功 进入Error 报警 2 开机

2 等待物料 无 物料传感器ON 信号稳定 等待 报警 3 装料

3 定位 A03 定位工件 物料就绪 动作成功 重试2次 报警 4 关键

4 加工 A04 激光加工 定位完成 控制器结束 停机 报警 5 主工艺

5 卸料 A02 打开夹具 加工完成 信号到位 重试 报警 1 循环

👉 原则:

✔ 每一步只做一件事

✔ 必须有完成条件

✔ 必须有失败策略

✔ 必须有超时策略

📌 步骤表 = 自动运行核心逻辑

三、③ 互锁与异常表模板(Interlock Table)

👉 作用:保证设备不会误动作

👉 这是稳定性的关键

InterlockID 条件 禁止动作 影响范围 恢复方式 优先级 备注

I01 安全门未关 禁止所有轴运动 全局 关门复位 高 安全

I02 真空未建立 禁止加工 加工流程 真空建立 中 工艺

I03 控制器报警 禁止所有动作 全局 Reset 高 必须

原则:

✔ 所有安全条件必须列出

✔ 所有互锁必须可解释

✔ 恢复方式必须明确

📌 互锁表 = 系统稳定性保障

四、三张表之间的关系(关键理解)

动作表 = 定义设备能力

步骤表 = 定义流程顺序

互锁表 = 定义安全边界

五、工程建议(非常重要)

在真正项目中:

✔ 先写动作表

✔ 再写步骤表

✔ 最后写互锁表

不要直接画流程图。流程图只用于展示,这三张表才用于实现。

六、确保三张表的完整性,出现遗漏容易补充:

1、先说结论(工程经验)

自动化设计不可能完全不遗漏,关键是让遗漏 能被快速发现、可局部修复、不会连锁崩塌

所以重点不是"避免遗漏",而是:

✔ 可追踪

✔ 可验证

✔ 可扩展

2、如何保证三张表尽量不遗漏(设计阶段)

核心方法只有 3 个:

方法①:用"场景驱动检查法"(最有效)

不要只看表本身,要用 设备运行场景去推演。可以逐条问:

开机时会发生什么?

用户点暂停会发生什么?

通信断开会发生什么?

物料缺失会发生什么?

急停恢复会发生什么?

然后检查:

👉 这些场景在三张表里有没有对应逻辑

如果没有,就是遗漏。

这方法比看流程图有效 10 倍。

方法②:用"逆向推导法"

从最终目标反推。

例如目标:

设备稳定运行

反问:

稳定需要什么?

得到:

能停机

能恢复

能报警

能继续

再问:

这些在表里有没有定义?

没有 → 就是遗漏。

方法③:用"三表交叉校验法"

三张表必须互相能映射。

检查规则:

✔ 动作表 vs 步骤表

问:

👉 步骤里用到的动作,动作表是否存在?

若步骤引用不存在动作,

设计有漏洞。

✔ 步骤表 vs 状态机

问:

👉 每个步骤在哪个状态执行?

若步骤没有状态归属,

系统会乱。

✔ 互锁表 vs 动作表

问:

👉 所有危险动作是否有互锁限制?

若某动作没有安全约束,

就是隐患。

3、如何保证遗漏能快速处理(工程关键)

真正成熟设计,不是没有漏洞,是漏洞不会引发重构。关键做 3 件事。

方法①:让步骤表支持"插入步骤"

如果流程写死:

1 → 2 → 3 → 4 → 5

新增步骤会崩。

但若流程结构是:

StepID / NextStep

就可以:

👉 插入新步骤

👉 修改跳转关系

无需改系统架构。

这叫:

✔ 可扩展流程模型

方法②:动作接口必须稳定

若动作接口稳定,即使流程变化:

👉 不需要改底层代码

例如:

新增工艺步骤,只需新增:

Step = 调用某动作。而不是写新控制逻辑。

方法③:互锁设计必须集中管理

互锁若写在各流程里,

新增安全规则会爆炸。

正确做法:

统一 InterlockManager

新增互锁只需:

添加一条规则

系统自动生效。

这叫:

✔ 安全策略集中化

4、真正保证设计可靠的终极方法

不是图,不是表,

而是:

👉 仿真推演

做 3 种推演。

✔ 推演 1:正常运行流程

模拟:

启动 → 运行 → 完成 → 循环

检查:

是否有卡死步骤

是否有无出口状态

✔ 推演 2:异常中断流程

模拟:

运行中 → 断电

运行中 → 急停

运行中 → 通信断开

检查:

是否能进入 Error

是否能恢复

✔ 推演 3:用户乱操作

模拟:

Run 时点 Stop

Pause 时点 Reset

Error 时点 Start

如果这些行为没有定义,

就说明设计不完整。

5、工程上最强的做法(高级团队用)

叫做:

👉 逻辑测试用例表

像软件测试一样。

编号 场景 期望行为 覆盖表项

T01 Run时急停 进入Error 状态机

T02 无物料启动 阻止运行 互锁

T03 加工失败 重试或报警 步骤表

只要每条用例都能找到:

👉 表中对应逻辑,设计就可靠。

6、总结一句工程真理

自动化设计的可靠性不来自:

❌ 图画得多漂亮

❌ 表写得多详细

而来自:

✔ 场景推演

✔ 交叉校验

✔ 可扩展结构

✔ 集中化策略

只要做到这四点:

👉 遗漏不会消失,但不会造成灾难,这才是工业级设计。

怎样评估 状态机的完整性,异常处理的合理性。动作接口的清晰性?用状态机控制流程,而不是流程控制状态机具体什么意思?

一、如何评估【状态机的完整性】

状态机完整性的本质只有一句话:

任何时刻,设备都必须处于一个确定状态,并且有合法去向

评估时按这 5 条检查。

✔ 1. 是否覆盖所有运行阶段

问自己:

设备可能经历哪些阶段?

开机;初始化;待机;运行;暂停;停止;异常;恢复

👉 如果状态机里缺任何一个,就是不完整。

典型错误:

没有 Pause 状态

没有 Recover 状态

Error 直接回 Idle

这些都会导致逻辑漏洞。

✔ 2. 每个状态是否都有"出口"

检查方式:

拿一张状态图,逐个问:

👉 如果当前在这个状态,可能发生什么?

例如:

Ready 状态:

  • Start

  • Stop

  • Error

👉 如果某状态没有任何出口,程序会卡死。

✔ 3. 是否有"非法输入处理"

例如:

设备正在 Run,用户突然点 Reset。

状态机必须定义:

👉 是否允许

👉 转到哪里

👉 是否先停机

👉 没有这些规则,状态机会乱跳。

✔ 4. 是否区分"系统状态"和"流程步骤"

很多人混淆:

Step 3:定位中,这不是状态机状态,而是流程内部阶段。

状态机只描述:

Idle / Run / Pause / Error

📌 状态机是"设备层级"

📌 步骤是"工艺层级"

✔ 5. 是否能从任何状态安全停止

工业系统最关键:

👉 从任何状态必须能进入 Stop 或 Error

👉 如果有状态不能停机,就是危险设计。

七、如何评估【异常处理的合理性】

异常设计最常见问题:

👉 只考虑"报错",没考虑"恢复"

评估时按这 4 条。

✔ 1. 每个动作是否有三种结果

一个动作执行后必须有:

成功;失败;超时

👉 如果缺任何一种,逻辑会出现悬空。

✔ 2. 是否区分错误类型

异常必须分类:

安全错误(必须停机)

工艺错误(可重试)

通信错误(可恢复)

👉 如果所有错误都进入 Error,设备会频繁停机。

✔ 3. 是否定义恢复路径

问:

Error → 怎么回 Run?

Pause → 怎么继续?

通信断开 → 怎么重连?

👉 没有恢复路径,只能重启设备。这就是很多设备不稳定的原因。

✔ 4. 是否避免"隐式恢复"

例如:

轴未到位 → 自动重新发送指令

这就是隐式恢复,

容易导致:

无限重试;机械损坏;状态不同步;

恢复必须:

👉 显式、可控、可记录。

八、如何评估【动作接口的清晰性】

动作接口清晰的标准只有 3 条。

✔ 1. 动作是否"原子"

原子动作 = 只做一件事。

正确:

MoveAxis

ClampOn

LaserStart

错误:

PrepareAndProcessWorkpiece

这种接口会:

👉 混入流程逻辑

后期无法维护。

✔ 2. 动作是否"无状态"

动作接口不应该:

判断流程

修改状态机

决定下一步

动作只负责:

👉 执行硬件命令并返回结果

否则:

👉 层级混乱。

✔ 3. 动作是否有统一返回模型

推荐统一返回:

Success

Fail

Timeout

不要每个动作自己定义结果,

否则流程层会混乱。

九、最关键问题:

什么叫"状态机控制流程,而不是流程控制状态机"

这句话是自动化软件设计的分水岭。

我用两个架构对比给你看。

❌ 错误结构:流程控制状态机

很多人这样写:

Step 1 → MoveHome → 状态=Run

Step 2 → WaitSensor → 状态=Run

Step 3 → Error → 状态=Error

也就是说:

👉 流程代码决定设备状态

问题:

流程跳转时状态乱

Pause / Stop 很难插入

异常处理混乱

无法多流程共存

这是初级自动化结构。

✔ 正确结构:状态机控制流程

正确逻辑是:

状态机决定系统行为

流程只是状态下的任务

结构应是:

系统状态 = Run

Run状态允许执行流程

流程执行 Step 3

若发生错误

状态机转 Error

关键点:

👉 状态机拥有最高控制权

流程只是被调度。

用现实比喻理解

流程 = 工人任务清单

状态机 = 工厂管理制度

工人不能决定:

是否停产;是否进入维护;是否安全检查

这些由制度决定。

同样:

👉 流程不能决定设备状态

👉 状态机必须控制流程

正确的软件层级应该是

状态机层(最高权力)

流程执行层

动作接口层

而不是:

流程层

随便改状态

十、工程总结(最重要)

真正成熟的自动化系统满足:

✔ 状态机完整

任何情况都有归属状态

✔ 异常有恢复路径

不是只会报警

✔ 动作接口原子化

不混入流程逻辑

✔ 状态机控制流程

不是流程控制系统

做到这四点:

👉 系统基本不会崩

十一、 评审设计时检查:

✔ 每个状态都有出口

✔ 每个流程有结束条件

✔ 每个动作有反馈

✔ 每个错误有处理方式

相关推荐
执笔画情ora2 小时前
postgresql管理-pg_hba.conf 文件详解管理
数据库·postgresql
JZC_xiaozhong2 小时前
BPM如何打通“请款→审批→付款”全链路?构建企业资金流转闭环
大数据·运维·数据库·数据分析·数据集成与应用集成·业务流程管理·流程监控
wsad05322 小时前
Vue.js 整合传统 HTML 项目:注册页面实战教程
前端·vue.js·html
XXYBMOOO2 小时前
Flarum 主题定制:从零打造你的赛博朋克/JOJO 风格社区(含全套 CSS 源码)
前端·css
西柚小萌新2 小时前
【MySQL数据库】--借助AI快速画数据库ER图
数据库·mysql
EnCi Zheng2 小时前
1. AI数据库工具对比 [特殊字符]
数据库·人工智能
一水鉴天2 小时前
整体设计的自动化部署完整方案 20260311 之3 加三个附件 readme/addon/plugin(豆包助手)
运维·自动化
feasibility.2 小时前
Agent-Browser: 适合ai的浏览器自动化 CLI 工具(以OpenCode为例)
人工智能·机器人·自动化·skill·opencode·openclaw
升鲜宝供应链及收银系统源代码服务2 小时前
升鲜宝生鲜配送供应链管理系统生产加工子模块的详细表设计说明
java·大数据·前端·数据库·bootstrap·供应链系统·生鲜配送