☰
三菱PLC变址寄存器实现螺丝机配方管理,换型不再改程序
2026/10/19 0:36:59 网站建设 项目流程

做三轴螺丝机项目,最让我头疼的不是走位精度,也不是电批扭矩,反而是配方管理。第一版程序就写了四种产品型号,直接拿比较指令一段段选参数,等客户说要加第五个型号,我发现光梳理坐标就得翻小半个程序。后来我用三菱PLC的变址寄存器把配方管理重写了一遍,思路彻底换了过来——加型号不再需要改PLC程序,只需要在触摸屏上往空的配方槽里填参数。这篇就把当时从踩坑到理顺的完整过程记录下来,给还在用“笨办法”写配方的朋友一个参考。

1. 螺丝机换型,换的不只是产品,还有一整套参数

1.1 三轴螺丝机的动作循环与配方参数清单

三轴螺丝机的工作循环其实不复杂:产品放到夹具里,X/Y轴把电批定位到第一颗螺丝上方,Z轴快速下降,到一定深度后切换慢速,电批接触螺丝并启动,达到扭矩或圈数后停批,Z轴抬起,X/Y移到下一颗螺丝位置,重复直到整块板子打完。

问题在于“下一颗螺丝在哪”和“用什么扭矩打”,这跟产品型号强相关。A型壳体4颗螺丝,B型壳体6颗螺丝,C型壳体有8颗,而且螺丝规格不一样,扭矩转速都不同。有的产品还要分两次下压,先预锁后终锁。这些参数归纳起来就是一组“配方”:螺丝数量、每颗螺丝的X/Y/Z坐标、扭矩上限、拧紧转速、Z轴快进深度、Z轴慢进深度、电批启动等待时间。

真正常用的参数项,算下来十几个到二十几个字不等。坐标一般按脉冲数存,因为我们走的是步进或伺服发脉冲控制,不换算成毫米,调试的时候示教一下,当前脉冲值直接写进配方,直观又不容易错。

1.2 不用变址寄存器之前,我的配方切换代码

第一版程序我犯了绝大多数新手都会犯的毛病——把配方做成“开关”。X0到X3当作产品选择信号,然后每个产品写一大段MOV:

产品1号:把D1000开始的坐标和参数搬到当前运行区。 产品2号:把D2000开始的坐标和参数搬过来。 产品3号:把D3000开始的坐标和参数搬过来。

一个产品8颗螺丝,坐标24个字,加上扭矩转速一堆参数,一条MOV只能搬一个字,一个产品就是几十条指令。四个产品下来,程序里光搬运就占了几百条。表面上能用,实际维护很痛苦:

第一,新增产品要复制粘贴一大段,改错一个D地址,坐标就乱了; 第二,改某颗螺丝的坐标,得先找到是哪个产品的哪一段,眼花是常态; 第三,程序扫描周期被一堆MOV拖慢,动作程序被挤在后面,响应变差。

客户说“下周加三个新型号”的时候,我意识到这条路走不通了。

1.3 从“给每个型号写逻辑”到“用配方号驱动逻辑”

后来我换了个视角:配方表本质上就是一张二维表,行是配方号,列是参数。程序要做的只有一件事——根据当前配方号,把对应那一行的数据整行搬到运行区。就像图书馆管理员按编号去书架上拿一本书,不需要为一本书专门修一条路。

这就需要PLC能“按计算出来的地址去取数”,也就是变址寻址。有了这个能力,无论配方表里是4个型号还是60个型号,程序逻辑始终只有一套:校验配方号、算偏移量、批量搬数据。这也是我这个项目里最核心的思路转变。

2. 变址寻址:D5000Z0这种写法,本质是给PLC加了个数组下标

2.1 V/Z寄存器到底怎么用

三菱FX系列PLC里有两组变址寄存器:V0到V7,Z0到Z7,一共16个。它们本身不存业务数据,专门用来“改地址”。写法很简单,看一个例子:

MOV K10 Z0 // 把10放进Z0 MOV D5000Z0 D200 // 这行指令实际访问的是D5010

D5000Z0的意思就是“D5000这个基地址加上Z0里面的值”。Z0等于几,实际地址就是D5000加几。这个“加”发生在指令执行的那一瞬间,Z0不变,所有用到D5000Z0的指令都会自动跟着偏移。这跟C语言里的数组下标完全是一个道理,arr[3]就是base地址加3个元素的偏移量。

2.2 变址寻址的本质是数组下标运算

有了变址寄存器,配方管理的核心公式就出来了:

基地址 = 配方存储区的起始D地址
偏移量 = 配方号 × 单个配方占用的D字数
实际地址 = D(基地址) + 偏移量,写成D5000Z0

只要单个配方的长度固定,配方号从哪号开始,偏移量就是可计算的一一映射。我在程序里先把配方号乘上40,结果放进Z0,然后D5000Z0自然就指向了第N号配方的第一个字。这个映射关系是整个配方管理的命脉,后面所有流程都围着她转。

2.3 为什么16位偏移对这个场景足够用

FX3U的V/Z寄存器都是16位,最大能表示32767的正偏移。我们的配方库假设60个配方,每个40字,最大偏移是59×40=2360,远小于32767。所以完全用16位指令处理,不需要考虑32位变址的组合用法。

也有朋友问,万一配方数量扩到很大怎么办?我的建议是,先看D区总量。FX3U的D区一共8000个字,你不可能把整个D区都拿来做配方库,还要留坐标示教缓冲、运动控制数据、通信缓冲等。按常规设备几百个配方已经算很多了,16位偏移妥妥够用。如果哪天真超出范围,再研究V和Z组合成32位偏移的用法,那个属于极端场景,一般项目碰不到。

3. 配方存储区规划:先画好表格,再想怎么写程序

3.1 数据区整体分配方案

写代码之前,先把D区当成一张Excel表来规划。我用的FX3U,分配方案如下:

地址范围用途长度
D0当前配方号(运行中)1字
D100HMI配方号输入框1字
D200-D239当前运行参数区40字
D240-D279配方切换暂存区40字
D300-D339HMI配方编辑区40字
D5000-D7399配方存储区(60个配方×40字)2400字
D7400-D7999备用扩展600字

这些区域各有各的职责。D200区是动作程序唯一读取的参数来源,所有轴走位、电批扭矩都从这一块拿数据。D300区是触摸屏的编辑缓冲区,客户在屏上改配方时,改的是这里。D5000区才是真正的“配方库”,长期保存着所有型号的参数。

这里有一个关键原则:配方存储区的内部结构和D200运行区、D300编辑区完全一致。第0个字是配方编号,第1个字是螺丝数量,第2个字是扭矩上限……每个区的40个字含义一一对应。这样才能实现整行BMOV一键拷贝,不用穿来穿去地对字段。

3.2 单个配方的内部结构设计

单个配方固定占40个字。前7个字是通用参数,中间24个字是8颗螺丝坐标预留,最后9个字留给扩展和校验位。具体如下:

相对偏移参数说明
+0配方编号写入时自动填入,用于校验
+1螺丝数量最大8颗,实际打多少由这个值控制
+2扭矩上限电批扭矩设定值
+3拧紧转速电批转速设定值
+4Z轴快进深度从起始位置快速下降的深度
+5Z轴慢进深度接近工件时切换慢速的深度
+6拧紧等待时间电批启动后的延时判定
+10到+33第1至第8颗螺丝坐标每颗3个字,X/Y/Z脉冲值
+34到+39预留/校验字可存校验和或产品名编码

为什么固定40字而不按实际螺丝数量动态变化?因为固定长度才能用“行号×行宽”直接算偏移。如果每个配方长度不一样,程序就得先扫描一遍找每一行的起点,麻烦得多。把8颗螺丝坐标全部预留出来,是一种“空间换简单”的做法,实际只有4颗的型号空间稍微浪费一点,但程序逻辑大幅简化,非常划算。

3.3 结构一致性原则:工作区、编辑区、存储区完全同构

这个原则我想多说几句。D200、D300、D5000三个区,内部布局必须一模一样。比如D200+10是当前运行的第一颗螺丝X坐标,D300+10就是HMI编辑区的第一颗螺丝X坐标,D5000+10就是配方存储区某个配方的第一颗螺丝X坐标。

这样做的好处是,无论是从存储区搬到运行区,还是从存储区搬到编辑区,都只需要一条BMOV指令,一个字都不用单独处理。很多工程师栽在“只搬参数忘了搬坐标”或者“字段位置记反了”上,根源就是三个区的布局不一致。如果你现在要改配方结构,也记住同步改三个区,千万不要只改其中一个。

4. 配方管理三套核心流程:写库、读库、换型应用

4.1 配方号校验与偏移量计算

配方管理的总入口是D100,这个字由触摸屏输入,代表客户想操作哪个配方号。任何流程开始前,先做范围校验。配方号允许的范围是0到59,同时必须大于等于0。校验结果放在M50里,范围外直接切断后续操作。

校验方式和偏移计算如下:

// 配方号范围校验 LD D100 K59 // 如果 D100 <= 59 AND D100 K0 // 且 D100 >= 0 OUT M50 // M50 = 配方号有效 // 偏移量计算 MUL D100 K40 D10 // D10 = 配方号 × 40 MOV D10 Z0 // Z0 = 偏移量

MUL的结果是32位,低16位存在D10,高16位存在D11。由于最大偏移只有2360,D11永远为0,直接用D10就行。

校验和偏移计算是公用的,写库、读库、换型应用三条流程都从这里起步。这样要改单个配方长度,只需要改K40这一个常数,全程序都跟着变,不用到处找。

4.2 HMI存配方:从编辑区搬到存储区

客户在触摸屏上改好D300-D339的参数后,点“保存到配方库”,HMI置位M100。PLC侧的逻辑是:

// 写入请求入口 LD M100 // HMI请求 AND M50 // 配方号有效 ANI M101 // 忙标志,上次还没完成 ANI M0 // 设备不在运行中才开始写入 SET M101 // 置忙,防止重复触发 // 整行搬送:编辑区 -> 配方存储区 BMOV D300 D5000Z0 K40 // 强制写入配方编号到第一个字,作为数据头校验 MOV D100 D5000Z0 // 写完回读比较,防止写入异常 MOV D5000Z0 D20 CMP D100 D20 M520 // 相等时M520导通 // 结束 RST M100 RST M101 SET M102 // 写入完成标志,HMI可检测

写入完成以后,配方库中对应那一行就是HMI编辑区当时的内容。D5000Z0的Z0还是之前算好的偏移,所以这条BMOV搬送的正好是“配方号×40”对应的存储位置。这个“整行搬送”就是变址寄存器最出彩的地方——一行代码替代了几十行MOV。

4.3 查询与加载:把存储区数据读回编辑区

客户想看看某个配方里参数是什么,或者想基于某个旧配方做新配方,就需要把存储区的数据装载到编辑区。逻辑和写入正好反过来:

LD M110 // HMI“读取配方”请求 AND M50 ANI M101 SET M101 // 校验配方是否已建立 CMP D100 D5000Z0 M520 // 存储区第一个字应等于配方号 ANI M520 PAGE M530 // 不一致则报“配方未建立” // 整行搬送:配方存储区 -> HMI编辑区 BMOV D5000Z0 D300 K40 RST M110 RST M101 SET M112

这个流程里有一个容易被忽略的细节:先做配方号一致性检查。如果某个配方槽从来没写过,D5000Z0那个位置可能是0,而D100是5,CMP必然不相等。这时候不搬数据,直接提示客户“该配方未建立”,避免客户看到一堆零还以为参数本来就没有。

4.4 应用配方:存储区搬到运行区,运行中禁止切换

真正开始生产前的换型动作,是把选中的配方搬到D200运行区。这个流程多了两道保险:

LD M120 // HMI“应用配方”请求 AND M50 ANI M101 ANI M0 // 设备运行中禁止切换 SET M101 // 先搬到暂存区D240,避免直接写运行区 BMOV D5000Z0 D240 K40 // 校验暂存区数据头 MOV D240 D21 CMP D100 D21 M520 // 校验通过后,整行拷贝到运行区 BMOV D240 D200 K40 RST M120 RST M101 SET M122

为什么先搬到D240暂存区,再搬到D200?因为D200是动作程序每时每刻都在读的区域。PLC的正常扫描周期内,BMOV执行完之前动作程序不会读到一半的数据,所以理论上直接搬也没事。但有中断程序、定位模块或高速处理场景时,万一正在读坐标读到一半,数据就乱了。而且,按我个人的习惯,设备安全和数据一致永远不怕多一道保险。暂存区的成本只是一个D区尺寸,换来的是绝对的稳定。

5. BMOV批量搬送与运行时的安全互锁

5.1 用BMOV一次搬40字,配合Z0完成整行拷贝

三菱的BMOV指令,作用是把源地址开始的N个字一次性搬到目标地址开始的N个字。配合变址寄存器Z0,就成了“把第N号配方整行搬走”的利器。

BMOV D5000Z0 D200 K40 // 从第(5000+Z0)个地址开始搬40字到D200 BMOV D300 D5000Z0 K40 // 从D300搬40字到第(5000+Z0)个地址

BMOV源和目标都支持变址,所以同一行的搬运方向相反也只是改一下前后位置。要注意的是,源和目标不能有地址重叠。我们的配方库在D5000以后,运行区和编辑区在D200、D300,完全错开,没有任何重叠风险。如果是其他项目把编辑区和存储区放在相邻位置,就要小心重叠问题,严重的话会导致数据被循环改写。

还有个细节:BMOV传送点数K40,最大不能超过512。配方长度超过512的情况基本不存在,但如果你的配方设计得很长,记得分多段搬送,或者改成循环逐字搬运。

5.2 坐标读取代码:按当前螺丝号动态取坐标

配方数据搬进D200运行区之后,动作程序怎么用这些坐标?这也是变址寄存器的一个典型应用场景。当前正在打第几颗螺丝,这个序号放在D450里,从0开始计数,比如第0颗、第1颗……第7颗。

MUL D450 K3 D451 // 坐标偏移 = 当前螺丝号 × 3 MOV D451 Z1 // 放进另一个变址寄存器 MOV D207Z1 D460 // 取X坐标,D460为目标 MOV D208Z1 D461 // 取Y坐标 MOV D209Z1 D462 // 取Z坐标

D207是D200运行区里坐标数组的起点。Z1等于0时,操作的就是第一颗螺丝的坐标D207、D208、D209;Z1等于3时,操作第二颗螺丝的坐标D210、D211、D212。程序只需要循环增加D450的值,就能逐颗读出所有螺丝坐标,不需要为每一颗螺丝单独写一段定位逻辑。

这里也用上了“结构一致性”——坐标段在单配方内的偏移是+10到+33,到运行区后就是D200+10=D210?不对,前面的表格里我写了坐标段偏移+10,对应D207?让我重新理一下:

当前运行区D200-D239,40个字: D200=配方号 D201=螺丝数量 D202=扭矩上限 D203=转速 D204=快进深度 D205=慢进深度 D206=等待时间 D207-D230=8颗螺丝坐标,每颗3字,共24字 D231-D239=预留

所以坐标起点是D207。上面的代码用D207Z1,Z1=0时取D207,这个起点是对的。之前第3章的表格里我写“+10到+33”,但实际操作里坐标起点是D207对应偏移+7,需要统一一下。

让我修正单配方内部布局,把坐标段往前挪:

D5000单配方40字: +0 配方编号 +1 螺丝数量 +2 扭矩上限 +3 拧紧转速 +4 Z快进深度 +5 Z慢进深度 +6 拧紧等待时间 +7 到 +30 是8颗螺丝坐标(每颗3字,共24字) +31 到 +39 预留

这样D200运行区里,+7对应D207,和前面的代码一致。第3章表格和代码全篇统一。

5.3 换型时保证安全:双缓冲和互锁逻辑

设备运行中切配方,最危险的情况是:第一颗螺丝刚打完,Z轴正在移动,突然D200区坐标被换成另一个产品的坐标,轴就会走错位置,轻则报警,重则撞夹具。所以我在应用配方流程里加了三个互锁条件:

第一,设备处于运行状态时,M120应用请求直接无效。这个判断用的是M0,运行标志位,运行中置位。换型只能在设备停止状态下进行。 第二,写入配方库也要求设备不运行。因为编辑区D300的数据如果正被某条运动指令读取,写入就会产生冲突。 第三,HMI上的“保存”“读取”“应用”三个按钮,在PLC逻辑层互相锁住。一个流程没走完,其他流程不允许启动。这个用M101忙标志统一管理,任何流程进行中,M101为ON,其他请求全部被ANI M101拦掉。

这三条互锁在实际项目里帮了大忙。很多现场事故不是程序算错,是操作员在设备运行时误点了按钮。PLC逻辑层的互锁挡在HMI按钮之前,操作员按了没反应,会去看是不是设备还在运行。哪怕HMI上忘记做灰色效果,PLC层面也兜得住。

6. 断电保持、越界保护与MES远程换配方

6.1 配方区必须设置的断电保持参数

配方数据是设备的长期记忆,一断电就丢的话,客户第二天开机还得重新输参数,这绝对不行。但很多工程师想当然地以为D区的数据天然断电保持,实际上不是。

三菱FX3U的D区保持范围是在PLC参数里配置的,不是所有D区都带电池保持。我习惯在PLC参数里把D5000到D7399这一整段配方存储区设为锁存,让停电后配方仍然存在PLC里。这样客户现场断电重启,只需要选一下配方号按应用,就能恢复生产。

不过也要提醒一点,锁存靠PLC电池,电池没电照样丢。所以我会在设备交付的时候,用HMI的配方导出功能把配方表存一份到电脑或U盘,同时教客户怎么备份恢复。示教完坐标、调好扭矩后,第一时间导一份,后面怎么折腾都不慌。我也建议在程序里加一个配方初始化标志,首次上电检测到配方区全零且标志位没建立,自动从备份区恢复默认配方,防止电池掉电导致设备懵掉。

6.2 越界与数据校验:把异常拦截在写入之前

配方号越界是变址方案最容易出的问题。D100一旦超出配方范围,偏移量也跟着超范围,D5000Z0就会跑到配方库以外,可能读到D7400的备用区甚至更远。那边可能存着其他数据,搬进来以后动作程序拿到一堆乱七八糟的坐标,后果不堪设想。

所以配方号范围校验M50是整个配方管理的第一道闸门。D100小于0或大于59,所有流程全部切断。这道校验在写入、读取、应用三个流程里都要串联,不能只在某一个流程里加。

第二道校验是配方的“头字校验”——每个配方的第一个字强制存配方编号本身。写入时自动覆盖成D100,读取和应用前先CMP比较,不一致就报警提示“配方未建立或数据损坏”。这个设计成本极低,但能拦住两类问题:一是客户在HMI上输错配方号,读出来的数据张冠李戴;二是PLC电池掉电,配方区数据变成乱码,头字校验能第一时间发现。

6.3 MES/上位机通过Modbus远程换配方

配方管理做成这样之后,再往上走就顺理成章了。如果客户要上MES系统,或者产线要集中管理设备配方,只需要在PLC里把配方号D100、应用请求M120、完成反馈M122这些软元件映射到Modbus寄存器或线圈。上位机通过Modbus总线往D100写一个配方号,再把M120置位,设备就自动切换配方了。

这个过程中,上位机完全不需要知道配方数据存在哪个具体地址,也不需要关心偏移量怎么算。它只需要发出“请把5号配方应用下去”这个指令,剩下的偏移计算、数据搬送、校验、互锁,全在PLC程序里完成。变址寄存器在这里起到了封装的作用——把复杂的地址逻辑收敛在PLC内部,对外暴露的只是一个简单的配方号接口。

这套结构后来被我沿用到了其他设备上,点胶机的胶量参数、锁付设备的扭力曲线、多头机的工位偏移,都是同一个套路:固定行宽、配方号乘行宽、变址寄存器做偏移、批量搬送进工作区。

最后说一点实际体会:配方管理这东西,代码写出来不难,难的是结构设计。先把D区表格画清楚,把三个区的结构对齐,再动手写指令,后面基本一遍过。调试的时候,我也习惯在监视表里同时看D100、Z0、D5000Z0三个值,确认它们之间的关系像预期那样联动。这个习惯让我少走了很多弯路,建议你也试试。

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

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

立即咨询