SMART200自由口通讯读取托利多电子秤重量:接线、解析与调试
搞配料、包装、检重这些产线的人估计都碰上过这种局面西门子SMART200 PLC和一台托利多电子秤明明离得不远秤上的重量数字跳得清清楚楚PLC里却死活读不到。要么收进来是一串乱码要么干脆没反应最后只能靠操作工看秤手工抄数。这篇就围绕SMART200自由口通讯把路子捋一遍——从硬件接线、口参数到XMT/RCV程序框架、报文解析再到超时和报警处理。以我调这类秤的经验九成问题其实不在硬件而在于开头三步没走对协议模式没搞清楚、物理链路没接好、口参数没对齐。适合正在做老秤改造、新产线通讯调试或者纯粹想搞懂自由口原理的朋友参考。1. 为什么偏偏要用自由口秤的报文让Modbus库英雄无用武之地1.1 电子秤通信模式的两种面孔托利多秤的串口通讯大体分两种模式。第一种是连续输出秤只要上了电、处于称重状态就按自己设定的周期往外发当前重量PLC只负责收。第二种是命令应答PLC先发一个读取命令秤收到后再回一帧当前数据一问一答。连续输出简单粗暴程序只需要管收包但有个问题——你无法主动控制和秤的对话节奏而且像清零、去皮这类操作如果秤也支持串口命令就得走命令应答。命令应答模式需要你先把秤侧的命令字搞清楚再在PLC里组帧发送程序上多一层状态管理但可控性明显更高。我个人在配料类项目里更倾向命令应答因为每一帧数据都对应一次明确的请求程序里好做超时判断也方便判断秤到底是在线还是已经掉线。1.2 SMART200自由口到底能干多少活S7-200 SMART的集成串口物理层是RS485默认走PPI协议与编程软件通信。当你在程序里把串口改成自由口模式之后这个口的协议就完全交给你定义了波特率、数据位、校验位可以配收发全靠XMT和RCV两条指令每个口的发送完成、接收完成、字符到达都有对应的中断事件。自由口模式下CPU不会替你区分帧所有字节按原始形态进出所以你要自己定一帧到什么时候算完。这是它的灵活之处也是很多初学者觉得难的地方。记住一点它是半双工发和收不能同时进行程序状态机要避免一边发一边收的冲突。另外自由口模式下Port0不再响应PPI编程协议好在SMART200有以太网口在线监控走网线就行这个后面还会细说。1.3 为什么Modbus RTU库在这里第一轮就被淘汰SMART200自带的Modbus RTU主站库确实好用但是它的报文结构是固化死的功能码、寄存器地址、数据区全部按标准Modbus帧打包。托利多这类电子秤走的是厂商自定义的ASCII字符串协议帧头、状态位、重量段、单位都是特定排列有些帧尾还带异或校验字节。你没法在MBUS_MSG里塞进去自定义ASCII报文所以正确做法就是绕开Modbus库直接用自由口的XMT/RCV来收发。判断标准很简单翻一下秤的通讯协议手册如果帧格式里出现了大量ASCII可打印字符比如字母、逗号、正负号而不是标准的十六进制功能码加寄存器地址那就别折腾Modbus了。硬要用库去套最后只能是在软件里反复改寄存器映射浪费时间还收不到正确数据。2. 接线、口参数和第一行SMB30动手前的三个关键决定2.1 从秤的RS232到PLC的RS485一段最容易被忽略的路大多数托利多秤随机标配的串口是RS232而SMART200集成Port0是RS485两者电平标准不一样直接怼上去是没用的。常规做法是外接一个RS232转RS485转换器转换器RS232那一侧接电子秤的串口RS485那一侧的两根线接到PLC的A、B端子上。接之前一定翻手册确认PLC侧DB9的3脚和8脚定义不同批次产品引脚标注有差异别想当然用万用表量一下最稳。转换器的选购有几个关键点要选有源供电的型号别贪便宜用无源的秤的232口驱动能力有限很容易出现单独接电脑正常、接上PLC就没反应的情况有条件就选带光电隔离的现场变频器、伺服干扰大的时候能救命波特率范围至少要覆盖9600到19200。另外如果这台秤本身支持RS485选件或者PLC端加了RS232信号板那可以省掉转换器但A/B线的顺序、屏蔽层接地这些同样不能错。2.2 口参数必须两边对齐波特率、数据位、校验位一个都不能错电子秤面板里通常都有串口参数设置菜单波特率、数据位、校验位、停止位都可以改。PLC自由口的SMB30里也要配成完全一致。最常见的组合是9600,8,N,1也就是9600波特率、8位数据位、无校验、1位停止位。但我遇到过不少老秤默认是7位偶校验这种情况下PLC如果还按8N1收收到的字符串会整体错位基本都是乱码或者干脆收不到。调参数时先用秤把输出模式、波特率确认好再在程序里按相同参数设置。顺序很重要先调秤再写PLC两边挨个对齐。如果现场有多台秤最好把每台秤的当前设置都记下来尤其是博途里看不到的秤面板参数一旦改了设置没记录下来下次断电重启之后排查起来要命。2.3 SMB30运行时切换协议的那几个字节SMART200的自由口是靠写特殊寄存器来激活的Port0对应SMB30Port1对应SMB130。SMB30的位含义见下表位含义常用值SM30.0-1协议选择00PPI从站01自由口10PPI主站01SM30.2-4波特率0109600001192000114800010SM30.5-6校验00无01偶校验10奇校验00SM30.7数据位08位17位0把这些位拼成一个字节9600、8位数据、无校验、自由口就是16#09如果秤要求7位偶校验那就是16#A9。程序里只需要一条MOVB指令把值写入SMB30串口立即切到自由口。这里有个比老S7-200方便很多的地方SMART200的编程调试走以太网口所以哪怕你把Port0切成了自由口也不影响在线监控和下载程序调试体验好很多。很多老工程师担心一写SMB30就掉编程连接在SMART200上完全不必有这个顾虑。3. XMT/RCV的双人舞初始化、缓冲区、接收完成中断怎么编排3.1 RCV控制字节接收规则由你定制自由口接收不是傻傻地等RCV指令有一个配套的控制字节SMB87里面每一位都可以定义接收的触发和结束条件。SM87.7是总开关必须置1SM87.4是结束符检测置1后RCV遇到SMB89里指定的结束字符就认为一帧结束SM87.3是超时检测置1后配合SMW92里的毫秒数超过时间没收到数据就自动结束接收SM87.5是空闲检测置1后通过SMW90设定静默时长来判定一帧结束。最常用的组合是结束符超时兜底正常帧按结束符收完异常情况由超时来终止避免RCV永远挂起。接收缓冲区用V区开辟比如VB200开始。RCV执行后系统会把实际收到的字节数写到缓冲区的第一个字节后面的字节才是真正的报文内容。这个首字节非常关键后面解析帧长、判断是否收到完整数据都靠它。缓冲区的长度至少要能装下一字节长度最大帧长我习惯把SMB94最大字符数设成32遇到超长帧直接按错误处理避免缓冲区被冲掉。3.2 中断事件的交通规则ATCH、ENI和事件号自由口程序离不了中断。Port0的接收完成中断事件号是23发送完成是9每收到一个字符的中断是8。程序里先用ATCH指令把对应的中断程序和事件号绑在一起再执行ENI开全局中断。这里有个建议接收完成中断里只做收尾动作——比如把接收完成标志位置1、把接收长度保存到固定变量——不要在里面做复杂的字符串解析。解析放到主程序或者轮询子程序里做原因很简单中断程序里逻辑越短越不容易破坏主循环的时间节拍也越不容易和主程序抢变量。还有一个小细节RCV是一次性的收完一帧后它会自动失能。如果还要继续收必须在代码里再次执行RCV。所以程序结构上通常做成接收完成中断置位 → 主程序发现标志后解析、处理 → 处理完再次RCV、清零标志。这套循环顺手了通讯状态机就立起来了。3.3 先搭一个能收能发的裸框架下面这段是初始化部分的STL风格示意对应上电后把Port0切自由口并立即开始第一次接收LD SM0.1 // 首次扫描脉冲 MOVB 16#09, SMB30 // Port09600, 8, N, 1自由口模式 MOVB 16#98, SMB87 // 允许接收 结束符检测 超时检测 MOVB 16#0A, SMB89 // 帧尾结束符换行 MOVW 100, SMW92 // 100ms超时 MOVB 32, SMB94 // 最多接收32字节 RCV VB200, 0 // 启动第一次接收 ATCH INT_RCV, 23 // 绑定接收完成中断 ENI // 全局开中断发送侧也一样把要发的命令按长度字节数据的格式放缓冲区然后XMT。比如命令只有一个字符R那VB100里放1VB101里放16#52。如果还要在发送完成后知道已发完可以把发送完成中断也绑定上置一个发送空闲标志。裸框架跑通之后再往里面加解析和业务逻辑心里就踏实了。这个阶段我习惯先把两块通信状态字M变量加上注释M0.0接收完成、M0.1发送空闲后面所有逻辑都围绕这两个标志展开程序不会乱。4. 不定长报文到底怎么收结束符RCV和字符中断拼包两种打法4.1 结束符方案SMB89设成0A帧尾干净利落如果秤的帧尾固定且唯一最简单的方法是结束符接收。把SMB89设成帧尾字符的ASCII码比如秤以回车换行结尾就把SMB89设成16#0A换行。RCV接收到这个字符自动判定一帧结束转到接收完成中断。在接收完成中断里先看SMB86状态字节有没有错误位再看缓冲区首字节的长度是否符合预期。这套方案很省事但有一个前提结束符在报文中不能出现在其他位置。托利多秤的数据部分基本是数字和逗号换行符只会出现在帧尾所以实测很稳。命令应答模式下我一般先执行RCV再发XMT顺序别反。提示命令应答模式下务必要先执行RCV再执行XMT。接收没有挂好就发命令秤的应答可能从第一个字节就丢了。先让接收挂好再发命令这样秤的应答一到RCV立刻就能接住不会丢第一个字节。如果你发现收到的数据总是少一个字符或者首尾不齐第一反应就应该是检查这个顺序。4.2 字符中断方案每个字节都自己说了算有些秤的协议帧尾不固定或者一帧里可能出现多个换行这时候RCV结束符方案就有点不好用。可以改用每接收一个字符触发一次的中断Port0对应事件8在中断里把SMB2接收到的字符逐个存入自己维护的缓冲区手动计数。帧结束怎么判断常见做法是配合一个超时窗口如果距离上一个字符超过比如50ms还没有新字符进来就认为这帧结束了。字符中断方案的优点是逻辑完全你自己说了算协议再怪也能拼出来代价是每个字节都打断一次CPU程序里还要维护缓冲区指针、长度计数器、帧结束判定。不过9600到19200波特率下SMART200完全扛得住。如果既有帧尾又要防异常可以在字符中断方案里加上最大长度保护超过预定长度直接丢弃重来。写这个方案时建议把缓冲区指针和长度计数放在同一个V区连续地址调试的时候从变量表里一眼就能看到拼包进度。4.3 现场怎么选两种方案的对比与混搭两种方式各有各的适用场景我整理了一张对比表方便直接在项目里定方案对比项结束符RCV方案字符中断拼包方案实现复杂度低配置好即可高需要自己拼缓冲区适用协议帧尾固定、报文干净帧尾不固定、协议怪异CPU开销小较大但9600波特率无压力可靠性高系统内置判断取决于拼包逻辑是否严谨典型场景托利多连续/应答帧PLC与自定义仪表、扫码枪如果让我选一律优先结束符RCV。只有遇到帧尾不固定、或者调试中发现结束符可能混在数据里才换字符中断。还有一招混搭用RCV正常接收同时把超时打开这样万一秤掉线或者发出半帧数据RCV也会在超时后收回控制权不会把整个通讯卡死。这个兜底机制我每次都会加哪怕是连续输出模式也一样。5. 重量数值是怎么从字符串里抠出来的ASCII解析的全过程5.1 先从帧里定位用FIND/MIDR把数字段切出来假设秤在命令应答模式返回这么一帧实际格式以你手头那台秤的协议手册为准ST,GS,000.120 kg\r\n我们需要的是中间那个000.120也就是7个字符的数字段。先不要急着一个个数偏移量除非你能确定帧格式永远不会变。稳妥的做法是先用FIND指令在接收到的字符串里找GS,这个特征子串找到之后位置就确定了再用MIDR指令从特征串后面截取固定长度比如截7个字节得到000.120。如果秤的帧里还有毛重/净重标志位找特征串时也要区分清楚——想读毛重就找对应的GS标记想读净重就找另一个标记别拿错字段去算。字符串指令在S7-200 SMART里都有FIND负责查找子串位置MIDR负责提取子串。注意第一个字符串操作数往往是长度字节ASCII字符的格式所以定义查找子串时也要先在V区把长度和字符放好。整个过程最好封装成一个解析子程序输入是接收缓冲区首地址输出是重量值、符号、状态位以后换秤的协议格式只改子程序内部就行。我这里用的ST,GS,只是演示结构不同型号的秤字段名可能不一样但定位思路完全通用。5.2 没有现成的ASCII转浮点指令那就自己数位权S7-200 SMART并没有一条字符串转浮点的捷径指令ATH只是把十六进制ASCII字符转成字节不能直接拿来做带小数点的十进制字符串转换。所以这个步骤必须自己写。我的做法是把数字段拆成整数部分和小数部分分别累加。假设数字段是000.120去掉前面的正负号和中间的小数点之后整数部分是000小数部分是120。用一个循环扫描字符串每遇到一个数字字符就减去16#30得到真正的数字值整数部分按位权累加小数部分累加成千分位再除以1000。比如120累加成120最后得到0.120再和整数部分合并。符号位单独判断遇到负号在最后取负。这里有一个容易被带偏的细节十六进制ASCII转整数指令处理的是0x30到0x39这种十六进制数字的ASCII范围很有限不要拿它来做多位数十进制转换。自己写循环虽然看着笨但当秤返回的是6位整数、3位小数时这个子程序就是一劳永逸的。写得通用一点比如把小数点位置、整数位宽、小数位宽都做成参数后面接其他品牌的秤也能复用。5.3 单位与精度别把kg读成了t解析完成后还要考虑单位换算和精度。秤返回的单位可能是kg、g甚至t程序里必须和工艺要求的单位一致。我遇到过项目里PLC端要做累计量秤返回kg但数据库要求t直接拿原始值累加最后报表差了三倍。正确做法是把单位统一成工艺单位在解析子程序出口处就完成换算后面所有逻辑都用统一单位。另外浮点数比较要留余量。PLC浮点是单精度32位两次运算的结果可能差0.0001程序里判断重量是否到某个阈值时不要用等于号硬比用差值绝对值小于允许误差的方式写。解析子程序跑起来之后先挂一段时间的变量监控表盯着VD区里的浮点数和秤面板显示对比几分钟确认小数位和跳变都对再往下做报警逻辑。尤其是秤在动态称重状态下数值会抖动程序里最好做一次软件滤波取连续几帧稳定值再输出。6. 通讯不能只做通这一下超时重试、掉线报警和几个实战坑6.1 别让程序永远等下去超时与通讯状态机命令应答模式下最忌讳的就是程序里傻等发了命令之后死等接收完成秤一直不回就直接卡死在那。自由口程序一定要有状态机思路。简单的做法是维护两个标志允许发送、接收完成。一个周期内如果允许发送就组帧、发命令、把允许发送清零如果接收完成标志为1就解析、处理、然后允许发送置1进入下一轮。RCV的超时时间由SMW92确保超时后接收结束程序能继续往下走不会因为一帧坏数据卡住整个系统。再用一个通讯失败计数器。连续几次超时没有任何有效帧就置掉线报警位同时把重量值保持在一个安全值触屏上弹电子秤通讯故障恢复条件很简单连续收到若干帧有效数据自动清零报警位。这套机制看着基础但在产线上能省不少半夜去现场的电话。计数器的复位逻辑也要写清楚别出现报警置起来容易、消掉难的问题。6.2 校验和与数据合法性防乱码更要防错值比收不到更危险的是收到一个错值还在继续用。如果秤支持校验帧尾通常会带一个或两个校验字节。常见的BCC异或校验做法是把数据部分的每个字节逐次异或得到一个单字节和帧里附带的校验值比对。接收完成之后先跑一次校验子程序对不上就把这一帧丢弃不计入重量数据。别以为只有收到乱码才需要校验。现场有一次是秤的通讯板老化偶发把某一位数据翻转字符看起来完全正常但重量差了几公斤。加了校验之后这种异常帧直接被识别出来。就算秤没有校验也至少要做合法性判断重量值是否在传感器量程范围内、符号位是否合理、正负号是否符合工艺逻辑。数据安全这件事宁可在程序里多写几行判断也别太相信串口。尤其是涉及到配料配方值的场景一帧错值就可能把整罐料配错损失远大于那几行程序。6.3 实测中那些最刁钻的故障四条排查链路最后列几条我在实际调试中踩过、也在别人项目里见过的坑。第一能收到数据但是全乱码。优先查口参数波特率、数据位、校验位一定要和秤面板设置一致查完口参数再看转换器供电无源转换器接上PLC后带不动负载数据会碎成一堆字节。第二时通时断几分钟一次。这种情况多半不是程序问题是物理链路问题。检查屏蔽层是否单端接地485线是不是和动力电缆缠在一起走了同一个线槽转换器有没有隔离。变频器一启动通讯就断的现场差不多都是这类原因。第三命令模式发出后秤没反应。先别急着改PLC用串口助手直接和秤对话确认PC发命令能收到应答。如果PC能通而PLC不行看XMT缓冲区长度字节对不对、命令字符的ASCII码有没有写错、通讯端口选的是Port0还是Port1。这一条排查链路能快速把问题定位到秤的设置还是PLC程序。第四接收不完整、帧长度飘忽不定。多半是SMB94最大字符数设小了帧被截断或者SMB89结束符和秤实际帧尾不一致。还有一种隐蔽情况RCV只执行了一次下一次接收没重新挂上看起来就是通一次之后再也不动。如果要把这套东西用到自己现场我建议按这个顺序推进先不开PLC程序用一台电脑串口助手把秤的真实报文抓下来确认模式、口参数、帧格式然后再写自由口的收发裸框架用变量表观察接收缓冲区和解析结果最后才加报警、累计这些业务逻辑。每一步都有明确验证点出了问题也知道在哪一段找比直接堆代码、猜问题要快得多。