☰
HVAC控制器本地与远程温度监测:PJ85718DM+STM32F429NI实战
2026/10/22 1:06:11 网站建设 项目流程

做 HVAC 控制器这些年,温度监测是我绕不开的必修课。风机盘管、冷梁、组合式空调箱,都需要同时知道“控制柜附近温度”和“管道里温度”。这两个温度一个代表设备本体健康状况,一个代表环境热负荷,处理不好就会导致变频器误判、除霜误动作、能效计算失真。前阵子我用 PJ85718DM 和 STM32F429NI 搭了一套本地与远程温度监测方案,从芯片选型到电路接线,从 I2C 驱动到现场抗干扰,一路踩了不少坑,也总结了一套能直接复用的做法。这篇文章就把整个项目的实际过程写下来,给做嵌入式、楼宇自控、HVAC 控制器开发的朋友做个参考。

1. 项目背景与整体方案设计

1.1 HVAC 应用对温度监测的核心需求

HVAC 里的“温度监测”不像开发板上插个传感器、串口打印个数字那么简单。真正的工程项目里,一般要同时监测好几个温度点:控制柜里 PCB 附近的环境温度、回风口或送风管道里的空气温度、冷水管或热水管表面温度,有些场合还要看室外温度。

本地温度的意义在于保护设备。主控板上的处理器、电源模块、驱动芯片发热严重,如果机柜内温度过高,即使环境温度正常,设备也可能寿命缩短、误报警。远程温度的意义在于控制逻辑。送风温度、回风温度直接影响压缩机频率、风机转速、电动阀开度,温度值不准或者响应慢,舒适度马上变差,能耗也会上升。

所以这套系统的需求从一开始就很明确:至少两路温度采集,一路本地,一路远程;温度分辨率要高,误差尽量控制在 ±0.5°C 以内;传感器和 MCU 之间通信要稳定;环境温度范围要覆盖 -10°C 到 85°C,因为空调外机附近可能更极端。算下来,普通热敏电阻加 ADC 的方案虽然便宜,但每路都要做分压电阻校准、线缆补偿、查表转换,批量生产时会很痛苦。于是我把目光放到数字温度传感器上。

1.2 PJ85718DM 和 STM32F429NI 的选型考量

PJ85718DM 是一颗双通道数字温度传感器芯片,同时支持本地温度测量和远程温度测量。本地通道就是芯片内部自带的温度传感单元,直接反映 PCB 附近的温度;远程通道通过外部接口接到远端测温元件上,可以测管道或者较远区域的温度。

选它有几个原因:

第一,I2C 接口,这是最成熟的数字通信接口之一,STM32 的资源也丰富,软件层面不需要折腾复杂的单总线时序。第二,分辨率和精度能打。配上 12 位 ADC 时,温度转换结果的分辨率能到 0.0625°C,在 HVAC 控制的 0.1°C 精度需求面前足够用了。第三,芯片带 ALERT 引脚,可以硬件触发高温报警,不用 MCU 一直轮询温度寄存器。第四,远程通道支持二极管测温法,这种方式的抗噪声能力比模拟电压传输强很多,适合现场线缆比较长的场景。

STM32F429NI 则是因为这颗料在工业控制领域非常成熟。Cortex-M4 内核,带硬件浮点单元,主频能跑到 180MHz,Flash 有 2MB,RAM 也够大。做 HVAC 控制器不仅要跑温度采集,还要跑 PID 控制算法、风机转速调节、RS485 通信、LCD 显示逻辑,这些任务同时压在一个小芯片上,STM32F429NI 的资源一点都不紧张。

当然,有人会问:直接用带温度传感器的无线模块不行吗?行,但成本高,而且 HVAC 现场经常是金属管道、混凝土墙面,无线信号衰减很不可控。用有线方式把本地和远程温度线引到主控板,反而是最稳妥、成本最低的方案。

1.3 整体系统架构怎么搭

这套系统的结构拆开看并不复杂:PJ85718DM 作为温度采集前端,通过 I2C 总线挂在 STM32F429NI 上;STM32F429NI 负责读取、滤波、报警判断,同时通过 RS485 总线把处理后的温度数据送给上位机或楼宇自控系统;本地还有一个 LCD 屏显示实时温度。

远程温度传感器的物理位置根据项目场景变化比较大,可能在同一个控制柜里,也可能在几米外的风管上。为了保证信号质量,远程传感器和主控板之间用双绞屏蔽线连接,线缆长度控制在 10 米以内。这样一套下来的信号链是:远端温度 -> 远程通道 -> I2C -> STM32F429NI -> RS485 -> 监控中心。

这套架构的好处是本地和远程两路温度由同一颗芯片采集,时间上完全同步,不存在两路传感器由两块芯片分别采集、采样时刻对不齐的问题。对于 PID 控制来说,两个温度读数时间一致非常重要,否则算出来的偏差是错位的。

2. 硬件设计与接线细节

2.1 PJ85718DM 引脚定义与最小系统

拿到芯片先看引脚。 P J85718DM 的封装是 SOP-8,引脚不算多,但每个引脚都不能马虎。我自己整理了一份引脚功能表,方便画原理图时对照:

引脚功能说明接线建议
VDD电源正极接 3.3V,并联 100nF 和 10µF 去耦电容
GND电源地连接系统地,注意单点接地
SDAI2C 数据线接 MCU PB7,上拉电阻 2.2kΩ 到 VDD
SCLI2C 时钟线接 MCU PB6,上拉电阻 2.2kΩ 到 VDD
A0地址选择位接 GND 时地址 0x48,接 VDD 时地址 0x49
ALO报警输出开漏输出,接 MCU 外部中断引脚,上拉 10kΩ
DXP远程测温正端经滤波电容接远端二极管正极
DXN远程测温负端经滤波电容接远端二极管负极

最小系统很常规:电源、I2C 上拉、远程测温接口。需要注意的地方集中在两处:电源去耦和远程线缆接口。

PJ85718DM 虽然功耗低,但工作时内部 ADC 需要稳定的参考电压。如果电源处直接和继电器、风机驱动共用,吸合瞬间的跌落会直接影响测温结果。所以我建议给传感器单独走一小段电源线,至少一个 10µF 钽电容放在芯片附近,确保瞬间电流变化不会被拉出毛刺。

I2C 上拉电阻我选了 2.2kΩ。这个值在 400kHz 快速模式下是标准选择。如果总线过长、寄生电容过大,可以改成 1kΩ,但要注意功耗;如果只有一路传感器,线又很短,用 4.7kΩ 也能工作。关键是要知道:上拉电阻太小会导致 SDA 低电平压降不够,太大则上升沿变慢,容易产生通信错误。

2.2 STM32F429NI 与传感器之间的连接方式

STM32F429NI 的 I2C1 外设映射到 PB6 和 PB7,这是最常用的引脚组合。ALERT 报警脚可以接到 PA0,利用 EXTI0 外部中断来响应温度超限。

在实际项目中,我把 ALERT 接到了一个普通的 GPIO 上,而不是直接接 MCU 的中断脚。原因是 HVAC 现场电磁环境复杂,一个误触发的中断会打断控制流程;用 GPIO 轮询加上 20ms 去抖,比直接中断可靠得多。虽然牺牲了一点实时性,但换来了稳定。

连接时还要考虑 I2C 总线上可能有多个设备。我原先的设计里除了 PJ85718DM,还有一片 EEPROM 和一片实时时钟芯片,都挂在同一条 I2C 总线上。这种时候就要注意地址冲突,PJ85718DM 的 A0 引脚给了我调整地址的空间,片选 EEPROM 用 A1、A2 来区分,确保每个设备地址唯一。

STM32F429NI 与传感器之间还有一个容易忽略的细节:I2C 总线上的器件最好都接到同一个电源域。如果 MCU 是 3.3V,传感器也是 3.3V,那就没有任何问题;万一是 5V 传感器配合 3.3V MCU,就必须加电平转换,不能硬接。我这套系统全是 3.3V,所以省掉了电平转换的麻烦。

2.3 远程测温的传感器接口与抗干扰处理

PJ85718DM 的远程通道并不是直接输入一个模拟电压,而是通过 DXP、DXN 两个引脚去测量远端二极管或者三极管 PN 结的温度特性。这种做法的好处是:传感器把物理温度转换成结电压的变化,芯片用电流源激励和差分测量提取温度值,线缆电阻对测量的影响被大幅抑制。

远程测温最关键的硬件处理是两个地方:接口滤波和线缆选择。

DXP 和 DXN 引脚之间要并联一颗 100pF 到 1nF 的差分电容,位置尽量靠近 PJ85718DM 的引脚。这个电容有两个作用:一是滤除来自长线缆的共模噪声,二是能吸收静电脉冲。电容太小没效果,太大又会让测量响应变慢,我实测 470pF 是一个比较均衡的值。

远端测温元件我使用的是普通小信号三极管的基极-发射极结,把集电极和基极短接,形成一个等效二极管。在管道表面安装时,用导热胶把三极管固定在铝制安装块上,铝块再贴在管道外壁。注意安装块要跟管道充分接触,中间不能有空气间隙,否则温度传导滞后会很明显。

远距离走线必须用屏蔽双绞线,屏蔽层单端接地。我有一次图省事用了普通的跳线,结果远程温度读数在继电器动作时跳了四五度,后来换成双绞屏蔽线并重新接地,问题立刻消失。在 HVAC 这类大电流设备附近,温度信号线本质上是模拟量传输,抗干扰措施绝对不能省。

2.4 电源系统与功耗设计考虑

整个系统的功耗大头其实是 MCU 外设和继电器,传感器本身消耗很小。但是 STM32F429NI 如果全速运行,主频跑到 180MHz,外设全开,功耗并不低。HVAC 控制器通常要求整机功耗做得很省,所以我让 STM32F429NI 平时跑 80MHz,温度采集完成后进入 WFI 等待事件模式。

PJ85718DM 正常工作电流只有几百微安,可以忽略不计。远程通道的电流源在测量期间才打开,空闲时自动关闭,这也进一步降低了功耗。如果设备使用电池供电,可以把传感器的转换模式设成“单次转换”,需要读数时再触发一次转换,能节省不少电量。但在市电供电的 HVAC 场景里,我建议使用连续转换模式,避免每次触发转换后等待的问题。

3. 软件实现与数据处理

3.1 PJ85718DM 寄存器初始化和读取流程

PJ85718DM 的寄存器地图并不复杂,我用到的核心寄存器如下:

寄存器地址名称说明
0x00LTEMP本地温度数据寄存器,16 位
0x01RTEMP远程温度数据寄存器,16 位
0x02CONFIG配置寄存器,设置分辨率、模式
0x03STATUS状态寄存器,指示温度超限
0x04THIGH高温报警阈值寄存器
0x05TLOW低温报警阈值寄存器

上电后,我先给 STM32F429NI 和传感器都加了 50ms 的延迟,等传感器内部上电复位完成后才开始通信。初始化代码里做三件事:配置 I2C 地址、写 CONFIG 寄存器选择 12 位分辨率、设置 THIGH 和 TLOW 阈值。

CONFIG 寄存器的值需要按位操作。12 位分辨率对应的转换时间大约是 160ms,如果希望更快,可以选 11 位、约 80ms,但精度会降到 0.125°C。我在这套系统里选 12 位,160ms 的刷新周期对 HVAC 控制完全够用。

初始化完成后,就可以循环读取温度了。I2C 读取时序是先发送寄存器地址,然后连续读两个字节。温度数据的格式是左对齐 12 位,补码表示正负温度。

3.2 温度数据转换的代码实现与注意事项

我用 STM32 的 HAL 库写了对应的读取函数。核心代码是这样:

#include "stm32f4xx_hal.h" #include <stdint.h> #define PJ85718DM_ADDR 0x48 #define REG_TEMP_LOCAL 0x00 #define REG_TEMP_REMOTE 0x01 float pj85718_read_local(I2C_HandleTypeDef *hi2c) { uint8_t reg = REG_TEMP_LOCAL; uint8_t buf[2]; uint16_t raw; int16_t signed_raw; float temperature; HAL_I2C_Master_Transmit(hi2c, PJ85718DM_ADDR << 1, &reg, 1, 100); HAL_I2C_Master_Receive(hi2c, PJ85718DM_ADDR << 1, buf, 2, 100); raw = (uint16_t)((buf[0] << 4) | (buf[1] >> 4)); if (raw & 0x0800) { raw |= 0xF000; } signed_raw = (int16_t)raw; temperature = signed_raw * 0.0625f; return temperature; }

这里有几个地方容易出错,我特意说明一下。

首先是数据拼接。温度寄存器是 12 位有效数据,放在 16 位寄存器的高 12 位,低 4 位是无效的。拼接时要把第一个字节左移 4 位,第二个字节右移 4 位,再按位或。如果直接读首字节加次字节当成 16 位整数,换算出来的温度会是错的。

其次是有符号数的扩展。温度可能是负的,比如室外温度 -10°C 时,原始数据是补码。判断 bit11 是否为 1,如果是,就把高 4 位全部补 1,这样转换成 int16 之后乘以 0.0625 才是正确的负数。

最后是 HAL 函数的返回值处理。实际工程里不能忽略返回值,如果 I2C 通信失败,直接沿用上一次的有效温度值,而不是返回一个错误码。这样至少不会出现温度值瞬间跳变到 0°C 的情况。

3.3 本地与远程温度数据滤波算法

硬件上的抗干扰只是一部分,软件滤波同样重要。我在这套系统里做了两级处理:滑动平均和中值滤波。

滑动平均的窗口设成 8 个点,每来一个新数据就丢掉最旧的一个,这样可以有效平滑温度信号。滑动平均的优点是计算量小,适合在 STM32F429NI 这种资源充足的芯片上随便跑。缺点是对于突发性尖峰干扰,比如继电器吸合瞬间产生的电磁脉冲,即使只有一个点异常,也会在窗口里留下 1/8 的痕迹。

所以我还加了一层中值滤波,做法是取最近 5 次原始数据,排序后取中间值作为本次有效数据。中值滤波对尖峰干扰的抑制效果非常好,一个坏点直接被排在窗口外,根本不参与最终结果。实际测试下来,两级的组合可以做到远程温度读数在强电磁干扰下仍然非常平稳。

滤波后的温度数据还有一个用途:用于 PID 控制。这里我要提醒,控制用的温度要使用滤波后的值,但报警判断应该用滤波前的原始值。原始值滞后小,能更快发现真实的温度超限;滤波后的值更适合做精确控制,两者不要混用。

3.4 远程数据上报与 Modbus 从站实现

STM32F429NI 采集到温度后,本地 LCD 显示是一方面,更重要的是要把数据送到远程监控端。这项目里我用的是 RS485 加 Modbus RTU 协议,这是楼宇自控系统最通用的对接方式。

STM32F429NI 自带多个 USART,我用 USART3 接了 RS485 收发器。Modbus 从站地址设为 1,保持寄存器中规划两个地址:40001 存本地温度值,扩大 10 倍存储以便保留一位小数;40002 存远程温度值,同样扩大 10 倍。

Modbus 的帧解析并不复杂,但有一点让我吃了不少苦头:RS485 的收发切换时序。收发器有一个 DE 引脚控制发送使能,发送完一帧数据之后必须延时一段时间再切换回接收模式,否则最后一个字节会被截断。我用的解决方法是发送完最后一个字节后,延迟一个字符时间再拉低 DE。这个时间可以通过计算波特率得到,比如 9600 波特率下,一个字节 10 位,大约 1.04ms,我留了 2ms 才切换,非常稳妥。

上位机每隔 1 秒读一次这两个寄存器,数据刷新频率完全满足楼宇自控的需求。如果后续要扩展更多温度点,只需在保持寄存器里继续增加地址,不用改通信协议。

4. 调试踩坑与现场问题解决

4.1 I2C 总线锁死的完整排查过程

这套系统第一次长时间跑,到第三天的时候,STM32F429NI 突然读不到温度数据,LCD 上的温度开始闪烁。接上调试器一看,HAL_I2C_Master_Transmit 一直返回 HAL_BUSY。

我先用逻辑分析仪抓了 I2C 波形,发现 SDA 一直处于低电平。这种情况十有八九是 I2C 总线被某个从机拉死了,或者通信过程中出现错误状态,从机没释放总线。PJ85718DM 在远程线缆受到静电冲击时,偶发进入了异常状态,会把 SDA 拉死,主控无论怎么发 START 信号都没用。

解决方法是先让 MCU 的 I2C 控制器复位,然后把 SCL 引脚配置成普通 GPIO,手动翻转 9 个时钟脉冲,让从机完成一次复位。9 个时钟过后 SDA 会被释放,再重新配置 I2C 外设即可恢复通信。

void i2c_bus_recover(GPIO_TypeDef *scl_port, uint16_t scl_pin, GPIO_TypeDef *sda_port, uint16_t sda_pin) { int i; HAL_I2C_DeInit(&hi2c1); GPIO_InitTypeDef gpio = {0}; gpio.Pin = scl_pin; gpio.Mode = GPIO_MODE_OUTPUT_OD; gpio.Pull = GPIO_PULLUP; HAL_GPIO_Init(scl_port, &gpio); gpio.Pin = sda_pin; gpio.Mode = GPIO_MODE_OUTPUT_OD; HAL_GPIO_Init(sda_port, &gpio); for (i = 0; i < 9; i++) { HAL_GPIO_WritePin(scl_port, scl_pin, GPIO_PIN_RESET); HAL_Delay(10); HAL_GPIO_WritePin(scl_port, scl_pin, GPIO_PIN_SET); HAL_Delay(10); } HAL_GPIO_WritePin(sda_port, sda_pin, GPIO_PIN_SET); MX_I2C1_Init(); }

另外,我在软件上加了通信超时计数:连续 5 次 I2C 操作失败就调用总线恢复函数,同时给主控增加一个软件看门狗。这样即使现场再有异常,系统也能自愈,不需要维护人员到场断电重启。

4.2 远程温度读数偏高,排查到校准和线缆问题

刚把远程温度探头装到送风管上时,上位机读回来的温度比实际温度高了 1.2°C。第一反应是热电偶装错,但检查之后发现是远程信号线太长,线缆上的压降和噪声影响了温度转换。

PJ85718DM 的远程测温原理是基于电流源激励,理论上对线缆电阻不敏感。但实际线缆上除了直流电阻,还有分布电容和电感。当电流源快速切换时,分布电容会储能,导致 DXP 和 DXN 之间的电压信号产生轻微偏移,反映出来就是温度偏高。

我做的处理有两步:一是在远程端增加一阶 RC 滤波,二是做一次两点校准。RC 滤波是指把线缆本身的分布电容效应控制住,在 DXP、DXN 之间并一个 1nF 电容,让信号更平稳。两点校准则是在 0°C 和 25°C 两个温度点记录实际误差,算出增益和偏移量写入软件校准系数。

校准公式很简单:

真实温度 = 读取温度 * 增益系数 + 偏移量

我实测结果是增益系数 0.996,偏移量 0.3°C。经过校准后,远程通道的误差控制在 ±0.3°C 以内,满足 HVAC 项目要求。

4.3 继电器动作瞬间温度跳变的处理

这套系统在现场控制柜里工作时,旁边就是继电器和接触器。每次继电器吸合,远程温度数值都会跳一下,虽然持续时间很短,但在上位机曲线图上会看到一个尖刺。

这个问题的根源是共模噪声通过线缆耦合进了远程测温通道。我做了三处整改:一是把远程信号线换成屏蔽双绞线,屏蔽层单端接地;二是在传感器电源引脚对地加一个 100nF 电容;三是把报警和温度读取任务放到不同的时间片,避开继电器动作的那几十毫秒。

这里最有效的其实是软件配合:在继电器动作期间,暂停温度滤波数据的更新,等稳定 100ms 后再继续读取。因为 HVAC 控制中继电器的动作频率很低,每次动作间隔至少几秒钟,暂停 100ms 根本不影响控制性能,却能极大提升数据的干净度。

4.4 HVAC 现场常见问题速查表

我把这次项目中碰到的问题和解决办法整理成了一张表,方便后面维护时快速对照。

现象可能原因解决办法
I2C 通信卡死总线被从机拉死或静电干扰9 个时钟恢复总线,开启通信超时重试
远程温度偏高线缆分布电容影响增加 DXP/DXN 差分电容,软件校准
继电器动作时温度跳变共模噪声耦合屏蔽线单端接地,继电器动作时段暂定采样
低温时读数不稳定远程安装位置导热不良使用导热胶固定探头,确保与管道紧密接触
掉电后温度恢复慢传感器上电复位时间不足上电延迟 50ms 后再初始化

这张表是给现场的维护同事准备的,嵌入式开发尤其是这样,不是代码写完就结束了,后续的现场问题定位和长期稳定性同样重要。

最后分享一点实际操作体会

这套本地与远程温度监测方案,我先后试过三种不同的远程测温接法,最终确定的这套组合在稳定性上最让我放心。PJ85718DM 的本地通道和远程通道共用一个时钟源和数据链路,省去了多芯片之间数据同步的麻烦,STM32F429NI 的资源又足够富余,做滤波、报警、Modbus 上报所有事情都能在一个控制周期里完成。

有一点我特别想强调:硬件设计时不要吝啬那一颗差分电容和屏蔽线,温湿度信号在 HVAC 现场特别容易被干扰。软件上一定要给 I2C 做好异常恢复,不要以为单片机不死机就万事大吉,总线锁死一样让你头疼。我踩了这些坑之后,再启动类似项目时,先把远程线缆的屏蔽和传感器供电隔离做好,后面调试会顺很多。

这套方案后续如果做扩展,可以考虑在 STM32F429NI 上增加多路 I2C 或者挂载多颗 PJ85718DM,配合地址扩展芯片实现十几个温度点的采集,本质上架构不用变,只要在软件里加一层设备管理。希望这次分享能帮你少走几步弯路。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询