☰
SFC顺序功能图:让PLC顺序控制清晰高效
2026/10/3 6:06:09 网站建设 项目流程

做PLC项目这些年,我见过太多人把顺序控制写得一团糟——有人用梯形图串几百行置位复位,有人用中间继电器把逻辑写成“意大利面”,改一个节拍就要顶着图纸看半天。直到我用上顺序功能图(SFC,Sequential Function Chart),才算找到顺序控制该有的打开方式。SFC在IEC 61131-3标准中被列为PLC编程语言之一,用步、转换条件和有向连线把整个工艺过程画成一张流程图,程序结构一眼就能看懂,调试时设备走在哪一步清清楚楚。这篇文章不讲教科书官话,我以一个工控老手做项目时的思考过程,把SFC的基本结构拆开揉碎,从步和转换到底层运行原理,从单序列到并行分支,再到真实调试里踩过的坑,一次讲清楚。

1. 顺序功能图到底是什么:从IEC 61131-3说起

1.1 SFC的定位与适用场景

SFC最初源于法国的Grafcet方法,本质上是把控制系统看成一组“稳定状态”的集合,设备从一个状态切换到另一个状态,必须满足特定的转换条件。后来IEC 61131-3把这个思想标准化,成了PLC编程语言家族中的正式成员。现在主流PLC品牌基本都支持SFC,只是名字略有不同:西门子叫S7-GRAPH,三菱在GX Works里叫SFC,施耐德叫Grafcet,CODESYS里直接就叫SFC。名字不一样,底层逻辑是一套。

什么时候该用SFC?我的判断标准很简单:只要你的设备流程有明显的“步骤感”——先做什么、再做什么、条件满足才进入下一步——就适合用SFC。比如装配线的工位动作、灌装机的清洗流程、物流分拣线的输送逻辑、热处理炉的工艺曲线切换,这些场景如果用梯形图硬写,程序会又长又难维护;换成SFC,整个工艺过程就像画流程图一样留在程序里,谁来看都能秒懂。

很多人有一个误区,以为SFC只能做“一步一步走”的简单动作序列。实际上SFC真正的强项在于表达复杂逻辑:分支、跳转、并行、循环都能画出来,而且每一步的“动作”可以由梯形图、ST结构化文本、FBD等功能块完成,相当于用SFC搭骨架,用其他语言填血肉。这种层次化设计,才是大型程序该有的样子。

1.2 一个最直观的入门案例

先看一个最简单的案例:电机星三角启动。传统梯形图写法会有一堆定时器和互锁触点,而SFC的写法是三个步:第一步“停止”,转换条件是“按下启动按钮”;第二步“星形启动”,转换条件是“延时5秒到”;第三步“三角形运行”,转换条件是“按下停止按钮”返回第一步。整个程序画出来就是三个方框两条线,逻辑清清楚楚。

这个例子虽然简单,但已经把SFC的核心逻辑带出来了:设备不会同时处于“星形”和“三角形”两个状态,每一步必须等待条件满足才进入下一步。记住这个思维模式,后面所有复杂结构都是它的扩展。

2. SFC最核心的底层元素:步、转换、有向连线

2.1 步:状态的最小单元

在SFC中,“步”是一个方框,代表系统的一个稳定状态。每个步都有一个“活动”和“不活动”的属性,当前正在执行的步叫活动步,它对应的动作会被执行;其他步叫不活动步,对应的动作不输出。整个SFC程序运行的过程,说白了就是“活动步在步与步之间传递”的过程。

步的命名大有讲究。我见过新手把步命名为S1、S2、S3,图省事,结果程序写大了之后对不上工艺位置,调试时还得翻注释。我的习惯是用“工位号+动作”命名,比如“工位2气缸伸出”“清洗完成等待”,这样在触摸屏上做状态显示时,直接把步名映射过去就能让操作工看懂设备当前在干什么。好的步名本身就是文档,SFC在这方面天然比其他语言占优势。

这里必须强调一个概念:初始步。初始步是SFC程序启动时唯一活动的步,用双线方框表示。没有初始步,整个程序上电后不知道从哪个状态开始,运行逻辑就是乱的。我见过不少刚接触SFC的工程师,画流程时只顾着业务步骤,忘了画初始步,结果编译报错“没有初始步”或者运行时状态不确定。记住,初始步一定不能缺,而且整个图里通常只有一个。

步的活动与失活还涉及扫描周期的问题。PLC是循环扫描执行的,SFC里的步切换不是“瞬间完成”的,而是在一个扫描周期内完成状态更新。如果你在同一个扫描周期里又判断步状态又修改输出,可能出现一步的输入还没稳定、下一步就已经激活的情况。所以写SFC的动作和转换条件时,务必要考虑到PLC的扫描时序,有条件的地方该用边缘检测就用边缘检测。

2.2 转换条件与有向连线

步与步之间用有向连线连接,线上画一条短横线,旁边标注转换条件。这里有一个容易混淆的点:转换条件写的是“满足条件”,而不是“动作结果”。比如“气缸伸出到位”是个条件,“气缸伸出”是个动作,前者放在转换条件上,后者放在动作里,两个位置别搞混。

转换条件的成立有一个非常重要的规则:只有当前级步是活动步,并且转换条件为真,转换才会发生。这句话看起来简单,实际应用时很多坑都出在这里。比如你写了一个“启动按钮按下”的转换条件,用的是电平信号而不是上升沿,那么只要按钮一直按着,条件就会一直为真,可能连着触发多次转换。这种问题在单序列里不算严重,但在选择序列里可能导致一个条件触发多个分支,顺序全乱。所以转换条件里能用上升沿/下降沿的地方,尽量用沿信号。

有向连线的方向也有讲究。SFC默认从上往下执行,向下的连线箭头可以不画;但如果流程有回跳,比如从后面的步跳回前面的步,连线就变成从下往上,这时候必须加箭头。这是画图规范,也是编译器的语法要求,不画箭头有些软件直接报错,有些软件运行时会按默认方向处理导致逻辑错误。

2.3 动作与动作修饰符

每个步可以挂一个或多个“动作”,动作框画在步方框的右侧,用一个矩形框表示。动作框里面写上“修饰符+动作名称”,比如“N:电机启动”“S:夹紧气缸置位”“P:计数器加1”。动作修饰符是SFC里一个被很多人忽略但极其重要的知识点,我做了一个整理:

修饰符含义典型使用场景
N(非存储)步活动时执行,步失活时停止电机、风扇等持续执行的动作
S(置位)步活动时执行并保持,直到被R复位夹紧气缸、电磁阀的保持状态
R(复位)对指定的S动作复位释放气缸、解除保持
P(脉冲)步刚激活时执行一个扫描周期数据装载、边缘触发动作
D(延时)步激活后延时执行等待稳定后启动动作
L(限时)动作执行的时间受限制声音报警、闪烁提醒

这几种修饰符在调试时能帮你省掉大量定时器。比如我要实现“料仓门打开后,5秒后开始下料”,不用额外写定时器,直接在步右侧挂一个“D:下料启动”动作,步激活开始计时,到5秒才输出。但要注意,不同PLC对D修饰符的时间设置位置不一样,CODESYS里是在动作属性里填时间,三菱是在动作框下面加一个时间标注,实际使用时先查一下手册。

动作的执行与步的活动状态绑定,但有一些细节值得注意:S置位型的动作在步失活后依然保持输出,这时候别的步如果想要这个输出消失,必须用R动作明确复位。很多初学者被S动作坑过,以为“步失活了输出就没了”,只有N动作是这种特性,S不是。设计时要想清楚每个输出到底是“持续执行类”还是“状态保持类”,不要混用。

3. SFC三大基本结构一次讲清:单序列、选择序列、并行序列

3.1 单序列:最简单也最基础的流程骨架

单序列就是一条线走到底,没有任何分支。一个步接一个步,每个转换条件满足就进入下一步,直到流程结束或回到初始步。它适合工艺流程非常固定的场景,比如:传送带前进→到位→定位顶升→夹具夹紧→加工→加工完成→松开→退回。

写单序列时最容易犯的错是把所有动作都堆在一个步里。我看到过有人一个步里挂七八个动作,各种输出全放一起,结果现场只要有一个气缸动作没到位,整个流程就要停。单序列的设计原则是“一个步只完成一个阶段的任务”,一个阶段里如果动作之间没有耦合关系,可以放一起;如果有先后条件,就应该拆成多个步。比如“夹紧并钻削”,夹紧没到位之前不应该钻削,那这两件事就要拆成两个步;而“启动油泵并打开冷却液阀门”如果彼此独立且必须同时做,就可以放一个步里。

单序列还有一个特点:任何时刻只有一个活动步。这既是优点也是约束。优点是逻辑简单,不会出现竞争;缺点是效率低,如果几个工序互不影响却必须排队等待,就会浪费节拍。这就是下面要讲的选择序列和并行序列发挥作用的地方。

3.2 选择序列:按条件走不同分支

选择序列解决的是“根据条件走不同路径”的问题。它在公共步后面分出一个或多个分支,每个分支前面有一个转换条件,条件先满足的分支被激活,其他分支不激活。汇合时,不管走了哪个分支,最终都汇合到公共步。

选择序列在画法上有个关键特征:每个分支各有独立的转换条件,用单横线分支。举个实际例子:充填机检测到有瓶→走灌装流程;检测到无瓶→走等待流程。这两个流程不可能同时执行,只能选一条,这就是典型的选择序列。

设计选择序列时,最需要警惕的是转换条件重叠。假设分支A的条件是“光电开关有信号”,分支B的条件是“光电开关无信号”,表面上看互斥,但如果光电开关信号抖动了,或者在PLC扫描的瞬间信号状态发生了变化,两个条件可能在一个扫描周期内都为真或都为假。如果都为真,理论上SFC会优先选择靠左的分支(不同PLC实现可能有差异);如果都为假,流程就卡住了。我的做法是给这种条件加上沿检测,或者把条件写成“有信号且未超时”“无信号且未超时”这种绝对互斥的形式,宁可多写几个变量,也别留下模糊地带。

汇合点的设计同样有讲究。选择序列汇合时,各分支可以随时汇合,不需要同步等待,因为本来就是“只走了一条路”。但如果你画成了并行汇合的双横线,那编译器就会按并行规则处理,要求所有分支都到达才继续,逻辑就完全变了。画图时区分单横线和双横线的含义,是SFC最基本的修炼。

3.3 并行序列:多路同时进行的同步控制

并行序列解决的是“多路同时进行,全部完成后才继续”的问题。画法上用双横线表示同步分离,多个分支同时激活;汇合时也是双横线,所有分支都走到汇合步前的最后一步后,才能越过汇合线进入下一步。这里的关键词是“同步”:并行不是随意的同时,而是有严格汇合点,缺一个分支都不行。

一个典型的例子是双工位装配机:左工位装螺丝,右工位装卡簧,两个动作互不影响,可以同时进行。但下一步是“压合”,必须等两边都装完才能执行。用并行序列表达,两个分支同时活动,等左右工位都完成并满足转换条件,汇合后才进入压合步。

并行序列实现起来有一个常见的坑:分支动作执行时间差异太大,导致一个分支早就完成了,另一个分支还在慢慢跑,设备节拍被拖在最短的那个分支上。这不算程序错误,属于工艺平衡问题,但调试时往往被误认为是逻辑问题。遇到这种情况,我一般先判断两个分支是否真的有“汇合等待”的必要,如果没有必要,就把并行结构拆成两个独立的选择序列,让快的分支先去干别的活。

还有一个容易踩的坑是并行分支里的转换条件。并行分离时,双横线之上可以有一个公共的转换条件,也可以没有;但如果每个分支都有自己独立的启动转换条件,就变成了“选择+并行”的混合逻辑,画法上需要特别小心。我在CODESYS里见过不少新手把并行分离画成了选择分离,编译不报错,运行逻辑却完全不对。判断方法是看分支口是单横线还是双横线,只要看到双横线,就一定按并行逻辑去理解。

4. 进阶结构:跳转、循环与子步复用

4.1 跳转与循环:让流程具备灵活性

实际工艺流程很少是线性的,常见的还有“不合格就回到前一步重做”“等到温度到了才继续加热”“计数不到就循环返回”这些需求。SFC里用跳转和循环来解决。

跳转的本质是:某个步的转换条件得到满足后,不是沿着有向连线走到下一步,而是通过一个“跳转标志”直接跳到目标步。画法上是一个箭头指向目标步的方框,箭头旁边标注跳转目标名称。跳转可以向前,也可以向后;向前跳可以跳过某些步骤,向后跳就形成循环。

循环是最常见的跳转应用。比如一个计数搬运流程,每搬运一次,计数器加1,没到10次就跳回“搬运步”,到了10次就进入“下料步”。用SFC写这种逻辑,不需要像梯形图那样单独写循环指令,只需要在两个步之间画一个带有计数转换条件的回跳线即可。计数器可以用动作框里的P修饰符加一个计数变量,转换条件判断计数器是否到达目标值,然后配合“计数器清零”的动作,一个典型的循环结构就完成了。

这里有一个细节大家容易忽略:跳转目标不能指向一个“正在活动”的步。如果你循环跳回的步本身就是当前活动步,那就相当于自己跳自己,逻辑上会产生冲突,轻则这个周期不动作,重则导致步状态错乱。设计循环时,跳转目标一般是前一步或更早的步,尽量避免跳回当前步。

4.2 子步/宏步:大型程序的抽象利器

当一个项目大到有几十个步时,如果把所有步都平铺在一张SFC图表里,整个图会非常长,看前头忘后头,调试时来回拖动滚动条,效率极低。SFC提供了“宏步”机制解决这个问题,有些品牌称为“子步”或“复合步”。

宏步的做法是把一组有完整意义的步封装成一个“大步骤”,在总图表里显示为一个加粗方框,双击进入才能看到里面的详细步。比如“自动加工循环”这个宏步里面包含“定位”“夹紧”“进刀”“退刀”“松开”五个子步,在总图里只显示一个方框,让整个流程的顶层结构保持清爽。

使用宏步时要注意两个问题。第一,宏步的“进入”和“退出”必须有明确的转换条件,否则编译器不知道什么时候该激活内部的第一步、什么时候该认为整个宏步完成。第二,不同PLC对宏步的使用方式差异很大,CODESYS里是用调用另一个SFC POU的方式实现,西门子S7-GRAPH里有专门的“复合步”类型,施耐德则是在图表里插入宏步符号。建议你在选型阶段就看清楚软件对宏步的支持程度,别等到程序写了一半再重构。

宏步最大的价值在于团队协作。大项目分给多人开发时,每个人负责一个宏步,接口就是进入条件和退出条件,内部逻辑互不干扰。这比几百行梯形图大家挤在一个程序块里改,体验好太多。

5. 实操:在CodeSys里搭一个完整的SFC程序

5.1 需求分析与流程分解

我拿一个非常经典的“空托盘堆垛机”案例来演示,简化成三个工位的联动:托盘到位→检测合格→堆垛;托盘到位→检测不合格→剔除;堆垛完成或剔除完成→重新开始。这个需求同时包含单序列、选择和循环,用来练手刚好。

先做需求分析,把动作和数据分开。动作类包括:输送电机正转、输送电机停止、升降台上升、升降台下降、堆垛计数。条件类包括:托盘到位信号、检测合格信号、堆垛高度到限、剔除完成信号。注意,动作要和条件分开列,很多新手喜欢把一个信号既当触发又当反馈,到头来逻辑乱成一团。

然后是流程分解:第1步初始,等待托盘到位;第2步检测,合格进第3步,不合格进第5步;第3步堆垛;第4步堆垛完成,返回第1步;第5步剔除;第6步剔除完成,返回第1步。把这几句话翻译成SFC图,就是“初始步→等待步→选择分支→两条支路汇合→跳回初始步”的结构。

5.2 分步搭建SFC的过程

以CODESYS为例,我建议按以下几个步骤操作:

第一步,新建POU,语言类型选SFC。这一步选错后面改起来很麻烦,CODESYS里SFC和ST、梯形图是不同的POU类型,不能随便切换。

第二步,添加初始步。在图表的起始位置放一个初始步(双线框),命名“Init”。然后在初始步右侧的动作框里写上启动时需要的初始化动作,比如“电机停止”“计数器清零”。

第三步,画“等待托盘到位”步。从初始步往下拉一条有向连线,放置一个普通步,命名“WaitPallet”,动作框里写“N:输送电机正转”。

第四步,添加转换条件。在步和步之间点击添加转换,编辑转换条件为“托盘到位信号 AND 检测请求”。转换条件建议用ST语言写,CODESYS里可以直接在转换属性里输入表达式。

第五步,画选择分支。从“检测”步往下拉,分出两条支路,一条往“堆垛”步,一条往“剔除”步。堆垛分支的转换条件是“检测合格”,剔除分支的转换条件是“NOT 检测合格”。两个条件一定要写成绝对互斥形式,比如加一个“检测完成”信号作为共同的使能条件,避免条件重叠。

第六步,汇合。两条支路都汇合到一个公共步“EmptyMachine”或者直接跳回“Init”。这里我建议加一个“EmptyMachine”步,让设备真正做完清尾动作再回初始,不要直接从堆垛跳到初始,容易丢失“堆垛完成”的反馈。

第七步,编译。CODESYS在编译时会有SFC语法的检查,比如有没有初始步、跳转目标是否存在、分支画法是否正确。第一次编译通常会提示几个警告,逐个双击查看,基本都是分支汇合不够规范的问题。

5.3 编译调试与运行时观察

SFC的调试体验是我最喜欢的部分。在CODESYS里在线连接PLC后,打开SFC图表,每个步旁边会显示当前活动状态,活动步是蓝色高亮,一眼就能看到设备卡在哪个环节。这一步比梯形图的“查找哪里为ON”高效太多了。

调试时建议打开SFC的“单步模式”或“Intelligent Debug”功能,可以手动强制满足转换条件,观察步的切换是否正确。我调试的思路是:先把所有转换条件从自动改为手动置位,逐一验证每个分支能正常走通;然后再把条件切回自动,观察实际传感器信号是否与程序预期一致。这么做能把“程序逻辑问题”和“传感器接线问题”快速分开,杀鸡儆猴式的排障法。

运行时的状态监控还有一个实用技巧:把活动步编号映射到一个整数变量,然后送到触摸屏显示。这样操作工看着屏幕就知道设备停在哪个工位,不用等维修工到场。这个是SFC项目的“隐藏福利”,用梯形图时得额外写好几行代码才能实现。

6. 常见问题与排查技巧实录

6.1 流程卡死不动的排查思路

做SFC调试,遇到最多的问题就是“流程走着走着不动了”。这时候先不要怀疑PLC坏了,按顺序排查:第一步看软件在线监视,确认当前停在哪个步;第二步看这个步的转换条件是否满足;第三步看转换条件用到的输入点、变量是否有实际值;第四步看是否有别的步还在活动,导致转换规则不成立。

SFC卡死最常见的三个原因:一个是转换条件写错变量名,信号到了但比较的地址不对;另一个是条件用了电平信号而不是沿信号,按钮按完了条件已经变回假,所以不触发;还有一个是并行汇合时某个分支没走到位,卡在汇合线上。这三个原因占据了实际问题的八成以上,排查时优先检查。

还有一个隐藏很深的问题:步动作里的输出如果被别的地方“抢控制”了,会导致设备看似卡死。比如步动作里写了气缸伸出,但梯形图其他程序段又对同一个输出做了复位,两边打架,输出就悬在空中。SFC不是孤立存在的,它跟其他语言共享变量空间时,一定要做好输出地址的规划,同一物理输出只在一个地方控制。

6.2 分支互斥与死锁问题

选择序列的分支互斥问题,我在前面已经提醒过。这里补充一个更隐蔽的场景:夹紧气缸有两个传感器——夹紧到位和松开到位。程序里写了两个选择分支,一个走“夹紧完成”分支,条件为“夹紧到位传感器ON”;另一个走“报警”分支,条件为“松开到位传感器ON”。表面看互斥,但如果气缸运动到中间位置,两个传感器都是OFF,流程就卡住了。

这种问题在电气设计时就应该规避,PLC程序里只能在传感器状态“稳定并且对应”时做分支判断。我的做法是在两个传感器都OFF时,不进入任何分支,而是启动一个“气缸运动超时报警”守护动作,等传感器状态确定后再继续。这样一来,机械卡滞等异常情况也能被程序捕获,而不是莫名其妙卡死。

并行序列的死锁则多是结构问题:两个分支一个依赖另一个的完成信号才能继续,结果双双等待,谁也走不动。这种逻辑矛盾在画图阶段很容易忽略,我会在评审图纸时专门检查并行分支之间有没有“交叉依赖”的变量。只要发现分支A的转换条件里用了分支B的动作结果,就要警惕死锁风险。

6.3 上电初始化和复位设计

SFC上电后的第一个扫描周期,初始步必须被激活。如果程序在意外断电前停在一个中间步,重新上电后不应该继续从那个步走——除非设备断电保持工艺状态。绝大多数设备不具备这种条件,所以我的习惯是:上电后一律回到初始步,初始步里把所有输出复位到安全状态,操作工需要手动按下“回原点”之后,才能进入自动流程。

复位设计还有一个容易忽略的角落:S置位型动作。因为S动作有保持功能,如果设备在上电前的状态里S动作已经置位了,即使回到初始步,输出也还是保持的。所以初始步里至少要对全项目的S置位动作做一次R复位,把保持型输出清干净。这一点没做好,会出现“程序已经复位但气缸还在夹紧”的危险情况。

如果你用了断电保持寄存器,还要注意保持变量与初始化逻辑的配合。比如计数器、步编号这些变量,如果掉电不清零,上电后可能跳到莫名其妙的步骤。我的建议是:除了设备必须保持的工艺参数,步状态和临时变量一律掉电清零,宁可多花几秒重走流程,也不能让设备带着旧状态继续跑。

7. SFC与其他PLC语言的搭配使用心得

7.1 SFC与梯形图、ST的边界在哪里

很多刚接触SFC的朋友问我:是不是用了SFC就不用梯形图了?完全不是。SFC解决的是“流程怎么走”的问题,梯形图和ST解决的是“每一步做什么”的具体逻辑。一个SFC项目里,动作框里写梯形图、转换条件里写ST表达式,是非常标准的主流做法。

梯形图更适合写“有大量触点互锁逻辑”的部分,比如手动操作、安全回路的联锁。ST更适合写“需要计算和数据处理”的部分,比如PID运算、配方参数换算、字符串处理。而SFC是更高层的“组织者”,把梯形图和ST组织进一个有节奏的流程骨架里。三者没有谁取代谁,而是各管一摊。

我见过一个反面案例:有人非要用SFC去写一个简单的启保停回路,步骤反而比梯形图复杂,调试也不方便。SFC不是万能工具,它的代价是需要管理人员对流程有全局认知,项目越简单,梯形图的直接性优势越明显。我会在方案阶段就定好“用哪种语言”的基调,模式一般是:手动/单动逻辑用梯形图,自动顺序流程用SFC,复杂运算用ST,通信协议处理用ST或C语言扩展。

7.2 混合编程的选型建议

小设备、工序固定、流程不超过10步,直接用梯形图加ST就足够。中等设备、有多工位或多种产品模式,强烈建议上SFC,哪怕前期多花两天学习成本,后期调试和维护能省下成倍时间。大型流程、批量控制、配方驱动,那就不能只是把SFC当步进控制用,要把SFC和配方管理、报警管理结合起来,用宏步搭顶层架构,用SFC管单元流程。

选型时还要考虑团队水平。如果你所在团队对SFC完全陌生,那就先拿一个小项目练兵,别直接上大项目。我的经验是用一个改造项目,在原有梯形图基础上新增一个SFC自动流程块,和原有手动逻辑并存,既不影响设备运行,又能让团队在实践中掌握SFC,这样过渡最平滑。

SFC还有一个隐含优势值得提:它天然逼着你把“状态”设计清楚。梯形图写的程序经常是各种标志位满天飞,用SFC设计流程时,你就必须定义清楚每一个稳定状态和每一个转换条件,这本身就是对工艺理解的一次梳理。把流程图想清楚了,代码怎么写都是顺的。

我个人在实际项目里最深的体会是,SFC程序的“可追踪性”真的太重要了。设备半夜停机,维修工打电话过来,我远程看一眼SFC高亮的步和未满足的转换条件,基本就能判断是传感器问题还是逻辑边界问题,不再需要翻几百行梯形图逐个排查。如果你现在正被复杂的顺序控制折磨,建议先用一个小工位把SFC跑起来,体验一下“看流程图调试设备”的感觉,你会回来感谢这个选择的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询