
连续做了几套空调和风柜的控制改造之后我对“温度测量”这件事的理解完全变了。早期方案都习惯在主控板上放一个热敏电阻测到的只是电路板附近的空气温度而机组真正关键的位置——风管送风口、表冷器盘管、回风混合区——全靠维护人员拿测温枪去点。这个项目里我换了一种做法主控选用 STM32F207ZG温度前端用一颗 PJ85718DM这颗芯片能够同时输出本地温度和远程温度两路数据。也就是说一条 I2C 总线上控制器自身的温度和环境远端关键点的温度就都拿到了。把它用在嵌入式和 HVAC 场景里就会发现“本地与远程温度”同时被监测不是参数上的卖点而是控制逻辑真正的刚需。下面把选型思路、硬件接线、固件实现和控制逻辑完整拆开讲一遍。1. 本地和远程两个测量点为什么在 HVAC 里一个都不能少1.1 只测一个点机器就会按错误的信息做决策HVAC 系统的控制从来不是“看到一个温度”就能干活的。风柜要判断制冷状态是否正常需要看表冷器盘管表面温度和回风温度的差值变频压缩机要判断散热情况需要看冷凝器进出风温差冬天防冻保护要动作则必须盯着最容易结冰的那个远端盘管点。这些位置在物理上离控制板可能只有几十厘米也可能隔了数米线缆。如果只依赖控制器本体的温度逻辑上等于闭着眼睛开车主板附近温度正常不代表盘管没有冻结风险机箱风扇吹得很舒服不代表功率模块已经快要过温。所以选测温方案的时候我的原则很直接至少要能同时覆盖两个空间位置。一个点给控制器的自身工况做“健康管理”另一个点给被控对象做“过程测控”。二者缺一不可。1.2 PJ85718DM 与 STM32F207ZG 的角色分配这颗方案里STM32F207ZG 负责所有上层事务I2C 总线上定时读取两路温度做滑动滤波执行温差判定、风扇调速和保护连锁同时还跑着 Modbus 或者私有协议和上位机通信。它的 Cortex-M3 主频跑到 120MHz外设接口又多配这种多任务场景非常从容。PJ85718DM 则专门干模拟前端这件事。它的本地通道在芯片内部完成温度-数字转换远程通道通过一个外部二极管结来测远端的温度。芯片空闲的时候把两个通道轮流转换STM32F207ZG 只需要按寄存器地址取值就行。对比传统的“NTC 热敏电阻 运放 ADC”方案好处很明显没有模拟校准的烦恼没有长线干扰放大问题而且温度数据是数字量误差一致性很好。对 HVAC 这种需要长期稳定运行、又经常被维护人员校准的设备来说省下来的调试工时非常可观。1.3 远程温度的本质说穿了就是测量一个二极管结很多新接触这类芯片的人第一次看“远程温度”会误以为它带了一个无线电温度探头。其实不是它的远程通道就是一个电子学上的“二极管结温度传感器”。简单解释一下原理半导体 PN 结的正向压降会随温度变化大约每升高 1℃ 压降下降 1.82.2mV。把一个小三极管接成二极管形式——基极和集电极短接接到芯片的 D发射极接到 D-——芯片内部施加恒定偏置电流测量这个结的压降再经过内部转换器计算就还原成温度值。这个思路的好处是传感器体积小、热响应快而且没有 NTC 的“电阻-温度”非线性问题校准工作少很多。实际项目里我常用 SOT-23 封装的小三极管当远端探头效果很稳定。2. 硬件连接怎么布局才不辜负这颗双通道芯片2.1 本地通道的放置位置直接影响主板自身保护是否有效本地通道虽然号称“芯片内部”但它测的是芯片自身封装附近的温度。所以 PJ85718DM 在 PCB 上的位置不能随意摆。我的习惯是放在控制板进风口一侧避开大功率开关管、电源变压器和 DRAM 发热区域。也不要贴得太靠近 MCU 晶振旁边晶振功耗虽小但在高负载频率下依然会产生局部温升导致本地通道读数偏高几度。还要考虑外壳内部的气流方向。如果板子被闷在密封塑料壳里而旁边又有变压器持续发热本地温度测到的其实是“机箱内热空气温度”而不是“电子元件所在环境的真实温度”。这种情况下做出来的过温保护阈值往往偏保守设备容易被误保护停机。调试中我遇到过一辆控制柜本地温度比环境实测高 8℃ 的情况最后就是把传感器芯片从发热源附近挪开同时调整了安装支架的散热开孔才解决。2.2 远程探头的连接四根线比两根线更能抗干扰远程二极管只需要两个电气端点但走线方式直接决定测量精度。HPJ85718DM 这类芯片在处理远程结压降时通常需要消除线缆电阻的影响工程上推荐的办法是四线连接或至少两条线紧密绞合。我的做法是把 SOT-23 的小三极管焊在一个小型端子座上连线用双绞线引出。绞合是必须的因为两根等长并行线如果靠近变频器输出电缆会把共模干扰对称地引入两端芯片内部的差分处理能抵消大部分如果两根线平行但不绞合感应的差模噪声就会直接折算成温度误差。线缆长度方面我通常控制在 3 米以内。超过这个长度结电压信号衰减、寄生电容增大采样稳定性和抗干扰能力都明显下降。如果真的需要更远距离应当在信号链里加对应的驱动电路而不是简单把线拉长。另外远程走线严禁和 220V 动力线、风机驱动线绑在一起走同一个线槽。强电侧一启动远程温度跳动几度是常有的事。2.3 I2C 总线细节上拉电阻、电平匹配与地址分配PJ85718DM 的 SCL 和 SDA 是开漏输出必须接上拉电阻。STM32F207ZG 的 GPIO 工作在 3.3V而不少 HVAC 控制板上还有其他 5V 器件这时候要注意电平匹配。我一般直接用 3.3V 供电给传感器芯片上拉电阻接 3.3V避免 3.3V 和 5V 混用导致芯片输入过压。上拉阻值选 4.7kΩ总线长度短、布局紧凑这个值很好用如果总线上挂的设备特别多才考虑降低到 2.2kΩ。地址分配也不要忽略。HVAC 控制板上常同时存在 EEPROM、实时时钟、温湿度传感器I2C 地址冲突很常见。PJ85718DM 这类芯片通常留出一个或多个地址脚通过接高/接低来改变地址位。接地址脚的线上我习惯加一个 10kΩ 下拉或上拉电阻不要直接悬空避免上电瞬间引脚状态不确定导致地址漂移。而且多个 I2C 器件共用一条总线时读卡前先做个总线扫描把所有设备地址打印出来可以省掉后面的一大堆踩坑时间。3. 寄存器读数和温度换算固件侧最关键的实现细节3.1 寄存器结构与数据格式寄存器地址和位宽因具体批次会略有差异我以手上这颗样片为例给出参考框架。芯片内部一般分成配置寄存器和数据寄存器两类。数据寄存器里本地通道占两个字节远程通道也占两个字节高字节是温度整数部分低字节包含小数位和符号信息。有些型号把低字节的低 5 位作为扩展精度有些是低 7 位读出来之后要根据数据格式做右移再乘分辨率系数。这里最容易踩的坑是“无符号就拿来算了”。温度可以是负值冬天防冻保护场景下冷静态回风温度就可能是 -10℃ 甚至更低。如果固件只把两字节拼成一个 uint16_t用无符号数乘系数-5℃ 会被算成 250℃ 左右之类的大正数。正确做法是拼完后做符号扩展判断高字节最高位如果是 1就把高 16 位全部填充为 1得到一个正确的 int16_t再乘比例系数。这一步漏了负温度区段整个逻辑全是错的。3.2 一个可以直接抄的读取函数下面是参考性质的读取函数按常见的“寄存器指针 读两字节”方式处理#include math.h /* 从芯片读取一个通道的温度返回摄氏度失败返回 NAN */ float read_temp_channel(I2C_HandleTypeDef *hi2c, uint8_t dev_addr, uint8_t reg) { uint8_t buf[2]; int16_t raw; if (HAL_I2C_Mem_Read(hi2c, dev_addr, reg, I2C_MEMADD_SIZE_8BIT, buf, 2, 100) ! HAL_OK) { return NAN; } raw (int16_t)((uint16_t)((buf[0] 8) | buf[1])); /* 以常见的 13 位分辨率为例低 5 位是小数部分 先去掉低位再按 LSB0.0625℃ 换算 */ raw 3; /* 符号扩展避免负温度被当作大正数 */ if (raw 0x1000) { raw | 0xF000; } return (float)raw * 0.0625f; }调用时就分两次读float t_local read_temp_channel(hi2c1, 0x90, LOCAL_TEMP_REG); float t_remote read_temp_channel(hi2c1, 0x90, REMOTE_TEMP_REG);这里的0x90是示例地址实际地址要按硬件接法确定。注意HAL_I2C_Mem_Read的地址参数一般要求是 8 位格式的 I2C 设备地址和裸地址的对应关系要查对应 HAL 手册别把地址高低位搞反。3.3 采样、滤波与标定HVAC 系统里面有风机、压缩机、电磁阀运行电流变化很大温度读数在个别采样周期出现尖峰是很正常的事。我通常不直接拿单次采样值去做控制。控制循环每 200ms 读一次两路温度丢进一个长度为 5 或 8 的环形缓冲区取中位值作为有效输入。中位值滤波比简单平均更能抗尖峰噪声而且不会让控制响应变得迟钝。标定环节也很重要。双通道芯片出厂前已经做过程校准但系统级误差还包含电路板发热、远程探头线阻、焊接差异等。第一次装机调试时我会用经过计量的参考温度计放在本地通道旁边等热平衡后记录差值在固件里加一个偏移量。远程通道则在 0℃ 冰水混合物状态做单点校准。这样做完之后整个系统的绝对误差通常在 ±0.5℃ 级别在 HVAC 控制里足够用了。4. 把两路温度落进 HVAC 控制逻辑4.1 温差而不是绝对温度控制逻辑里我最强调的一件事不要总盯着绝对温度做判断要多用两路温度的差值。比如风柜制冷工况下正常情况送风温度比回风温度低 58℃如果温差逐渐缩小说明盘管换热能力下降或者制冷量不足。这种判断用t_remote减t_local就够了。假如只看送风绝对温度夏天环境温度是 35℃ 还是 28℃同样一个“送风 18℃”的结论背后的工况完全不同不做补偿就容易判断错误。防冻保护也同理。冬天盘管进水温度降低远程通道的温度下降到约 2℃ 时应该先启动风机提高盘管温度到 0℃ 持续 30 秒以上才触发防冻保护停机。这种二级阈值比一个单一温度跳变报警可靠得多。4.2 风机调节与压缩机保护联动两路温度还能直接用来生成风机调速的输入量。我的做法是把本地温度作为控制器机箱散热依据把远程温度作为机组换热依据两者里取更“危险”的那个作为调速主变量。具体公式用很简单的 P 控制加限幅/* 伪代码根据温度差值输出风机占空比 */ float setpoint 30.0f; /* 目标送风温度根据工况设定 */ float error setpoint - t_remote; /* 误差负值代表送风过冷 */ float duty 40.0f 2.0f * error; /* 基础风量 40%误差乘比例系数 */ duty clamp(duty, 20.0f, 100.0f); /* 限幅保护 */压缩机保护则参考本地和远程温差当盘管温度接近环境温度时说明系统可能缺制冷剂或换热失效这时候给压缩机一个告警信号等人工确认后再决定是否停机。实际控制里我会加回滞区间比如进入保护的条件是温差小于 1℃退出保护条件是温差重新超过 3℃。没有回滞系统会在临界点附近反复启停压缩机是非常忌讳频繁起停的。4.3 远程探头的故障识别不能省两根远程线在外场使用时间长了端子氧化、断线、短路都可能出现。PJ85718DM 这类芯片在远程通道异常时会读出超范围的数值比如接近 0V 压差或过大压差转换出来的温度会跑到 -64℃ 或者 127℃ 附近。固件里一定要做故障识别而不是把这些无效值直接送进控制运算。我的做法是读到温度后先判断是否落在 -40℃125℃ 之外如果是马上标记远程通道故障控制逻辑切回“只依赖本地温度”的降级模式同时向上位机报故障码。低温报警不要立刻停机用“持续故障超过 10 秒才确认”的方式滤掉瞬态干扰否则线缆接头松一下整个系统就停机维护成本太高。5. 实测现场最容易撞上的三个坑5.1 远程温度读数跳变先从走线查起第一次在现场调试远程温度正常工作时很稳但只要主机柜里的变频器一启动远程温度就会在真实值和真实值加 5℃ 之间来回跳。我检查了固件滤波也检查了采样时序最后发现远程探头的那两根信号线被现场工人顺手跟变频器输出电缆绑在了同一个线槽里而且没有绞合。这是典型的差模干扰。变频器输出端的 PWM 电压跳变通过寄生电容耦合到信号线上干扰信号并不对称芯片的差分处理抵消不掉。我把两根信号线拆出来单独套了屏蔽线并双端接地又换成绞合走线问题立刻消失。这里要补充一句屏蔽层单端接地就可以了双端接地反而容易形成地环路。5.2 I2C 偶发 NACK 甚至总线卡死第二种常见问题是 I2C 通信偶尔失败。有时候读一次失败下一次又恢复了有时候整个 I2C 总线挂死SCL 和 SDA 全部被拉低。用示波器看波形SDA 上升沿很缓像是一条倾斜的线说明上拉电阻太大或者总线电容过重。HVAC 现场线缆长、屏蔽层电容大4.7kΩ 上拉在实验室能跑拉到现场就不行。我把上拉电阻改成 2.2kΩ并把总线通信速率从 400kHz 降到 100kHz之后卡死频率明显降低。另外固件里加一个 I2C 超时重置机制每次读取设 50ms 超时一旦超时就先把总线恢复成 GPIO 模式手动翻转 SCL 九次再重新初始化。这样处理从根上保证通信不会长时间卡死。5.3 温度读数整体偏高先查电源和校准还有一个常见的系统性偏差本地温度读数比参考温度计高 23℃远程通道也偏高差不多。这不是芯片坏了多半是供电电压偏高或者芯片靠近热源又或者是校准没做。先看 VDD 是否在规格范围内。芯片的内部基准源随供电变化会有一定漂移供电电压偏高会带来系统性偏差。排除供电问题以后再做一次单点校准把参考温度计和传感器放在同一热源旁边稳定 30 分钟记录差值写入偏移寄存器或者固件补偿。这个流程在现场特别管用很多“看起来不准”的问题其实都是校准缺失。别一上来就怀疑芯片精度PJ85718DM 这类数字输出的器件本身误差并不大绝大多数偏差来自身边环境。最后分享一点工作习惯调试这种本地与远程温度监测系统我最深的体会是底层读取和上层逻辑要分得足够开。底层只负责把两路温度读准、滤波、做故障标记上层只根据温度值执行温差判断、调速和保护。这样分开以后现场排查问题时能很快定位是采集问题还是策略问题不用每次拿着示波器在代码里翻半天。如果接下来你准备把它用到自己的项目里建议先拿两路通道在常温下比对一遍。等确认本地与远程读数在实验室环境非常接近以后再开始写控制算法。因为控制逻辑里的所有阈值都建立在可靠温度数据上源头错了后面每一步都会跟着错。这套方案改造成本不高却能省掉大量现场调试时间值得一试。