PIC18F96J94+PJ85718DM双链路温度监测HVAC控制方案
做嵌入式和 HVAC 温控的朋友应该都有体会测温本身不难难的是把温度测准、传得出去、并且在本地和远程两头都能稳定看到同一份数据。前阵子我完成了一个基于双链路温度监测的 HVAC 控制方案主控选的是 PIC18F96J94传感器端是 PJ85718DM整体覆盖了设备面板本地实时显示和 RS485 远程上报两条路径。这篇文章把需求拆解、硬件接口、软件状态机、协议设计和调试踩坑完整复盘一遍给正在做温控、环境监测或者楼宇自控相关项目的同学做个参照。1. 先别急着画板先把“本地和远程”这件事拆明白1.1 HVAC 场景里温度从来不是单点数据HVAC 指的是供热、通风与空调系统常见于楼宇自控、机房环境控制、新风机组、风机盘管这类设备。这类设备的温度监控几乎从来不是单点的一台空调箱至少要关注送风温度、回风温度有的还要叠加冷冻水进出水温度和室外补偿温度。为什么这么较真因为控制策略依赖的是温度差值、变化趋势和热惯性。回风温度只能反映房间整体热负荷的滞后结果送风温度直接决定人员舒适度两者偏差过大说明风量分配或者盘管换热出了问题。所以项目标题里强调“本地与远程温度”本质上是在说两种空间维度的数据本地是设备面板旁现场人员肉眼可见的温度远程是数十米甚至数百米外监控中心或上位机需要汇总的温度。这两类数据的采集链路、传输方式和可靠性要求都不一样放在同一个项目里处理最先要做的是分清职责边界。1.2 本地和远程监测技术路线的分水岭在哪本地监测的核心诉求是直观、稳定、低延迟。设备面板上能看到当前送风温度和回风温度刷新周期一两秒完全够关键是显示不能闪烁、数值不能乱跳不然现场维护的人看两眼就想拆机器。远程监测则完全相反数据要能长距离传输要能抵抗现场强电干扰要能被上位机轮询最好还能兼容已经存在的楼宇自控通讯习惯。所以我的方案里本地链路用 PIC18F96J94 直接驱动段式 LCD远程链路走 RS485 总线以类 Modbus 的协议上报温度寄存器。两条链路共享同一份经过滤波和标定的温度数据不会出现现场 LCD 和上位机各读一套温度、数值对不上的情况。这个拆分思路是最重要的一步硬件和软件的架构都围绕它展开。1.3 为什么选 PIC18F96J94 当主控选型阶段我对比过好几颗常见的 8 位机最后锁定了 PIC18F J94 系列。核心原因有三个。第一这系列自带段式 LCD 驱动模块可以直接推玻璃液晶省掉外部的显示驱动芯片BOM 成本和 PCB 面积都好看。第二3.3V 供电搭配多种低功耗模式在 24V AC 供电的 HVAC 控制盒里发热控制得很好整机温升对传感器读数的影响可以压到很低。第三外设接口齐全I2C、UART、SPI、ADC 都有“本地传感器采集 远程通信 段码显示”这三类任务不需要拼凑资源。这里多说一句它的内部振荡器。J94 系列的内部时钟精度在校准后足够支撑 RS485 在 9600bps 下稳定运行省掉一颗晶振和一个起振电容PCB 又能干净一点。当然如果你手头的具体型号是 J94 系列里其他容量或封装的变体只要确认 LCD 驱动和 UART 资源在位这套方案可以直接平移过去。2. 硬件方案选型与接口设计2.1 PJ85718DM 传感器模块的接入方式PJ85718DM 这边我当成一颗数字温度采集模块来用。它内部已经把敏感元件、信号调理和数字转换做在一起对外走 I2C 接口主控读寄存器就能拿到温度。采购时一定要让供应商提供数据手册几个关键参数必须逐项确认供电电压范围、I2C 从机地址、温度寄存器地址与数据格式、测量精度、转换时间。以我这边用的配置为例3.3V 供电I2C 总线速率 100kbps上电后首次转换完成大约需要几十毫秒之后工作在连续转换模式每次读寄存器拿到的都是最新值。硬件上SCL 和 SDA 必须各加一颗上拉电阻I2C 是开漏结构取值在 4.7k 到 10k 之间总线电容偏大时用小一点的上拉。电源引脚旁 0.1uF 陶瓷电容要贴着放PCB 入口再放一颗 10uF 钽电容吸收现场电源波动。如果某个批次拿到的 PJ85718DM 是模拟输出版本方案也不用推翻把它当作电压输出型传感器输出端直接进 PIC18F96J94 的 ADC 通道把后面第 3 节的数字读取流程换成 ADC 采样加查表换算就行。两种形态我都测过代码上预留一个编译开关就能同时兼容。2.2 传感器远端布线和 RS485 的关系这里要专门强调一个很多人容易搞错的点I2C 不适合长距离传输。有人图省事想从几十米外的风管里把 PJ85718DM 直接通过 I2C 拉回控制板结果要么通信不稳定要么抗干扰差。I2C 是给板级通信设计的超过一两米就开始冒风险。所以这个项目里PJ85718DM 只负责本地就近测量位置就在控制板附近最多一两米的柜内线缆。真正需要“远程测点”的场景我分两种方式处理一种是远端传感器和一个小采集板放一起采集板完成转换后通过 RS485 把数值打包上报另一种是 PJ85718DM 作为本地基准温度远程温度数据由 RS485 总线上挂载的其他远程采集站点提供主控汇总后一起显示、一起转发。对应到标题就是“本地温度由 PJ85718DM 直接读远程温度通过 RS485 总线上的远程站点合并数据”这套组合在现场跑下来最稳。2.3 电源、隔离与保护电路HVAC 现场最不缺的就是干扰。控制盒里通常有继电器、接触器、压缩机启动回路温度传感器这种小信号最容易遭殃。我的做法是24V AC/DC 进板后先过防反接二极管和自恢复保险丝再走 DC-DC 降到 3.3VDC-DC 输出侧加 LC 滤波传感器供电从滤波后的 3.3V 单独引一路避免和继电器驱动、LCD 这类瞬态负载共用同一根电源线。RS485 侧必须加 TVS 管和共模扼流圈A/B 差分线对之间并 120Ω 终端电阻。这个终端电阻不是随便加的它是用来匹配总线阻抗、消除反射的只能加在物理总线最远的两端设备上中间的设备不要并否则总线负载变重、通信反而变差。本地链路和远程链路的硬件要点差别不小我做成了一张速查表设计项本地链路LCD 显示远程链路RS485 上报核心器件PJ85718DM PIC18F96J94 LCD 驱动PIC18F96J94 UART 485 收发器传输介质板级 I2C线长控制在 1~2 米内双绞屏蔽线理论可达数百米抗干扰手段电源滤波、地线隔离、传感器单独供电共模扼流圈、TVS、120Ω 终端电阻数据可靠性CRC 校验可省略重读即可必须带 CRC16 和超时重试机制刷新要求1~2 秒刷新无闪烁轮询周期 100ms~1s可配置3. 软件架构与温度采集实现3.1 温度采集链路采样、滤波、标定三步走软件上温度采集不能“读一次就用”。我把它拆成采样、滤波、标定三个环节。采样环节要保证读到的数据是干净的、有节奏的。用 PIC18F96J94 的定时器产生一个 50ms 的中断节拍每次中断里对 PJ85718DM 发起一次 I2C 读取。不要在主循环里靠 delay 去读那样一旦被其他任务打断采样间隔就乱了。滤波环节用的是“滑动平均 去毛刺”组合。滑动平均窗口取 8 次把测量噪声压掉去毛刺是维护一个上下限当前值和上一次合法值之差超过 3 个 LSB 就丢弃防止继电器吸合瞬间的脉冲干扰直接进入数据链。标定环节解决的是精度问题。数字传感器出厂精度一般在正负 0.5 到 1 度但对 HVAC 控制来说还不够好尤其是变风量机组希望做到正负 0.3 度以内。我通常做两点标定用恒温槽或冰水混合物提供一个 0 度基准点再用精密温度计在 40 度左右提供一个高温点测出实际偏差后算出 offset 和 gain 两个系数写入 EEPROM。每次上电读系数换算温度时套进去。这个做法成本低、效果好比换更高精度的传感器划算得多。3.2 主循环调度与状态机设计整个固件我跑的是一个简单的状态机加时间片轮询没有上 RTOS8 位机资源没必要那么铺张。状态分为四态采集、换算、显示、通信。采集态定时器节拍触发执行 I2C 读取读到的原始值放入环形缓冲。换算态从环形缓冲取数据滑动平均套标定系数换算成带一位小数的温度值。显示态把温度值拆成段码更新 LCD。LCD 刷新放这里保证和采集解耦显示永远不会因为通信忙碌而卡住。通信态检查 RS485 接收缓冲区有完整帧就解析有查询请求就组帧回复。这四个状态由主循环轮询每个状态函数执行时间控制在 1ms 以内外部中断只置标志位绝不在中断里做耗时处理。实测下来 CPU 占用率不到 20%剩下的余量留给以后扩展 PID 算法或者多路传感器。3.3 LCD 驱动与刷新策略段式 LCD 和以前用的数码管完全是两个脾气。数码管你不停地刷新没问题段式 LCD 如果刷新频率不对或者驱动波形不对称就会出现对比度变浅、闪烁、甚至“烧屏”一样的残留。J94 系列自带 LCD 驱动模块只要把 LCD 配置寄存器设对用内部时钟生成驱动波形液晶由硬件自己周期性刷新软件只需要在数据变化时更新段码寄存器。我的刷新策略是温度值 1 秒更新一次中间完全不碰 LCD 寄存器。这样段码数据稳定驱动波形稳定液晶寿命和观感都有保障。如果暖气设备要求更快响应可以把刷新周期调到 500ms但不要低于 200ms段式玻璃液晶真没必要追那个数字。4. 核心代码与协议设计4.1 I2C 读取和温度换算的参考实现PIC18F96J94 的 MSSP 外设做 I2C 主机非常顺手。读取 PJ85718DM 的流程是发从机地址加写位写寄存器指针再发从机地址加读位连续读两个字节得到温度数据。参考代码如下// I2C 读取 PJ85718DM 温度寄存器16位数据 uint16_t pj85718dm_read_temp_reg(uint8_t reg) { uint16_t val 0; I2C1_Start(); I2C1_Write(PJ85718DM_ADDR 1 | 0); // 从机地址 写 I2C1_Write(reg); // 寄存器指针 I2C1_Restart(); I2C1_Write(PJ85718DM_ADDR 1 | 1); // 从机地址 读 val (uint16_t)I2C1_Read(1) 8; // ACK val | I2C1_Read(0); // NACK I2C1_Stop(); return val; }如果 PJ85718DM 的数据格式是补码的 0.01 度每 LSB换算就很简单int16_t raw (int16_t)pj85718dm_read_temp_reg(PJ85718DM_TEMP_REG); float temp_c raw * 0.01f; // 原始温度 temp_c temp_c * gain_coef offset_coef; // 两点标定补偿要注意的是 I2C 读操作必须带超时。如果在现场传感器线被老鼠咬断或者接插件氧化I2C 总线可能一直卡在等待 ACK 的状态没有超时的代码会让整机看起来像是死机。我的做法是在发送和接收两边各加一个计数器超过 100 次循环没完成就强制发 Stop 释放总线并置一个传感器错误标志显示界面上出现“Err”而不是一个骗人的固定数值。4.2 Modbus 风格寄存器映射与 CRC16远程通信我采用的是 Modbus RTU 风格的实现没有用完整协议栈只实现了功能码 03读保持寄存器和功能码 06写单个寄存器。这样做的好处是上层上位机、组态软件基本都能直接对接不用另外写驱动。寄存器映射设计如下寄存器地址内容说明0x0000本地温度PJ85718DM 实测值单位 0.1 度0x0001远程温度RS485 远程站点上报值单位 0.1 度0x0002温差本地与远程温度差单位 0.1 度0x0003状态字bit0本地传感器故障bit1远程通信超时CRC16 Modbus 的实现网上版本很多我直接贴一个自己验证过的查表版本uint16_t crc16_modbus(const uint8_t *buf, uint16_t len) { uint16_t crc 0xFFFF; for (uint16_t i 0; i len; i) { crc ^ buf[i]; for (uint8_t bit 0; bit 8; bit) { if (crc 1) crc (crc 1) ^ 0xA001; else crc 1; } } return crc; }组帧的时候 CRC 低字节在前、高字节在后这是 Modbus 的固定顺序踩坑的人很多别搞反。4.3 看门狗和低功耗调度的搭配HVAC 设备常常要求无人值守看门狗是必须的。J94 系列自带看门狗我给看门狗设了 2 秒溢出。关键在于“喂狗”的位置不能在主循环开头喂而是放在状态机所有分支都跑完之后喂这样任何一路逻辑卡死狗都会把芯片拉回来。我还把 EEPROM 里的标定系数做了双备份主备份和副备份各带一个校验和一旦主备份损坏自动切到副备份并置标志位避免现场设备因为掉电丢标定数据而测出离谱温度。5. 调试实录与常见问题排查5.1 温度读数跳变八成是电源和接地的问题调试阶段最容易遇到的现象是LCD 上温度数值稳定但只要旁边继电器一吸合数值立刻跳 1 到 2 度。很多人第一反应是传感器坏了其实大概率是电源被污染。我排查的顺序是先看 3.3V 电源纹波继电器动作瞬间有没有尖峰再查传感器地线是不是和继电器驱动回路共用了走线最后才去怀疑传感器本身。解决办法就是第 2 节说的传感器独立供电、独立地线、电源加 LC 滤波。这三点都做到之后我实测温度数值的抖动幅度从正负 0.3 度降到了正负 0.05 度以内。5.2 RS485 远程丢帧和误码的处理实录远程通信的问题集中在三处波特率误差、终端电阻、地电位差。J94 内部振荡器虽然出厂校准过但温度和电压变化后还是会有偏差。我调试时遇到过上位机偶尔收错帧用示波器量波形发现波特率差了将近 2%当即改成使用 UART 模块的内部高精度时钟源偏差降到 0.5% 以内9600bps 下再没丢过帧。终端电阻的问题前面说过现场施工队伍经常把每台设备都加上 120Ω结果总线负载太重通信距离和带负载能力直线下降。地电位差的问题要靠共模扼流圈和 TVS 管解决如果现场两端设备相隔很远地电位不一致宁可把两端的信号地断开只靠差分信号传输。5.3 常见问题速查表现象可能原因检查顺序温度读数周期性跳变电源纹波、地线共用示波器看 3.3V 纹波再查布线I2C 读不到数据上拉电阻缺失、地址错误、线序接反量 SCL/SDA 静态电平确认地址位LCD 对比度淡LCD 偏压配置不对、刷新率过低检查 LCD 配置寄存器、供电电压远程偶尔丢帧波特率偏差、终端电阻位置错误示波器量波形检查总线两端整机偶发复位看门狗超时喂、电源跌落查喂狗位置检查 DC-DC 输出跌落标定后温度仍然偏标定系数没写入 EEPROM、写错地址上电读系数打印核对每个问题我在现场都真实遇到过尤其是“看门狗把整机拉复位”那个排查了很久才发现是一个 I2C 读取函数在传感器异常时没有超时退出主循环卡死导致喂狗超时。所以我在代码规范里定了一条死规矩任何外设操作必须配超时任何状态机分支必须保证能回到主循环。结尾这个项目做完之后我最大的体会是温度监测项目真正的技术含量不在“读温度”本身而在数据可信度和链路鲁棒性。一把示波器、一组可靠的标定数据、一条带超时的软件逻辑比换更高规格的传感器更能解决现场问题。最后再分享一个小技巧如果你手头的 PJ85718DM 数据手册写得不详细最笨也最有效的办法是上电后遍历一遍 I2C 地址把应答的设备地址打印出来确认避免因为默认地址和手册标注不一致而浪费一整天。这套基于 PIC18F96J94 加 PJ85718DM 的双链路监测方案后续还可以直接扩展出湿度监测、PID 控温输出和故障预警日志骨架已经打好剩下就是往里面挂功能的事了。