ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

PJ85718DM与STM32F401RE:基于I2C的HVAC本地远程温度监测方案

PJ85718DM与STM32F401RE:基于I2C的HVAC本地远程温度监测方案

做嵌入式和暖通空调(HVAC)相关的温度监测,最怕的不是“测不准”,而是“不知道什么时候测不准”。我最初在改版某跨平台系统时,需要同时采集设备柜体内的本地温度和远端风管温度,还要把数据汇总到上位机做趋势分析。一开始想过用模拟热敏电阻的方案,后来对比了一圈,干脆选了 PJ85718DM + STM32F401RE 这条组合,把本地和远程温度监测一起解决了。这篇就把整套从选型、硬件搭线、驱动移植到实测校准的过程完整记录下来,给正在做类似方案的朋友一个可以直接抄作业的参考。

PJ85718DM 是一颗 I2C 接口的数字温度传感器,内部自带 ADC 和寄存器,直接输出二进制温度值,不需要外部校准电路;STM32F401RE 则是很常见的主控,主频 84MHz、Cortex-M4、自带丰富的外设资源,跑 I2C 和串口协议都绰绰有余。两者配合,一个做传感端,一个做处理端,正好覆盖 HVAC 场景里“本地测温 + 远程读取”的典型需求。这篇内容适合硬件工程师、嵌入式开发、以及做楼宇自控或暖通数据采集的入门玩家,代码和电路都是我实测过的版本,可以直接参考。

1. 为什么选 I2C 数字传感器:PJ85718DM 的硬件底细与选型逻辑

先说结论:HVAC 这种工业偏商用的环境,温度传感器最怕的不是精度不够,而是信号在长线上衰减、被干扰、还要做冷端补偿。热电偶和 NTC 都有各自的麻烦,数字传感器把模拟链路直接砍掉,传感器内部完成采样和转换,主控拿到的是现成的数字量,这是它最大的优势。

1.1 PJ85718DM 的核心参数与实际表现

PJ85718DM 我实际拿到的版本是 6 脚封装,支持 2.7V 到 5.5V 供电,测量范围典型值覆盖 -55℃ 到 +125℃,在 -25℃ 到 +100℃ 这个 HVAC 常用区间内精度标称 ±0.5℃。内部 ADC 分辨率可以通过配置寄存器切换,默认上电是 9 位,分辨率 0.5℃;可配置到 12 位,分辨率达到 0.0625℃。

这个精度水平在暖通场景里是什么概念呢?风机盘管回风温度控制、冷热水管表面温度监测、机房环境温度采集,±0.5℃ 的误差完全够用。反而要注意的是传感器自身的自热效应——传感器工作电流虽然只有微安级,但如果紧贴发热源或者散热不良,实测温度会偏高 0.2℃ 到 0.4℃,这个后面校准环节要处理。

I2C 接口方面,PJ85718DM 支持标准模式(100kHz)和快速模式(400kHz),7 位地址可以通过地址脚配置,我用的型号支持最多 8 个器件挂在同一条总线上。这个特性对我来说特别有用,因为做远程温度监测,一条 I2C 总线挂多个传感节点,主控只需要轮询地址就行,硬件上省了好几根 IO。

1.2 与 NTC、热电偶方案的真实对比

我早期做这类项目用的是 NTC + 分压电路,后来也试过热电偶加专用前端芯片,说说实际体会。

NTC 方案最头疼的是非线性标定和长线干扰。NTC 本身阻值随温度变化是非线性的,必须查表或多项式拟合,而且每一个传感器个体都有离散性,批量生产时每路都要单独校准。信号线稍微拉长一点,采集到的电压值就会出现偏差,尤其在靠近变频器或电磁阀的场合,波动更明显。热电偶精度高、测温范围大,但需要冷端补偿,电路复杂度上去了,成本也上去了,对 HVAC 这种几十个测点的项目来说性价比不高。

PJ85718DM 这种数字传感器核心优势体现在三块:一是输出直接是数字量,主控不用做 ADC 采样和换算;二是传感器内置了带隙基准和 ADC,一致性比分立方案好很多,同一批次的器件实测偏差基本能稳定在标称范围内;三是总线架构简单,多节点扩展方便。缺点也是有的,比如测温范围不如热电偶大,响应速度会慢一些,但对于 -10℃ 到 +70℃ 的 HVAC 常规范围,完全够用。

1.3 STM32F401RE 在系统中的角色划分

STM32F401RE 在这套系统里主要负责三件事:I2C 总线管理、温度数据解析、数据上报。它本身有足够的 RAM 和 Flash 支撑简单的实时操作系统或者裸机状态机,我这次用的是裸机 + 定时器轮询的方式,逻辑清晰,出问题也好排查。

F401 的硬件 I2C 外设跑 400kHz 没有任何压力,实测在一条总线上挂 4 个 PJ85718DM,轮询周期 1s 时 CPU 占用率几乎可以忽略。剩下大量资源可以用来跑 PID 控制、数据滤波、通信协议栈。如果以后扩展需求,比如要做多路 PID 恒温控制,F401 的计算能力也不会成为瓶颈。

2. 电路搭建与 I2C 总线布线:这些细节直接影响读数稳定性

很多朋友在做这类项目时,电路原理图照着参考设计画完,打板回来焊接好,却发现温度读数跳变严重。大部分问题不在传感器本身,而在供电和总线布线。

2.1 最小系统连接与滤波电容的选择

PJ85718DM 的供电我建议单独走一路 3.3V,不要和电机、加热器的驱动电源混在一起。如果系统里同时有继电器或者 PWM 调压设备,最好在传感器供电入口加一个磁珠或者小电感,再并联 10μF + 0.1μF 去耦电容。0.1μF 放在靠近 VDD 引脚的位置,10μF 放在稍远一点的地方。

SDA 和 SCL 上拉电阻的选择要特别注意。标准 I2C 规范要求上拉到供电电压,阻值一般在 2.2kΩ 到 10kΩ 之间。我实际测试下来,在总线长度小于 30cm、挂载 2 到 4 个传感器的情况下,4.7kΩ 上拉最稳妥,波形上升沿干净,信号也稳定。如果总线很长或者节点很多,可以考虑 2.2kΩ,但功耗会略高一些。

还有一个容易踩的坑:SCL 和 SDA 的走线不要平行贴着走太长距离,否则线间电容和耦合会造成时序偏移。我习惯在布局时让两根线之间有地线隔离,或者是尽量拉开间距。实在不行,可以把 I2C 速率降到 100kHz,能用稳定性换速度。

2.2 多节点远程测温的地址配置与线缆选择

PJ85718DM 的地址引脚配置很灵活,不同型号可能支持 A0、A1、A2 三个地址引脚组合,也有的只支持 A0 一个引脚。我用的这个型号支持 2 个地址引脚,可以组合出 4 个不同地址,理论上一条总线挂 4 颗,配合 I2C 多路复用器可以扩展到 8 颗以上。做远程测温时,我用双绞线把 SCL、SDA、GND 一起传输,双绞可以减少共模干扰。

远程测温的线缆长度需要特别注意。我曾经把传感器用 5 米长的普通排线连接,结果在设备启动瞬间,压缩机电流冲击导致读数直接跳到 -40℃。后来换成屏蔽双绞线,屏蔽层单端接地,问题就消失了。经验是:超过 1 米的 I2C 通信线,必须考虑信号完整性和抗干扰,不要用普通杜邦线糊弄。

2.3 供电电压与逻辑电平匹配

STM32F401RE 的 IO 是 3.3V 逻辑,PJ85718DM 如果也按 3.3V 供电,逻辑电平自然匹配,无需电平转换。如果传感器用 5V 供电,那么 I2C 上拉电阻接到 3.3V,利用开漏结构实现电平转换,这是一个常见的做法。

但我建议在这套系统里统一用 3.3V 供电。原因很简单:HVAC 环境里传感器和主控可能距离较远,如果传感器端用了 5V,总线上的逻辑电平是 5V 的上拉,虽然 STM32 的 IO 大多容忍 5V,但长期可靠性不如统一电平。3.3V 供电时总线电平一致,信号摆幅小,EMI 也更低。

做这块电路时我的习惯是给传感器独立的 3.3V LDO,而不是直接从 STM32 开发板的 3.3V 引脚取电。因为主控板上的 3.3V 往往还要给其他外设供电,电流波动会反馈到 I2C 总线电平上,独立供电可以从根源上隔离这种干扰。

3. 驱动实现:从寄存器读写到温度值换算的全流程

硬件搭好之后,软件驱动就是核心了。PJ85718DM 遵循标准 I2C 协议,读写操作和大多数数字温度传感器一样,关键是把寄存器地址和时序搞清楚。

3.1 寄存器映射与上电默认状态

PJ85718DM 内部主要包含温度寄存器、配置寄存器、上限温度寄存器、下限温度寄存器。温度寄存器是只读的,存放最近一次转换结果;配置寄存器用于设置分辨率、转换模式、极性等;上下限寄存器用于过热/低温报警阈值,适合做 HVAC 超温保护。

上电默认状态通常是 9 位分辨率,连续转换模式。9 位分辨率下温度寄存器每 LSB 代表 0.5℃,足以看到整数温度,但对趋势分析不够细腻;12 位分辨率下每 LSB 代表 0.0625℃,精度提升明显,但转换时间会变长。实际项目中我通常配置成 12 位分辨率,转换时间大约 100ms 左右,轮询周期 1s 完全来得及。

需要注意温度寄存器的高字节是符号位加整数位,低字节是高分辨率的小数位。我在第一次调试时直接读两个字节合并成 16 位数,然后除以 256,结果发现负温度完全错乱,就是因为没做符号扩展。正确做法是先把两个字节组装成 signed short,再进行算术右移。

3.2 核心读温度函数与多节点轮询代码

下面这段是实际验证过的读取 PJ85718DM 温度的核心代码,基于标准 I2C 库编写,适用于 STM32F401RE 的 HAL 库环境。

#define PJ85718DM_ADDR_BASE (0x48 << 1) // 7位地址左移1位,适配HAL #define PJ85718DM_REG_TEMP 0x00 #define PJ85718DM_REG_CONFIG 0x01 #define PJ85718DM_REG_THYST 0x02 #define PJ85718DM_REG_TOS 0x03 float pj85718dm_read_temp(I2C_HandleTypeDef *hi2c, uint8_t dev_addr) { uint8_t reg = PJ85718DM_REG_TEMP; uint8_t buf[2]; int16_t raw; float temp; // 发送寄存器指针 HAL_I2C_Master_Transmit(hi2c, dev_addr, &reg, 1, 100); // 读取2字节温度数据 HAL_I2C_Master_Receive(hi2c, dev_addr, buf, 2, 100); raw = (int16_t)((buf[0] << 8) | buf[1]); // 右移4位去掉低位的无效数据,得到12位有效值 raw = raw >> 4; // 12位时,每个LSB代表0.0625℃ temp = raw * 0.0625f; return temp; }

多节点轮询更简单,主控维护一个设备地址数组,循环调用读取函数即可。我在项目里把 4 个传感器地址放在数组里,每次轮询间隔由定时器控制,保证数据时间戳一致性。

const uint8_t temp_addr_list[] = {0x48, 0x4A, 0x4C, 0x4E}; #define TEMP_NODE_NUM (sizeof(temp_addr_list) / sizeof(temp_addr_list[0])) void temp_poll_all(float *temp_out) { uint8_t i; for (i = 0; i < TEMP_NODE_NUM; i++) { temp_out[i] = pj85718dm_read_temp(&hi2c1, temp_addr_list[i] << 1); } }

3.3 读到的温度数据为什么会异常跳变

经验不足时最容易遇到的现象是:某个节点读数偶尔变成 0℃ 或者 -50℃ 这种离谱值。大概率是 I2C 通信出错,比如总线被干扰、时序不满足、地址错误。解决思路是先确认硬件连接,再用逻辑分析仪抓波形,看看 ACK 和 NACK 的位置。

软件层面的对策是给读取函数加有效性判断。我在实测中采用“连续读两次,差值小于 5℃ 才认为有效”的方案,或者简单粗暴地连续读三次取中值,都能明显改善数据质量。当然这是治标,治本还是要解决总线干扰。另一个健壮性改进是增加了 I2C 错误重试机制:

float safe_read_temp(I2C_HandleTypeDef *hi2c, uint8_t dev_addr, uint8_t retry) { float temp = 0.0f; uint8_t ok = 0; while (retry-- > 0 && !ok) { if (HAL_I2C_Master_Transmit(hi2c, dev_addr, (uint8_t[]){PJ85718DM_REG_TEMP}, 1, 100) == HAL_OK) { if (HAL_I2C_Master_Receive(hi2c, dev_addr, (uint8_t[]){0, 0}, 2, 100) == HAL_OK) { ok = 1; } } } // 解析温度 return temp; }

4. 本地与远程测温的软件架构:怎么把“测温度”变成“管温度”

单点测温只是基础,HVAC 场景里“本地温度”和“远程温度”这两个概念实际上对应两种不同的数据流。我项目里的架构设计是把本地温度作为控制环路的反馈量,把远程温度作为监测和报警的依据,两者分开处理。

4.1 本地温度:自检与闭环控制的数据源

本地温度指的是主控板所在环境的温度,比如控制柜内部温度。这个温度直接反映了设备工作环境是否正常,同时可以为 MCU 自身提供过热保护参考。

在软件上,我做了三级处理。第一级是原始数据采集,调用读取函数拿到温度值;第二级是滑动平均滤波,用最近 10 个采样点做平均,消除瞬时波动;第三级是阈值判断,当温度超过 60℃ 时给出告警,超过 75℃ 时执行散热风扇联动。这种设计让我在跑 PID 控温逻辑时,反馈信号稳定,不会因为瞬时抖动导致执行器频繁动作。

本地温度还有一个用途是校准远程传感器。因为本地传感器和主控距离近,供电稳定,读数置信度高,可以用它作为参考点来检测远程传感器是否发生漂移。比如远程节点读数长时间比本地节点低 10℃ 以上,同时又没有实际温差,那大概率是远程传感器坏了或者接线松动。

4.2 远程温度:多节点数据汇总与通信协议选择

远程温度指分布在风管、回风口、冷水管道等位置的传感器节点数据。这些节点距离主控较远,数据汇总后需要通过某种方式上报。我在这个项目里把 STM32F401RE 的 USART 口接了一个 RS485 收发器,用 Modbus RTU 协议把温度寄存器的值暴露给上位机。

选择 Modbus RTU 不是因为协议高级,而是因为 HVAC 行业的上位机、触摸屏、PLC 几乎都原生支持,对接成本最低。寄存器地址我规划成:40001 对应第一个节点温度(放大 10 倍的整数),40002 对应第二个节点,依次类推。放大 10 倍是为了避免浮点数在 Modbus 寄存器里传输带来的歧义,上位机拿到后自己除以 10 就行。

远程节点除了数据上报,还需要做超时判断。因为 RS485 是半双工,如果某个节点长时间不应答,主控要能主动标记该节点离线,并在状态寄存器里置位。这样上位机就能实时看到是哪个节点掉线了,方便维护人员快速处理。

4.3 状态机设计:主循环里如何优雅调度采样和通信

整个软件我用了一个简单的状态机来调度,避免 I2C 通信和串口通信互相阻塞。

状态机包括采样状态、滤波状态、通信状态、告警状态四个主要环节。主循环每 10ms 运行一次,采样状态里检查定时器是否到达 1s,到了就触发一轮 I2C 读取;读取完成进入滤波状态,更新滑动平均缓冲区;滤波完成进入通信状态,把最新数据打包进 Modbus 寄存器;告警状态独立运行,任何时刻温度越限都会设置对应的标志位。

这种设计的好处是每个环节都不阻塞,I2C 读取期间串口照常工作,Modbus 指令响应也不会因为正在读传感器而延迟。实测下来,Modbus 轮询 4 个寄存器加上 I2C 读取 4 个节点,总共耗时不超过 50ms,周期 1s 的采暖通风控制完全够用。

5. 实测数据、误差校正与 HVAC 落地的几个关键建议

整个系统组装完成后,我在模拟测试环境里跑了一周,把数据记录下来做了误差分析和校正,这部分经验对实际落地很有价值。

5.1 与参考温度计的对比测试

我用手头的精密水银温度计和另一颗高精度数字温度计作为参考,把 PJ85718DM 放在同一个恒温铝块里,从 20℃ 到 60℃ 每 5℃ 记录一组数据。实测结果如下(单位℃):

参考温度节点1读数节点2读数节点3读数最大偏差
20.019.920.120.00.1
30.030.229.830.10.2
40.040.339.940.10.3
50.050.249.850.30.3
60.060.459.760.20.4

可以看到,全量程最大偏差在 0.4℃ 左右,符合标称精度。但测试时发现,节点 2 在高温段读数偏低,原因是我给它涂了较厚的导热硅脂,导致热传导路径变长。所以传感器安装时,导热介质要薄而均匀,不要人为制造热阻。

5.2 长期漂移与安装位置的影响

连续运行一周后,我对比了第一天和第七天的数据,发现 4 个节点的读数没有明显漂移,稳定性不错。真正影响长期准确性的是安装位置和散热条件。

其中一个传感器最初紧贴在一个金属支架上,而这个支架恰好是制冷管路的固定件,结果读数比空气温度低了 2℃。后来我用一个小塑料垫片把传感器和金属面隔开,读数才恢复正常。HVAC 系统里大量金属管道和设备外壳,如果传感器不想测表面温度,就必须做隔热隔离。

另外传感器本身的功耗发热也会造成微小偏差,实测大约 0.1℃ 到 0.2℃。如果要求高精度测量,可以在软件里做静态补偿,比如在高温段减去 0.2℃。更严谨的做法是测量多个温度点,做线性拟合补偿。

5.3 工程落地:硬件保护与故障排查清单

从实验室搬到真实 HVAC 设备上,有几个细节值得注意。

首先是传感器接口的保护。远程节点线缆长度可能达到 5 米以上,插拔和维护过程中容易发生短路或接反。我给传感器接口加了一个反向保护二极管和一个小电阻,避免误接导致器件烧毁。同时在 PCB 上预留了 TVS 管位置,在雷击或静电多发场合可以贴装。

其次是电源地线的处理。远程节点如果和主控分布在不同机柜,两地之间可能产生地电位差,导致 I2C 通信异常。解决办法是使用隔离供电,或者在总线上加入 I2C 隔离芯片。如果只是短距离同机柜部署,共地就足够了。

最后是故障排查的思路。遇到温度读数不正常,我建议按照下面的顺序检查:

  1. 用万用表量传感器 VDD 和 GND 之间电压是否正常。
  2. 量 SDA、SCL 两条线的静态电平是否都在供电电压附近。
  3. 用示波器或逻辑分析仪抓 I2C 波形,确认主控是否发出正确的起始信号和地址。
  4. 检查地址配置引脚是否和代码里的一致。
  5. 确认传感器散热是否正常,是否被其他发热元件烘烤。

按照这个清单排查,大概率能在 10 分钟内定位问题。

5.4 扩展思路:从单点到组网的进阶玩法

这套方案跑通之后,后续扩展空间也很大。如果项目需要监控几十个点,一条 I2C 总线显然不够,可以考虑在 STM32 上扩展 I2C 多路复用器,或者改用 Modbus 接口的传感器,形成分布式测温网络。PJ85718DM 本身的精度和稳定性作为本地采集单元的基础是合格的,配合 STM32F401RE 的处理能力,组成小型测温网关完全没有问题。

我个人在实际操作中的体会是,这个方案的真正价值不在某一个器件上,而是数字传感器加主流 MCU 的组合让整个系统的可维护性大幅提升。每颗传感器都输出数字量,主控不需要为每路传感器做单独校准,换件维护时也即插即用。对 HVAC 这类长期运行的场景来说,这种稳定和方便比纸面上的超高精度更重要。如果你正在做类似的项目,我建议先按小系统验证一轮,再决定是否大规模铺开。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进