简介:西门子1200 PLC脉冲控制步进电机工程实例,面向工业自动化领域PLC编程与运动控制工程师,解决多台步进电机精确同步、气缸联动及非通讯机器人本地控制等实际应用问题。工程涉及四台步进马达的脉冲序列生成与协调调度、传感器与电磁阀的I/O编程、机器人运动逻辑约束调试,适合需要掌握多轴控制和气动系统集成的中高级开发人员。压缩包共33个文件,以XML配置文件、数据库文件(db)、组态与编译文件(cfs、info)等为主,整体仅2.28MB,目录划分清晰,便于直接导入博途环境查阅程序结构。目前已有2702人学习下载,资源包含完整PLC工程源码、硬件组态数据及项目调试记录,可帮助读者理解从电气接线、逻辑编写到设备验收的完整流程,是学习西门子1200运动控制与多任务协调的实用参考资料。
1. 四轴步进控制实例:一条脉冲线怎样同时管住 4 个马达
接手一份西门子 S7-1200 控制 4 个步进电机的 PLC 程序实例时,我第一反应是“又要加扩展模块”,结果翻完硬件接线图才发现,1200 本体自带的 4 路高速脉冲输出点就可以直接拖 4 个步进驱动器,脉冲、方向各占一个输出点,CPU 不用额外插任何定位模块。整套程序把回零、绝对定位、相对定位、多轴轮询这些动作都写全了,对想用 PLC 替代专用运动控制卡、又不想碰伺服复杂参数的工程师来说,这是一个非常典型的步进电机控制入门骨架;改造一下,小型四轴点胶机、贴标机甚至桌面机器人的底层运动逻辑都能直接拿它做底子。
2. 硬件接线与选型:4 个步进马达怎么接到 1200 本体上
2.1 选型:本体脉冲输出够不够,信号板怎么补
S7-1200 选型时先看 CPU 型号。以 1214C DC/DC/DC 这类晶体管输出的型号为例,本体上带 4 路高速脉冲输出,输出点地址分布在 Q0.0 到 Q0.3 附近,每路最高能输出 200 kHz 的脉冲。4 个步进电机刚好对应 4 路脉冲加 4 路方向,数量上不用加扩展模块,这也是这份实例用 1214C 而不是更小型号的原因。
如果选了只有 2 路高速输出的小 CPU,那第 3、4 轴就得靠信号板补。常见做法是加一块高速数字量信号板,把输出点扩到 4 路以上。选型时建议算一笔账:电机最高转速、驱动器细分、丝杠导程三者相乘之后得到的脉冲频率,必须小于 CPU 单路输出上限,否则高速段必然丢步。比如电机要跑 600 转/分,细分设 1600 脉冲/转,丝杠导程 10 mm,那输出频率就是 600 / 60 × 1600 = 16000 Hz,远远够用;但如果细分拉到 6400,转速还要 1500 转/分,频率就直接翻到 160 kHz,离上限不远了。
2.2 步进驱动器接线:脉冲、方向、使能三根线的接法
这份实例里步进驱动器接的是脉冲加方向模式,也就是最常见的 PULSE/DIR 方式。驱动器上一般有 PULSE+、PULSE-、DIR+、DIR-、ENA+、ENA- 六个端子,S7-1200 晶体管输出是源型输出,导通时输出点输出 24V,所以要接脉冲正端,脉冲负端接回 PLC 的 M 端。
接线对应关系如下表:
| PLC 输出点 | 驱动器端子 | 说明 |
|---|---|---|
| Q0.0 | PULSE+ | 轴 1 脉冲 |
| Q0.1 | DIR+ | 轴 1 方向 |
| Q0.2 | PULSE+ | 轴 2 脉冲 |
| Q0.3 | DIR+ | 轴 2 方向 |
| 其他 Q 点 | 类推 | 轴 3、轴 4 |
| PLC M 端 | PULSE-、DIR- | 公共回路 |
| PLC M 端 | ENA- | 使能公共端 |
| PLC Q 点或 24V | ENA+ | 使能信号 |
使能端如果不需要 PLC 主动控制,可以直接把 ENA+ 接 24V、ENA- 接 M,让驱动器一直使能。需要程序控制时,用一个 Q 点接 ENA+,通过置位/复位来控制驱动器使能,这样急停时可以在程序里立刻撤使能,避免电机堵转发热。多数驱动器内部已经集成限流电阻,不需要额外串电阻;如果遇到老款驱动器没有内置限流,串一个 2 kΩ 左右的电阻再接到 PULSE+ 上更稳妥。
2.3 公共端与电气注意:共地问题最容易翻车
脉冲进不去的故障里,十有八九是公共端没共地。PLC 的 M 端、驱动器的 COM 端、开关电源的 0V 这三者必须接在同一个电位上,否则驱动器光耦两侧没有完整回路,脉冲信号到了驱动器端就是悬空的,指示灯一点都不亮。
S7-1200 源型输出接驱动器时,用的是“脉冲正端接 Q 点、负端接 M”的方式。如果换成了漏型输入的驱动器,就得把公共端接到 24V 上,接法完全不同。上电前先看一下驱动器说明书里的光耦内部结构,确认是共阳还是共阴,这一步看错了,程序写得再好电机也不会动。
电源容量也是要注意的点。4 个步进电机同时启动时,电流峰值可能冲到 4 A 以上,开关电源如果按稳态电流选,启动瞬间电压会被拉低,驱动器低压报警,甚至 CPU 都跟着掉电复位。我一般按驱动器额定电流的 1.5 倍选开关电源,并在这份实例的电源进线端加了 470 μF 的电解电容和 0.1 μF 的 CBB 电容。
2.4 上电前的接线检查清单
上电之前按这个顺序过一遍,能省掉大半排查时间:
| 检查项 | 内容 | 错接后果 |
|---|---|---|
| 输出点地址 | PLC 程序里的轴组态地址是否与实际接线一致 | 电机不动或乱动 |
| 公共端 | PLC M、驱动器 COM、电源 0V 是否共地 | 脉冲信号悬空 |
| 细分拨码 | 驱动器拨码与组态里“每转脉冲数”是否一致 | 定位距离不准 |
| 限位开关 | 常开还是常闭,输入点地址是否与组态一致 | 回零找不到原点 |
| 电源容量 | 是否留有 1.5 倍余量 | 多轴同时启动掉电 |
3. 程序架构与轴组态:PLC 程序实例的骨架长什么样
3.1 程序块分层:OB、FB、DB 怎么分工
拆这份 PLC 程序实例时,块结构非常清晰:OB1 只管主循环调度,四个轴的工艺对象各自独立,运动指令放在一个统一的 FB 里,位置、速度、加减速参数全部收进一个数据块。这种分层让“逻辑代码”和“工艺参数”彻底分开,改位置、改速度不用碰逻辑,HMI 上直接写 DB 变量就行。
程序块大致分这几层:
| 块类型 | 名称 | 作用 |
|---|---|---|
| OB1 | Main | 主循环,调用轴控制 FB |
| FB1 | FB_AxisControl | 四轴运动指令统一调用入口 |
| FB2 | FB_HomeSequence | 回零时序处理 |
| DB1 | DB_MotionConfig | 四轴全部工艺参数 |
| DB2 | DB_MotionCommand | 启动命令、目标、状态字 |
| FC1 | FC_AlarmHandle | 错误码解析与报警输出 |
这种做法的好处是,后续换电机、换丝杠导程时,只改 DB1 里的机械参数,FB 代码一行不动。如果是一股脑把运动指令全写在 OB1 里,改一个轴就要翻半天逻辑块。
3.2 轴工艺对象组态:脉冲接口和机械参数怎么设
S7-1200 的运动控制是通过工艺对象“轴”来管理的。在组态界面里新建四个轴,分别为 Axis_1 到 Axis_4,每个轴的接口类型选“脉冲”,然后分配脉冲输出点和方向输出点,指定回零输入点。这一步的地址必须和实际接线严格对应,程序里就算写了 MC_MoveAbsolute,组态里地址对不上,驱动器也收不到脉冲。
机械参数里,最关键的一项是“每转脉冲数”。驱动器的细分设成 1600 脉冲/转,这里就填 1600;如果驱动器上拨码改成了 3200,这里必须同步改,否则程序里写的距离和实际走的距离会差一倍,这是定位不准的第一大根源。如果电机通过丝杠带动负载,还要填丝杠导程,单位是 mm/转。方向参数里有一个“反向”选项,电机转反了不用拆线,改这个勾选就行。
动态限制里,速度上限、加速度上限、急停减速度都要填。很多新手在程序里给的速度明明很大,但电机始终跑不快,其实就是因为组态里的上限比程序值小,运动指令在启动时就被钳位了。这个上限在调试阶段设得保守一点,比如 60% 额定速度,等机械没问题了再放开。
3.3 数据块设计:位置、速度、加速度参数集中管理
这份程序里的 DB 设计很值得借鉴。它没有给每个轴单独建一个 DB,而是定义了一个 UDT 结构体,然后声明成一个长度为 4 的数组,四个轴共用一套字段。
这个 UDT 大致长这样:
TYPE ST_MotionAxis STRUCT AxisName : STRING; // 轴名称,比如 "搬运轴" TargetPos : REAL; // 目标位置,单位 mm Velocity : REAL; // 运行速度,单位 mm/s Accel : REAL; // 加速度,单位 mm/s² Decel : REAL; // 减速度,单位 mm/s² HomeCmd : BOOL; // 回零触发信号 AbsMoveCmd : BOOL; // 绝对定位触发信号 Done : BOOL; // 轴动作完成标志 Error : BOOL; // 轴错误标志 ErrorID : WORD; // 错误码 END_STRUCT END_TYPE然后 DB1 里声明变量:
MotionAxes : ARRAY[0..3] OF ST_MotionAxis;这样 HMI 上做四轴画面时,列表控件可以直接绑定这个数组,轴 1 到轴 4 的地址偏移完全规律,写画面脚本都不用逐个轴单独处理。
3.4 主循环调度:一个 FB 怎么轮询四个轴
主程序里没有把四个轴的运动指令重复写四遍,而是写了一个统一的 FB_AxisControl,在 OB1 里调用,FB 内部用轴号索引分派指令。核心是先把命令参数从 DB 数组里取出来,再按轴号调用对应的 MC_MoveAbsolute 指令实例。
// OB1 主循环 "FB_AxisControl"(ReqData => "DB_MotionCommand", CfgData => "DB_MotionConfig");FB 内部再根据命令帧里的轴号,把参数搬运到对应轴的运动指令背景 DB 上。这样以后加第 5 轴,只需要在 UDT 数组里扩一个元素,再在 FB 里加一个指令分支,不需要新开一整套代码。多轴设备最怕的就是每个轴一套逻辑,改一个轴忘了另一个,这种集中调度的结构在维护阶段会舒服很多。
4. 核心程序拆解:脉冲控制步进电机的完整调用链路
4.1 回零 MC_Home:先保证坐标系不乱
步进电机本质上是开环控制,CPU 断电后,电机实际位置和程序记录的位置就失联了。所以四轴上电后第一件事必然是回零,把每个轴拉回机械原点,建立坐标系。这份程序里回零逻辑单独放在 FB_HomeSequence 里,是因为回零动作有明确的时序要求:轴 1 回零完成后,轴 2 才能开始,避免多轴同时找原点时撞到机械结构。
程序中触发轴 1 回零的核心调用是这样:
"MC_Home_DB_1"(Axis := "Axis_1", Execute := "DB_MotionConfig".MotionAxes[0].HomeCmd, Position := 0.0, Mode := 2, // 主动回零:找限位再离开 Done => "DB_MotionConfig".MotionAxes[0].Done, Error => "DB_MotionConfig".MotionAxes[0].Error, ErrorID => "DB_MotionConfig".MotionAxes[0].ErrorID);这里的 Mode 参数决定回零方式,常见取值有两个:Mode = 2 是主动回零,轴会以设定速度朝参考点开关方向运动,碰到限位后反向离开,再以爬行速度回到参考点位置,定位精度高;Mode = 3 是被动回零,直接把当前位置设成 Position 值,适合有绝对编码器或机械结构自带硬定位的场合。步进电机没有编码器反馈,最稳妥的选择就是 Mode = 2,用限位开关作为物理参考。回零完成后,程序把 Done 标志置位,后续绝对定位指令才有意义。
4.2 绝对定位 MC_MoveAbsolute:四轴各归各位
回零之后就能跑绝对定位了。MC_MoveAbsolute 的特点是目标位置是相对于原点的,不是相对于当前点。之所以强调这一点,是因为很多刚接触运动控制的开发者会把绝对定位当成相对定位用,结果就是第二次执行时位置跑飞。
下面是轴 1 绝对定位的核心代码:
// 从配置 DB 读取轴 1 参数并触发绝对定位 "MC_MoveAbsolute_DB_1"(Axis := "Axis_1", Execute := "DB_MotionConfig".MotionAxes[0].AbsMoveCmd, Position := "DB_MotionConfig".MotionAxes[0].TargetPos, Velocity := "DB_MotionConfig".MotionAxes[0].Velocity, Acceleration:= "DB_MotionConfig".MotionAxes[0].Accel, Deceleration:= "DB_MotionConfig".MotionAxes[0].Decel, Direction := 1, // 1:正方向,2:负方向,0:最短路径 Done => "DB_MotionConfig".MotionAxes[0].Done, Busy => "DB_MotionConfig".MotionAxes[0].Busy, CommandAborted => "DB_MotionConfig".MotionAxes[0].Aborted, Error => "DB_MotionConfig".MotionAxes[0].Error, ErrorID => "DB_MotionConfig".MotionAxes[0].ErrorID);参数里值得注意的有两个:Direction 和 CommandAborted。Direction 默认是 0,表示走最短路径,在旋转轴或某些机械结构上,最短路径可能和期望方向不一致,所以这里显式设成 1,保证每次都从正向趋近目标位置。CommandAborted 是运动过程中被新命令打断时置位的信号,程序里必须对它做处理,否则操作工在 HMI 上连续点两次启动,第一次动作被第二次打断,如果没有复位逻辑,轴可能停在半路,下一步动作就乱了。
4.3 相对定位与 JOG 手动:调试阶段离不开的两条指令
调试设备时用得最多的其实是相对定位和手动点动。相对定位 MC_MoveRelative 的参数和绝对定位几乎一样,区别只在 Position 被解释为“从当前位置再走多少”。这份程序里把相对定位专门用在换料、顶升这类固定行程动作上,比如顶升气缸对应的轴每次上升 50 mm,不管当前位置是多少,执行相对定位都能走到同一段行程。
手动模式用 MC_MoveJog 实现:
"MC_MoveJog_DB_1"(Axis := "Axis_1", JogForward := "DB_MotionCommand".JogFwd, // 正向点动按钮 JogBackward:= "DB_MotionCommand".JogBwd, // 反向点动按钮 Mode := 2, // 2:连续运行 Velocity := 20.0, // 手动速度,mm/s Acceleration := 50.0, Deceleration := 50.0);手动速度我建议设成自动速度的 10% 到 20%,太快了视野跟不上,手一抖就撞机械限位。JOG 指令执行时,只要 JogForward 变成 FALSE,轴就会按 Deceleration 减速停车,所以急停按钮除了断使能,还要在程序里把这个 FALSE 信号同时撤掉。
4.4 多轴时序协调:机器人控制场景的联动逻辑
四轴设备一旦联动,核心问题就变成了“谁等谁”。这份程序里用 Done 位加状态字的方式做轴间互锁:轴 1 的 Done 是轴 2 的启动条件,轴 2 的 Done 是轴 3 的启动条件,以此类推。
典型的状态机逻辑:
CASE "DB_MotionCommand".Step OF 0: // 等待启动 IF "DB_MotionCommand".Start THEN "DB_MotionConfig".MotionAxes[0].AbsMoveCmd := TRUE; "DB_MotionCommand".Step := 1; END_IF; 1: // 轴 1 运动中 IF "DB_MotionConfig".MotionAxes[0].Done THEN "DB_MotionConfig".MotionAxes[0].AbsMoveCmd := FALSE; "DB_MotionConfig".MotionAxes[1].AbsMoveCmd := TRUE; "DB_MotionCommand".Step := 2; END_IF; 2: // 轴 2 运动中 IF "DB_MotionConfig".MotionAxes[1].Done THEN // 全部到位,完成信号 "DB_MotionCommand".Finished := TRUE; "DB_MotionCommand".Step := 0; END_IF; END_CASE;这里有一个很容易被忽略的点:Done 信号是脉冲性质,执行指令的 Execute 位撤掉后,Done 会跟着复位。所以状态机里做完一步动作,要立刻把对应的 AbsMoveCmd 清掉,否则同一个命令会重复触发。另外,绝对定位执行过程中如果遇到急停,CommandAborted 会置位,但 Done 不置位,状态机必须单独判断 Aborted 信号跳转到错误处理状态,不然程序会卡在“等 Done”里出不来。
4.5 使能、急停与错误复位:MC_Power 和 MC_Reset 的配合
轴使能直接在程序开头统一处理。MC_Power 有两个关键输入:Enable 为 TRUE 时轴使能,为 FALSE 时轴去使能;Stop 输入为 TRUE 时轴紧急停止,但保持使能状态。急停逻辑一般这样写:急停按钮按下时,把 4 个 MC_Power 的 Stop 全部置 TRUE,同时把各轴的速度命令清零,再延时 200 ms 后断开使能,这样电机先减速再掉使能,不会因为突然失电而惯性滑动。
错误复位用 MC_Reset:
"MC_Reset_DB_1"(Axis := "Axis_1", Execute := "DB_MotionCommand".ResetCmd, Done => "DB_MotionCommand".ResetDone);复位之后紧接着要重新回零,因为错误发生时的位置已经不可信。程序里可以设计成:错误恢复后强制进入回零状态机,不允许直接运行自动程序。这个强制逻辑虽然在调试时会让人多等几十秒,但能避免设备带病运行。
5. 避坑记录:步进电机控制的典型翻车现场
5.1 现象:电机嗡嗡响不转,轴一直抖动报警
上电后程序运行,驱动器指示灯亮,但电机不转,只发出嗡嗡声。检查 PLC 输出点,用万用表量 Q 点对 M 的电压,手动置位该 Q 点时驱动器脉冲指示灯没有反应。原因是 PLC 程序组态里的脉冲输出地址与实际接线不一致,比如组态写的是 Q0.0,实际线接到了 Q0.2。还有一个高频原因:PLC 的 M 端没有和驱动器 COM 共地,光耦回路不通。
解决方法是先用程序强制置位输出点,确认 Q 点到驱动器端这条物理链路是通的;然后再核对轴组态地址和实际接线。两个都正确后,再用示波器或万用表频率档测 Q 点是否有脉冲输出。链路不通时,优先查公共端,链路通但不转,再查频段、速度参数。
5.2 现象:定位位置每次都差几个脉冲,速度越快偏差越大
轴低速运行时定位正常,把速度调上去之后,每次停止位置都差一段距离,而且速度越快偏差越大。这个现象十有八九是丢步:步进电机加速时间太短,脉冲频率瞬间跳到高速段,电机转子和定子磁场跟不上,就丢了几步。另一个常见原因是加减速时间在程序里填了 0,电机直接从静止跳到目标速度。
解决方法是把加速度和减速度参数调大对应的时间值,比如原来 5000 mm/s² 的加速度改到 2000 mm/s²,拉长加速过程。同时检查驱动器细分与轴组态里的每转脉冲数是否一致。细分不一致时,偏差会是固定比例,比如每次都多走一倍,而丢步是随机偏差,两者从现象上就能区分。
5.3 现象:回零后原点位置漂移,越跑越偏
回零完成后第一次定位是准的,跑几个循环后原点位置就偏了。查下来限位开关用的是常闭触点,机械振动导致触点瞬间抖动,PLC 输入端收到一个错误的断开信号,主动回零逻辑把抖动当成了真实限位,提前完成了回零。
解决方法是先在 PLC 输入点组态里打开数字量输入滤波,滤波时间设 1 ms 到 5 ms,滤掉高频毛刺;然后在程序里对回零信号加确认逻辑,连续读取到稳定电平超过 20 ms 才认为有效。如果机械上允许,把限位开关从常闭改成常开,安全逻辑也更合理,断线时能直接报故障,而不是一直当作“未碰限位”。
5.4 现象:单轴动正常,四轴同时动就复位或丢步
单个轴调试都好,一旦四轴同时启动,设备偶尔会整体掉电复位,或者其中一两个轴丢步。检查开关电源,发现容量刚好只够稳态电流,四个电机同时加速时电流冲击把电压拉到了 DC 电压允许范围以下,PLC 直接掉电重启。
解决方法是换更大容量的开关电源,按驱动器额定电流的 1.5 倍以上选型;同时在电源输出端并联大容量电解电容,吸收瞬间冲击。如果不想换电源,程序里也可以做“错峰启动”:四个轴的 Execute 信号间隔 100 ms 发出,避免电流峰值叠加。这种方法虽然简单,但能立竿见影。
5.5 现象:HMI 上改了速度没反应,程序里改也没用
画面里把速度从 5000 改成 8000,启动后电机速度没有变化。查下来发现轴组态里的最大速度限制设成了 5000,程序里给 8000 的指令,MC_MoveAbsolute 在启动阶段就把速度钳位到 5000,不会报错,也不会超出。这就是前一章说的“上限写在组态里”的坑。
解决方法是把速度上限在组态里放宽到机械允许的最大值,比如 12000,然后在 DB 里用程序做软限制,HMI 输入值先和 DB 里的允许范围做比较,超出就弹出提示。这样既能保护机械,又不会出现“改了没反应”的玄学问题。在调试阶段,每次改动速度参数后,我都会看一眼轴状态字里的实际速度反馈,确认程序跑出来的速度和设定值一致,再往下调其它参数。
6. 二次开发:把 4 轴实例改造成机器人控制骨架
6.1 扩到 6 轴、8 轴:把轴调用抽成通用分支
这份实例的架构决定了扩展轴数不需要伤筋动骨。先修改 UDT 数组长度,从 4 改成 6 或 8;然后在 FB_AxisControl 里把运动指令的分支调用复制一份,轴号加一。因为所有轴共用同一个 UDT,HMI 的配方表可以直接用数组长度作为循环上限,不需要为每个轴单独写画面逻辑。要注意的是,S7-1200 的运动指令背景 DB 不能直接用数组下标动态访问,所以轴号分派只能用 CASE 语句或 IF-ELSE 链展开,这一步别写成 FOR 循环,编译都过不去。
6.2 把动作封装成配方表
四轴设备真正干活时,流程是固定的:轴 1 到位,轴 2 夹紧,轴 3 下压,轴 4 复位。建议在 DB 里增加一张配方表,每行记录一个工位的四轴目标位置和速度,用配方号做索引。HMI 上做“一键换型”时,只需要把当前配方号对应的参数搬运到 MotionAxes 数组里,再触发启动命令,四轴就会自动按新配方跑。搬运参数时注意先停掉正在执行的自动程序,在停止状态下切换配方,否则四个轴可能跑到一半突然跳变目标位置。
6.3 与上位机或触摸屏对接
S7-1200 默认支持 S7 协议,上位机直接用 S7 通信读写 DB 块就行。建议把 HMI 需要读写的变量全部集中放在一个 DB 里,用符号名发布,不要让上位机去读散布在各个 FB 背景块里的变量。通信状态字单独留一个 Word,上位机写命令后,PLC 处理完写回状态,这样上位机可以判断命令是被接受还是被拒绝,不至于把通信断线当成设备故障。
6.4 验证方法:空载慢速到全速,最后统计重复精度
每一次改动程序,我习惯按这个顺序验证:先空载、低速、单轴跑一遍回零加绝对定位;然后逐步提到目标速度,注意听电机有没有异常噪音,丢步时电机声音会突然变轻或变闷;最后用百分表打一个固定位置,连续回零加定位十次,记录每次的位置偏差。重复定位精度控制在正负 0.05 mm 以内,才算这台设备能交付。
第一次做四轴项目时,我为了赶进度,跳过慢速测试直接全速跑,结果连丢三步,把一块工件压弯了。从那以后,我每次改完位置、速度或者加减速参数,都强制自己走一遍“空载慢速、空载全速、负载标定”三步验证,再急也得走完。希望这份实例的拆解能帮到你,少踩几个我当年踩过的坑。
本文还有配套的精品资源,点击获取