☰
汇川AM系列PLC跑马灯程序详解:从工程搭建到仿真调试
2026/9/28 1:46:31 网站建设 项目流程

最近在几个工控交流群里,看到不少人在问汇川AM系列PLC的案例,尤其是“跑马灯程序”这种入门级项目,问的人比想象中多。原因不难理解:AM系列是汇川基于Codesys体系的中大型PLC,和传统三菱、西门子那种“一开机就是梯形图”的体验完全不同,很多人第一步就卡在工程结构上。我拿AM401做了个8路跑马灯,从建工程、写程序到仿真验证走了一遍,把关键细节和踩过的坑整理出来。这篇内容对刚入手AM系列的电气工程师、从三菱或西门子转Codesys的人应该都有帮助,哪怕你是纯新手,只要懂点PLC基础,按步骤操作也能跑通。

为什么专门挑跑马灯?因为它虽然简单,却把PLC开发的五个核心步骤全串起来了:建工程、配任务、写逻辑、映射IO、仿真验证。你在跑步马灯时养成的习惯,直接决定后面做伺服、做总线、做CNC时会不会返工。这篇文章就以AM401为例,从InoProShop环境搭建开始,到三种跑马灯实现思路,再到仿真排错和向真实工程扩展,一次讲透。

1. 跑马灯这个入门项目,为什么值得用AM系列重做一遍

1.1 别小看跑马灯:它覆盖了Codesys体系最核心的几个机制

很多人觉得跑马灯就是“几个灯轮流亮”,三菱PLC里写个梯形图,几十步就完了,至于这么兴师动众吗?这话在传统PLC上没错,但在AM系列这种Codesys平台上,跑马灯的价值完全不在“灯”,而在它被迫你搞清楚的三件事。

第一件事是任务调度。Codesys体系不像老式PLC那样只有一个扫描周期,AM系列可以配置多个任务,每个任务有自己的周期和优先级。跑马灯程序放在哪个任务里、任务周期设多少,会直接影响定时精度。你在做传统PLC时可能从来不需要关心“任务扫描时间”这个指标,但在AM上,程序只是躺在那里,不挂到任务下面它根本不会执行。

第二件事是符号编程习惯。AM系列的程序是基于变量名和功能块组织的,IO地址只是底层映射。你写arLamp[2]和直接写%QX0.2,在功能上等价,但可读性和可维护性天差地别。跑马灯这个案例不大不小,正好逼着你养成“先声明变量、再操作符号、最后映射IO”的习惯,这个习惯在Codesys里比什么都重要。

第三件事是仿真调试闭环。AM系列的仿真不是摆设,它是真正能把程序跑起来的虚拟PLC。但很多人下载了程序却不知道下一步该干嘛,因为仿真模式下没有真实的输入信号,按钮不会自己按下去,传感器不会自己触发。你得学会用强制、写入、监视这些调试手段来模拟现场信号。跑马灯需要启动信号、需要观察8路输出时序,恰恰把这一整套调试方法都练习了一遍。

所以说,跑马灯项目不是“杀鸡用牛刀”,它是一个把Codesys编程范式从零到一打通的最佳载体。

1.2 AM系列与H5U的差异:选型直接影响编程体验

群里常见的一个纠结点是:入门用H5U还是AM系列?这两个都是汇川的中型PLC,也都基于Codesys,但用起来差别不小。

H5U走的是“硬件PLC+Codesys风格编程”的路线,工程结构被简化过,上手快,但很多底层机制被封装得比较死。比如任务调度、自定义功能块、复杂数据类型的自由度都比AM系列低。AM系列则更接近纯正的Codesys开发环境,你可以自定义任务、自己写功能块、用数组和结构体、甚至调库函数。从学习角度看,AM系列能让你对Codesys的理解更深刻,后面转到CODESYS平台的其他品牌PLC基本无缝衔接。

还有一个很多人忽略的点:AM400系列和AM600系列虽然都是Codesys,但定位不同。AM401/AM402适合中小型设备控制,自带IO点数适中,扩展灵活;AM600性能更强,还支持CNC和电子凸轮这类高级功能。如果以后想往运动控制、数控方向走,直接学AM600的工程思维会更省事。跑马灯这个项目在AM401上做和在AM600上做,程序结构完全一样,区别只在于设备型号的选择和后续扩展能力的上限。

如果你手头已经有H5U或者EASY320,这篇文章的程序思想同样适用,只是工程创建和IO地址映射的界面略有不同,核心逻辑完全一致。学PLC最忌讳“只会按这个型号的按钮”,我建议你把关注点放在“为什么这么配、为什么这么写”上。

1.3 学AM系列的人,通常卡在哪几个环节

根据我在各种技术群里潜水观察的经验,大家学AM系列最容易卡住的位置,集中在下面几个场景:

  • 新建工程后找不到“扫描周期”的设置入口,程序写好了不知道为什么不执行。这类问题本质上是没理解“任务”的概念。
  • IO地址不知道去哪查。AM401本体自带的8路输出到底是%QX0.0还是%QX1.0,手册里写得清楚,但新手就是找不到地方确认。
  • 仿真下载成功,点运行,然后呢?没有输入信号,程序一动不动,很多人就在这一步放弃了。
  • 程序逻辑在纸面上没问题,但仿真时定时器不动作、输出不变化,最后发现是变量没有映射到物理输出,或者任务周期和定时器周期混淆。
  • 遇到总线扩展、伺服调试之后,连轴器的IP地址搜不到,怀疑硬件坏了,其实是PC网卡没配到同一网段。

这篇文章后面几个大节,基本就是围绕这些痛点来的。

2. InoProShop工程搭建:型号确认、任务配置和IO映射

2.1 新建工程前,先把这两件事确认清楚

很多人一打开InoProShop就急着“新建项目”,结果选完型号开始干活,等到下载程序时才发现固件版本对不上,或者CPU型号选错了,只能推倒重来。我建议新建工程前,花两分钟确认两件事。

第一件事是CPU的具体型号。AM401有多个子型号,比如AM401-CPU1608TP和AM401-CPU1608TN。TP是PNP源型输出,TN是NPN漏型输出,如果你后面要接真实负载,输出类型跟负载的公共端接法必须匹配。仿真阶段虽然不接实物,但型号选错了,程序里的IO地址、任务能力都会跟着变,所以还是老老实实按铭牌选。

第二件事是InoProShop软件版本与固件版本的兼容性。AM系列使用InoProShop编程软件,不同版本的软件对新旧固件的支持有差异,连接设备或仿真前最好确认一下。仿真的话问题不大,但如果你手头有真实PLC,建议把固件和软件版本对齐,省得后面报一些莫名其妙的通讯错误。

新建工程的路径是:打开InoProShop,点击“新建项目”,选择对应CPU型号,输入项目名称,确定后进入工程树。工程树里你会看到“Device”“PLC Logic”“Application”“任务配置”这几个核心节点。Device下面挂的是硬件资源,Application下面是程序代码、全局变量、任务配置这些软件资源。

2.2 变量声明与IO映射:绝对地址和符号地址的关系

AM系列的编程入口是PLC_PRG这个程序组织单元,双击就可以开始写代码。但写代码之前,我强烈建议你先在变量表里把要用到的变量全部声明好,尤其是IO变量。

AM401本体自带的IO地址有规律可循。输入一般在%IX0.0到%IX0.7,输出在%QX0.0到%QX0.7,具体以你选的型号手册为准。但在程序中直接写%QX0.0是完全不推荐的做法。一来可读性差,维护的人看到%QX0.2不知道它是灯还是阀;二来一旦硬件地址调整,你得把所有程序翻一遍。

正确的做法是在全局变量表里先定义符号变量,再通过InoProShop的“映射”功能将符号地址绑定到物理地址。比如:

VAR_GLOBAL bLamp0 AT %QX0.0 : BOOL; bLamp1 AT %QX0.1 : BOOL; bLamp2 AT %QX0.2 : BOOL; bLamp3 AT %QX0.3 : BOOL; bLamp4 AT %QX0.4 : BOOL; bLamp5 AT %QX0.5 : BOOL; bLamp6 AT %QX0.6 : BOOL; bLamp7 AT %QX0.7 : BOOL; END_VAR

这样写的好处是,程序逻辑里你永远操作的是bLamp0这个名字,即使以后硬件输出换到%QX1.2,也只要改这一行映射声明,程序主体一行都不用动。

如果你用的是数组做跑马灯,还可以把数组跟连续IO地址做映射。AM系列的输出地址如果是连续排列的,理论上可以定义一个ARRAY[0..7] OF BOOL配合绝对地址映射,不过这种做法在跨平台移植时容易出问题,建议只是作为一个优化思路,新手阶段还是老老实实逐个变量映射,逻辑更清晰。

2.3 任务配置:你的程序放在哪个周期里跑,决定了定时精度

任务配置是Codesys体系区别于传统PLC最深的一道坎。新建的Application默认带一个MainTask,PLC_PRG就是挂在它下面执行的。你双击“任务配置”,可以看到任务周期、优先级、看门狗这些参数。

跑马灯程序对任务周期没有苛刻要求,默认的1ms或4ms都能满足。但你要理解一个关系:如果任务周期是4ms,你的程序最短只能感知到4ms的变化,即使内部定时器精度再高,输出刷新也是按任务周期来的。反过来说,如果任务周期设成1ms,而程序里有很多大循环、通讯指令,任务可能在一个周期内跑不完,这时候系统会报任务超时,严重的会直接停掉这个任务。

跑马灯阶段,我建议把任务周期设为4ms,优先级保持默认,先跑起来再说。后面做伺服控制、高速脉冲输出时,再把周期压缩到1ms或者更短。这种“先验证功能,再压性能”的思路,能帮你省去很多排错时间。

还有一个容易踩的坑:做完调试后,程序下载进仿真PLC,但改动程序后忘了重新下载和重新运行,于是看到的还是旧逻辑。InoProShop的在线修改机制会自动更新一部分变化,但不是所有改动都能生效,最稳妥的办法是:停止任务、重新登录、下载、运行。步骤多几步,但不会出幺蛾子。

3. 跑马灯核心程序:三种实现思路及代码拆解

3.1 思路一:TON定时器驱动计数器,输出定位

这是我最推荐新手掌握的写法,逻辑非常朴素:一个定时器产生节拍脉冲,一个计数器记录当前应该亮哪一盏灯,然后用比较赋值把灯的图案输出。

先看ST代码:

PROGRAM PLC_PRG VAR xRun : BOOL := FALSE; (* 总启动信号 *) tonTick : TON; bTick : BOOL; (* 节拍脉冲,持续一个扫描周期 *) iStep : INT := 0; (* 当前步数 *) arLamp : ARRAY[0..7] OF BOOL; iLoop : INT; END_VAR
// 定时器:每次计时到500ms后,自动复位重新开始 tonTick(IN := xRun AND NOT tonTick.Q, PT := T#500MS); bTick := tonTick.Q; // 计数器:节拍脉冲到来时步数加1,超过7就回0 IF bTick THEN IF iStep >= 7 THEN iStep := 0; ELSE iStep := iStep + 1; END_IF END_IF // 输出定位:只有和iStep相等的索引对应的灯亮 FOR iLoop := 0 TO 7 DO arLamp[iLoop] := (iLoop = iStep); END_FOR // 映射到物理输出 bLamp0 := arLamp[0]; bLamp1 := arLamp[1]; bLamp2 := arLamp[2]; bLamp3 := arLamp[3]; bLamp4 := arLamp[4]; bLamp5 := arLamp[5]; bLamp6 := arLamp[6]; bLamp7 := arLamp[7];

这里的核心技巧是IN := xRun AND NOT tonTick.Q。如果你把定时器输入直接接xRun,那当定时时间到后tonTick.Q会一直保持TRUE,计数器会疯狂累加,根本停不下来。用AND NOT tonTick.Q把定时器的输出接回输入,等于告诉它:时间一到,下一周期我就复位你,重新开始计时。这样bTick就是一个持续一个任务周期的脉冲信号,正好用来驱动计数器。

这个方案的优点是逻辑简单、周期完全可控。想跑快点,把T#500MS改成T#200MS;想跑两圈再复位,把判断条件改成IF iStep >= 15。缺点是不太容易扩展出“两盏灯同时流动”这类效果,因为输出定位逻辑是“只亮一个索引”。

3.2 思路二:数组循环移位,实现双向流动和自定义花样

如果想让跑马灯流动方向可变,或者要做出“灯带来回扫”“两灯同跑”等花样,数组循环移位是更好的选择。ST语言中没有直接对布尔数组做整体移位的指令,所以要用FOR循环配合临时变量手动移位。

核心逻辑是这样:

VAR xRun : BOOL; bDirection : BOOL := FALSE; (* FALSE=左移, TRUE=右移 *) tonTick : TON; bTick : BOOL; arLamp : ARRAY[0..7] OF BOOL; iLoop : INT; bTemp : BOOL; (* 回绕时保存被挤出去的位 *) bInitFlag : BOOL := TRUE; (* 首次运行初始化 *) END_VAR
tonTick(IN := xRun AND NOT tonTick.Q, PT := T#300MS); bTick := tonTick.Q; // 启动时只点亮第一盏灯 IF bInitFlag AND xRun THEN arLamp[0] := TRUE; FOR iLoop := 1 TO 7 DO arLamp[iLoop] := FALSE; END_FOR bInitFlag := FALSE; END_IF // 每次节拍移位 IF bTick THEN IF bDirection THEN // 右移:从高位往低位搬,先保存最高位 bTemp := arLamp[7]; FOR iLoop := 7 TO 1 BY -1 DO arLamp[iLoop] := arLamp[iLoop - 1]; END_FOR arLamp[0] := bTemp; ELSE // 左移:从低位往高位搬,先保存最低位 bTemp := arLamp[0]; FOR iLoop := 0 TO 6 DO arLamp[iLoop] := arLamp[iLoop + 1]; END_FOR arLamp[7] := bTemp; END_IF END_IF

这个方案里有几个细节值得注意。

一是移动方向不同,循环的方向不一样。右移时FOR iLoop := 7 TO 1 BY -1,也就是从下标7开始往0方向赋值,保证每个位置都从邻居手里拿到值;左移则相反。写反了会出现整组数据被单一值覆盖的问题。

二是回绕保存。跑马灯的移动是环形的,移出去的位要补到另一头。很多人第一次写会漏掉bTemp保存这一步,导致循环移位后某一端变成全FALSE,灯跑着跑着就只剩一侧在亮。

三是初始化的位置。bInitFlag这个变量只在第一次xRun有效,目的是避免移位前整个数组全是FALSE,那样不管怎么移都没有灯。你在仿真时要留意,如果先把xRun置TRUE,再复位,bInitFlag可能已经被清掉了,这时候数组里还是全FALSE的状态,跑不起来。正确做法是先在变量监视表里把bInitFlag改回TRUE,或者把它做成一个可复位的初始化命令。

这个方案的扩展性体现在,你可以任意构造arLamp的初始值来实现不同花样。比如让两盏灯同时亮,初始化时设arLamp[0]:=TRUE; arLamp[4]:=TRUE;,后面循环移位就会自动保留“两灯保持固定间距同跑”的效果。

3.3 思路三:WORD位串移位,代码最简、执行效率最高

如果你的跑马灯数量不超过16路,还有一个更“PLC味”的写法:用WORD类型做移位寄存器。WORD本质上是一个16位的位串,右移和左移都有现成的SHL、SHR指令,根本不用写FOR循环。

VAR xRun : BOOL; tonTick : TON; bTick : BOOL; wLamp : WORD := 16#01; (* 每次只有1位为1 *) bLampArr : ARRAY[0..15] OF BOOL; iLoop : INT; END_VAR
tonTick(IN := xRun AND NOT tonTick.Q, PT := T#500MS); bTick := tonTick.Q; IF bTick THEN wLamp := SHL(wLamp, 1); // 左移1位 IF wLamp = 16#0000 THEN wLamp := 16#0001; // 移出边界后重新从第0位开始 END_IF END_IF // 从WORD中取出每一位,放到输出数组 FOR iLoop := 0 TO 15 DO bLampArr[iLoop] := (SHR(wLamp, iLoop) AND 16#0001) <> 16#0000; END_FOR

这段代码最漂亮的点在边界处理。SHL(wLamp, 1)把位整体向左移,如果wLamp原来是16#8000,左移一位就变成16#0000,刚好是一个“移出边界”的标志。这时候判断一下归位到16#01,就实现了环形循环。

这个方案的优势是代码量少、扫描开销极低,而且你可以一次性预设多个位同时为1,实现多灯并行跑。缺点是对新手不太友好:SHR、AND、<>这些位操作的含义要理解,而且一旦超过16路,就要用两个WORD拼接或者改用DWORD,逻辑复杂度会上一个台阶。

如果只是做一个8路跑马灯,三种方案都能满足要求。但我的建议是:第一个方案作为主方案,因为它最直观,后续修改周期和维护程序时最省心。第二、三种方案可以当作思维拓展,尤其当你要做带方向切换或其他花样的灯带时再拿出来用。

3.4 三种方案对比,方便你按场景选择

方案核心原理周期控制可维护性扩展花样的难度推荐场景
计数定位TON产生节拍,计数器定位最容易,只改PT高,逻辑直白中等,多灯并行要加数组判断入门学习、基础状态显示
数组循环移位FOR循环手动搬移数组元素容易,只改PT中等,需理解回绕逻辑高,可自定义任意初始图案方向可变的灯带、花样流水灯
WORD位串移位SHL/SHR对布尔位串移位容易,只改PT中低,位操作需要经验低,16路内最简输出路数固定、追求极简代码

表格里“周期控制”都说容易,因为定时器节拍这个设计是统一的,区别只在于每次节拍到来时“怎么改变输出图案”。跑马灯项目的精髓就是“节拍+状态更新”两步走,你可以把节拍看成心跳,把状态更新看成动作。设备里的告警灯闪烁、料道分拣、工具换刀顺序控制,本质上都是这个套路。

4. 仿真运行全流程:从编译到动态追踪,步步有坑

4.1 第一次做仿真,按照这个顺序点下来

程序写完只是第一步,接下来要把它放到仿真PLC里跑起来。InoProShop的仿真模式不需要真实硬件,在电脑上就能模拟完整的PLC运行环境,调试跑马灯绰绰有余。

大致流程是:先点击“生成”菜单里的“生成”,让软件编译整个工程。编译通过后会显示0个错误,有警告可以暂时不理,但要看清警告内容。然后点工具栏上的“仿真”按钮进入仿真模式,或者在在线菜单里切换。接着点击“登录”建立与仿真PLC的连接,这里一般会让你生成一个仿真环境,确认即可。登录后点“运行”,程序就开始执行了。

这中间有一个经常被忽略的动作:登录前要确认工程树里“PLC Logic”下的Application已经处于“已生成”状态,并且设备配置没有红色叉号。如果硬件配置有问题,登录会直接失败或者在下载时报错。

进入仿真模式后,右侧的编程界面会变成监视状态,变量名旁边会显示当前值。你看到xRun还是FALSE,程序逻辑当然不会动。下一步就是给仿真环境创造输入信号。

4.2 没有实物IO,怎么模拟输入信号:写入、强制、追踪三件套

仿真和在线调试最大的不同,就是没有真实按钮和传感器给你按。所有输入信号本质上都是变量,你需要手动改变这些变量的值来模拟现场输入。

操作方式很简单:在变量监视表里,右键xRun,可以看到“写入值”和“强制”两个选项。写入值的含义是临时把它改成TRUE,但程序在下一个扫描周期可能会根据逻辑把它的值重新计算回来。强制则更霸道,它会锁定这个变量的值,就算程序里有赋值语句也覆盖不了。对于跑马灯的总启动信号,我建议用“强制”来模拟一个常闭的启动按钮,先把xRun强制成TRUE,再看程序动作。

如果你希望更像真实情况,比如模拟按钮按一下就松开,那就用“写入值”先把xRun写成TRUE,等半个周期再写回FALSE。注意xRun作为BOOL变量且程序里没有对它赋值的语句,写入后能保持住,这种情况跟真实按钮并联自锁回路的行为差异不大。

追踪功能是仿真调试的利器。跑马灯需要看8路输出随时间的变化,如果靠肉眼看监视表里的TRUE/FALSE切换,眼睛会累瞎。InoProShop支持把变量加入跟踪列表,以波形的方式展示一段时间的值变化。你可以把bLamp0到bLamp7、iStep加进去,跑几秒钟,然后暂停跟踪,观察波形是不是一个灯亮500ms再切换到下一个灯。波形观察最大的价值是让你一眼看出时序关系对不对,而不是一个个数TRUE的个数。

4.3 仿真中常见的三个坑,含ER75负载报警

第一个坑是登录成功后程序不运行,或者运行了但输出全不亮。排查思路按顺序来:看任务配置里PLC_PRG是不是挂在某个任务下;看Application是否处于运行状态;看xRun到底有没有被强制成TRUE;再看输出映射地址是不是超出了CPU的输出范围。这些问题基本都是新手期最容易碰的,解决办法也很直接,逐个变量监视就能定位。

第二个坑是定时器不动作。很多人直接把tonTick的IN接TRUE,忘记在代码里统一控制它的启停,导致定时器虽然一直在跑,但节拍脉冲逻辑无法和总启动信号联动。另一个常见原因是任务周期写得太长,定时器的PT是500ms,任务周期4000ms,导致定时器的时间基准抖动很大,波形看起来不是均匀的。把任务周期调到10ms以下基本就正常了。

第三个坑是ER75报文。我曾经在调一个通讯任务时遇到过这个报警,第一反应是硬件出问题了,后来查文档才知道ER75是任务负载率过高或者看门狗超时的提示。简单说,就是程序在一个任务周期内没跑完,超时了。仿真阶段跑马灯程序逻辑很简单,一般不会触发ER75,但如果你同时开了逻辑任务、通讯任务,又把任务周期压得很短,比如1ms,就有可能出现这个报警。解决办法分两步:先看任务配置里每个任务的耗时统计,确认是哪个任务超时;然后要么把周期放宽到10ms,要么在超时任务里关掉不必要的子程序调用。跑马灯这种演示项目完全没必要追求极限周期。

关于ER75,还有个隐藏点:仿真模式下电脑CPU性能会直接影响任务执行速度,如果电脑配置一般,同时又开着很多程序,仿真器的“任务运行时间”会比真实PLC长很多。这时候看到的ER75可能只是电脑卡顿导致的假象,重启仿真器或者关闭后台程序再试一次。

5. 从跑马灯到真实设备:总线轴、伺服联动和通讯扩展

5.1 把跑马灯的开关量输出,换成EtherCAT总线轴控制

跑马灯程序的最终目的不是让你在公司里做个灯带展示,而是让你理解“节拍驱动状态更新”这个套路。在真实设备里,这个套路最常见的应用是总线运动控制。

AM系列支持EtherCAT主站,可以挂汇川IS620N这类伺服驱动器。假设一个场景:8个工位,每个工位对应一个执行气缸或一个伺服定位动作,设备要求按顺序轮流触发。抛开气缸的传感器互锁不谈,核心逻辑其实和跑马灯一模一样:一个计数器加一个定时器,按顺序输出当前工位的使能信号。区别只是输出的不是bLamp0,而是通过EtherCAT往轴的控制字里写使能命令。

做EtherCAT配置时,先要在设备树里扫描到从站,然后把伺服电机的实际速度和位置信息映射到PDO对象字典。很多人在这一步报错,是因为PLC和伺服之间的EtherCAT线序不对,或者伺服没有正确上电。扫描不到从站时,先检查网线、再检查伺服电源、最后看从站是否有报错LED。这个排错顺序适用于几乎所有总线系统。

跑马灯代码迁移到总线控制后,需要注意一个区别:开关量输出是即时的,写bLamp0:=TRUE后输出马上有反应;而总线的命令要经过一个通讯周期才能到达伺服,通常还有几毫秒的延迟。如果你要求多个轴精确同步,就不能简单依赖扫周期轮回,得用EtherCAT的分布式时钟功能,配合电子凸轮或者位置同步,这部分就不是跑马灯能覆盖的了。

5.2 Modbus RTU轮询调度:跑马灯逻辑的经典“复用”

跑马灯“轮流点亮”的思路,在通讯轮询上体现得淋漓尽致。比如一台PLC要控制32台变频器,常见的做法是Modbus RTU轮询:按顺序给1号变频器发指令、等它应答、然后给2号发、等应答……这个“按顺序发送”的框架,就是一个跑马灯。

伪代码大概是这样的:

// 伪代码,仅示意轮询结构 CASE iStep OF 0: 发送Modbus请求到站号1; 标志位置位; 1: 检查站号1应答完毕; 若完成,iStep := iStep + 1; 2: 发送Modbus请求到站号2; 标志位置位; ... END_CASE

注意这里驱动iStep的不再是定时器,而是“通讯完成标志”。这个过程其实比跑马灯更高级:跑马灯的节拍是时间驱动,设备轮询的节拍是事件驱动。但底层状态机的写法完全一致。你把跑马灯的“定时器节拍”换成“完成标志触发”,再用CASE语句区分当前轮到哪个站,一个标准的轮询程序就出来了。

这也是为什么我建议跑马灯不要只看“实现出来”,而是要把“状态机+节拍”的思想吃透。实际设备里的报警闪烁、流水线工位切换、多变频器轮询、配方步进跳转,全都是这个思路的变体。

5.3 位置环前馈、追标系统和CNC:跑马灯节拍思想的高阶延伸

搜索热词里频繁出现“汇川位置环前馈”“追标”“Linux CNC PLC”,这些都是从跑马灯往运动控制方向跨的典型词汇。位置环前馈是在伺服调试软件里调出来的,比如用InoDriveShop连接伺服驱动器时,需要设置速度前馈和位置前馈增益。前馈的作用是提前补偿指令运动带来的跟随误差。很多人在这个环节调不好,其实是因为没有理解“节拍”的概念:运动执行有相位问题,前馈就是补偿相位差。

InoDriveShop搜索不到伺服地址,是另一个高频问题。绝大多数情况不是硬件坏了,而是PC网卡和伺服驱动器的IP不在同一个网段。汇川伺服默认IP通常是192.168.1.10,你把本机IPv4地址手动改成192.168.1.x(如192.168.1.2),子网掩码255.255.255.0,然后断电重启伺服,Ping一下能通再搜索。这个坑跟AM系列PLC搜索不到从站是同一个原因,牢记“同一网段”这四个字能解决一大半通讯问题。

追标系统是包装机械里非常经典的应用,它要做的是让印刷图案和切刀位置始终保持固定的相位关系。跑马灯的“节拍”在这里升级成了“主轴电子凸轮表的相位位置”。你不需要理解凸轮曲线的每一条公式,但你必须理解“当前主轴位置对应什么动作”这个状态机思想,这恰好就是跑马灯程序在8个灯上训练过的东西。AM600系列还提供CODESYS的CNC功能,可以解析G代码并驱动总线轴运动,底层也是“把程序段拆成离散步进执行的节拍”。

所以,如果你把跑马灯项目认认真真做一遍、仿一遍、再试着改一改,你的收获绝对不只是会点灯。它是一把钥匙,打开了Codesys体系的任务调度、符号编程、状态机设计、仿真调试这一整套方法论。后面不管是接伺服、挂总线、做视觉还是做追溯,底层都是一样的.

最后再说几句我的体会。跑了这么多年现场,我最大的感受是:很多高级问题之所以难解,往往不是难在算法,而是难在基础的动作没有做得足够规范。跑马灯虽然简单,但你在它身上是否养成了变量先声明、任务周期明确、IO映射清晰、仿真必追踪的习惯,会一路影响你后面所有项目。把这个项目吃透,比急着去抄一个大项目代码有价值得多。建议你拿到本文的工程文件后,别只停在“仿出来能跑”,试着改一改周期、改一改方向、加一个复位逻辑,你会发现每次改动都在加深你对PLC程序组织和调试流程的理解。

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

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

立即咨询