温度监测这事儿,单看电路不复杂,但一旦摊上“本地”和“远程”两个词,性质就变了。本地好办,传感器往板子上一贴,I2C线短、电源干净,数据基本一读一个准。远程要命的地方在于线缆长度、供电压降、总线电容、现场干扰,随便哪一项都够让温飘掉几度。最近我在做一个暖通智能化的项目,就是用 PJ85718DM 这颗数字温度传感器搭配 STM32L073RZ 作为主控,同时兼顾嵌入式和 HVAC 场景下的本地与远程温度监测。跑了一圈下来,硬件、驱动、低功耗、故障诊断都踩了一遍,把过程整理出来,给后面要做类似方案的朋友一个参考。
这个组合解决的是很实际的问题:一个主控带两条甚至更多温度采集通道,一条在板内,测设备环境温度;一条通过连接器引到远端,测风管、回风管或者水管的温度。PJ85718DM 本身支持 I2C/SMBus,分辨率能做到 0.0625°C,远程测量抗干扰能力不错;STM32L073RZ 是 Cortex-M0+ 内核的低功耗 MCU,跑传感器轮询、滤波、报警逻辑绰绰有余,而且 Stop 模式下的功耗很低,很适合做常年在线、电池供电或者需要满足节能认证的控制器。整篇文章会围绕硬件设计、I2C 布线、驱动与滤波、低功耗调度、故障排查这五部分展开,每个环节我都尽量给出可以直接参考的参数和做法。
1. 方案总体设计与芯片选型逻辑
1.1 先搞清楚“本地”和“远程”到底差在哪
开始动手之前,我先把场景定义理了一遍。本地温度监测,传感器一般就在 MCU 同一块板子上,甚至只是为了测环境温度顺便做个 TOP 散热补偿,这时候总线长度不到几厘米,问题集中在 PCB 布局和传感器自身的测量精度上。远程温度监测则完全不同,传感器可能会被装在几米甚至十几米外的风管探头里,中间穿过设备的强电区、变频器附近,这时候需要考虑的不只是通信协议,还有线缆带来的寄生电容、电源走线压降、ESD 和浪涌侵入,以及在恶劣工况下的故障隔离。
在 HVAC 场景里,远程点的温度往往才是控制的核心变量,比如送风温度、回水温度,直接决定 PID 参数怎么调。而本地温度的作用更多是保护性的,比如机箱内温度过高时需要降频或者报警。两个通道的优先级和数据更新周期不同,这就要求软件上不能一把梭地做统一轮询,而是要分开调度。
1.2 为什么用 PJ85718DM 而不是热敏电阻
做温度采集,最省成本的方案当然是 NTC 热敏电阻配一个分压电阻进 ADC。但这种方案在设备里有两个天生缺点:一是每个通道都需要单独校正,尤其在 0°C 到 50°C 这个 HVAC 常用区间,NTC 的离散性明显;二是 ADC 采样很容易受电源噪声和参考电压波动影响,长线传输时更明显。
PJ85718DM 走的是数字传感器路线。它内含 12 位 ADC,精度等级在这个量级的传感器里属于很能打的,I2C 接口直接给 MCU 输出数字量,省掉了放大器、滤波网络和校准表。这颗芯片还带了可编程报警输出,超过上下限时 ALERT 引脚自动拉低,省得 MCU 一直轮询寄存器。对于 HVAC 这种经常要设温度阈值的场景,这个功能非常实用,后面我会专门展开讲用法。
1.3 STM32L073RZ 在这类工程里的不可替代性
STM32L073RZ 属于 STM32L0 系列,Cortex-M0+ 内核,主频最高 32MHz。性能不算强,但在这个用途上完全够用。它的 Flash 有 192K,SRAM 20K,还带 6K 的独立 EEPROM,用来存校准参数、开关机记录或者 Modbus 从站地址都不用额外挂存储芯片,这在控制板的小体积约束下很有优势。
我更看重的是它的外设配备。它带了 2 个 I2C 接口,其中一个还兼容 SMBus 时序参数,和 PJ85718DM 这类支持 SMBus 的传感器配合时,可以在长线通信中利用 SMBus 的超时机制恢复总线错误。这是很多同类 M0+ MCU 没有的细节,也是我选择这颗芯片的直接原因之一。低功耗方面,Stop 模式下带 RTC 的典型电流可以做到微安级,后面我会算一笔完整的账。
2. 硬件设计:两个温度通道的天壤之别
2.1 本地通道的 PCB 布局要点
本地传感器离 MCU 很近,设计上反而容易疏忽。我吃过一次亏:把传感器放在板边缘,旁边就是功率 MOSFET 和继电器,结果读到的温度在继电器吸合瞬间跳了大约 0.4°C。后来把传感器移到了离发热器件远一点的位置,并在底下铺了一块完整的地铜皮,问题就消失了。
PJ85718DM 的电源引脚需要加 100nF 去耦电容,这一点不能省。很多应用笔记会强调“推荐 100nF+1μF 组合”,但在板载短走线场景下,100nF 贴近 VDD 引脚已经够用。真正重要的是不要在传感器下面走电源或大电流回路,否则地弹噪声会直接耦合进芯片内部的 ADC 参考。传感器属于模拟类器件,即使数字输出,也应该按照模拟器件的布局规范对待。
2.2 远程通道的接口电路与保护
远程通道是这篇内容的核心,因为绝大多数问题都出在这。远程探头如果直接通过排针焊一根长线到传感器,I2C 总线是不一定能正常工作的。原因很简单,I2C 规范要求总线电容不超过 400pF,普通双绞线的分布电容大约在每米 50 到 70pF,3 米就接近极限,10 米直接超标。
我在项目里采用的思路是:板载侧放一个 I2C 缓冲器,距离远的传感器挂在一个单独的总线段上。这样远端总线电容和近端总线电容被隔离,MCU 侧的上拉电阻可以按短总线优化,远端上拉电阻按长线优化。没有缓冲器的时候,也可以通过降低总线速率来缓解,把 I2C 时钟降到 100kHz 甚至 60kHz,实际测试 5 米屏蔽双绞线还能稳定通信。
接口处还要加瞬态保护。HVAC 现场最常见的不是慢干扰,而是电磁阀动作和变频器启停产生的尖峰,这些尖峰会通过线缆传导到传感器供电和 I2C 信号线上。我在连接器端加了 TVS 阵列,电源线上加了一个小电感组成的简单的 π 型滤波器,实测继电器频繁开关的测试台上没有再出现复位或数据错误。远程传感器的 VDD 和 GND 必须单独走一对双绞线,不能和信号线混用,否则传感器内部 ADC 的参考电位会随电流波动,直接表现为读数周期性跳变。
2.3 上拉电阻如何计算
I2C 总线上拉电阻的选择不是随手填个 4.7kΩ 就完事。上拉阻值需要权衡上升时间和拉电流。总线电容大时,RC 常数变大,上升沿变缓,导致通信误码;上拉阻值太小时,SCL/SDA 灌入电流偏大,芯片输出低电平可能压不到 VIL 阈值以下。
考虑最普通的 5V 供电场景,传感器和 MCU 都是 3.3V 系统,则上拉电阻接 3.3V。上升时间 t_r 按照 1MHz 模式下最大 300ns 来估算,等效公式是 t_r ≈ 0.8473 × R_pullup × C_bus。假设总线上电容 300pF,想做到 300ns,R_pullup 需要小于 1.18kΩ。但长线场景下总线电容更大,我实际把上拉电阻放到 1kΩ 才稳住。要注意的是,阻值太小会增大开漏输出低电平时的电流,3.3V/1kΩ 约 3.3mA,在允许范围内,但如果用的是 5V 供电,电流会到 5mA,部分传感器就会吃不消,需要仔细核对数据手册。
| 总线长度 | 估算电容 | 推荐速率 | 上拉电阻参考 |
|---|---|---|---|
| < 0.2m | < 50pF | 400kHz | 4.7kΩ |
| 1~3m | 100~300pF | 100kHz | 2.2kΩ |
| 3~10m | 300~700pF | 60~100kHz | 1kΩ 或加缓冲器 |
这个表格是实际测试的参考值,具体还要看线缆特性和是否屏蔽。屏蔽层单端接地,不要两端同时接,避免形成地环路。
3. 软件实现:从读取寄存器到稳定可靠的温度数据
3.1 I2C 寄存器操作与初始化
PJ85718DM 这类传感器的 I2C 操作比较简单,就是写配置寄存器、触发转换、读温度寄存器三步。初始化流程我一般这样写:先发一个软件复位命令让芯片回到默认状态,等上电稳定后再配置分辨率、转换周期和报警阈值。特别注意传感器上电需要一点时间,建议等 10ms 之后再发第一条命令,有的板子一上电立刻发命令会收不到 ACK。
设备地址可以通过引脚配置,默认地址一般是 0x48 这类序列。如果挂在同一个 I2C 总线上多颗传感器,地址必须不同,这是硬件设计阶段就要确认的。本地和远程共用一条总线时,我一般让远程传感器地址可拨码选择,方便现场多设备组网时避开冲突。
// 伪代码:读取温度并转换为浮点值 uint8_t addr = 0x48 << 1; uint8_t reg[2]; int16_t raw; i2c_write_byte(addr, 0x04); // 触发一次转换,具体寄存器以数据手册为准 delay_ms(10); i2c_read_16bit(addr, 0x00, (uint8_t *)&raw); float temp = raw * 0.0625f; // 12位分辨率,每个LSB对应0.0625°C很多人在这一步踩坑:有符号温度的处理。低温时原始值是补码形式,如果把 int16_t 直接强转成 uint16_t,负数会变成很大的正数,最后算出来是几百摄氏度。正确做法是先读取 16 位寄存器,再按有符号数解读,和上面伪代码一样。
3.2 温度换算与数字滤波
温度换算的公式本身不难,难的是怎么让数据“稳住”。传感器输出的原始值在静止环境下也会有 ±0.1°C 左右的跳动,这对 HVAC 控制来说问题不大,但如果后面接了 PID 或者报警判断,原始抖动可能会导致输出反复横跳。我的做法是加一层低通滤波,而不是简单取平均值。
取平均值有它的缺点:一旦出现一个毛刺,平均值会被瞬间拉偏,随后要等很多个周期才能恢复。低通滤波则更平滑,每次更新只按比例接受新值。具体代码如下:
static float filtered_temp = 25.0f; float alpha = 0.2f; float current = raw * 0.0625f; filtered_temp = (1.0f - alpha) * filtered_temp + alpha * current;alpha 我根据采样周期调整。如果 1 秒采一次,alpha 取 0.2 到 0.3 比较合适;如果 100ms 采一次,alpha 要更小,否则滤波效果太弱。这种滤波器的延迟在可控范围内,不会影响 HVAC 这种慢变量的控制。
3.3 报警阈值与滞后区间的设计
PJ85718DM 的 ALERT 输出接 MCU 的 EXTI 引脚,温度超过上限或者低于下限时自动触发。硬件报警比软件轮询的响应快得多,而且在 MCU 休眠时依然有效,这是硬件传感器方案的一大优势。
报警阈值设置的关键是必须加滞后(hysteresis),否则温度在阈值附近轻微波动时,ALERT 引脚会高频翻转,MCU 被反复唤醒。我一般设上下限各留 2°C 的滞后空间。比如上限 60°C,上限报警阈值就设 60°C,解除阈值设 58°C。传感器内部通常有 T_HYST 寄存器,用它来做,不需要在软件里额外维护状态。
ALERT 引脚是开漏输出,需要接上拉电阻。这个细节很多原理图都会画,但实际焊板子时容易漏。另外,如果一个总线上挂了多颗传感器,所有 ALERT 引脚直接线与,MCU 只能知道有一颗超限,不知道具体是哪颗。解决方法是靠读回所有传感器的状态寄存器来判断,或者每颗传感器用单独的 GPIO 接 ALERT。我在方案里是每颗传感器独立一根 ALERT 线,成本增加不多,排查问题方便很多。
4. 本地/远程双通道监控的应用逻辑
4.1 两种通道的不同调度策略
本地通道和远程通道虽然用同一个芯片型号,但运行逻辑完全不同。本地通道测的是设备内部环境温度,变化速率相对快,需要更短的采样周期和更高的刷新率,我按 200ms 轮询一次。远程通道测的是空调风管、水管温度,热惯性大,温度变化慢,1 秒甚至 5 秒轮询一次都够。这样的差异化调度能显著降低平均功耗,也减轻总线的通信压力。
如果把两路放在同一个 I2C 总线上,还要注意总线空闲时间的分配。远程总线可能因为长线原因跑 100kHz,而本地总线可以跑 400kHz,中间用 I2C 缓冲器之后两段互不影响。实测双通道同时采样时,只要轮询错开几十毫秒,数据稳定性就很好。
4.2 远程传感器故障检测逻辑
远程放在现场,故障率比本地高一个量级。传感器线缆松了、被老鼠咬了、端子进水氧化,都会导致总线异常。我在固件里做了三类诊断:
第一种是无响应检测,I2C 通信连续 N 次无 ACK 就判定传感器离线。第二种是数据合理性检测,比如读取温度超出芯片物理可测范围(低于 -55°C 或高于 +150°C),直接判定为异常。第三种是数据跳变检测,远程通道 1 秒采一次,正常温度不可能连续两次相差超过 10°C,如果出现就说明采集链路有问题,需要标记并保留上一帧有效数据。
检测到故障之后,我会把故障码记录到 EEPROM,同时通过 UART 或者 Modbus 上报给上位机。HVAC 控制系统后面接的还是楼宇自控,必须要让它知道当前数据是故障值而不是真实值,否则执行器会按错误的温度动作。
4.3 与执行器联动的报警逻辑
在 HVAC 项目里,温度监测不是只给上位机看,它还需要直接联动风机、阀门和执行器。这套系统的本地温度一般用于设备保护,比如散热风机控制——机箱温度超过 45°C 时开启风机,回落到 40°C 以下时关闭,中间 5°C 的滞回区间防止风机频繁启停。
远程温度则参与控制算法,比如送风温度反馈到 PID 调节冷阀开度。远程探头安装在风管中央的探头套管内,热响应延迟明显,PID 参数要放得足够软,否则系统容易震荡。我在调试时发现,同一套 PID 参数在本地温度参与控制时很稳定,换成远程温度后就开始过冲,就是因为远端热惯量大。后来把采样周期加长、滤波系数调小,才把曲线压下来。
报警输出方面,ALERT 引脚直接接到 MCU 唤醒引脚后,MCU 可以用最快速度响应超温事件,即使处于低功耗睡眠模式,也能在超温瞬间被唤醒并且做安全处理。这个特性让 HVAC 控制器可以在待机状态下保持安全警戒,而不用每隔几毫秒就跑一次主循环。
5. 嵌入式场景下的低功耗与可靠性设计
5.1 用 STM32L073RZ 把功耗压下来的方法
STM32L073RZ 的低功耗能力是这个方案的第二个落脚点。HVAC 控制器不一定要求极致的省电,但在很多嵌入式终端设备,比如电池供电的数据记录仪里面,功耗直接决定了电池寿命。
我习惯把系统工作状态分成 Active、Sampling、Sleep 三档。Active 状态处理命令或通信,MCU 全速运行;Sampling 状态只是做一次温度采样和滤波,运行时间控制在 10ms 以内;其余时间全部进入 Stop 模式,用 RTC 定时唤醒。
代码上需要把不用的外设时钟全部关掉,尤其是 I2C 外设,在采样完成后要调HAL_I2C_DeInit()或者关闭时钟,这个操作对功耗影响很明显。如果传感器也不需要用,就可以用 GPIO 控制外部负载开关切断传感器电源,只保留 MCU 的 Stop 模式。
5.2 实测功耗估算
我做了一个粗略的功耗模型,给电池供电的应用做预算。假设 MCU 内部运行频率 32MHz,活动电流约 8mA,I2C 采样和滤波耗时 10ms;Sleep 模式下 Stop 模式带 RTC 电流约 2μA;传感器每次读全流程约 10mA 峰值,持续 5ms。按每 1 秒采样一次来计算:
单次采样能量约等于 (8mA + 10mA) × 10ms,约 0.18mAs;1 秒内的耗电就是 0.18mAs 加上 Sleep 电流 2μA × 1s(约 0.002mAs),加在一起平均电流在 0.18mA 左右。如果把采样周期放大到 30 秒,平均电流就只有约 8μA,两节 AA 电池可以运行非常久。这也是为什么 HVAC 控制的传感器节点通常会采用更慢的采样频率。
| 配置 | 平均电流 | 使用时长(两节2000mAh电池) |
|---|---|---|
| 1秒采样一次 | 约180μA | 约1.3年 |
| 30秒采样一次 | 约8μA | 约28年(受自放电限制) |
| 纯Stop模式 | 约2μA | 约100年(理论极限) |
当然,实际项目里还要考虑电压转换效率、电动势衰退和自放电,这个计算只做参考,但方向是明确的。
5.3 传感器供电的动态开关
远程传感器的供电和本地传感器不同,必须能独立关断。原因是现场探头的线缆可能很长,即使传感器进入待机状态,电缆上的漏电流、上拉电阻的电流叠加在一起,也可能会吃掉可观功耗。用一个 P-MOSFET 做负载开关,MCU 的 GPIO 控制栅极,当需要采样时打开传感器电源,采样完成后立刻关闭。
控制这个负载开关还要注意延时。传感器上电后内部振荡器需要起振,稳定时间一般在几毫秒到几十毫秒,必须在供电彻底稳定后再发起 I2C 通信,否则第一读到的数据不可靠。我实测了一下,开启到数据稳定大约需要 20ms 左右,体现在功耗上也就是多 15ms 的高电平电流,在长周期采样里完全可以接受。
6. 调试实录:这几类坑,替你踩过了
6.1 I2C 长线通信偶发 NACK
项目联调那天,远程传感器接了一根 8 米的屏蔽双绞线。故障现象很典型:系统启动后能正常读数十几秒,然后就开始随机 NACK,复位后又恢复,过一会又出错。用示波器看 SCL/SDA 波形,发现远程侧的上升沿坡度明显变缓,而且数据线在 SCL 下降沿附近存在明显振铃。
排查下来是双重问题叠加。一是总线电容太大,近 600pF,而板子上默认用的是 4.7kΩ 上拉电阻,RC 时间常数过长;二是接线没有用屏蔽层做信号回流。对策是把远程总线速率降到 100kHz,上拉电阻换成 1kΩ,屏蔽层单端接地。改完后连续跑了 8 小时,没有再出现 NACK。
6.2 远程探头的温度彻底偏离
另一个项目里,远程读数比实际温度高 3°C 到 4°C,而且很稳定。首轮排查方向都放在传感器校准上,换了几颗芯片也没用。后来发现探头安装位置在一个风机盘管的回风弯头附近,气流组织有局部回流,探头刚好处于一个微热区。这不是电子问题,而是安装位置导致的测量误差。
HVAC 现场特别容易出现这种“电气正常但数据却不对”的情况。探头必须按气流方向安装在直管段,距离弯头或阀门保持足够距离;套管最好通到管道中心,避免贴近管壁。后来把探头重新定位到直管段中间,数据立刻恢复正常。
6.3 故障排查速查表
| 现象 | 可能原因 | 处理办法 |
|---|---|---|
| 上电后 I2C 无 ACK | 传感器供电未稳定 | 延长上电等待时间 |
| 上电后 I2C 无 ACK | 地址冲突 | 检查拨码地址或焊接地址配置 |
| 通信偶发 NACK | 总线电容过大、上拉过弱 | 降速、换小阻值上拉、加缓冲器 |
| 温度读数偏高且稳定 | 布线整流、安装位置错误 | 调整探头位置,检查气流路径 |
| 温度读数间歇跳变 | 电源干扰或接触不良 | 检查供电线缆和连接器端子 |
| 整机功耗偏高 | 传感器供电未关断 | 加入负载开关控制 |
6.4 最后一点个人习惯
做这种混合场景的温度采集项目,我现在养成了一个习惯:硬件原型阶段就把远程接口的完整线缆长度和布局固定下来,然后带着真实线缆一起做软件调试。千万别用短杜邦线代替长线联调,软件逻辑没问题不代表现场没问题。等整套系统搬到现场再调长线通信,成本是最高的。
另外,EEPROM 里我会存一份温度偏移校准值。每套设备出厂时做一次冰水浴和常温对比,把每个通道的偏差写进去,代码读取温度后再叠加这个偏移量。这个做法花不了多少时间,但能显著提升整个系统的温度精度表现,对 HVAC 这种要过计量验收的项目很加分。