S7-200 SMART与高压仪表Modbus RTU通讯方案与调试实践
前一阵做的一个改造项目要把现场几台高压仪表的电压、电流、温度数据汇总到一台西门子200smart里再通过触摸屏显示并上送监控系统。设备已经跑了一段时间程序在机器上稳定运行。今天把从仪表选型、RS485接线、Modbus RTU通讯程序到现场调试踩坑的完整过程整理出来给后面再碰200smart和高压仪表通讯的朋友一个可以直接上手的参考。1. 先说清楚这个项目到底在干什么协议为什么是Modbus RTU1.1 高压仪表通讯的现场痛点高压柜里的多功能电力仪表、微机保护装置、温控仪本身都是独立的测量设备。它们把电压互感器、电流互感器的模拟量转成数字量在本地显示没问题但要把这些数据给到PLC绕不开通讯。很多第一次做这类项目的朋友容易一上来就琢磨“用自由口协议自己写帧”。我的建议是先翻仪表手册看它支不支持Modbus RTU。绝大多数高压智能仪表出厂协议就是Modbus RTU从站地址、寄存器地址都在手册里写得清清楚楚。你自己用自由口写一套报文解析不是不行但没有必要纯属给自己找麻烦。另一个选择是4-20mA硬接线把电压、电流变送成模拟量给PLC模拟量模块。这种方式在点数少的时候勉强能用但高压柜里的仪表通常有一堆数据三相电流、三相电压、有功、无功、频率、温度全部变送过去线缆成本和通道数会直接把你逼疯。RS485一根双绞线把所有数据带回来这才是主流做法。1.2 为什么用S7-200 SMART做主站这个项目本来就不大不需要上300/400级别的PLC。200 SMART自带一个RS485口1.1版本以上CPU还支持网口程序下载和后续接触摸屏都方便。它的指令库里带了Modbus Master功能块调用MBUS_CTRL和MBUS_MSG这两个指令就能完成主站功能不需要自己处理CRC校验和报文组帧开发工作量小很多。还有一个优势是它的库指令把Modbus RTU主站封装得比较成熟。你只需要告诉它从站地址、功能码对应的地址范围、寄存器数量、数据存放的V区地址剩下的事情库自己去处理。200 SMART的CPU还支持通过信号板扩展第二个串口如果以后要同时接触摸屏和多个仪表也不会捉襟见肘。关键要理解一点在Modbus这条总线上PLC是主站高压仪表是从站。主站主动发请求从站响应。所以通讯不上先别急着怀疑仪表先看主站侧程序有没有把请求发出去这是后面排查的主线。2. 硬件接线和仪表参数设置这步错了程序写得再好都没用2.1 RS485接线屏蔽双绞线、终端电阻和共地问题原理上RS485是差分信号A、B两根线A接仪表A()B接仪表B(-)。看起来简单但现场90%的通讯不稳定都出在这根线上。第一线缆必须用屏蔽双绞线。普通平行线缆抗干扰能力很差尤其是高压柜附近电磁环境非常恶劣一次合闸、接触器吸合产生的骚扰足以让通讯瞬间中断。建议用截面积0.5-1.0平方毫米的屏蔽双绞线屏蔽层单端接地接到柜体接地排上。单端接地是为了避免形成地环路这点很多资料会提但现场经常有人把屏蔽层两端都接了反而引入更多干扰。第二极性不能接反。接反的直接表现是仪表完全无响应或者偶尔能连上但数据经常报CRC错误。如果你的USB转485调试工具能读到仪表PLC读不到第一件事就检查A/B有没有对调。第三终端电阻问题。按规范RS485总线两端各要接一个120Ω终端电阻。距离短、从站少的时候不加也能跑但一遇到干扰就容易偶发超时。高压柜项目里仪表数量一般不多距离也就是柜间走线我的习惯是靠近PLC这一端接一个120Ω电阻最远端的仪表端子旁再接一个。如果仪表内部已经带拨码开关可以接入终端电阻那就直接用仪表上的。第四共地问题。光靠A/B两根差分线并不等于两台设备之间有共同参考点。有些仪表在高压强干扰场合会出现无故通讯中断排查半天最后发现PLC侧和仪表侧的485参考地电位不一致。解决办法是给PLC的RS485口的0V或信号地和总线上某一台仪表的信号地连一根等电位线。但要注意这必须建立在两边都没有强干扰地环路的前提下不能盲目乱接。2.2 把仪表侧通讯参数调成和PLC完全一致很多新手程序写了半天读不到数据不是程序问题是仪表自身的从站地址、波特率、数据格式没配对。Modbus RS485通讯参数必须完全一致波特率、数据位、停止位、校验位、从站地址一个不对都会失败。本项目用的几台高压仪表默认参数是9600, 8, 1, 无校验从站地址分别是1、2、3。这个比较典型。有些仪表出厂地址是1如果两台都是1总线上就会冲突表现为两台表都时好时坏。所以上电前先用仪表面板或设置软件确认每台表地址唯一。数据格式方面需要注意仪表手册里的“字节顺序”说明。有的仪表寄存器存的是整数有的存的是IEEE754浮点数浮点又分高字在前、低字在前。这个差异直接影响你PLC侧数据转换后面专门讲。3. PLC端通讯程序的完整思路核心就两个指令3.1 MBUS_CTRL初始化主站保持每个扫描周期都执行在Micro/WIN SMART软件里从指令树的“库”里找到Modbus Master调用两个指令MBUS_CTRL和MBUS_MSG。MBUS_CTRL负责把RS485口设置成Modbus主站模式。它的参数不多Mode填1表示主站模式Baud填9600Parity填0表示无校验如果仪表是偶校验则填2Timeout是超时时间单位毫秒一般设500。Done和Error分别给一个位和一个字节用来显示初始化是否成功。有一点要特别注意MBUS_CTRL的使能端要一直有效每个扫描周期都执行不能只在首次扫描时执行一次。否则Modbus主站模式可能被复位后面MSG全部失效。我最开始做的时候用SM0.0常开触点让这个指令全程跑几乎没有再出过主站模式丢失的问题。还有一种情况如果你用了扩展信号板做第二个串口那需要调用针对该端口版本的Modbus库。不同库存储区要分开分配这里的坑后面单独说。3.2 MBUS_MSG单次读写与多表轮询逻辑MBUS_MSG是真正干活的功能块每次执行完成一次读或写操作。参数逻辑很清晰First是新请求启动位每发起一个新请求时给一个脉冲Slave是从站地址可以填常数也可以填VW变量RW是读或写0读1写Addr是要操作的寄存器地址Count是寄存器个数DataPtr是数据在PLC侧存放的起始V区地址。但有一个限制MBUS_MSG一次只能针对一个从站发起一个请求同一时刻只能有一个请求在进行。所以如果现场有3台高压仪表你必须用轮询的方式一台接一台地读。轮询思路可以概括成一个状态机初始化一个轮询指针比如VW100指针为0时触发1号表的读请求等1号表的Done置1后把指针改为1触发2号表的读请求再等2号表Done置1触发3号表3号表完成后指针清零开始下一轮。具体程序可以做成分支式当VW100等于0且上次1号表请求Done为0时触发MBUS_MSGSlave填1DataPtr填VB2000读完后DONE上升沿把VW100改成1。当VW100等于1且上次2号表请求Done为0时触发MBUS_MSGSlave填2DataPtr填VB2016读完后DONE上升沿把VW100改成2。当VW100等于2且上次3号表请求Done为0时触发MBUS_MSGSlave填3DataPtr填VB2032读完后DONE上升沿把VW100改成0。这样每台表的数据存放在独立的V区互不干扰方便触摸屏读取。如果仪表数量更多可以用间接寻址把Slave和DataPtr都做成变量用循环逻辑驱动但数量少时分支式最直观、最好调试。每个MBUS_MSG的First端必须在Done为0时保持为1、Done置1后变0避免重复发请求。我在First端用了一个内部位M10.0由“轮询指针匹配且上次Done为0”的串联条件置位Done上升沿复位。这样每一帧报文之间留出了Modbus协议要求的静默间隔通讯更稳。3.3 读回来的数据怎么换算成工程量读回来的原始数据直接能用吗不能。Modbus寄存器里存的是整数或浮点数的原始值要变成电压、电流、温度还要根据仪表手册做系数换算。举个例子某型号仪表手册写寄存器40021开始依次存放Ua、Ub、Uc三个线电压每个占1个寄存器单位是0.1V。也就是说如果读到的原始值是2200实际电压是220.0V。换算公式就是实际值 寄存器值 × 0.1。如果是电流可能放大倍数不一样。有些仪表电流用1A或5A测量输入寄存器里存的是0.01A为单位那读到的值要乘以0.01。如果柜子里还有互感器变比仪表内部一般已经折算过了你读到的直接是实际一次侧电流但必须看手册确认不能想当然。如果遇到浮点数格式的仪表情况稍麻烦。两个连续寄存器组成一个32位IEEE754浮点数PLC读到的是4个字节。200 SMART内部存储浮点数的方式和仪表传输顺序往往不一致常见导致“读出来的数完全不对”的问题。处理方式是把VB区里这4个字节按仪表要求的字节序重新排列再用MOV-DR把调整后的双字移动到实数寄存器里。具体是高位字在前还是低位字在前以仪表手册为准。实测中我遇到过不少仪表是高字节在前也就是VB0、VB1是浮点的高16位VB2、VB3是低16位而200 SMART默认读进来的顺序可能需要高低字对调。这个坑写程序时要提前预留出转换逻辑不要等数据乱套了再临时改。4. 现场调试排查链路通讯不灵时按这个顺序来4.1 先用电脑加USB转485确认仪表本身没问题项目调试阶段我最先干的不是写PLC程序而是拿一台笔记本、一个USB转RS485转换器先跟高压仪表直接通讯。把转换器的A、B接到仪表485端打开串口调试工具按仪表手册设置9600、8、1、无校验从站地址1发一条03功能码读保持寄存器报文比如读40021开始的两个寄存器。如果仪表返回了正常数据说明仪表、线缆、参数都没问题你的问题只在PLC侧。如果仪表无响应检查A/B是否接反、地址对不对、波特率对不对、仪表是否处于通讯未开启状态。这一步能把问题范围缩小一大半。很多朋友上来就埋头改PLC程序最后发现是仪表的通讯地址被密码锁住了纯属浪费时间。先分层定位这是最有效的调试方法。4.2 用MBUS_CTRL和MBUS_MSG的Error代码定位故障层如果电脑能读到仪表PLC读不到就要看MBUS_MSG的Error输出。Done置1时Error里有错误码按库手册查一下就知道问题方向:Error代码含义常见原因0无错误正常1请求发送错误485接线断路、极性接反2接收到响应但CRC错误波特率/数据格式不一致、干扰3超时无响应从站地址错误、从站未开机、线缆断开101-112从站返回异常码寄存器地址非法、功能码不支持等比如Error101通常对应Modbus异常码01表示仪表不支持你请求的功能码或者你访问的寄存器不存在。这时候看仪表手册确认地址在不在合法范围内、填的400xx对不对、功能码是否被仪表开放。Error3超时最容易被误判成“通讯费用问题”。其实多数时候是地址填错。比如仪表手册写“协议地址0x0000对应40001”你在PLC里却填了40000那仪表收到的是不存在的地址自然不响应。Modbus协议地址从0开始而200 SMART库的Addr参数里4xxxx表示保持寄存器其中40001对应的协议地址是040002对应1这个1的偏移很容易踩。4.3 数据值翻倍、负数、乱码怎么处理通讯能读通了不代表数据就对了。有三类现象很典型第一种读到的数据明显是实际值的10倍、100倍。这通常不是程序问题而是仪表寄存器本身按放大系数输出。比如电压互感器二次侧100V对应一次侧10kV仪表内部可能把一次值放大10倍显示寄存器里单位是0.1V或1V。你要做的就是根据手册里的“缩放因子”乘回去。第二种读取的有功功率或电能出现负数。高压计量中四象限功率是正常的不代表仪表坏了。但如果PLC侧用了有符号整数处理负值会变成很大的正数。处理方式是先把寄存器值按有符号整数读入再用整数转实数指令转成浮点最后按需加符号判断。第三种读出来的浮点数完全离谱比如电压明明是220V读出来是1.234E38或者小数点位置乱跳。基本可以断定是字节序或字序没对。检查一下你PLC里4个字节的排列顺序跟仪表手册是否匹配。这里可以给一个最土但有效的办法先用电脑串口调试工具读回这4个字节的十六进制比如仪表返回CD CC 8C 40把这4个字节按不同顺序排列后用在线计算器转成浮点数看哪个结果符合220.4就知道正确的字节顺序了。5. 可以直接参考的程序要点以及一些投运后才知道的维护经验5.1 一个典型的小型项目程序框架如果你的现场也差不多是3台左右的高压仪表可以参考下面这个框架在Micro/WIN SMART里搭起来变量地址按你自己程序重新规划MBUS_CTRL指令参数EN: M0.0全局允许位置1常通Mode: 1主站模式Baud: 9600Parity: 0无校验Timeout: 500毫秒Done: M0.1Error: MB1轮询状态位VW100轮询指针0、1、2分别对应3台仪表M10.0当前请求触发位M10.1当前请求完成标志MBUS_MSG指令1负责1号表EN: M10.0First: M10.0Slave: 1RW: 0Addr: 40021Count: 8DataPtr: VB2000Done: M10.1Error: MB11当M10.1置1时把VW100加1同时复位M10.0。VW100为1时激活指令2Slave填2DataPtr填VB2016VW100为2时激活指令3Slave填3DataPtr填VB2032完成后再复位VW100为0。这样一个循环周期内3台仪表各读一遍。触摸屏上看到的数值直接关联VB2000开始的V区在触摸屏里做线性转换或直接在PLC里把工程量算好放在另一组VD实数区。我的经验是尽量在PLC里完成换算触摸屏只做显示这样后续要上送监控系统也方便。5.2 库存储区和变量地址冲突一个容易被忽略的坑200 SMART调用Modbus Master库时系统会要求分配“库存储区”Library Memory。默认可能在VB0开始的一段范围。如果你自己的程序里用了VB0、VB1、VB2这些地址会跟库发生覆盖。库运行时会往这些V区写中间数据把你的数据搞得乱七八糟。这个坑很隐蔽因为编译不一定报错但运行时数据会莫名变化。最简单的解决办法是在Micro/WIN SMART里右键“库存储区”指定一段你程序不用的V区比如VB500-VB950然后你自己的数据统一从VB1000开始使用。分配完了记下来以后程序里不要再碰这段地址。另外一个相关细节MBUS_MSG的Done位和Error字节不能设在同一字节里。比如Done用M20.3Error用MB20那么Error一旦写入M20.3这个位就被覆盖了你的完成判断会失灵。常见的做法是Done放在M区单独一位Error单独占一个MB字节例如Done用M10.1Error用MB11。5.3 项目投运后遇到的抗干扰和稳定性问题机器跑起来后会遇到一个有意思的现象白天调试的时候一切正常晚上生产一启动通讯就开始偶发中断。这种大概率是动力电缆与485线敷设在同一线槽内电磁干扰导致误码。我处理过的一个案例通讯线有一段和动力线平行走了大概十几米运行时有负载波动就报警。后来把485线挪到远离动力线的独立桥架屏蔽层单端接地问题基本消失。还有一次是PLC侧电源和仪表的开关电源共用一个回路接触器吸合瞬间通讯就断。给PLC侧加了个隔离型RS485中继器同时把仪表侧的开关电源换成了带EMC滤波的型号通讯就稳定了。建议第一次调试就做好几件事通讯线用屏蔽双绞线、屏蔽层单端接地、PLC和仪表尽量分开供电、走线避开变频器和动力电缆。这些如果等投运后再改改线成本远远高于一开始就做对。5.4 一点长期运行的小技巧最后分享一个我自己用得很顺手的习惯在程序里留一个通讯状态累计逻辑统计每台仪表连续通讯失败的次数。比如MBUS_MSG返回错误且非0时给对应的计数器加1超过3次就置一个“通讯异常”位在触摸屏上弹报警。成功一次就清零。很多现场故障是偶发性的你不会一直盯着监控屏有了这个累计报警维护人员能第一时间知道某台表通讯不稳定。这个逻辑实现起来很简单用几条比较和加法指令就行但投运后的价值非常大。高压仪表通讯这类项目原理不复杂真正拉开差距的都在细节地址偏移、字节顺序、库存储区、终端电阻、抗干扰。把这几个点都处理好通讯基本不会给你添乱。