ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

HVAC双通道温度采集实战:PJ85718DM与MK51DN512CLQ10方案解析

HVAC双通道温度采集实战:PJ85718DM与MK51DN512CLQ10方案解析

做HVAC控制器这些年,温度采集这块我一直不太愿意用传统的NTC热敏电阻方案。原因很简单:NTC换一个电阻封装就要重新标定一次,ADC通道还要单独校准,而且在现场强电干扰下,引线稍微拉长一点读数就飘。后来在一个项目里把PJ85718DM和MK51DN512CLQ10搭在一起用,才算把“本地温度”和“远程温度”两路监测一次搞定。这篇文章就围绕这套组合,把硬件连接、寄存器操作、固件读取、现场排障和校准经验完整梳理一遍,给正在做嵌入式环境监控或者HVAC控制板的朋友一个可参考的落地思路。

1. 为什么用“本地+远程”双通道:HVAC 温度监测的真实需求

1.1 HVAC 场景里“本地”和“远程”分别指什么

HVAC 系统里,温度监测从来不是一个点的事。控制器主板本身要防过热,芯片、功率器件、电源模块的温度得盯着,这是“本地温度”;同时风管、回风、送风、压缩机表面、冷凝器盘管这些位置也要测,这是“远程温度”。传统做法是本地一路 NTC 加远程一路 NTC,每路都占一个 ADC 引脚,还要在电路上做分压电阻、滤波电容,批量生产的时候每块板子都要校准。

用 PJ85718DM 这类带本地和远程双通道的数字温度传感器,情况就简单很多。本地通道测芯片自身或 PCB 附近的温度,远程通道通过一对 D+/D- 引脚外接一个二极管探头,就能测几米外的目标点温度。它的远程通道走的是二极管正向压降随温度变化的原理,和 NTC 完全不同,抗干扰能力和线缆长度容忍度都高不少。

我实际用下来的体会是,这种结构特别适合 HVAC 控制器:板子内部温度一片,外部关键点温度一片,两个数据都通过同一个 I2C/SMBus 总线读到主控里,不需要额外的信号调理电路,校准工作量也大幅下降。

1.2 为什么选择 PJ85718DM 而不是普通热敏电阻

NTC 方案在 HVAC 里很常见,但它有几个绕不开的痛点。首先 NTC 是非线性的,温度越高阻值变化越平缓,需要查表或者用 Steinhart-Hart 方程做拟合;其次 NTC 的标称阻值和 B 值存在离散性,批量生产时一致性要靠选档或软件标定来兜底;再者 NTC 导线一旦靠近继电器、接触器这些强电器件,采样值很容易被干扰。

PJ85718DM 属于数字输出型温度传感器,温度数据直接通过总线以数字形式传输,MCU 不需要做 ADC 采样,也就不存在基准电压误差和采样时序抖动的问题。远程通道虽然外接的是二极管(通常是 2N3904/2N3906 这类三极管的 BE 结,或者专用的二极管探头),但传感器内部通过在不同电流下测量二极管压降差来计算温度,抵消了二极管绝对压降离散性的影响。这个原理让它对探头本身的个体差异不敏感,换一个探头基本不需要重新校准。

要说明的是,我没有拿它去做超低温或者超高精度的计量级应用,那种场景还是得靠 PT100/PT1000 加高精度 ADC。但在 HVAC 这种 -20°C 到 +125°C 的范围内,±1°C 左右的精度完全够用,而且它是数字接口,系统集成成本低很多。

1.3 MK51DN512CLQ10 在这套方案里扮演什么角色

MK51DN512CLQ10 是 Kinetis K51 系列里带 512KB Flash 的 Cortex-M4 主控,用来做 HVAC 控制器比用 8 位单片机从容不少。它的 I2C 模块支持标准模式和快速模式,用来和 PJ85718DM 通信非常合适;同时它还跑着 Modbus 通信、风扇 PWM 控制、继电器逻辑、LCD 显示这些任务,温度读取只是其中一个任务模块。

在这个方案里,MK51DN512CLQ10 负责三件事:初始化 I2C 总线并配置 PJ85718DM 的工作模式;周期性读取本地和远程温度寄存器,换算成真实温度值;根据温度阈值做报警判断,把结果分发给控制逻辑或者上传给上位机。

K51 系列另一个实用点是它的 GPIO 带上拉使能配置,可以减少外部上拉电阻的依赖。不过我在实际项目中还是外挂了 4.7kΩ 上拉,后面会专门说原因。总的来说,这颗 MCU 的性能余量很大,温度采集只占用它很少的资源,剩下的算力都留给控制策略。

2. 硬件连接:从传感器引脚到 MCU 引脚的完整链路

2.1 PJ85718DM 典型引脚定义与接线

拿我这块测试板来说,PJ85718DM 的引脚功能大致分四组:电源、I2C 总线、地址选择、远程二极管接口。电源引脚接 3.3V,VCC 和 GND 之间放一个 0.1uF 去耦电容,位置尽量靠近芯片。SDA、SCL 是总线引脚,分别接 MK51DN512CLQ10 的 I2C0 对应引脚,并配上拉电阻。

地址选择脚一般有两个,A0 和 A1,通过高低电平组合可以让传感器在 I2C 总线上占用不同地址。这在我这个项目里很有用,因为控制板可能同时挂两个温度传感器,一个测控制器内部温度,另一个测风管温度,靠不同的地址区分,总线只要一组。

OS/ALERT 引脚是开漏输出的比较器输出,可以配置成中断输出。我把这个引脚接到了 MK51DN512CLQ10 的一个 GPIO 上,并使能了上升沿中断,用于温度越限时的快速响应。平时主控不需要轮询温度状态,等报警触发再说,这样 CPU 占用率更低。

实际接线时要注意,SDA、SCL、ALERT 都是开漏结构,必须接上拉电阻,否则总线拉不高,通信直接失败。我习惯用 4.7kΩ,总线速度在 100kHz 到 400kHz 之间都很稳。如果总线上挂的设备多,可以适当降到 2.2kΩ,但注意不要低于 1kΩ,否则驱动电流偏大,对传感器和 MCU 都不友好。

2.2 远程二极管探头怎么接:D+ 和 D- 的布线要点

PJ85718DM 的远程通道有两根线,D+ 和 D-。远程探头最常见的做法是拿一颗小信号三极管,比如 2N3904,把基极和集电极短接,当作二极管用。基极-集电极短接的那一端接 D+,发射极接 D-,这样就能形成传感器需要的二极管结构。

布线方面,高铁军规有一条:D+/D- 必须走双绞线或者紧贴在一起的平行线,并且周围用地线包住。我踩过坑,一开始图省事用普通的杜邦线飞了两根线出来,长度大概 80 厘米,结果读数在 25°C 附近反复横跳,波动超过 3°C。后来换成双绞线,读数立刻稳定下来。

原因很简单,远程通道的测温原理基于毫伏级的二极管压降测量,线上的噪声和寄生电容都会直接影响测量结果。双绞线可以抑制共模干扰,同时要避免 D+/D- 在 PCB 上长距离并行走线,防止两条线之间形成寄生电容耦合。

还有一点经验:远程探头线尽量不要和继电器控制线、220V 动力线走同一个线槽,尤其是距离超过半米的时候。HVAC 设备里继电器动作瞬间会产生很强的感性尖峰,如果温度线贴得太近,轻则读数跳变,重则把传感器内部电路打坏。我在测试中发现,即便用了双绞线,只要和动力线平行走线超过 1 米,远程温度在继电器动作前后还是会有 0.5°C 左右的波动,这在要求严格的场合是不可接受的。

2.3 HVAC 现场环境下的信号完整性与防护措施

HVAC 控制柜里是典型的电磁干扰环境:接触器吸合、断开、变频器开关、风机启停,这些都会在电源和信号线上制造噪声。这套方案里,I2C 总线本身是低速总线,抗干扰能力还行,但远程二极管线属于高阻抗模拟前端,必须重点保护。

我的做法是在 D+/D- 靠近传感器入口的位置各串联一个 1kΩ 到 2.2kΩ 的电阻,然后对地并联一个 1nF 到 10nF 的滤波电容。这个串联电阻并不会破坏测温,因为传感器测的是电流切换下的压降差,而串联电阻上的压降是固定的,只要两个测量点的激励电流不变,电阻的影响就可以忽略。这个细节其实很多参考设计里都有,但实际布板时容易被省略。

I2C 总线这边也要考虑防护。传感器和主控如果不在同一块板上,或者中间通过连接器走线,建议在总线引脚上并联 TVS 管。我用的是一颗双向 TVS 阵列,能同时保护 SDA、SCL 和 ALERT。另外,HVAC 控制板经常工作在温度变化大的环境中,PCB 上要注意避免传感器周围有大电流走线,否则本地温度读数会被 PCB 上的热点干扰,测出来的不是空气温度,而是铜箔温度。

3. 寄存器与协议:SMBus 交互的底层逻辑

3.1 温度数据寄存器与读取格式

PJ85718DM 这类 SMBus 温度传感器,内部寄存器布局基本遵循一个约定:通过写入命令寄存器地址来选择要读的数据,然后用重复起始条件(repeat start)读回数据。

我这边用的寄存器布局是这样的:0x00 是本地温度数据,0x01 是远程温度数据高字节,0x10 是远程温度数据低字节,0x02 是状态寄存器,0x03 是配置寄存器,0x04 是转换速率寄存器,0x05 到 0x08 是本地和远程的高/低温度报警阈值。

本地温度一般是一个字节,分辨率为 0.5°C/LSB,以二进制补码表示。远程温度则是两个字节,高字节是整数部分,低字节的高几位是小数部分,合起来能达到 0.125°C 的分辨率。读取的时候必须把高低字节都读出来,并且注意高低字节之间要连续读,防止传感器在两次读取之间更新了数据,导致高低字节不是同一时刻的快照。虽然在实际使用中这个问题影响很小,但严谨的做法是连续读完再合并。

3.2 状态寄存器与报警阈值寄存器的使用

状态寄存器里通常有几个标志位:远程温度高于上限、远程温度低于下限、本地温度高于上限、本地温度低于下限,还有远程二极管开路/短路检测标志。我在固件里每次读取温度后都会顺便读一下状态寄存器,把报警标志保存下来,但不立即处理,而是在任务循环里统一判断。

报警阈值寄存器的用处是让传感器自己在超限时拉低 ALERT 引脚,这样 MCU 可以用中断方式知道温度异常,而不是一遍遍轮询。阈值是 8 位有符号数,分辨率同样是 0.5°C/LSB,写入时需要先把目标温度乘以 2 转成整数再写入。比如想设置远程温度 85°C 报警,就要写入 0xAA(因为 85 * 2 = 170 = 0xAA)。

关于阈值的设置,我想多说一句:在高温度波动频繁的 HVAC 环境里,不要把上阈值设得和正常工作温度太近,否则 ALERT 引脚会频繁触发,主控的中断处理会被淹没。我通常把远程温度上阈值设成正常工作最高温度加 10°C 到 15°C,比如正常 65°C 的工况,报警阈值设到 80°C。

3.3 MCU 侧 I2C 外设与传感器的交互关系

MK51DN512CLQ10 的 I2C 外设支持主模式收发,使用上和大多数 Cortex-M 平台的 I2C 模块类似。关键在于它需要先把引脚复用配置成 I2C 功能,这一步很多人容易漏。我在初始化时把 SCL 和 SDA 引脚复用为 ALT2 功能,并开启内部上拉,然后配置 I2C 分频系数。

SMBus 和 I2C 在电气层面基本兼容,逻辑上略有区别。PJ85718DM 支持 SMBus 的快速命令协议,比如写一个字节、读一个字节、读两个字节。对 MCU 来说,实现这些操作不需要太复杂的协议栈,只需要按部就班地做:启动、发地址+写、发寄存器地址、重复启动、发地址+读、连续收字节、停止。

有一点要注意,SMBus 的 SCL 低电平超时特性在某些传感器里存在,但大多数此类传感器并不强制要求主控支持超时复位。我这边没有实现 SMBus 超时检测,只依赖 I2C 通信失败后的软件重试机制,实测运行很稳定。

4. 固件实现:从 I2C 驱动到温度计算的完整代码

4.1 I2C 初始化与单次温度读取流程

MK51DN512CLQ10 的固件我用的是寄存器级配置,没有依赖特定 SDK 版本,方便后续移植。初始化部分把 I2C0 模块时钟打开,配置引脚复用,设置波特率。以外部 16MHz 晶振、总线时钟 48MHz 为例,I2C 分频寄存器配置成的 100kHz 总线频率足够用了。

下面是 I2C 初始化的核心代码:

void I2C0_Init(void) { SIM->SCGC4 |= SIM_SCGC4_I2C0_MASK; // 打开 I2C0 模块时钟 SIM->SCGC5 |= SIM_SCGC5_PORTB_MASK; // 打开 PORTB 时钟 PORTB->PCR[2] = PORT_PCR_MUX(2) | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK; // SCL,下拉 PORTB->PCR[3] = PORT_PCR_MUX(2) | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK; // SDA,下拉 I2C0->C1 = 0; // 关闭 I2C I2C0->F = 0x17; // 配置分频,约 100 kHz I2C0->C1 = I2C_C1_IICEN_MASK | I2C_C1_MST_MASK; // 使能 I2C,主机模式 }

启动位和停止位的处理我做成两个小函数,发送地址和收发数据的过程都在一个状态机里跑。实际项目中我没有用阻塞等待的方式,而是在中断里维护一个简单的队列,但因为代码比较长,这里先用阻塞方式说明核心逻辑。

4.2 远程温度和本地温度的换算公式

读取远程温度的完整 I2C 序列是这样的:先发设备地址加写位,再写寄存器地址 0x01,然后发重复起始,再发设备地址加读位,连续读两个字节(高字节和低字节),最后发停止位。

远程温度的高字节是 8 位有符号数,单位是 1°C;低字节的高 3 位是小数部分,每一位代表 0.125°C。所以合并后的温度值可以这样算:

int16_t remote_raw_to_temp(uint8_t hi, uint8_t lo) { int16_t temp = (int8_t)hi; temp *= 8; temp += (lo >> 5); // 取低字节的 bit7~bit5,各代表 0.125°C return temp; // 单位:0.125°C } float remote_temp_c = remote_raw_to_temp(hi, lo) * 0.125f;

用这个公式,比如高字节读回 0x41(十进制 65),低字节读回 0x20(bit5 置位),那么温度就是 65 * 1 + 1 * 0.125 = 65.125°C。这个分辨率放在 HVAC 场景里完全够用。

本地温度更简单,它就是高字节的一个字节,1 LSB 代表 0.5°C,直接用有符号转换:

float local_temp_c = (int8_t)local_byte * 0.5f;

我在代码里把两个温度值都转成了浮点型,方便后续直接在 Modbus 寄存器里上报,避免在业务逻辑里反复做定点换算。

4.3 报警配置与故障恢复逻辑

报警配置需要在初始化时把四个阈值寄存器都写一遍。这些阈值寄存器都是 8 位有符号数,以 0.5°C 为步进。例如本地温度上阈值设为 70°C,就写入 0x8C(70 * 2 = 140)。

写阈值寄存器的代码逻辑和写任何配置寄存器一样,先发写命令,指定寄存器地址,然后写入数据字节。我在配置完成后会再读回来验证一次,防止 I2C 干扰导致写入失败。这一点在批量生产中比较重要,因为如果报警阈值没写进去,设备可能在超温时没有任何反应。

故障恢复方面,我加了三个处理:通信失败重试、报警状态轮询、远程二极管异常检测。如果连续三次 I2C 读操作都返回错误,我在固件里会重启 I2C 模块并重新初始化传感器,同时把故障记录到错误日志。远程二极管如果开路或者短路,状态寄存器里的对应标志会置位,这时远程温度读数没有意义,我直接把远程通道标记为故障,而不是把错误的温度数据送进控制逻辑。

5. HVAC 落地场景与现场实测排障

5.1 风管送风温度监测:长线远程探头的实用调整

风管送风温度是 HVAC 控制里最常用的参数之一。我在这套系统里把远程二极管探头固定在风管内部,导线从风管引到控制板,实际走线距离接近 1 米。初期测试时遇到的问题是读数比风管内的参考温度计低了大约 0.8°C,而且波动偏大。

排查下来发现,主要原因有两个。其一是远程探头没有做导热封装,只是裸二极管放在风管里,和空气的换热不充分,响应速度慢;其二是 D+/D- 在控制柜内部那段走线贴近了一块开关电源的散热片,引入了热量影响。解决办法是把探头装进一个铜制的小套管里,套管再伸进风管,既增加了导热面积,又屏蔽了辐射干扰。

另外一个实用经验:如果风管内部有凝露风险,探头要做好密封处理,否则水汽凝结在 D+/D- 之间会改变漏电流,温度读数会慢慢偏移。我后来在探头外面套了热缩管,只露出感温部分,这个问题就解决了。

5.2 压缩机壳体温度监测:继电器动作时的抗干扰处理

压缩机壳体温度通常用于判断压缩机是否过载运行。这个测量点距离控制箱往往有 2 到 3 米,而且中间要经过压缩机本身的电源线、接触器控制线,干扰非常严重。

我在这套系统上实测过一次,接触器闭合的瞬间,远程温度读数偶尔会跳变 2°C 到 3°C,持续几十毫秒后恢复。虽然这个短暂的跳变不足以触发误报警,但如果阈值设置得比较紧,可能导致误动作。

处理方案分为三层:第一层在传感器端 D+/D- 上增加 1nF 差分电容,吸收高频干扰;第二层在 MCU 固件里做软件滤波,连续采样三次取中值;第三层是遇到温度跳变超过 5°C/100ms 的情况,直接丢弃该次采样,等待下一轮。三层叠加后,继电器动作对读数的影响彻底消失了。

如果你也在类似的场景里做温度采集,我建议别急着改硬件滤波参数,先把示波器探头接到 D+/D- 上看清楚干扰波形,是共模还是差模,再对症下药。盲目加电容会把传感器的响应速度拖慢,反而影响实时性。

5.3 空调控制器本地过热保护:本地通道的独特价值

本地通道的典型用途是做控制器自身过热保护。MX51DN512CLQ10 这类 MCU 虽然运行温度范围宽,但 HVAC 控制柜夏天在阳光直射下内部温度可能达到 70°C 以上,功率器件就更热了。PJ85718DM 的本地温度感应来自芯片内部或 PCB 上的热通路,读到的数据能真实反映主控芯片附近的温度状况。

我在这套系统里做了一件事:把本地温度作为降频策略的输入。当本地温度高于 65°C 时,控制逻辑会降低风扇 PWM 最低转速,加强散热;高于 85°C 时,直接进入保护模式,关闭部分输出。这个逻辑在连续高温天的运行中确实触发过几次,保护动作准确。

值得提醒的是,本地温度测的是传感器芯片自身的结温或封装温度,不是空气温度。如果 PCB 上有一块发热严重的功率器件,本地温度会被它拉高,这时候要判断是应该做整机散热还是局部隔热处理,不要一味降低控制器的输出能力。

6. 调试校准与批量生产的最后一步

6.1 总线时序的验证方法

新板子第一次上电,我最先做的事不是看温度读数,而是用示波器抓 I2C 波形。SDA 和 SCL 的时序是否正确、是否存在毛刺或低电平毛刺,这些用万用表根本看不出问题。示波器抓取起始条件、停止条件和数据位电平,确认地址字节正确之后,才会跑固件里的读取逻辑。

如果波形看起来不对,第一排查方向是上拉电阻值。总线上升沿太缓,说明上拉电阻偏大或者总线电容过大;如果出现台阶,可能是总线上的设备有冲突或者地址冲突。这里有一个经验:MCU 内部上拉和外部上拉同时使能时,波形可能因为上下拉驱动能力差异出现小台阶,所以我在最终量产版本里故意禁用了内部上拉,只保留外部 4.7kΩ 上拉,波形干净很多。

远程温度读数的验证则要靠示波器的 D+/D- 波形。正常工作时,D+/D- 上能观察到传感器内部切换电流产生的微小电压跳变,大约几毫伏到十几毫伏。如果看不到这个跳变,多半是探头断线或者 D+/D- 接反了。

6.2 远程探头校准:用冰点做基准的实操流程

远程通道的校准流程,我的习惯是先把 D+/D- 短接,看传感器返回的错误状态,确认开路检测正常;然后用一个已知特性的二极管探头,在恒温槽里和基准温度计对比,记录误差曲线。

在条件有限的情况下,冰水混合物是一个很容易获得的 0°C 基准。做法是把探头密封好后放进冰水混合物中,等读数稳定后记录误差值。需要注意的是,探头要完全浸没且不接触冰块本身,避免局部温度不均。0°C 校准做完以后,再用手握着探头调到人体温度附近做第二个点,基本能保证 0°C 到 50°C 这个常用区间足够准确。

另一个实际经验是:如果传感器的远程通道支持多个偏置电流档位,校准前要把电流档位固定下来,因为不同档位下测到的二极管压降差略有不同,切换档位会导致读数偏移。我在这套系统里固定在一个档位不动,省去了很多麻烦。

6.3 批量生产的统一性注意事项

批量生产时,温度传感器方案比 NTC 省心的地方在于无需逐板标定,但也不是完全不需要注意。我的建议是每块板子在出厂测试时做一次总线通信自检,读一次传感器 ID 和温度,确认焊接和贴片没有问题。

地址冲突是批量生产中比较容易出现的问题。如果一块板上多路传感器共用同一组 I2C 总线,贴片机必须保证 A0/A1 引脚焊接正确,否则两片传感器的地址会重复,导致总线上设备互相干扰。我在设计 PCB 时给 A0/A1 预留了 0Ω 电阻切换位,方便生产不同型号时调整地址,避免重新改板。

固件升级也要考虑寄存器兼容性。不同批次的同型号传感器,寄存器定义可能会有细微差异。稳妥的做法是固件启动时读取传感器 ID 寄存器,校验型号,不匹配就进入错误日志并停止温度采集,而不是在未知状态下运行控制逻辑。

我把这套方案在空调控制器和空气处理机组上都跑过,连续运行几个月的稳定性比之前 NTC 方案好很多。如果你也在做类似的东西,建议第一步就用示波器把总线时序和远程二极管波形抓清楚,这一步省不了,后面所有调试都会顺利得多。

RELATED READING

延伸阅读

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