ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

用MCGS触摸屏实现HJ212环保数据上报:协议解析与4G模块实战

用MCGS触摸屏实现HJ212环保数据上报:协议解析与4G模块实战 上个月去一个乡镇污水站处理通讯故障业主急得不行站房里的数采仪连续两天上报不了数据后台平台一直显示“设备离线”。我到现场一看问题说复杂也复杂——老式数采仪里的4G模块死机了重启之后TCP链路没有自动恢复需要人工干预。但这个不算复杂的故障硬是让站点数据缺失了两天。让我印象更深的不是故障本身而是那个站房里有一台MCGS触摸屏平时就用来显示液位、流量和几个水质参数接口和算力都富余得很。我当时冒出一个想法这台触摸屏完全有能力把数采仪的通讯任务接过来只要它能把HJ212报文拼对再交给一个4G模块发出去。这个想法后来真落地了。触摸屏脚本拼报文、串口接外置4G模块发数据整套改造没用新硬件只花了一下午调试。这篇文章就把完整做法摊开写HJ212报文的每一字节怎么来的、MCGS脚本里怎么写CRC校验、4G模块怎么配置、以及我在现场踩过的那些坑。适合做环保数采仪运维、设备改造或者自动化集成的工程师参考。新入门的朋友也别慌第二、三节先把协议和链路看懂后面照做就行。1. 一个现场故障让我重新评估了触摸屏的定位那次故障之后我认真算了一笔账。一台专业数采仪的价格从几千到上万不等交期往往还不短。而绝大多数环保站房里都已经躺着一台触摸屏它的CPU、内存、串口资源其实比很多老旧数采仪还要强。既然触摸屏本身就能做字符串运算、能通过串口读写数据那它天然具备“协议转换终端”的能力缺的只是有人帮它把HJ212这套规则用脚本表达出来。再说说适用边界。如果你的现场已经有MCGS触摸屏并且需要向HJ212监控平台上报污水、废气在线监测数据这篇文章可以直接照着做。如果你在做新设备集成这套逻辑同样可以作为“触摸屏直接上网报数据”的低成本方案。但有一条要提前说清楚触摸屏替代的是数采仪的通讯功能现场仪表的传感器信号采集、PLC逻辑控制这些事触摸屏没有能力也不应该去接管分工要搞清楚。还有一个容易被忽略的点触摸屏本身通常没有公网通信能力所以必须搭配4G模块。这个模块选对了项目成功一半选错了后面全是泪。后面第三章专门讲选型和链路这里先不展开。从那次以后我养成了一个习惯到现场先盘点站房里有什么是可用的、闲置的、能改造成本的设备而不是急着下单买新设备。很多时候答案就在你眼皮底下。2. HJ212报文拆解每个字段都在告诉后台“我是谁、我在哪、我测了什么”2.1 一帧报文的骨架HJ212是污染源在线自动监控(监测)系统的数据传输标准目前主流现场用的是2017版。整帧报文的结构其实不复杂由几个固定部分组成帧头两个ASCII字符##数据段长度4位十进制数例如0200数据段一组由分号分隔的字段是报文的正文CRC校验码4位十六进制数帧尾回车换行即\r\n0x0D 0x0A串起来长这样##0200QN20240512103000000;ST31;CN2011;PW123456;MN010000A8900016F000169DC0;CPDataTime20240512103000;CODCr23.5,NH3-N1.2,pH7.35A1B2\r\n注意一个很容易搞混的地方这里的0200是4个ASCII字符0200表示的是后面的数据段一共有200个字符而不是十六进制数值0x0200。另外CRC校验的范围就是从这4位长度字符的第一个字符开始一直到数据段最后一个为止后面写脚本的时候这个范围必须踩准。2.2 数据段里的关键字段数据段才是真正有信息量的地方每个字段用;分隔。常用固定字段看这个表字段含义示例QN请求时间戳精确到毫秒QN20240512103000000ST系统类别废水是31ST31CN命令编号2011代表实时数据上报CN2011PW访问密码PW123456MN监控点编码由平台分配MN010000A8900016F000169DC0CP数据内容用包裹CPDataTime...ST这个字段要特别留意。不同监测对象的代码不一样废水是31废气是21地表水是23。写错了平台很可能直接把报文丢弃而且从报文格式上你根本看不出问题这类错误在调试阶段最隐蔽。CN是命令类型日常用得最多的是2011实时数据上报。设备注册、心跳应答用的又是另外的编号比如心跳常用1013之类的命令。如果你只做一个基础上报项目CN2011就够用心跳和注册等需求放到后面扩展。CP里装的是监测因子多个因子用逗号分隔。因子自带一个时间戳DataTime格式是年月日时分秒14位CPDataTime20240512103000;CODCr23.5,NH3-N1.2,pH7.35这里要提醒一句不同平台对因子字段的命名规则不完全一致。有的平台认因子名称CODCr、NH3-N有的平台认因子编号比如w01001这类。动手之前先找对接方要一份数据字典按他们约定的字段名来拼能省掉后面大把返工时间。2.3 CRC校验到底算什么CRC是新手最容易栽跟头的地方我见过太多项目卡在校验失败上一个星期。HJ212用的CRC-16校验多项式是0x1021初值是0xFFFF校验范围是“4位长度 数据段”这一段字节流。算出的16位结果转成4位大写十六进制放到数据段后面。常见的错误有两个一是只算了数据段没把4位长度字符算进去二是算完把高低字节对调了。HJ212标准里最终结果按高低字节正常排列显示不是小端方式。想确认自己算得对不对最稳的办法是拿一个已经验证过的HJ212报文生成工具在同一段数据上算一遍CRC再跟你的脚本结果对比。别靠眼睛猜这个必须用工具交叉验证。2.4 先说个判断原则后文所有脚本的逻辑归根结底就一个目标拼出的字符串必须严格满足上面的骨架和字段规则。我的习惯是先用手工构造一条最小报文用工具算出CRC在调试助手里手动发一遍确认平台能收到、能入库。然后再去写触摸屏脚本。这一条顺序非常重要。协议问题先用串口调试工具验证不要让触摸屏的变量问题、串口问题混进来不然你根本说不清是协议错了还是链路没通。3. 硬件链路规划触摸屏、4G模块和服务器之间到底怎么接3.1 触摸屏选型的三个注意点做这件事的首要条件触摸屏必须有一个备用串口最好是RS232和RS485都支持。MCGS的TPC系列里TPC7062、TPC1061算是现场最常见的型号都至少带一个串口够用。串口类型决定接线方式RS232用三根线TX、RX、GNDRS485用两根线A、B千万别接反。第二个注意点是触摸屏的脚本能力。MCGS嵌入版支持类似VBScript的脚本语言能做字符串拼接、循环、条件判断这是拼报文的基础。如果是太老的非嵌入版组态软件脚本功能弱很多做字符串运算会很吃力这种就不建议硬改了。第三个点是供电和现场环境。4G模块和触摸屏都需要稳定供电现场如果变频器干扰严重串口线尽量短用屏蔽线单端接地减少误码。别小看这一步我以前在现场吃过亏线路一长报文偶发乱码排查了半天才发现是干扰。3.2 4G模块的类型对比4G模块市场上的选择不少我按现场经验分成三类直接看表类型代表型号优点缺点推荐场景串口4G DTU有人USR-G780、WH-G405tf配置好自动连服务器、支持透传、自带心跳价格略高、需要单独配置现场稳定运行首选4G无线模块移远EC200、EC20成本低、可被脚本完全控制拨号建连流程要自己写深度定制、对成本敏感带4G功能的触摸屏MCGS部分新款型号一体化、无外部接线单价高、选型受限新上项目一次性到位如果给存量设备做改造我强烈推荐第一类串口4G DTU。原因是它上电自动拨号、自动连服务器、断线自动重连这些脏活累活硬件层面就干完了。触摸屏只需要专注于拼报文、往串口写数据职责分离以后故障也好定位。用裸模块虽然省点成本但拨号、建socket、收发状态处理全要在MCGS脚本里实现调试量翻好几倍不值得。3.3 串口参数和SIM卡准备触摸屏和4G模块之间就是一条串口链路两边参数必须一致。常见出厂参数是115200-8-N-1但不绝对。拿到模块先查手册或者用调试助手发指令读一下当前参数然后两边统一设置。只改一边就是给自己埋雷。SIM卡建议用物联网卡确认卡本身能访问公网并且服务器端的IP是公网IP或者有端口映射。很多内部组网环境里平台服务器在城域网内4G模块根本路由不到那个地址这类问题往往查了半天才发现是网络路径不通白折腾。3.4 服务器端要先准备好对接HJ212的平台本质上是一个TCP服务器监听某个端口等设备接入。调试阶段我强烈建议在电脑上装一个网络调试助手NetAssist这类监听一个端口让4G模块先连到电脑。这样你能亲眼看到报文有没有到、内容对不对比对着平台后台日志猜快太多。如果对接的正式平台已经把服务器地址和端口分配下来了把这些参数留给后面配置DTU用。MN编码、PW密码这些要么是平台分配的要么从现场旧数采仪里抄出来务必跟原设备保持一致否则平台会判定这是一台未注册设备报文直接丢弃。4. 在MCGS脚本里拼出一个合法HJ212帧变量、时间戳、长度和CRC4.1 变量怎么规划打开MCGS组态环境先建数据对象。我的习惯是分三类数值型存放监测因子比如fCOD、fNH3、fPH字符串型存放拼好的报文比如strFrame开关型用来控制上报的启动、标志串口是否忙数据对象在MCGS里是全局的脚本里可以直接引用。如果数据来自PLC或仪表让数值变量和通道绑定脚本生成报文时读变量就行不用管底层采集逻辑。4.2 时间戳QN和数据时间怎么来QN要求精确到毫秒格式是17位年月日时分秒加3位毫秒。MCGS脚本里取系统时间的方式在不同版本里略有差异我以嵌入版常用的写法为例qnStr !StrFormat(%04d%02d%02d%02d%02d%02d000, !Year(), !Month(), !Day(), !Hour(), !Minute(), !Second()) dataTimeStr !StrFormat(%04d%02d%02d%02d%02d%02d, !Year(), !Month(), !Day(), !Hour(), !Minute(), !Second())如果你的版本不支持!StrFormat的%d这种C语言格式就手工拼先用 !Year()转成字符串再用字符串截取函数补零。比如月份是5拼成“05”。QN末尾固定补3个0因为MCGS脚本拿不到真正的毫秒级时间补0即可平台一般不会严格校验毫秒值。4.3 拼接数据段和计算长度假设当前pH值、COD和氨氮分别存在fPH、fCOD和fNH3变量里拼接逻辑如下cpStr CPDataTime dataTimeStr ;CODCr !StrFormat(%.2f, fCOD) ,NH3-N !StrFormat(%.2f, fNH3) ,pH !StrFormat(%.2f, fPH) dataSeg QN qnStr ;ST31;CN2011;PW123456;MN010000A8900016F000169DC0; cpStr lenPrefix !StrFormat(%04d, Len(dataSeg))先拼数据段再用Len()取长度格式化成4位。%.2f控制小数位为2位MCGS会做四舍五入。这里有个细节如果某个因子当前没有数据不要拼一个空值进去直接省略这个字段或者拼一个平台约定的异常标志具体看平台要求。4.4 CRC校验的脚本实现CRC计算需要逐字节遍历MCGS脚本支持While循环也支持整除、求余运算实现如下 参与校验的字符串 4位长度 数据段 crcSrc lenPrefix dataSeg crc 65535 0xFFFF i 1 WHILE i Len(crcSrc) c Asc(Mid(crcSrc, i, 1)) crc crc XOR (c * 256) j 1 WHILE j 8 IF (crc AND 32768) 0 THEN crc (crc * 2) XOR 4129 0x1021 4129 ELSE crc crc * 2 ENDIF crc crc AND 65535 j j 1 ENDWHILE i i 1 ENDWHILE 转换成4位大写十六进制 digits 0123456789ABCDEF b1 crc \ 4096 b2 (crc \ 256) MOD 16 b3 (crc \ 16) MOD 16 b4 crc MOD 16 crcHex Mid(digits, b1 1, 1) Mid(digits, b2 1, 1) Mid(digits, b3 1, 1) Mid(digits, b4 1, 1) 组帧 strFrame ## lenPrefix dataSeg crcHex Chr(13) Chr(10)这段脚本就是整篇文章的核心。如果你用的MCGS版本把位运算写成BitXor这类函数形式把crc XOR (c * 256)对应换成函数调用即可逻辑不变。注意数据段长度是字符数HJ212报文里全是ASCII字符字符数和字节数是一致的不会出现中文那种一个字符占多个字节的情况。4.5 把报文送到串口MCGS里向串口发送字符串常规做法是在设备窗口添加串口父设备和对应的串口子设备子设备里关联一个字符串类型的通道。脚本里给这个通道赋值设备就会把字符串按配置好的串口参数发出去 dataSend为串口子设备中关联的字符串通道 dataSend strFrame发送完成后注意清空通道值或者等下一次触发再赋值避免把同一帧旧报文重复发出去。另外如果同一个串口上还挂了PLC或其他仪表要注意发送时机不要跟设备采集冲突否则数据会互相干扰。5. 让4G模块干活两种模块的配置路径与调试验证5.1 串口4G DTU的配置路径以有人USR-G780这类串口4G DTU为例先说最省心的路径。USB转RS232线连上模块打开串口调试助手先把模块切换到配置模式一般是上电时按住某个按钮或者发厂商规定的特定指令然后按手册逐条下发配置ATDNETID? 查询网络是否注册成功 ATSOCKETON,服务器IP,端口 设置目标服务器并建立连接不同厂家指令不一样有的DTU用配网软件直接填参数更直观甚至支持网页配置。核心要设的就三样服务器地址、端口、工作模式TCP透传。设好后重启模块观察指示灯通常有信号指示灯和连接指示灯两个都正常了再往下走。连接成功后模块就处于透传状态任何从串口进来的数据都会被原样转发到服务器。MCGS拼好的HJ212报文往串口一写模块就送出去了。这个模式下MCGS完全不需要关心TCP连接的事只管写数据。5.2 裸4G模块的AT指令路径如果手里是移远EC200这类裸模块流程就得自己控了。典型AT指令序列是ATCGDCONT1,IP,CMNET 设置APN ATQIACT1 激活移动网络 ATQIOPEN1,0,TCP,113.45.xx.xx,12345,0,0 建立TCP连接 ATQISEND0,200 告知模块要发送200字节 紧接着发送报文数据在MCGS里实现这套流程需要做一个状态机上电后逐条发AT指令、判断返回内容、超时重试。说实话调试量不小除非你确实需要把建连过程掌握在触摸屏手里否则生产环境还是优先考虑DTU方案省心很多。5.3 MCGS触摸屏调试助手怎么用调试阶段最有用的工具组合是PC上的串口调试助手 网络调试助手。先用PC代替触摸屏做一遍完整链路验证再切换到触摸屏。具体操作是这样USB转串口线连接4G模块调试助手里设置好波特率手动输入一条完整的HJ212报文——就是第二节里你手工验证过的那条——点发送。同时在PC上运行网络调试助手监听服务器端口看能不能收到相同内容。能收到说明4G链路没问题问题只剩触摸屏侧了。反过来也可以把调试助手接在触摸屏和4G模块之间监听。这里有个技巧把USB转串口线的TX接到触摸屏的TX不是RXRX接到4G模块的RX调试助手就能旁路监听到触摸屏实际发出的内容。这一步能解决后面90%的“平台收不到”问题因为你能直接看到触摸屏拼出来的字符串到底长什么样。5.4 一条测试链路的建议第一次测试的报文尽量简单别一上来就带七八个因子。先跑通最小帧##QN...;ST31;CN2011;PW123456;MN010000A8900016F000169DC0;CPDataTime20240512103000;pH7.35CRC\r\n平台能收到并应答再往报文里加因子、加格式细节。这样定位问题时思路是清晰的链路通不通、报文对不对、因子名对不对每一步都能单独验证不需要靠猜。6. 现场踩过的六个坑从“平台收不到”到“平台报CRC错”的完整排查6.1 坑一两边串口参数对不上模块收到的是乱码症状是整个报文发出去平台端毫无反应用调试助手监听触摸屏发出的数据发现是一串乱码。排查方法先用调试助手直连4G模块查看模块当前波特率。有些模块出厂是9600触摸屏配成115200就出现这个情况。解决办法是把两边统一或者通过调试助手下发AT指令把模块波特率改成跟触摸屏一致。改动后重启模块参数才会真正生效。6.2 坑二CRC计算结果不对平台一直报校验失败这是HJ212项目里出现频率最高的故障。平台能收到报文但提示CRC错误基本可以断定校验这段算得不对。我的排查顺序固定是这样确认校验范围是不是把4位长度也包含进去了HJ212明确要求包含。确认初值是不是0xFFFF多项式是不是0x1021。确认字节序计算结果的十六进制显示是不是高低字节对调了。用标准工具交叉验证拿同一段数据用PC上成熟的HJ212生成工具算一遍CRC和触摸屏脚本输出对比。尤其是第4步一定要做。很多次我以为脚本没问题一对比才发现MCGS里整数运算的位数跟PC上不一样导致结果差几位。第4.4节的脚本里每轮循环都做了crc crc AND 65535这一步就是为了把结果限制在16位内这个掩码不能省。6.3 坑三DTU工作在透传模式时AT指令发不进去调试过程中你可能想通过串口给DTU发个AT指令查状态结果模块把指令当成业务数据转发到服务器了。原因很简单DTU分透传模式和配置模式透传模式下一切串口数据都被转发。你需要用厂商规定的特殊方式进入AT模式比如上电时按住某个按钮、或者发送带特定前后缀的指令。不要在不清楚的情况下乱试容易把无关数据污染给服务器。手册翻一翻一分钟的事。6.4 坑四TCP连接建立后长时间不通信被平台断开平台通常要求设备定期上报如果上报周期太长平台或者运营商中间设备会把TCP连接判定为死连接直接断开。解决分两层一是DTU硬件层开启心跳包让模块定期发一个短字节保活链路二是在MCGS脚本里即使数据没有变化也按平台要求周期发送心跳报文。注意心跳和正式上报是两回事心跳保活的是TCP链路正式上报才是真正的业务数据两者缺一不可。6.5 坑五报文里出现中文和特殊字符MCGS触摸屏的字符串编码和HJ212平台用的ASCII可能有差异最稳妥的做法是报文里除了注释用途外一律不出现中文。因子名、字段名、分隔符都是ASCII字符。如果你非要带单位或中文说明先确认平台侧编码不要想当然。另外Chr(13)Chr(10)是帧结束标志。有的模块或平台对\n处理得很敏感会导致数据粘包。用调试助手的十六进制显示模式看一眼报文结尾确认是0D 0A而不是只有一个0A。6.6 坑六MN编码或者密码和平台不一致如果报文格式、CRC都正确平台还是不收最后一步检查MN和PW。这两个字段相当于设备在平台上的“身份证号”和“门禁密码”必须和平台录入的一致。从旧数采仪里抄MN时注意区分容易混淆的字符比如数字0和字母O、数字1和字母I抄错一位整台设备就是“未注册”状态平台不认。6.7 一条完整的排查链路我把现场排查顺序固定成下面几步每次按这个走基本半小时内定位PC串口调试助手直连4G模块手动发一条已知正确的HJ212帧确认平台能收到。如果收不到用网络调试助手在电脑上做TCP Server确认4G模块能不能连上、数据能不能到。如果连不上检查SIM卡、APN、服务器地址端口。如果连上了但平台收不到检查MN、PW、CN、CP因子名是否正确。触摸屏侧串口调试助手监听触摸屏输出核对发出的字符串和手动验证的那条是否完全一致、CRC是否一致。最后检查定时策略和频道占用串口是否被PLC等其他设备占用、发送频率是否过高导致粘包。这套流程的价值在于每一层都有明确的观测点。哪一步的结果和预期不一致问题就锁定在哪一段剩下的事就好办了。7. 从发出一条到稳定运行定时上报、心跳与多因子扩展7.1 定时上报的脚本控制跑通单条发送之后第一件事就是加定时策略。MCGS有循环策略或者脚本触发机制可以设定一个周期比如60秒每次触发把当前监测因子拼成报文并发送。我的建议是把“采集”和“发送”分成两个步骤先让触摸屏从PLC或仪表采集数据并更新变量再在发送策略里读变量、拼报文、发送。两步之间隔开几秒避免报文里用的是上一轮的旧数据。策略脚本里加一个开关变量控制是否允许发送。比如设备刚上电、4G模块还没拨号成功时不要急着发等DTU连接指示灯正常后再放开发送开关。7.2 心跳和断线重连心跳这块DTU硬件一般自带配置可以把心跳间隔设成平台要求的数值。如果用裸模块就需要MCGS侧定时发心跳帧。心跳报文不需要带因子数据保持最简结构即可重点是让链路和平台都认为设备在线。断线重连对DTU是自动的不用管。裸模块则需要在脚本里做状态机定期查询连接状态断开就重新执行建连流程。这个逻辑写起来不算复杂但要注意AT指令的返回时机给足超时时间别把重连做成风暴式刷屏那样反而会把服务器搞崩。7.3 多因子和多种监测对象的扩展当CP里要上报多个因子时只要在拼接CP时继续追加逗号和因子字段即可。现场常见的情况废水站上报CODCr、NH3-N、pH、流量废气站上报烟尘、SO2、NOx字段名以平台要求为准。不同监测对象ST不同这个要在脚本里做成可配置参数换站点时只改数据对象的值不改脚本逻辑。MN、PW、服务器地址、上报周期这些统统做成数据对象在触摸屏上留一个设置画面以后换点调试能省掉大量重复改脚本的时间。有一点再强调一遍因子编码规则各平台不尽相同有的平台认名称CODCr有的平台认编号w01001。对接前先找平台方要数据字典按平台约定拼CP字段比事后一条条返工强太多。7.4 顺带提一下MQTT上云的方向不少同行问过我这套触摸屏方案能不能把数据发到MQTT服务器或者阿里云物联网平台。答案是可以的前提是4G模块支持MQTT功能或者你用裸模块通过AT指令走MQTT通道。逻辑上仍然是触摸屏拼好数据帧通过串口交给4G模块只是模块侧的协议从TCP透明传输变成MQTT发布消息报文格式也从HJ212变成平台自定义的JSON或者透传内容。如果只做数据上云展示MQTT是更现代的方式如果对接的是HJ212监管类平台就必须走本文这套TCPHJ212路径。两条路并不冲突现场串口够多的话可以同时接两个模块一边上一个平台。7.5 最后分享一个现场经验那次改造完成后我在现场又待了一个小时专门观察一个完整的发送周期数据采集、报文拼装、串口发送、DTU指示灯、平台后台入库。每一步的时序都对得上我才敢离开。后来这台设备稳定跑了一个多月再没出现过离线。我个人体会是用触摸屏拼HJ212这件事真正的门槛不在CRC算法也不在协议字段而在你有没有把每一层通信链路都看得足够清楚。触摸屏是个会算字符串的终端4G模块是个会搬数据的管道服务器是个等数据的仓库——把这三者之间每一层都验证透了任何故障都有迹可循。下次再遇到数采仪通讯问题先别急着买新设备看看站房里还有什么是闲着的也许答案早就摆在现场了。
返回列表