基于PJ85718DM与PIC18F85J50的HVAC本地/远程温度监测设计
做嵌入式系统或者暖通空调HVAC控制的同行应该都有过类似的经历设备明明显示“温度正常”现场却已经热保护停机了。问题往往不是测错了而是测的温度根本不是你想关心的那个温度。这个项目里我用了一颗本地/远程温度前端PJ85718DM配合一颗PIC18F85J50单片机把板级本地温度和风道、房间里的远程温度放进同一套链路统一监测既解决了设备过热预警的问题也满足了空调机组远程温控的数据需求。对做楼宇自控、HVAC机组、储能柜、通信基站监控的朋友来说这套思路可以直接参考复用。1. 方案定位与整体设计1.1 嵌入式与HVAC场景下本地和远程温度分别指什么先把概念补齐。嵌入式设备里说本地温度通常指控制电路板本身、MCU附近、功率器件或电源模块表面那一路温度。它反映的是“设备自身有没有过热风险”比如处理器降频、接触器线圈过热、IGBT散热片温度超标这类数据直接决定了设备能不能继续运行。远程温度在HVAC场景里指的是真正的环境测点风管内的送风温度、房间回风口的温度、室外机附近的空气温度或者是被冷却机柜内部的温度。它反映的是“系统提供给人或设备的温湿效果”这路数据往往距离主控板有几米到几十米线缆要穿过金属桥架、和动力线走同一个线槽。实际项目里这两路必须分开测原因很简单。我之前处理过一台组合式空调箱的控制面板报警控制器报“机柜温度过高”但打开柜门很快降温到底该不该停机大家都拿不准。后来把板级温度和风道温度分开采集才发现主控板靠近接触器和变压器夏天柜内温度本来就接近55°C而真正要保证的送风温度其实正常。如果只测一路要么频繁误报警要么漏掉真正的故障。两路温度一起用还能做联动判断。比如HVAC的防冻保护盘管附近温度低于设定值同时回风温度也在往下走基本可以判断水路或者风阀出了问题如果只有一路异常可能是探头位置不对或者传感器本身坏了。本地和远程形成交叉验证整套监测的可靠性会高很多。1.2 为什么用PJ85718DM加PIC18F85J50这对组合先讲传感器这边。早期做温度采集最常用的是热敏电阻加ADC但HVAC柜内环境干扰很强热敏电阻输出的模拟电压长线传输后很容易被接触器吸合干扰影响而且每颗热敏电阻的B值曲线不完全一致批量生产时要逐个标定很麻烦。PJ85718DM这类的温度前端芯片把本地测温单元和外部远程测温通道做进了同一颗器件里直接输出数字量。本地通道测板温远程通道接一个外置探头放到风管或者房间远端不需要额外的恒流源、放大器和ADC校准。更关键的是它还有一个ALERT告警脚温度越限可以直接拉低接到主控的中断上比软件里轮询阈值更及时也省主控时间去扫寄存器。主控这边选PIC18F85J50主要看中三点。第一Flash和RAM在PIC18系列里属于中上水平存一套Modbus从站协议、温度滤波算法和配置参数完全够用第二这个型号有多个硬件UART和硬件SPI/I2C模块一路UART做RS485远程上报一路UART做调试输出I2C对接传感器外设能同时工作不用软件模拟吃CPU第三外部中断和定时器资源够接传感器告警脚、做采集周期调度都不需要抠门。对比过用普通8位MCU加运算放大器搭模拟采样电路成本表面上低一点但模拟链路在强电柜里的抗干扰、批量标定、故障排查全是隐性成本。数字传感器加数字总线的方案算总账反而更省。1.3 整体数据链路规划这套系统的数据流可以分成四条链路各管各的温度采集链路外置远端探头和板载本地测温单元接入PJ85718DM芯片通过I2C与PIC18F85J50通信读取两路温度值。远程上报链路PIC的UART接RS485收发器走Modbus RTU协议把本地温度、远程温度和状态字发给上位机或者楼宇BA系统。本地显示链路PIC通过SPI接一块LCD或者数码管现场人员不开上位机也能直接看温度方便设备调试和维护。告警动作链路PJ85718DM的ALERT脚接PIC外部中断温度超过高温阈值或者低于低温阈值时传感器硬件直接打断主控主控立刻执行保护逻辑。为什么要这样拆HVAC现场最麻烦的就是强电干扰和施工布线。数据在传感器端就转成数字量I2C线短距离走板内不会像模拟信号那样把几米外的干扰直接引进来。远程上报用RS485和Modbus是目前HVAC、楼宇自控和工业现场兼容性最好的一套组合上位机、触摸屏、PLC基本都能直接对接。本地显示是用来看现场状态的设备调试时不需要抱着电脑跑上跑下。这套链路设计的关键是“数据分层”底层负责采集中间层负责处理上层负责呈现和上报。每一层之间通过寄存器表、协议帧解耦后期换传感器型号或者换上位机平台都只改局部不用推翻重来。2. 硬件设计与引脚级细节2.1 PJ85718DM的寄存器模型与工作模式PJ85718DM这类本地加远程一体的数字温度传感器内部通常包含配置寄存器、本地温度寄存器、远程温度寄存器、状态寄存器和高温/低温阈值寄存器。具体地址和位域不同批次会有一点差异但设计逻辑是通用的配置寄存器决定工作模式、转换分辨率、报警极性等行为温度寄存器存放转换结果状态寄存器标记有没有越限、有没有转换完成阈值寄存器存储用户设定的报警上下限。它可以看成一支数字体温计但同时它自己也在测环境温度还拖着一根外置探头测远端温度。芯片内部完成远端探头信号的处理把微小的电压信号转换成数字量这对抗干扰很有帮助因为远端探头出来的小信号在芯片内部就被就地数字化了不会在板子上绕一大圈再被干扰。工作模式方面HVAC这类持续监测场景建议用连续转换模式温度变化能被及时捕捉嵌入式低功耗场景则可以用单次转换模式想省电的时候按需发起一次测量然后进入睡眠。报警阈值寄存器配置好后ALERT脚就能工作在比较独立的硬件告警状态即使主控在忙别的传感器也能自己盯住温度。配置这类芯片有个容易忽略的细节不少型号在刚上电时会有一段启动时间有些芯片的寄存器需要写入“软复位”命令再等待转换就绪否则读取的第一帧数据可能是空值。我的做法是在初始化流程里固定加一步延迟和状态寄存器等待确保所有外设准备就绪后再进入正常运行。2.2 PIC18F85J50的外设分配与接口设计PIC18F85J50的引脚资源比较多但也不能随手乱接。引脚分配需要先把复用外设固定下来再安排普通I/O否则后面画PCB时会发现走线绕成蜘蛛网。我在这套系统里的分配思路是这样的MSSP模块做I2C主模式速率定在400kHz对接PJ85718DM。SCL和SDA在板内走线距离很短不需要额外驱动。UART1接RS485收发器作为Modbus RTU从站接口默认波特率9600HVAC上位机轮询周期一般1到5秒这个速率完全够用。UART2接调试串口用来打印系统运行状态、转换原始值和滤波结果开发阶段非常有用量产时可以不接或者禁用。外部中断引脚接传感器ALERT脚配置为下降沿触发温度越限时PIC立刻进入中断处理。SPI模块接LCD显示屏刷新频率不高占用资源小。有个需要注意的地方PIC18F85J50同一组引脚往往由多个外设复用比如某几个引脚既能做I2C又能做SPI或者ADC。项目里必须先读清楚复用表把I2C的外设信号和RS485的UART信号放到不会冲突的引脚组上。我建议先用表格列一遍所有要用的外设功能再对照引脚复用关系做一次分配确认没有信号交叠再画原理图。此外ALERT脚最好加上拉电阻因为这类开漏告警输出需要外部上拉到高电平越限时拉低。如果省掉上拉中断脚的电平会一直飘进不了下降沿中断或者误触发不停。2.3 硬件布线、供电与去耦注意事项硬件设计里翻车最多的不是原理图而是供电和布线。先看供电PJ85718DM这类数字传感器如果工作在低电压而PIC18F85J50的外围电路电压不一致I2C电平就可能不匹配。稳妥做法是全部统一到同一逻辑电平面如果实在统一不了必须在SCL、SDA上增加电平转换电路而不是用一个电阻分压草草了事否则高速通信时波形边沿会变得很难看偶发数据错误。再看I2C上拉电阻。板内I2C线路不长时典型值选4.7k到10k都行。但如果传感器通过延长座或者排线连接线路电容变大上拉电阻太小会拖慢上升沿太大会导致信号边沿不够。实测下来85厘米以内的排线用2.2k比较稳20厘米以内的板内走线用4.7k没有任何问题。设计时最好预留贴不同阻值电阻的位置方便现场调整。远程探头线缆是另一处重点。HVAC现场尤其要注意探头线必须走屏蔽双绞线屏蔽层单端接地不要和接触器线圈线、变频器输出线平行走同一桥架。远端探头接口位置还要加ESD保护器件和简单的RC滤波因为柜内空间有限施工时经常有人把探头线跟强电线绑在一起不会有明显pp但干扰会体现在温度读数上。本地测温位置同样要慎重。要测“板温”传感器就离大功率发热元器件保持一点距离要测“芯片壳温”可以把探头或者传感器本体靠近芯片表面但不要直接压在散热片上。还有一个常被忽略的点机柜内空气不流动时本地温度寄存器反映的是局部热点的温度不是柜内平均温度所以本地测温点应该放在最容易超过设计阈值的那些元器件附近而不是放在PCB正中间图好看。3. 固件实现与温度数据处理3.1 初始化与寄存器配置固件部分要从初始化开始。核心思路是先让PIC的I2C外设就绪再让PJ85718DM进入已知状态最后配置转换模式、分辨率和报警阈值。初始化代码大致是这样的结构#define PJ_I2C_ADDR 0x9A // 7位地址左移后得到实际以手册为准 #define REG_CONFIG 0x01 #define REG_LOCAL_TEMP 0x05 #define REG_REMOTE_TEMP 0x07 #define REG_STATUS 0x02 #define REG_THIGH 0x03 #define REG_TLOW 0x04 void pj_init(void) { uint8_t cfg, status; I2C_Init(400000); // 主模式400kHz // 写配置连续转换12位分辨率告警极性低有效 cfg 0x60; I2C_WriteReg(PJ_I2C_ADDR, REG_CONFIG, cfg); // 写报警阈值先屏蔽做最保守的上下限 I2C_WriteReg(PJ_I2C_ADDR, REG_THIGH, 0x7F); I2C_WriteReg(PJ_I2C_ADDR, REG_TLOW, 0x80); // 等芯片完成一次转换 do { status I2C_ReadReg(PJ_I2C_ADDR, REG_STATUS); } while ((status 0x80) 0); }写配置时最忌讳的是把所有寄存器一次性写死。不同芯片的配置位含义有差异如果直接把手册里的示例值照搬很可能在量产批次的芯片上出现行为不一致。我习惯把配置值定义成宏并注释每个位域的作用后续换料或者调试时改起来很方便。初始化完成后可以先读一次本地温度和远程温度打印出来确认传感器的确在工作再进行后续的采集调度。3.2 温度读取、符号扩展与线性换算PJ85718DM这类芯片通常把温度值放在两个字节的寄存器里温度数据以二进制补码表示。读取之后不能直接当无符号数使用要先做符号扩展。对于12位分辨率、LSB对应0.0625°C的常见格式来说代码可以这样写int16_t read_temp(uint8_t reg_addr) { uint8_t msb, lsb; int16_t raw; msb I2C_ReadReg(PJ_I2C_ADDR, reg_addr); lsb I2C_ReadReg(PJ_I2C_ADDR, reg_addr 1); raw ((int16_t)msb 8) | lsb; if (raw 0x8000) { raw | 0xF000; // 符号扩展保留负温度 } // 右移4位得到12位有效数据对应0.0625°C的整数值 return (raw 4) * 100; // 返回放大100倍的温度单位0.01°C }为什么不直接返回浮点数因为在PIC18这类8位MCU上浮点运算虽然能用但会占用大量时间。HVAC项目的温度采集周期一般是100毫秒到1秒其实并不缺这点性能但少用浮点可以降低代码体积也方便后续移植到更小的芯片。读取远程温度时要特别留意远程通道的探头类型不同数据格式可能和本地通道不完全一致。有的芯片本地通道和远程通道的分辨率一样但有的远程通道因为外部探头特性非理想可能需要套用官方提供的一组校准系数。不要拿着本地通道的换算公式直接套远程通道要仔细看手册里的换算说明。3.3 软件滤波与远端探头线损补偿温度传感器原始读数在HVAC现场会出现随机波动主要来自风机振动、环境气流变化和电磁干扰。完全相信单次采样结果的代价是误报警所以我加了一阶低通滤波int16_t filter_temp(int16_t new_value, int16_t *filtered, uint8_t alpha) { *filtered ((int32_t)(new_value - *filtered) * alpha 128) 8; return *filtered; }alpha取255表示完全相信新值取1表示滤波非常重。HVAC系统本身热惯性很大温度不会突变一般把alpha放在32到64之间对应几秒的时间常数兼顾稳定性和响应速度。嵌入式过热保护场景则要区分对待如果监测的是芯片结温附近的温度滤波太重会导致保护滞后alpha可以放到200左右甚至不滤波直接把原始值用于判断。远端探头线损是另一个实际问题。远程探头线很长时线缆内阻和接触电阻会被温度传感器前端感知成额外的信号衰减导致测出来的温度偏高或偏低。硬件上最好选带屏蔽层的双绞线软件上做一段补偿表。具体做法是拿一段已知长度的短参考探头和长线探头同时测量同一热源记录差值在固件里查表修正。这种修正不严谨但很实用尤其现场不允许频繁断电接线的时候。3.4 温度数据的本地显示与远程上报数据上屏相对简单把滤波后的本地温度、远程温度和报警状态按固定格式显示在LCD上。调试阶段我会增加一屏显示原始ADC值或者寄存器值方便现场判断传感器有没有异常。这个调试界面在量产版本里可以隐藏但开发时很有用。远程上报走Modbus RTU从站我维护了一张数据映射表比如保持寄存器0x0000放本地温度0x0001放远程温度0x0002放状态字状态字里分别用bit表示传感器是否在线、是否越限。上位机只需要周期读取这三个寄存器就能完成监控。Modbus RTU报文本身不复杂。比如上位机下发01 03 00 00 00 03 05 CB含义是站号1功能码03读保持寄存器起始地址0x0000读3个寄存器后面是CRC校验。从机返回的帧里按顺序填充六个字节数据最后追加CRC16。CRC16算法是Modbus标准多项式0xA001代码逻辑固定网上有大量成熟实现不需要重复发明轮子。这里有个经验当从机响应时间超过了上位机期望的应答时间上位机往往会报超时。所以从机主循环里温度采集和Modbus处理要分优先级RS485接收中断里只收帧不处理业务等一帧收完整了再处理避免在上位机轮询时去做耗时的I2C读取和滤波计算。4. 调试实录与常见问题排查4.1 远程温度狂跳先怀疑机械连接这套系统调试时最头疼的是远程通道温度突然从正常值跳到-50°C或者85°C。第一反应不要查固件先去查硬件连接。我遇到过一次典型的现场问题远程探头线中间用端子排转接端子螺钉没压紧线缆在风机振动下接触电阻随机波动传感器把波动直接反映成温度跳变。用示波器抓探头信号线能看到低频毛刺电笔一碰就恢复。处理方式是重新压接端子线缆固定好屏蔽层单端接地问题立刻消失。这个案例说明一个规律数字传感器的数字输出不代表前端信号是数字的探头信号依然是微弱的模拟量。只要模拟量在物理上被干扰后面怎么滤波都没用。排查顺序应该是机械连接在前软件滤波在后。4.2 I2C偶发超时电平与上拉电阻两处暗坑另一个常见问题是I2C总线偶尔卡死读上来的温度突然全是0xFF或者总线挂住不响应。最初我怀疑是芯片时序问题反复检查代码也无果最后发现是主控和传感器两者供电电压不一致加上I2C上拉电阻值偏大导致高电平没有被可靠拉起来。把供电统一、上拉电阻换成2.2k之后连续运行三天没有出现一次卡死。为了保险固件侧也加了超时重试机制每次I2C通信前检查总线空闲状态发现SCL被拉低超过一定时间就执行总线恢复序列把SCL切换成GPIO手动翻转几帧释放总线。这套软件容错虽然不能解决硬件缺陷但能显著降低偶发故障造成的影响。4.3 实测温度偏离标定流程和两点校正设备装到现场后用户投诉送风温度和实测风温差2°C。这种情况先别急着改代码先做标定。标准做法是把探头和标准温度计同时放进冰水混合物和恒温槽分别稳定后记录原始寄存器值。标定的数学处理很简单当作线性校龄// T_cal k * raw b // T1, T2 为标准温度D1, D2 为对应原始读数 // k (T2 - T1) / (D2 - D1) // b T1 - k * D1两点标定之后还有微小的非线性但如果温度范围控制在0到70°C线性近似的误差基本可以接受。真正影响标定质量的是操作细节探头放进恒温槽必须等读数完全稳定再记录一般要等5分钟以上不能看数字差不多就抄记录标准温度计时不要让手接触温度计球泡否则又是一次人为误差。4.4 常见问题速查表现象大概率原因排查与处理远程温度跳变探头线端子接触不良、屏蔽层未接地、ESD击穿重新压接、固定线缆、单端接地、加保护器件I2C读回0xFF或总线卡死电平不匹配、上拉电阻过大、总线被拉低统一供电、换小阻值上拉、软件总线恢复温度整体偏高或偏低探头位置错误、未标定、线损未补偿检查探头安装位置、做两点标定、查表修正报警频繁误触发阈值设置过于贴近正常值、滤波太弱调宽阈值范围、增加滤波时间常数Modbus偶发超时从机处理耗时、波特率不匹配、地址错误优化主循环调度、核对CRC和站号本地温度异常高传感器靠近散热片、柜内气流不畅调整板级测温点位置、改善通风这套速查表是我实际调试中反复用到的省去了很多翻手册的时间。硬件和软件问题的比例大约七比三所以遇到异常先动手检查接线再动代码顺序别反过来。最后再分享一点个人体会。如果让我重新做一遍这个项目我会先把远端探头线的走向、固定方式和接地原则定死再开始标定。温度监测最难的不是把寄存器里的数字读出来而是让这个数字在真实环境里始终反映物理实际。软件滤波只能改善表象硬件和结构上的确定性才是稳定的基础。希望这套基于PJ85718DM和PIC18F85J50的实路方案能帮你少走几步弯路。