简介:面向工业自动化现场调试与PLC编程人员的一份技术文档,围绕西门子S7-1500(CPU1511-1 PN)对巴鲁夫RFID系统的读写控制展开,适合需要实现流水线托盘与工件信息追踪的工程师及中高级学习者参考。文档以单个docx文件打包,压缩包约708KB,编排完整:先说明适用场合与巴鲁夫分析单元、读写头、数据载体的硬件构成,再给出在博图V15下导入GSD文件完成硬件组态、调用FB31示例块、规划读写DB块的具体做法,随后以初始化、复位、读取、写入、数据转移等程序段配合MOVE、FILL指令逐项讲解,并附项目通用性总结。已有1859人学习下载,可作为搭建RFID工位、排查读写异常的实操参照。
1. 托盘到位却读不出码:这套方案的适用边界
某条装配线的托盘在工位停稳,读写头橙色工作灯闪了两下,PLC 里的读完成位却没置起来,操作工只能手动补录工件号。这类现场问题,八成不是 RFID 硬件坏了,而是 PLC 侧的控制字、数据长度或者设备名没对齐。西门子 1500 加巴鲁夫 RFID 的组合在工件追溯、托盘记忆、工序防错里很常见:分析单元最多挂 4 个读写头,读写头对着随工件移动的载码体读写,CPU1511-1 PN 通过 PROFINET 交换过程数据,博图 V15 负责组态和编程。这套资源给的是从 GSD 组态、FB31 调用到读写动作的完整链路,适合做产线追溯的电气和自动化工程师,也适合刚接手 RFID 工位、手里只有一份示例程序的人。下面按组态、程序、数据搬运、排错的顺序拆开讲,能照着复现。
2. 一套 RFID 到底由什么组成:分析单元、读写头、载码体的信号链
2.1 三件套分工与选型边界
巴鲁夫这套 RFID 拆开看是三件东西:分析单元、数据读写头、数据载体。分析单元是大脑,负责射频信号的调制解调、协议处理、多通道切换,再往上通过 PROFINET 把过程数据交给 PLC,它本身不带天线,也不直接对载码体说话;读写头是天线加前端,装在工位支架上,对着托盘上的载码体发场、收数据,正常工作时绿色电源灯常亮、橙色工作灯在读写瞬间闪烁;载码体是无源存储介质,从读写头的电磁场里取电,跟着工件或托盘跑,容量从几十字节到几千字节都有。
选型上最容易被忽略的是读写头的作用距离和载码体容量这两条边界。读写头的作用距离不是越大越好,托盘定位有重复精度问题,读写头选得距离太远,相邻工位的读写头容易互相干扰;选得太近,托盘稍微歪一点就读不到。常见做法是按托盘定位精度留一倍余量,把读写头有效距离压在托盘实际偏移范围的两倍以上。载码体容量则决定了你一次能搬多少数据:工件号、工序号、时间戳、质量标记加起来一旦超过载码体容量,写入就会报长度错误,所以程序里必须有一个长度校验,而不是等现场写失败才回头查。
分析单元的通道数是第二个边界。一个分析单元最多接 4 个读写头,意味着 4 个工位可以共用一台分析单元,省一路 PROFINET 节点和交换机端口,但也意味着这 4 个工位共用同一套过程数据区,通道号选错就会读到隔壁工位的数据。程序里对读写头通道号做常量约束,比在现场靠人记要可靠得多。
2.2 1500 侧的数据通道:命令区和状态区
PLC 并不直接“读卡”,它做的是往分析单元的输出区写命令、从输入区取状态和数据。分析单元在 PROFINET 上表现为一个从站设备,每个读写头通道在过程映像里占一段固定长度的输出字节和输入字节。输出区一般包含命令字、通道选择、数据长度、参数区和数据缓冲区;输入区包含状态字、错误码、当前数据长度和读回的数据缓冲区。
这个结构决定了三件事。第一,读写动作是一次“下发命令再等握手”的过程,不是调一个函数立刻返回结果,程序里必须有触发沿、忙等待、完成位和错误位。第二,数据长度是显式传的,你写了多少字节、读了多少字节,分析单元不会帮你猜,长度和载码体容量、数据区大小三者必须一致。第三,命令区是电平保持的,命令字写进去之后要等完成位回来才能改,中途改命令字等于让分析单元执行到一半切换任务,现场表现为偶发读错或者报通信错误。
提示:不同固件版本的分析单元,过程数据区里各字段的偏移和长度会有差异,一切以导入的 GSDML 文件生成的 I/O 地址和随示例程序附带的接口说明为准,不要照抄别处的偏移量。
理解了这条信号链,后面组态和编程就都是围绕“把命令区写对、把状态区读对”这一件事展开的。很多现场翻车不是逻辑写错,而是把命令区和状态区的对应关系搞混了。
3. 博图 V15 组态:GSD 导入、设备名分配与 I/O 地址落地
3.1 GSDML 导入与设备添加
巴鲁夫分析单元的 GSD 文件是 XML 格式的 GSDML,博图不能直接双击打开,要走“选项 → 管理通用站描述文件(GSD)”的路径安装,选文件所在目录,勾选后安装,装完在硬件目录的“其他现场设备 → PROFINET IO”下面才会出现对应设备条目。这一步翻车的典型表现是:文件明明在桌面上,博图里就是找不到,因为安装时选的是文件而不是目录,或者文件被解压工具改了扩展名。
装好之后在网络视图里添加设备,把它拖到 PROFINET IO 系统上,和 CPU1511-1 PN 连到同一网段。添加时会让你选设备型号和固件版本,这里必须和现场硬件铭牌上的订货号、固件版本对上,选错版本最常见的后果是过程数据区长度不一致,程序里按 16 字节写的命令,实际只映射了 8 字节,多出来的部分直接被丢弃。
设备添加完成后,硬件目录里会给出一组模块化的子模块,对应每个读写头通道。你需要按现场实际接了哪几个读写头,把对应通道的子模块拖进插槽,没接的通道不要拖。这一步直接决定 I/O 地址的分配:拖了几个通道,就有几组输入/输出起始地址,程序里所有的读写都基于这组地址展开。
3.2 设备名、IP 与 I/O 地址
PROFINET 认设备名不认 IP,这是新手最容易栽的地方。组态里给分析单元设好 IP 和 PROFINET 设备名之后,还必须在线用“分配设备名”把名字写进分析单元本身,否则 PLC 启动时找不到设备,诊断缓冲区里会出现设备名无法解析类的报错,常见代码形如 0x805A。IP 地址反而可以后分配,设备名不对,IP 设得再对也没用。
I/O 地址建议在组态阶段就规划成连续、可读的区段,并在符号表里给每个通道的输入区、输出区起符号名,例如RFID_CH1_I、RFID_CH1_Q。这样做的好处是程序里可以直接用符号访问,而不是靠绝对地址%I68.0这种数字去对,后期换通道或者加通道时改一处符号就行。地址规划还要留出对齐余量,别让两个通道的数据区在字节边界上交叉。
组态完成后编译,检查一遍设备视图里的 I/O 地址表,把每个通道的输入起始地址、输出起始地址、数据长度记在一张纸上,贴到电柜门内侧。这个习惯看着土,现场调试时能省掉大量“到底哪个地址是命令字”的来回确认。
3.3 下载与在线诊断
下载分两步:先编译硬件组态并下载到 PLC,再给分析单元分配设备名。分配设备名要在“在线访问”里选中有线网卡,扫描到分析单元后写入名字,写完之后把分析单元断电重启一次,让它带着新名字重新入网。重启后看 PLC 的诊断缓冲区,正常应该没有设备相关的报错,分析单元的 PROFINET 状态灯从闪烁转为常亮。
在线诊断阶段最值得看的是两处:一是设备视图里分析单元的模块状态,哪个通道报错一目了然;二是 PLC 的诊断缓冲区,通信类错误、模块缺失、数据长度不匹配都会在这里留记录。有些现场问题表现为“程序逻辑没错但就是读不到”,诊断缓冲区里其实已经写着通道未就绪,只是没人去看。养成下载后先扫一遍诊断缓冲区的习惯,比事后拿万用表量线要快。
注意:给分析单元分配设备名之后,如果又回组态里改了设备名,必须重新在线分配一次。组态里的名字和硬件里的名字不一致,PLC 启动就会挂起等待设备,表现为 CPU 的 BF 灯闪烁、程序不进入正常运行。
4. FB31 程序框架:控制字、DB 块与读写握手
4.1 FC 调用结构与 DB 块划分
示例程序里给的是一个编号 FB31 的 FB 块,内部封装了与分析单元的握手逻辑:接收命令、判断忙闲、输出完成位和错误位。实际项目里不建议在 OB1 里到处直接调 FB31,而是新建一个 FC 块作为包装层,在 FC 里调用 FB31 并给它配背景 DB。包装层的好处是把“命令码怎么填、通道号怎么选、数据指针怎么传”这些细节收在一处,上层程序只管调用和看结果。
DB 块至少要分四类:读取数据 DB、写入数据 DB、与控制层交互的读写命令 DB、以及给触摸屏用的显示 DB。读取数据 DB 存放从载码体读回来的原始字节和解析后的工件信息,写入数据 DB 存放准备写进载码体的内容,命令 DB 存放触发位、命令码、通道号、长度这些控制量,显示 DB 是给 HMI 看的镜像,避免 HMI 直接读写过程数据区造成地址冲突。
划分 DB 的时候有个原则:过程数据区是“生数据”,用户 DB 是“熟数据”。程序负责在两者之间搬运和转换,HMI 只碰熟数据。这样即使后面换了读写头型号、过程数据长度变了,也只需要改搬运那一段,HMI 画面不用动。
4.2 初始化、复位、读、写、开始五段逻辑
示例程序里有五段逻辑,对应五个动作:初始化、复位、读取、写入、开始。初始化在 PLC 启动或者工位使能时执行一次,把分析单元的命令区和参数区置到已知状态,避免上一次掉电前的残留命令被误执行;复位用于清掉分析单元的报错状态和读写状态位,一般在报警复位按钮上挂一次沿触发;读取是把读命令码通过 MOVE 指令送进命令字寄存器,再触发一次执行;写入同理,只是命令码不同、数据源指向写 DB;开始程序是在命令字写入之后真正让分析单元动作的那一步,也就是触发位的上升沿。
这五段逻辑的公共点是“一次性动作”,都必须用沿触发,不能用电平保持。用常 1 信号去触发读命令,分析单元会把它理解成连续读请求,总线负载上来之后表现为周期抖动,严重时读完成位一直不回来。程序里给每个动作配一个R_TRIG,是这套逻辑最省事的写法。
// FC "RFID_Call":包一层,隔离示例块接口差异 FUNCTION "RFID_Call" : Void VAR_INPUT iCmd : Int; // 命令码:取示例程序常量表,勿自造数值 iHead : Int; // 读写头通道号,1~4,对应组态里拖入的子模块 iLen : Int; // 本次读/写字节数,必须与实际数据区长度一致 iTrig : Bool; // 上升沿触发一次读写 iDataQ : Int; // 数据区在输出映像中的起始字节偏移 END_VAR VAR_OUTPUT oDone : Bool; // 分析单元回报动作完成 oBusy : Bool; // 握手进行中,此时禁止改命令码 oError : Bool; oStatus : Word; // 错误码,查手册而非猜 END_VAR VAR statTrig : R_TRIG; // 上升沿检测,防止常 1 重复下发 statFB : "FB31_DB"; END_VAR BEGIN statTrig(CLK := #iTrig); // 只在上升沿且通道号合法时下发,忙时直接返回 IF #statTrig.Q AND (#iHead >= 1) AND (#iHead <= 4) AND NOT #oBusy THEN #statFB.REQ := TRUE; #statFB.CMD := #iCmd; #statFB.HEAD := #iHead; #statFB.LEN := #iLen; #statFB.OFFSET := #iDataQ; ELSE #statFB.REQ := FALSE; // 单次请求,靠 REQ 的沿推进握手 END_IF; #statFB(); #oDone := #statFB.DONE; #oBusy := #statFB.BUSY; #oError := #statFB.ERROR; #oStatus := #statFB.STATUS; END_FUNCTION这段代码的关键点不在语法,而在三处约束:iCmd必须取示例程序里定义的常量,自己拍一个数值分析单元不认;iLen必须和载码体容量、DB 数组长度三者对齐;statFB.REQ用R_TRIG的输出驱动,保证一次触发只下发一次。OFFSET这类偏移参数在不同固件里名字可能不同,以随包接口说明为准,包装层的意义就是把这些差异挡住,上层不用改。
4.3 数据搬运:MOVE、FILL_BLK 与长度对齐
读回来的数据在过程映像的输入区里,是一串字节,要搬到读取 DB 里才能解析。写入方向反过来,先把写 DB 里的内容按长度填进输出区的数据缓冲区,再下发写命令。MOVE 指令负责小数据块的搬运,比如把控制字送进命令寄存器、把长度值送进长度寄存器;FILL_BLK(LAD 里叫 FILL,填充块)负责把一段数据整体复制填充到目标区。
// 1) 下发读命令:控制字与长度分别送命令区 MOVE(IN := 16#0001, OUT1 => "RFID_CH1_Q".Cmd); // 命令码取示例常量 MOVE(IN := 32, OUT1 => "RFID_CH1_Q".Len); // 本次读 32 字节 // 2) 读回后按长度搬运到用户 DB,避免整块覆盖 FOR #i := 0 TO "Cfg".DataLen - 1 DO "ReadDB".Raw[#i] := "RFID_CH1_I".Data[#i]; END_FOR; // 3) 写入前把发送区按实际长度填满,多余部分清零 FILL_BLK(IN := 0, COUNT := "Cfg".DataLen, OUT => "WriteDB".SendBuf);第一段是把命令码和长度写进输出区,注意长度值要和后面实际搬运的字节数一致,写 32 读 16 是最常见的长度错位。第二段用循环按配置长度搬运,循环上限用变量而不是写死数字,换载码体容量时只改配置。第三段用 FILL_BLK 把发送区按长度清零,避免上一轮的残留数据被当成有效内容写进载码体。填充长度如果大于 DB 实际数组长度,编译可能过、运行会越界,现场表现为相邻数据被莫名改写,这类问题查起来非常费时间,所以长度参数一定要来自同一个配置源。
5. 避坑与排查:现场翻车的五件事
5.1 设备名没写进硬件,PLC 启动挂起
现象:CPU 的 BF 灯闪,诊断缓冲区报设备名无法解析,程序停在启动阶段不进入运行。
原因:组态里设了 PROFINET 设备名,但没有在线把名字分配进分析单元,或者分配之后又改组态里的名字,两边对不上。
解决:在线访问里扫描到分析单元,重新分配一次设备名,断电重启分析单元,再回 PLC 看诊断缓冲区确认设备已就绪。改过组态就一定重分配,这条没有例外。
5.2 优化块访问配绝对地址指针
现象:程序下载后读写偶尔成功、偶尔读到一片零,或者写进去的数据错位。
原因:数据 DB 保持了默认的“优化的块访问”,块内变量没有固定绝对地址,而程序里用绝对地址或指针去访问这块数据,实际指向的偏移和预期不一致。
解决:把参与过程数据搬运的 DB 属性改成“标准(允许绝对访问)”,或者全程改用符号寻址,不混用两种方式。新建 DB 时就把属性定下来,比事后改省事。
5.3 触发位常 1,命令反复下发
现象:读写看上去能用,但总线周期抖动,完成位时有时无,分析单元日志里出现大量重复请求。
原因:触发信号用了常 1 电平或者自锁位,没有做上升沿检测,分析单元被连续请求淹没。
解决:每个动作前加R_TRIG,只在沿上置一次请求位;请求发出后检查BUSY,忙时不允许改命令码和长度。
5.4 填充长度和 DB 实际长度不一致
现象:写入后载码体里出现尾部乱码,或者读回的数据比预期短。
原因:FILL_BLK 的COUNT写的是一个数,DB 数组长度是另一个数,两者不一致;或者载码体容量小于写入长度。
解决:把长度做成一个全局配置常量,FILL、循环搬运、命令长度三处共用;初始化时先做一次长度合法性判断,超限直接报错,不下发命令。
5.5 多读写头通道号错位与字节序问题
现象:A 工位读到的是 B 工位托盘的数据;或者写入的数值读回来高低字节颠倒。
原因:分析单元挂多个读写头时,程序里通道号与实际接线通道不一致;数据跨字节时大小端处理没统一。
解决:通道号在程序里做常量约束并在 HMI 上只读显示,接线变更时同步改常量;字节序在搬运层统一处理,读回和写入各做一次转换,别在业务逻辑里零散地转。
6. 把单工位程序改成可复用模板:UDT + 状态机 + 回环验证
单工位跑通之后,下一步通常是复制到多个工位。直接复制 FC 和 DB 会得到一个越改越乱的项目,我的做法是先定义一个 UDT,把“通道号、命令码、长度、数据区指针、完成位、错误码”打包,再用一个数组按工位下标访问,这样加一个工位只是数组长度加一。
TYPE "UDT_RfidStation" STRUCT Head : Int; // 通道号 1~4,与组态子模块一一对应 Cmd : Int; // 当前命令码 Len : Int; // 数据长度,统一取自配置 Data : Array[0..63] of Byte; // 用户数据区,长度不小于 Len Done : Bool; Busy : Bool; Error : Bool; Status : Word; END_STRUCT END_TYPE控制逻辑从“五段散着写”收敛成一个状态机:空闲 → 下发 → 等待 → 完成/错误 → 空闲。状态迁移只在触发沿和握手位变化时发生,任何时刻只有一个状态在动作,排查时看一眼状态号就知道卡在哪一步。验证方法不靠肉眼盯托盘,而是做回环:往载码体写一组递增的测试数据,读回来逐字节比对,连续跑 200 次统计失败次数;再故意拔掉一个读写头,确认错误码能在 3 秒内上报而不是一直忙等。
| 状态 | 进入条件 | 动作 | 退出条件 |
|---|---|---|---|
| 空闲 | 上电或完成 | 清请求位 | 触发沿到来 |
| 下发 | 空闲 + 触发 | 写命令码、长度、通道号 | 请求位已置位 |
| 等待 | 下发完成 | 保持命令区不变 | Done 或 Error 回位 |
| 完成 | Done | 搬运数据、置完成标志 | 标志被上层取走 |
| 错误 | Error | 记录 Status、置报警 | 复位沿到来 |
这套模板落地时,长度配置、通道号常量、字节序转换三样东西必须集中在一处,散在程序里迟早会出问题。有次我在一个六工位项目上图省事,把长度直接写死在每个工位的调用里,后来换了容量小一档的载码体,只改了其中四个工位,剩下两个工位照常下发超长写命令,现场表现为偶发写入失败,查了大半天才定位到两个写死的数字。从那以后我每次做 RFID 项目,都强制走一遍“配置集中 + 回环测试 + 拔线验证”三件套,宁可前期多花半天,也不想在产线爬高拆支架。希望帮到你。
本文还有配套的精品资源,点击获取