FX3U PLC与绝对值编码器通讯实战:ADPRW与RS2指令详解
1. 绝对值编码器接入FX3U的真实场景与需求拆解绝对值编码器在工业现场用得很多尤其是那些断电后不能丢位置的场合——比如升降机构、旋转刀塔、闸门开度控制。它和普通的增量式编码器最大的区别在于增量式断电后位置就没了每次上电都得回原点绝对值编码器不管断电多久重新上电后读到的还是那个绝对位置值。三菱FX3U本身是个小型PLCCPU自带一个RS-422编程口和一个RS-485通讯口8针圆口。但实际项目里我们很少直接用CPU自带的那个圆口去接编码器原因有两个一是那个口通常要留给触摸屏或者编程用二是它的通讯参数配置灵活性有限。更常见的做法是加一块FX3U-485ADP-MB通讯扩展板或者用FX3U-485ADP配合RS/RS2指令来做。这里先厘清一个容易混淆的点FX3U-485ADP-MB这块板子支持两种工作模式——一种是Modbus RTU主站模式用ADPRW指令直接读写从站寄存器另一种是通用通讯模式用RS/RS2指令收发自定义报文。绝对值编码器如果支持标准Modbus RTU协议那用ADPRW最省事如果编码器是厂家自定义的串口协议很多国产绝对值编码器都是这种那就得用RS2指令自己拼报文。我这次调试的是一台支持Modbus RTU的绝对值编码器型号就不说了反正协议是标准的03功能码读保持寄存器。波特率96008位数据位无校验1位停止位。编码器作为从站站号设为1位置值放在两个连续的保持寄存器里高字在前低字在后组成一个32位有符号整数。注意绝对值编码器的分辨率直接决定了位置值的量程。比如17位单圈编码器一圈就是131072个脉冲如果是多圈编码器还要考虑圈数位数。读回来的32位数据要搞清楚哪几位是圈数、哪几位是单圈角度不然算出来的位置是错的。2. 硬件接线与通讯参数确认别在第一步就翻车2.1 RS-485两线制的接线逻辑FX3U-485ADP-MB的接线端子一般标着SDA、SDB、RDA、RDB、SG、FG。做两线制通讯时把SDA和RDA短接SDB和RDB短接然后SDA接编码器的A或DSDB接编码器的B或D-。SG是信号地如果通讯距离超过几十米建议把SG也接上能明显改善通讯质量。FG是屏蔽层接地接控制柜的接地排。这里有个新手特别容易犯的错把A和B接反了。RS-485的A和B在不同厂家的定义有时候是反的有的厂家标D和D-有的标A和B还有的标TR和TR-。最稳妥的办法是看编码器手册里的接线图确认哪个是正哪个是负。如果接反了通讯完全不通但硬件不会烧只是收不到数据。终端电阻的问题也值得说一句。RS-485总线在通讯速率较高或者距离较远时需要在总线两端各接一个120欧姆的终端电阻。9600这种低速短距离的场合不接也能通但如果现场干扰大或者通讯时断时续加终端电阻往往能解决问题。FX3U-485ADP-MB板子上没有内置终端电阻需要自己在外围电路上加。2.2 通讯参数的匹配编码器侧的参数一般通过拨码开关或者厂家上位机软件设置。需要确认的参数包括波特率、数据位、停止位、校验方式、站号。这些参数必须和PLC侧完全一致任何一个不匹配都通不了。FX3U-485ADP-MB在Modbus RTU主站模式下通讯参数是通过特殊数据寄存器D8400系列来设置的。具体来说寄存器含义我这次用的值D8400通讯格式H0C81D8401站号H0001D8402超时H000AD8403重试次数H0003D8404延迟时间H0000D8400这个值需要拆开看。H0C81对应的二进制是0000 1100 1000 0001。从低位往高位看bit0是数据长度1表示8位bit1-bit2是校验方式00表示无校验bit3是停止位1表示1位停止位bit4-bit7是波特率1000表示9600bpsbit8-bit15是通讯协议相关设置。这个值算错了通讯参数就不对报文发出去编码器也认不出来。实操心得D8400的值我建议用三菱官方手册里的通讯格式表来查不要自己凭感觉拼二进制。我见过有人把校验位设成偶校验结果编码器是无校验调了半天以为是接线问题。3. ADPRW指令的报文逻辑与梯形图实现3.1 ADPRW指令的参数含义ADPRW是三菱FX3U在Modbus RTU主站模式下的专用通讯指令格式是ADPRW S1 S2 S3 S4 DS1从站站号S2功能码03读保持寄存器06写单个寄存器16写多个寄存器等S3从站寄存器起始地址S4读写点数D本地PLC存储起始地址比如我要读站号1的编码器从寄存器地址0开始读2个寄存器存到PLC的D100和D101里指令就是ADPRW H1 H03 H0 H2 D100这条指令执行后PLC会自动拼出Modbus RTU报文站号01 功能码03 起始地址0000 寄存器数量0002 CRC校验然后通过485ADP板发出去。编码器收到后回复站号01 功能码03 字节数04 数据高字 数据低字 CRC。PLC自动解析后把数据存到D100和D101。3.2 梯形图程序的完整结构实际程序里ADPRW不能一直触发否则会连续发报文导致通讯混乱。通常用一个脉冲触发配合完成标志位来判断通讯是否结束。我用的梯形图逻辑是这样的第一段上电初始化。用M8002初始脉冲把通讯参数写入D8400到D8404同时把M8411置位表示使用485ADP-MB的Modbus模式。第二段定时触发。用T0做一个1秒的定时器T0常开触点触发ADPRW指令。ADPRW执行完成后M8029指令完成标志会导通一个扫描周期用这个信号复位定时器形成循环。第三段数据处理。D100和D101组成32位数据用DMOV指令把D100和D101传送到D200和D201然后根据编码器的分辨率做换算。比如17位单圈编码器一圈131072脉冲那实际角度就是(D200/131072)*360度。第四段错误处理。M8260到M8269是通讯错误标志位如果ADPRW执行出错对应的错误标志会置位。我在程序里加了判断如果连续3次通讯失败就输出一个报警信号到Y0提示操作人员检查接线。注意ADPRW指令的S3参数是Modbus寄存器地址不是PLC的D寄存器地址。有些编码器手册上写的寄存器地址是从1开始的比如40001而Modbus协议里是从0开始的需要减1。这个细节不注意读回来的数据就是错的或者直接通讯异常。3.3 32位数据的拼接与符号处理绝对值编码器返回的位置值通常是32位有符号整数。D100存高16位D101存低16位。拼接的时候要注意字节顺序和字顺序。三菱PLC里用DMOV D100 D200就是把D100和D101组成32位数据存到D200和D201。但这里有个坑Modbus RTU报文里的数据是高字在前、低字在后而三菱PLC的DMOV指令是D100为高字、D101为低字。如果编码器手册写的是低字在前那就得手动交换。符号处理也很关键。32位有符号整数的最高位是符号位如果编码器返回的是负数比如位置在零点以下直接当无符号数处理就会得到一个巨大的正数。我一般用D200和D201做比较判断或者直接用32位比较指令来处理。4. RS2指令自定义报文当编码器不走标准Modbus时4.1 RS2指令的收发机制有些绝对值编码器用的是厂家自定义的串口协议比如发一串特定的命令码编码器回一串固定格式的数据。这种场合就得用RS2指令。RS2指令的格式是RS2 S1 S2 S3 D1 D2S1发送数据的起始软元件S2发送字节数S3接收数据的起始软元件D1接收字节数D2执行标志比如我要发8个字节的命令存在D300到D303里接收10个字节存到D400到D404里指令就是RS2 D300 K8 D400 K10 M100M100导通时PLC通过485ADP板把D300开始的8个字节发出去然后等待接收。接收完成后M100自动复位接收到的数据存在D400开始的区域。4.2 自定义报文的拼装与校验自定义协议最麻烦的地方是校验。常见的校验方式有和校验、CRC校验、异或校验。和校验最简单把前面所有字节加起来取低8位就行。CRC校验复杂一些但Modbus RTU用的就是CRC16。如果编码器用的是CRC16校验PLC里没有现成的CRC指令得自己写一段程序来算。我一般用查表法或者逐位计算法。逐位计算法的逻辑是CRC初始值FFFF每个字节和CRC异或后循环右移8次每次如果移出的位是1就和多项式A001异或。这段程序写起来大概二十几步但算一次CRC大概需要几十毫秒对于9600波特率来说完全够用。实操心得自定义协议的编码器厂家一般会提供通讯协议文档里面会写清楚命令格式、返回格式、校验方式。如果没有文档可以用串口助手先抓一下编码器上电后主动发出的数据或者用厂家调试软件发一条命令用串口助手监听把报文抓下来分析。4.3 RS2与ADPRW的选型对比对比项ADPRWModbus RTURS2自定义协议适用场景编码器支持标准Modbus RTU编码器用厂家私有协议编程复杂度低一条指令搞定高需要自己拼报文和校验灵活性受Modbus协议限制完全自由想发什么发什么调试难度低报文格式固定高需要抓包分析通讯效率中等有协议开销高可以精简报文我个人的建议是如果编码器支持Modbus RTU优先用ADPRW省时省力。如果编码器只支持自定义协议那就老老实实用RS2把协议文档吃透先用串口助手在电脑上把报文调通再移植到PLC里。5. 调试过程中最容易卡住的几个环节5.1 通讯完全不通的排查顺序第一步确认接线。用万用表量一下A和B之间的电压静态时应该有几百毫伏的压差。如果电压是0说明接线断了或者编码器没上电。第二步确认参数。波特率、数据位、停止位、校验、站号这五个参数必须和编码器完全一致。我习惯用串口助手先在电脑上试电脑能通再换PLC这样能排除一半的问题。第三步确认指令。ADPRW的站号、功能码、寄存器地址、点数这四个参数任何一个错了都通不了。特别是寄存器地址有的编码器手册写的是十进制有的是十六进制要看清。第四步看错误标志。M8260到M8269会给出具体的错误代码比如M8260是超时错误M8261是校验错误M8262是站号错误。根据错误代码能快速定位问题。5.2 数据读回来但不对的情况通讯通了但数据不对通常有几种可能寄存器地址偏移。Modbus协议里寄存器地址从0开始但有些编码器手册从1开始需要减1。数据类型理解错误。编码器返回的是32位有符号数但程序里当16位处理了。字节顺序问题。高字和低字的位置搞反了。分辨率换算错误。编码器的实际分辨率和手册写的不一致或者多圈编码器的圈数位数没算对。我遇到过一次编码器手册写的是17位单圈但实际读回来的数据范围是0到65535明显是16位。后来查了半天发现是编码器的一个拨码开关设置错了把多圈功能关了变成了16位单圈。这种硬件配置问题光看程序是查不出来的。5.3 通讯不稳定的干扰问题RS-485通讯在工业现场受干扰是常态。如果发现通讯时断时续数据偶尔出错可以从以下几个方面改善加终端电阻。总线两端各接一个120欧姆电阻。屏蔽层接地。编码器电缆的屏蔽层接控制柜接地排但不要两端都接避免地环路。远离干扰源。编码器电缆不要和变频器输出线、伺服电机动力线走同一个线槽。降低波特率。9600不行就降到4800通讯速率越低抗干扰能力越强。增加重试次数。D8403里设置重试次数通讯失败时自动重发。注意如果现场有多台变频器或者伺服驱动器RS-485通讯受到干扰的概率会明显增加。这种情况下除了做好屏蔽和接地还可以考虑在通讯线上加磁环或者用带隔离的485中继器。6. 从单台编码器到多站轮询的扩展思路6.1 多站轮询的程序框架实际项目里往往不止一台编码器可能有好几台挂在同一条485总线上。这时候就需要轮询——依次和每个站通讯而不是同时发指令。轮询的程序框架大概是这样的用一个寄存器记录当前要通讯的站号ADPRW执行完成后站号加1如果超过最大站号就回到1。每个站的通讯结果存到不同的D寄存器区域互不干扰。轮询的间隔时间要算好。9600波特率下一条ADPRW报文大概10个字节加上编码器回复的报文一来一回大概20到30毫秒。如果挂8台编码器一轮轮询下来大概200到300毫秒。这个刷新周期对于大多数位置检测应用是够用的但如果要求更高的实时性就得提高波特率或者减少站数。6.2 轮询中的超时处理轮询最怕的是某一台站坏了或者掉线了导致整个轮询卡死。所以每台站的通讯都要有超时判断。ADPRW指令本身有超时设置D8402但轮询程序里最好再加一层逻辑如果某台站连续几次通讯失败就跳过它继续轮询下一台同时输出一个报警提示。我一般用计数器来实现每台站对应一个失败计数器通讯成功清零通讯失败加1加到3就跳过。这样即使某台编码器临时出问题也不会影响其他站的正常通讯。6.3 数据缓存与上位机交互多站轮询读回来的数据通常要传给触摸屏或者上位机。我习惯把每台编码器的位置值存到连续的D寄存器区域比如第一台存D500和D501第二台存D502和D503以此类推。触摸屏直接读这些寄存器就行不需要关心底层的通讯细节。如果上位机是组态软件或者SCADA系统可以通过FX3U的以太网模块或者串口模块把数据转发出去。转发的时候要注意数据格式的统一比如都转成32位有符号整数或者都转成浮点数避免上位机解析出错。7. 几个容易被忽略的细节与个人经验7.1 编码器上电后的初始化时间绝对值编码器上电后需要一定的初始化时间通常是几百毫秒到几秒不等。如果PLC上电后立刻开始发通讯指令编码器可能还没准备好导致前几次通讯失败。我的做法是在程序里加一个上电延时比如用T0做一个3秒的延时延时到了再开始轮询。7.2 485ADP-MB的站号设置FX3U-485ADP-MB作为Modbus主站时本身也有一个站号通过D8401设置。这个站号是主站自己的标识和从站编码器的站号是两回事。有些新手会混淆这两个概念把D8401设成编码器的站号结果通讯异常。D8401设成0或者1都行只要不和从站冲突就可以。7.3 通讯电缆的选择RS-485通讯建议用双绞屏蔽线线径0.5平方毫米以上。双绞的作用是抵消差分信号上的共模干扰屏蔽层的作用是阻挡外部电磁干扰。我见过有人用普通的平行线做485通讯短距离低速还能凑合一旦距离超过20米或者波特率提高到19200以上通讯就很不稳定。7.4 程序注释和文档记录最后说一个不是技术但很重要的点程序注释。ADPRW指令的S3参数是寄存器地址过几个月回头看根本记不住这个地址对应编码器的哪个参数。我习惯在程序里把每个ADPRW指令的站号、功能码、寄存器地址、数据含义都注释清楚这样以后维护或者换人接手能省很多时间。同样编码器的通讯协议文档、接线图、参数设置最好整理成一个文档存档。现场调试的时候可能觉得都记住了但过半年再回来改程序没有文档就得重新翻手册。实操心得我一般会在PLC程序里留一个调试模式用一个M位控制。调试模式下ADPRW的触发周期缩短到200毫秒方便快速观察数据变化正常模式下触发周期是1秒减少总线负载。这个技巧在多站轮询的时候特别有用调试阶段能快速定位是哪台站出了问题。