我要提问
ARTICLE DETAIL

资讯详情

前沿编程新知与开发实战干货的深度解读。

双通道温度传感器+低功耗MCU:嵌入式与HVAC双点测温完整方案

双通道温度传感器+低功耗MCU:嵌入式与HVAC双点测温完整方案 做过嵌入式温度采集的朋友应该都懂一个尴尬单板测温最简单一颗传感器焊上去I2C一读完事可一到系统级监测就麻烦板级温度、电池温度、管路温度、风道温度往往不在同一个物理位置少则隔几厘米多则拉出去两三米。我最近在调一套用 PJ85718DM 加 STM32L073RZ 的组合方案就是为了同时解决“本地温度”和“远程温度”两路采集的问题。不同于以往把两个传感器直接并联或者多挂一路总线这套方案只用一颗传感器芯片就能覆盖两个测温点再配一颗超低功耗 MCU 做数据汇总和上报正好覆盖嵌入式设备监控和 HVAC 暖通控制两类场景。整套东西做完之后我先说结论如果你手头正在选型做温度监测节点把本地测温与远程测温分开设计往往会遇到校零、线缆补偿、唤醒功耗、总线容性这一连串问题而把两个测温点交给同一颗双通道温度芯片再从 MCU 侧做统一调度会省掉非常多麻烦。这篇文章就把我从需求拆解、选型思路、驱动实现到现场踩坑的整条路径完整梳理一遍给正在做类似项目的朋友一个可参考的样板。无论你是刚接触嵌入式测温还是已经在 HVAC 项目里被远端探头精度折磨过都可以照着下面的思路复现。1. 为什么嵌入式与 HVAC 都在盯着“一路板载、一路远端”的双点测温1.1 嵌入式设备里的“本地温度”到底在测谁的体温嵌入式设备做温度监测大家最容易犯的误区是以为测温就是为了防止芯片烧毁。实际上板级温度的含义要宽得多。拿锂电池供电的设备来说电池表面温度和 PCB 板温需要同时监控——如果只测 PCB 温度电池在充放电过程中因为内阻发热导致的温升会被漏掉反过来如果只测电池温度主控芯片高负载时的热点又照顾不到。很多电池管理策略都要根据两路温差来判断散热风道是否堵塞或者充电电流是否需要降额。另一类典型场景是工业控制柜。控制柜内部电器件密集柜内温度往往比环境温度高出十几摄氏度而一些对环境温度敏感的传感器、光学器件则安装在柜外。此时需要在柜内测“本地温度”同时把一路“远程温度”探头引到柜外的环境监测点。之前我见过有的方案直接拉两根 I2C 线到柜外接第二颗传感器结果线长超过半米之后通信就开始不稳定最后还得换 485 或加中继成本一下子上去不少。1.2 HVAC 系统里的“远程温度”为什么不能省HVAC 也就是暖通空调系统温度测点天然就很分散。冷冻水系统的供回水温度一个在冷水机组出口一个在末端回水管两路之间可能有几米甚至几十米的距离组合式空调箱的送风温度和回风温度一个在风管深处一个在检修门附近变风量末端需要测房间温度和送风温度以便计算实际冷负荷。HVAC 项目里做“本地与远程”测温还有一个很现实的原因很多现场仪表箱和传感器探头是分离安装的。仪表箱内要做温度补偿探头装在风管、水管或者吊顶里两者之间是长线连接。过去常用热敏电阻加变送器把电阻变化转换成 4-20mA 电流环拉到控制器。这种方式稳定但成本不低每个点位的变送器、电源、屏蔽线、调试工时加起来一套多测点系统的硬件成本相当可观。用数字传感器直接走总线是更经济的方式难点在于长线传输稳定性这部分后面我会专门聊。1.3 两条业务线最后怎么在硬件上合流把嵌入式设备和 HVAC 的需求放在一起看底层诉求其实是同一个一块主控板上要读取一个板上温度同时读取一个远端温度并且要求尽量低的系统功耗、尽量少的外部器件、尽可能一致的测量精度。于是双通道温度传感器加超低功耗 MCU 这种组合就成了很自然的选择——传感器负责把本地和远程两路信号统一转换成数字量MCU 负责采样调度、数据处理、低功耗管理和对外通信。后续无论是做无线温湿度标签还是做 HVAC 供回水温差监测节点硬件平台都可以复用。2. 选型思路PJ85718DM 与 STM32L073RZ 各自扛下哪一摊2.1 PJ85718DM 的测温通路和寄存器模型按这类双通道温度芯片的常见实现PJ85718DM 内部会有一个带隙温度传感器用作本地测量另有一个远程测温输入通道用来接外部探头。本地通电即可读精度通常在 ±0.5℃ 到 ±1℃ 这个量级远程通道需要外部接一颗热敏电阻或半导体测温探头芯片内部完成激励、采样、线性化之后直接输出数字温度不需要我们自己搭电桥放大电路。开始读数据之前我习惯先按数据手册确认三件事。第一是 I2C 器件地址注意不同封装或不同订货号可能在地址引脚上存在差异第二是转换精度对应的分辨率常见的有 9 到 12 位可选12 位模式下温度 LSB 通常是 0.0625℃第三是寄存器映射至少要搞清楚温度数据寄存器、配置寄存器、报警阈值寄存器、远程测温状态标志位的位置。说实话很多朋友拿到芯片之后上来就按网上老代码抄结果读到一堆 0xFF 或者温度跳变大部分原因就是寄存器地址和转换位数没对上。2.2 STM32L073RZ 为什么适合当“配角”主控我选了 STM32L073RZ这是一颗 Cortex-M0 内核的超低功耗 MCU。选它的理由很简单一是要在低功耗模式下待机同时能用中断唤醒二是要有足够的外设把数据读出来还能往外发比如 I2C、LPUART、SPI 甚至是 USB三是 Flash 和 RAM 容量对这套应用来说很充裕驱动代码加协议栈加上报逻辑都装得下后续想加个引导升级程序也还有余量。在实际项目中我特别看中这颗 MCU 的 STOP 模式配合 RTC 唤醒能力。温度采集场景并不需要传感器时刻满速运行典型做法是每一分钟或者每五分钟唤醒一次完成一次温度转换和上报后再睡回去。如果主控选得不好休眠电流本身就有几十微安再算上传感器待机电流整机一年的电池消耗会非常难看。而 L0 系列在低功耗方面的表现确实对得起它的定位实测整板在深度睡眠下能压到几个微安级别具体数字后面算账的时候给出来。2.3 最小电路设计和功耗估算最小电路其实不复杂核心就是四根线电源、地、SCL、SDA。远程探头通过一个两线端子接到芯片的远程测温引脚。需要注意的是远程探头的引线最好用屏蔽双绞线屏蔽层单端接地。芯片电源脚旁放一个 0.1μF 陶瓷电容靠近引脚放置如果供电质量一般再并一个 10μF 的电解电容也没问题。I2C 上拉电阻先按标准值放 4.7kΩ 左右后续调试时再根据总线上实际挂载的线缆电容调整。为了把功耗说清楚我按一个典型时间片做预算。假设芯片完成一次温度转换加读取需要 30ms期间平均电流消耗约 500μA通信上报阶段如果选用低功耗无线模块或者只写本地 Log这一过程耗时 20ms平均电流按 15mA 估算剩余时间全部进入休眠休眠模式下传感器和 MCU 合计待机电流约 3μA。以 60 秒一个采样周期计算等效平均电流大约是平均电流 (0.03 × 0.5mA 0.02 × 15mA 59.95 × 0.003mA) / 60 ≈ (0.015mAh 0.3mAh 0.18mAh) / 60s ≈ 0.00825mAh/s这里简化算成 mA 时不太直观换个更直接的口径按上述时间分配一小时累计消耗 0.01915mAh 左右折算到平均电流约 19μA。一块 800mAh 的一次性锂电池理论上可以跑四年多当然实际还要算上自放电、电源转换损耗和极端温度下的电池容量衰减但整体量级已经足够说明方案的低功耗表现是很不错的。3. 驱动与调度把两路温度干净地读出来3.1 I2C 读取温度和远程通道的基本流程读取流程并不复杂但顺序很重要。我的代码流程是初始化 I2C 外设配置为 100kHz 标准模式唤醒传感器向配置寄存器写入连续的转换启动位等待转换完成这个时间跟芯片的转换位数有关12 位模式下可以预留 100ms读取本地温度寄存器的高字节和低字节读取远程温度寄存器的高字节和低字节拼接后按分辨率换算成摄氏度。下面是一段可运行的示意代码具体寄存器地址和位数请以器件手册为准// PJ85718DM 读取本地与远程温度示意代码 #define PJ_I2C_ADDR 0x48 #define REG_CONFIG 0x01 #define REG_TEMP_LOCAL_MSB 0x02 #define REG_TEMP_LOCAL_LSB 0x03 #define REG_TEMP_REMOTE_MSB 0x04 #define REG_TEMP_REMOTE_LSB 0x05 #define RES_12BIT 0x60 float pj_read_local_temperature(void) { uint8_t msb, lsb; int16_t raw; pj_write_reg(REG_CONFIG, RES_12BIT); HAL_Delay(50); msb pj_read_reg(REG_TEMP_LOCAL_MSB); lsb pj_read_reg(REG_TEMP_LOCAL_LSB); raw (int16_t)((msb 8) | lsb); return raw * 0.0625f; } float pj_read_remote_temperature(void) { uint8_t msb, lsb; int16_t raw; msb pj_read_reg(REG_TEMP_REMOTE_MSB); lsb pj_read_reg(REG_TEMP_REMOTE_LSB); raw (int16_t)((msb 8) | lsb); return raw * 0.0625f; }有两点值得特别注意。一是转换启动后一定要等足时间再读否则读到的是上一轮转换结果容易让人误以为“芯片坏了”。二是远程通道如果上游接的是热敏电阻类探头不同阻值范围对应的激励电流不同首次使用前必须确认封装型号与芯片内部配置匹配我见过有人拿一个常温 10kΩ 的 NTC 接到原本设计给 100kΩ 探头的通道上读出来的温度整体偏了快十度排查了很久才发现是这个问题。3.2 报警引脚怎么用才不浪费“低功耗”很多双通道温度芯片除了数据寄存器之外还带一个可编程的中断/比较输出脚。它可以在本地温度或者远程温度越限时主动把引脚拉低用来唤醒 MCU。这个功能在低功耗场景里特别有用因为它能省掉 MCU 进行周期读数的次数——正常情况下 MCU 可以睡得深深的温度高了之后芯片主动把主控喊起来。我在实际项目中是这样设计的把报警阈值本地上限设置成 85℃远程上限设置成根据探头安装位置给定的报警值。只有当其中一路越限时报警引脚才会触发 EXTI 中断把 MCU 从 STOP 模式唤醒。这样采样周期可以从 1 秒拉长到 60 秒甚至 5 分钟反正正常温度区间内不需要频繁读数异常时又能及时反应。设计中断回调时要注意在中断服务函数里做消抖处理避免温度在阈值边界来回抖动导致反复唤醒白白消耗电池。3.3 采样调度与功耗预算的完整节奏我在主循环里用一个简单的状态机管理采样节奏。系统上电后先做一次全量初始化接着进入快速测温模式前 10 个周期每 1 秒采一次用于上电自检和建立基线温度。稳定之后切换为周期测温模式每 60 秒采一次每次采集完成之后通过 LPUART 或者无线模块把数据发出去然后进入 STOP 模式等待下一轮 RTC 唤醒。状态机的好处是便于现场调试。联调阶段把采样周期临时改成 3 秒可以很快看到温度曲线交付前再调回 60 秒功耗立刻降下来。如果产品要求更低的功耗还可以在温差波动小于 0.2℃ 连续多次后把采样周期自动拉长到 300 秒一旦检测到温差变大马上缩短周期。这个自适应逻辑我在多个项目里反复用过效果非常明显省电不是一点点。4. 数据校准与抗干扰精度才是真正的工程难题4.1 远程通道的线缆误差与偏移校准温度采集系统里最容易被低估的误差来源是传感器到主控板之间那段线缆。数字温度芯片把模拟前端集成进去了线缆问题通常比纯模拟方案少一些但热敏电阻类远程探头仍然可能因为线路电阻、接插件接触电阻和探头自身离散性造成读数偏差。按照常见的做法现场校准可以分两步走。第一步是单点偏移校准把探头和标准温度参考表放在同一个恒温环境中记录芯片读数与参考值之间的差值在固件里存一个偏移量。第二步是两点斜率校准如果探头的实际响应曲线和芯片默认的线性化参数不完全一致可以在两个不同温度点比如 15℃ 和 45℃分别记录偏差然后做线性插值补偿。对 HVAC 应用来说两个点已经能得到相当不错的效果如果对精度要求更高可以再增加中间点做分段线性补偿。4.2 软件滤波与异常值剔除现场环境里偶尔会出现离谱的跳变读数。这些跳变往往来自瞬态干扰、I2C 通信误码或者探头接触不良。简单粗暴的做法是平均值滤波但这会把一个真实的高温瞬态也给抹平在报警场景里是不可接受的。更稳妥的做法是“限幅加滑动平均”的组合先把本次读数与上次读数比较如果差值超过设定的最大变化速率比如 2℃/秒判定为可疑值丢弃后重读一次如果重读仍然跳变很大则保留原始值并置一个数据有效标志让上层逻辑去判断。我做过一组对比测试不加滤波时芯片读数会在正常值附近偶尔冒出 3 到 5℃ 的尖峰使用限幅滑动平均后尖峰基本消失而且真实温度突变能在几百毫秒内反映出来。要注意的是滤波窗口不能开太大5 到 9 个样本足够窗口再大系统的温度响应就会变得很迟钝现场调 PID 的时候会有明显的滞后感。4.3 实测对比本地与远程通道的偏差控制以我调试的一块样板为例在一个可调温环境里用标准温度参考表做对照测到的基础数据大致如下标准参考温度本地通道读数远程通道读数远程通道校准后5.0℃4.9℃5.7℃5.1℃15.0℃15.1℃15.8℃15.1℃25.0℃24.9℃25.5℃25.0℃35.0℃35.1℃35.2℃35.0℃50.0℃50.2℃49.6℃50.1℃本地通道整体表现很稳偏差基本落在 ±0.2℃ 以内远程通道因为探头个体差异原始读数存在约 0.5 到 0.8℃ 的偏移经过两点校准后也被拉回到 ±0.2℃ 左右。对于嵌入式设备做温度保护这种用途这个精度已经足够对于 HVAC 供回水温差计算只要远程探头的偏移在校准后保持一致温差计算就不会被系统误差左右这一点比分毫不差的绝对值更重要。5. 踩坑实录我在这个项目里处理过的三类现场问题5.1 远程测温线上感应出 50Hz 工频干扰第一块样板装进电控柜里调试时远程温度读数开始抖动波动范围约 ±1.5℃而且明显有周期性。我把示波器探头夹在远程测温线两端看到幅度不小的 50Hz 工频波形。原因很直接测温线走在动力线槽同一个桥架里电缆之间存在容性耦合交流电源的干扰被感应到了信号线上。排查链路是这样的先用示波器确认干扰频率基本锁定为工频然后把远程测温线从动力线槽里抽出来单独走线干扰幅度立刻小了一半接着把线缆换成屏蔽双绞线屏蔽层在传感器端单点接地干扰基本消失最后在芯片的远程测温输入引脚靠近外壳处加了一颗 100pF 高频滤波电容波形更干净了。总结下来对付工频干扰优先次序是远离干扰源、屏蔽、滤波单纯加大软件滤波是下策会把真实温度响应也拖慢。5.2 I2C 总线上拉电阻和线缆电容打架第二块样板做了两块板子用短线连接一切正常接上 1.5 米长飞线后I2C 通信开始偶发失败温度数据每隔几分钟就会读到一次 0xFF。我一开始怀疑是地址冲突排查总线波形后发现 SCL 上升沿明显变缓是典型的容性负载过重。原因很明显板载上拉电阻值偏大加上长线和接插件形成的电容导致信号上升时间超过了 I2C 协议允许的上限。处理办法有两个方向。一是把上拉电阻从 4.7kΩ 换成 2.2kΩ增强上拉驱动能力实测可以让上升时间回到协议范围以内二是把 I2C 时钟从 400kHz 降到 100kHz进一步放宽对上升沿的要求。如果线缆长度超过两米我建议再考虑用 I2C 总线缓冲器或者转成差分信号单纯的电阻调整有限度。另外飞线两端最好各加一个 100Ω 串联电阻能有效抑制振铃和静电引入的毛刺。5.3 低功耗模式的“假睡”与频繁唤醒的功耗陷阱功耗测试时还遇到过更隐蔽的问题系统看起来进入 STOP 模式了但实际平均电流比理论预算高了一个数量级。逐项排查后发现问题出一颗 GPIO——远程温度探头的连接状态检测引脚没有配置成合适状态处于浮空输入引脚上感应到的噪声导致 MCU 频繁被外部中断唤醒每几秒就醒一次功耗自然压不下来。排查思路是先把外设逐个关掉观察待机电流变化再把所有 GPIO 统一配置为模拟输入或者固定电平输出看电流是否回升。那次就是通过二分法定位到唤醒源的。再之后我在初始化代码里增加了严格的“睡眠前检查”流程所有用不到的 GPIO 拉成确定电平EXTI 挂的唤醒源只保留报警引脚和 RTC外设时钟全部关闭。这套检查流程已经写进了我的低功耗设计习惯里每次合入配置前都要过一遍。6. 从 Demo 到产品两个落地方向的参考实现6.1 嵌入式侧电池供电的无线温度标签第一个落地方向是做成一个电池供电的无线温度标签。硬件上就是 PJ85718DM、STM32L073RZ、一个低功耗无线模块、一颗纽扣电池或者小型锂电池再加一个温湿度外壳。本地通道贴在主控芯片附近远程探头引到设备外部。固件里跑前面说的自适应采样节奏温度数据通过无线链路上传到网关再由平台端实时展示和告警。这种标签很适合给既有设备做温度后装改造。不需要改动被监测设备的任何电路只用导热胶把探头固定到目标位置整块标签独立供电寿命可以做到一年以上。对于经常要跑现场贴测温点的团队来说这套方案比每台设备都重新设计电路要快得多。6.2 HVAC 侧冷冻水供回水温差监测节点第二个落地方向是 HVAC 冷冻水供回水温差监测。冷水机组和楼宇自控系统通常已经在测这两个温度但很多项目现场需要一套独立于主控制器的校验用节点用来核对主管道上的测点是否存在漂移。这台设备装在配电箱或弱电间里本地通道测箱内环境温度远程两个探头分别绑在供水和回水管外壁或者置于测温套管中采集后用温差判定系统运行状态。安装时要注意探头的热耦合管壁测点需要打磨除锈之后再用导热硅脂加保温棉固定否则测出来的温度滞后和误差会让人怀疑硬件方案有问题。其实不是芯片不行是探头封装和安装没到位。对温差计算而言两只探头的采样节奏也尽量保持同步如果一次采集顺序是“先供水后回水”且间隔较大两路读数本身就会自带时间差温差就会出现几十秒级别的人为波动。我在软件里特意把两路读取放在相邻的代码位置并记录同一时标这样算出的温差才能真正反映系统趋势。6.3 围绕这套平台还可以继续扩展的方向这套平台后期还可以扩展出不少功能。比如在 MCU 里再加一路电池电压检测通过 I2C 把电压数据打包进上报帧用于远程诊断供电状态也可以把本地通道温度作为参考点去做热敏电阻探头的老化自检——当本地和远程都在同一环境且温差长期保持稳定时可以认为探头没有产生漂移。冷链运输、储能电池簇温度监测、机房微环境监控这些场景的测温架构和这套方案大同小异只是外壳、通信方式和上报协议需要按具体项目调整。最后再分享一条个人体会这套双路测温方案我在两个项目里各自实现过一遍第一条经验永远是“先想清楚现场安装方式再写代码”。很多温度数据的奇怪跳动最终都能追溯到探头安装、走线路径、接插件选型这些看似与软件无关的环节比如管壁探头没做保温处理导致的外界空气干扰比如接插件氧化造成的接触电阻变大。软件滤波和校准确实能修掉一部分问题但硬件侧的物理细节决定了最终精度上限。如果你正在抄这套 PJ85718DM 加 STM32L073RZ 的方案建议先照镜子看看自己的探头安装和线缆走线往往那里才是真正的坑。
返回列表