双通道温度传感器+STM32:HVAC控制器测温设计与调试详解
年前调一块暖通控制器板卡的时候温度采集方案折腾了我好几轮。主控选的是STM32L152RE传感器环节最开始想用NTC加比较器自己做后来换成PJ85718DM这颗“本地加远程”双通道温度传感器整个方案清爽了很多一颗芯片同时盯控制板自身的温度和风管远端测点温度I2C直接读回数字量省掉了大量模拟前端标定和量产一致性也更好处理。这篇文章就把整个项目的选型思路、电路设计、驱动实现、现场标定和踩坑过程完整写出来给正在做嵌入式或HVAC类温度监测方案的朋友做个参考。1. 项目背景暖通控制器里为什么会有两个测温通道1.1 应用场景拆解HVAC系统里的温度测点远不止面板上显示的那个室温。我手头这个项目要同时采集几类温度风管送风温度装在风管内部用来判断风机盘管出风是否正常换热盘管表面温度直接贴到盘管翅片或铜管上判断冷媒状态控制盒内部环境温度用来防止元器件超温功率器件附近温度大功率继电器或者驱动MOS管旁边的板温作为过热保护依据。这些测点的特点各不相同。风管内的温度变化很慢秒级甚至分钟级才有明显变化盘管表面温度受冷媒启停影响几分钟内可能波动好几度板级温度则跟负载和机箱散热直接相关需要及时响应。如果每个测点都放一颗完整的数字温度传感器不仅成本翻倍PCB面积和走线资源也吃不消有些空间非常紧凑的位置甚至塞不下一颗SOT-23封装的芯片。用“本地加远程”双通道方案就顺了传感器芯片本体放在控制板上本地通道测芯片附近空气或板温远程通道通过一对细线把外部二极管延伸到远端测点芯片基于二极管的电压温度特性换算那一小片区域的温度。这样一颗芯片解决本地和远端两个测点而且远端只增加一个廉价二极管连供电都不需要非常适合多出分散测点的HVAC应用。1.2 本地与远程测温的原理区别本地通道本质上测的是芯片内部PN结的结温芯片会通过内部ADC把电压信号转换成数字量我们读到的是直接可用的温度值。远程通道原理上有意思得多。它测的是外部二极管在不同电流激励下正向压降的差值也就是业内常说的ΔVbe测温。为什么不用单个Vbe值直接换算因为Vbe本身携带太多与温度无关的干扰因素二极管反向饱和电流的工艺偏差、串联电阻、漏电流甚至封装应力都会让绝对电压漂移。但如果用两个不同大小的电流分别测量Vbe再把两个读数做差那些与材料工艺相关的公共项会被消掉剩下的量基本只跟玻尔兹曼常数、电荷量和绝对温度相关线性度非常好。用生活化的方式理解就像量地面到屋顶的高度先拿卷尺量一次再换根绳子吊着量一次两个数值相减你就不用关心地面本身平不平了。ΔVbe测温也是这个道理它把二极管个体差异的影响压得很低。这就是远程二极管测温能跨批次保持一致性好的根本原因。1.3 全局数据流向PJ85718DM和STM32L152RE之间走I2C总线两个通道的温度值都放在芯片内部的寄存器里。主控STM32L152RE负责做初始化、定时读取、阈值判断和对上级系统上报PJ85718DM则始终工作在“模拟信号变数字量”的角色上。主控可以大量时间待在低功耗模式传感器越限时通过ALERT脚拉低来唤醒MCU这个机制对无人值守的HVAC控制器来说非常实用。整条数据链路并不复杂远程二极管或者本地结温 → 芯片内部调制和ADC → I2C寄存器 → STM32L152RE读取并处理 → LCD显示与通信上报。复杂度主要在驱动细节和标定下面一个个说。2. 硬件选型思路PJ85718DM 和 STM32L152RE 各自承担什么角色2.1 为什么选PJ85718DM而不是一堆单点温度传感器单点数字温度传感器不是不能用问题是每多一个测点就要多一路I2C设备地址、多一颗芯片的供电和去耦。地址引脚数量有限挂多了还得加I2C开关或改用SPI系统复杂度很快就上去了。PJ85718DM这类本地加远程芯片一颗设备地址只占一路却同时拿到了本地温度和一路远端温度。如果项目有几个分散测点我当时的做法很直接板上放两颗PJ85718DM地址引脚分别拉高拉低错开一颗测控制板本地和风管送风另一颗测驱动器件附近和盘管表面。I2C总线上地址逻辑清晰每颗芯片独立报警一颗出问题不会影响另一路。远程测点本身不带电源、不带芯片、不带地址概念结构上就是一对线加一颗二极管方便程度在维修和线束布置上体现得非常明显。2.2 STM32L152RE的低功耗和外设正好匹配STM32L152RE属于超低功耗L1系列Cortex-M3内核最高主频32MHz。对于温控器这类任务温度刷新周期是秒级主控完全不需要一直满频跑。L系列的优势在于多种低功耗模式之间切换的快和稳从停止模式恢复到运行只需要微秒级的时间这让“频繁小睡、醒来干一点活再睡”的架构变得可行。真正让我选它的还有两个细节。一个是它自带LCD段码屏控制器HVAC控制器面板上要显示温度、风机档位、模式段码屏是成本最低、阳光下最好读的方案省掉一颗外部显示驱动芯片BOM成本下降不少。另一个是它的I2C外设成熟稳定接PJ85718DM这类最高工作在400kHz的芯片完全没压力。板子上还要留几个备份I/O做按键扫描和故障灯控制L152RE的引脚资源也够。2.3 省掉模拟前端和查表标定用NTC方案最痛苦的环节不是算分压电阻而是每一条产线都要做温度标定。同一批100kΩ NTC在25℃附近个体差异就能差出好几度想要±0.5℃的精度每个探头都要单独校准并在固件里放校准表。这对于小批量产品来说工作量不小。PJ85718DM这类芯片把模拟放大、ADC转换和线性化都封装好了。我只需要用I2C读取已经换算好的温度值再针对远程二极管的理想因子偏差做一次小范围补偿就行。批量生产时一般只需要抽检不用逐台校准这在产线上是实实在在省时间。有个关键提醒选型时一定要先确认芯片支持的单次转换模式和报警中断能力有些便宜的单通道传感器不支持外部唤醒低功耗方案会受限。PJ85718DM在这一点上做得比较全面至少我这颗支持的寄存器功能覆盖了项目所有需求。3. 电路连接与PCB布局远程二极管不是随便接的3.1 二极管选型与极性远程通道的核心元件是外部PN结常见做法是选小信号三极管并把基极集电极短接用发射极和短接端作为二极管的两极。之所以不直接用普通发光二极管或整流二极管主要因为小信号三极管这类器件在高阻态下漏电流小温度特性更接近传感器芯片内部的理想因子假设误差最容易通过校准消除。接线极性一定要和芯片手册对齐通常D接二极管正端D-接负端。原理图上标注清楚封装图上也放上极性丝印。我在初版画PCB时嫌麻烦没标D/D-结果贴片厂把其中一块板的二极管方向贴反上电后远程通道读出一个-40℃左右的固定异常值排查了半天才定位到问题这个低级错误浪费了一整天时间。3.2 滤波电容和输入保护远程通道对噪声比较敏感尤其是走线要经过端子、接插件或者较长距离时线路上感应的高频噪声会直接叠加到毫伏级电压信号上。通常做法是在D和D-之间加一个小容值的陶瓷电容比如100pF到1nF靠近二极管侧放置在芯片侧的D/D-引脚之间再放一个10nF到100nF的电容起到滤波和防止射频干扰的双重作用。电容值不是越大越好。容值太大等于给信号加了低通惯性远程温度读数会变得迟钝甚至在温度骤变时出现明显滞后。我在调试中试过在远端放1uF电容结果风门从冷切换到热后读数要将近两分钟才跟得上实测值后来换成100pF才恢复正常。这类参数最好在目标线长和实际板卡上验证后再定。3.3 I2C总线上拉电阻的选择STM32L152RE的I2C引脚配置成开漏输出SCL和SDA必须靠外部上拉电阻拉到高电平。上拉电阻阻值会影响通信速度和抗干扰能力。理论上100kHz模式下可以容忍较大的上拉阻值但实际线缆、多个设备并联后寄生电容会让上升沿变缓。我踩过的坑是初始设计用了10kΩ上拉总线上挂两个PJ85718DM传感器离主控大概20cm刚开始正常样品测试时偶发读不到应答把速率降到50kHz才稳定。后来把上拉电阻改成4.7kΩ示波器上看波形上升沿明显变陡峭100kHz下连续读写几百次都不再出错。HVAC控制器板内走线通常不会太长4.7kΩ是个比较稳的起手值如果板子特别紧凑还可以降到3.3kΩ。3.4 板级布局和热源规避本地通道测的是芯片周围的环境温度可它偏偏就在发热区附近。布局时如果顺手把传感器塞到功率MOS管边上读出来的就不是控制盒内空气温度而是“那颗管子最近过得怎么样”。我后来把传感器放在靠近出风口的板边位置留出空气流通空间读数才恢复正常。远程二极管贴到风管或盘管表面时要确保接触面平整并适当加导热硅脂减少接触热阻。固定方式上用卡簧或铝箔胶带都比悬空放置更可靠因为空气层的隔热效果很明显会直接导致读取温度低于真实壁面温度。4. 驱动移植与数据处理从I2C读回度数只是第一步4.1 I2C初始化基础STM32L152RE的I2C外设初始化流程属于常规操作开GPIO时钟、配置SCL/SDA为开漏复用、配置I2C时钟源为合适的PCLK、设置标准模式或快速模式、使能外设。驱动层封装建议直接提供三个基础函数写入寄存器、读取寄存器、读取多字节温度值。下面是一段示意性质的初始化代码void i2c1_init(void) { GPIO_InitTypeDef gpio; I2C_InitTypeDef i2c; RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); gpio.GPIO_Pin GPIO_Pin_6 | GPIO_Pin_7; // PB6SCL, PB7SDA gpio.GPIO_Mode GPIO_Mode_AF_OD; gpio.GPIO_Speed GPIO_Speed_2MHz; GPIO_Init(GPIOB, gpio); i2c.I2C_ClockSpeed 100000; i2c.I2C_Mode I2C_Mode_I2C; i2c.I2C_DutyCycle I2C_DutyCycle_2; i2c.I2C_OwnAddress2 0; i2c.I2C_Ack I2C_Ack_Enable; I2C_Init(I2C1, i2c); I2C_Cmd(I2C1, ENABLE); }把I2C初始化放在系统时钟和GPIO配置之后上电后可以先用逻辑分析仪抓取SCL波形确认信号没有畸变再去做寄存器读写。4.2 寄存器配置要点PJ85718DM这类芯片通用寄存器布局大致包含配置寄存器、本地温度寄存器、远程温度寄存器、上限报警阈值、下限报警阈值以及扩展温度寄存器。具体偏移地址以实际数据手册为准但逻辑上要注意几个点分辨率配置通常用12位模式LSB对应0.0625℃左右够HVAC用工作模式连续转换或单次转换低功耗项目一定要支持单次模式报警阈值高低温阈值寄存器超限后ALERT脚输出有效电平转换率有些芯片支持可编程转换周期设置成4Hz或8Hz足够。读取流程可以写成一个固定函数先读远程温度高字节和低字节再做符号扩展和LSB换算。以下是一个简化示例uint16_t read_remote_raw(uint8_t dev_addr) { uint8_t reg PJ85718DM_TEMP_REMOTE; uint8_t buf[2] {0}; i2c_write_byte(dev_addr, reg); i2c_read_bytes(dev_addr, buf, 2); return ((uint16_t)buf[0] 8) | buf[1]; } float remote_temperature_c(uint8_t dev_addr) { uint16_t raw read_remote_raw(dev_addr); int16_t signed_raw (int16_t)raw; return signed_raw * 0.0625f; }低字节可能只使用高4位屏蔽掉无效位之后再参与计算避免无意义的跳动。4.3 转换时间与轮询节奏HVAC温度变化慢PJ85718DM每个通道转换时间通常在几十毫秒到几百毫秒之间读取一次双通道数据只需要毫秒级的I2C通信时间。我在固件里设置系统每2秒唤醒一次唤醒后触发一次单次转换等待转换完成后读取本地和远程温度再做软件滤波。这个节奏既保证了显示值的稳定也不至于让总线一直被占用。如果现场需要更快响应比如做过热保护可以把轮询周期压缩到200ms但要注意传感器自热和功耗的平衡这个后面单独讲。4.4 滤波与防跳变温度跳变在HVAC现场很常见特别是风机切换、压缩机启动瞬间读回来的原始值偶尔会跳出一两个尖峰。直接在界面上显示原始值是糟糕的体验室温明明没变屏幕上的数字却像打摆子一样上下抖。我常用的滤波算法是滑动窗口中位平均取最近9个采样值去掉最大值和最小值剩下的值求平均。这个算法在异常点只占少数时既平滑又能剔除尖峰毛刺。对HVAC这种温度惯性大的场景我实际测试下来比纯滑动平均稳得多。要注意窗口长度不能设得太大否则温度突变时响应太慢比如冷媒管道结霜保护会迟迟不触发。5. HVAC现场测试与误差校正实测数据比仿真更诚实5.1 实验室标定方法无论芯片声称精度多高实际项目都要自己做一次标定验证。我每次改板或换料都会先在恒温槽里做一轮校准。把远程二极管、参考温度计探头和待测板卡一起放入恒温槽在0℃、25℃、50℃和85℃四个温度点分别稳定后记录芯片读数再对比参考值的偏差。下表是一个典型标定记录格式设定温度参考温度本地通道读数远程通道读数偏差0℃0.1℃0.3℃-0.1℃0.225℃25.0℃25.2℃24.8℃-0.250℃49.9℃50.1℃50.3℃0.485℃85.0℃85.2℃85.6℃0.6如果偏差是一个近似常数的固定偏移直接写入偏移校准寄存器如果偏差随着温度线性变大就需要用两点法修正增益也就是调整理想因子补偿寄存器。缺少恒温槽的小团队可以用保温杯加冰水、加热水做粗略验证虽然精度一般但能快速发现大方向性错误。5.2 现场实测数据处理示例现场数据最能反映问题。我在一个测试样本上记录了风机启停过程中送风温度和板内温度的变化风机刚开启时送风温度从22.1℃缓步上升半小时后稳定在23.8℃控制板内部温度则从28℃缓慢爬到34℃。排除传感器后送风温度整体响应时间大约3分钟和系统热惯性吻合。本地通道虽然变化更快但经过滤波后也能稳定显示。如果现场读到的某一通道有明显周期性波动优先怀疑两件事一是远程走线是否与PWM电源线平行或者穿过继电器区域二是地线回路是否形成了噪声环路。不要一上来就怀疑传感器坏掉因为HVAC设备的电磁环境远比实验室恶劣干扰造成的波动才是家常便饭。5.3 误差来源分拆我习惯把最终误差分成四块来看传感器自身精度、远程二极管品质和走线电阻、电源纹波与地噪声、算法滤波造成的动态误差。静态标定能修正前两块的大部分后两块要靠硬件布局和采样策略配合解决。传感器自身精度主要由芯片内部基准和ADC决定通常可以通过校准寄存器修正远程二极管品质更换二极管品牌后需要重新确认理想因子一致性差的批次误差可达±1℃电源与地噪声供电不稳会直接影响比较器和ADC去耦电容位置不对也会引入误差动态滤波误差窗口越长越平滑但响应越慢要按工况折中选择。HVAC常规控制的精度目标建议设在±0.5℃以内这个水平对舒适性控制已经足够。追求更高精度不是不行而是需要对每一路远程二极管做逐点校准并在固件里放查表投入产出比不高。5.4 高低温老化与断电恢复验证HVAC设备不是一直在常温下工作。我专门跑过一轮85℃环境箱持续加电的老化测试监控本地和远程通道的长期漂移连续48小时读数稳定在±0.2℃范围。断电恢复测试也同样重要模拟一次意外掉电再上电确认芯片配置寄存器恢复默认值后ALERT报警脚不会残留拉低状态否则整机会出现“刚上电就被反复唤醒”的恶劣现象。6. 低功耗调理让整机长时间运行不失控6.1 MCU的低功耗策略STM32L152RE适合做低功耗温控器的原因在于它把“待机低功耗”和“快速唤醒”做到了较好平衡。项目里我把MCU配置成周期性唤醒大部分时间进入停止模式每1秒由RTC或定时器唤醒一次花几毫秒读取温度和按键状态刷新LCD之后再回到停止模式。整机功耗数据大致如下状态电流消耗说明运行模式8MHz读传感器LCD刷新约3~5mA每周期出现几毫秒停止模式RTC运行约2~4uA绝大多数时间停留整机平均电流约30~50uA取决于唤醒频率和LCD刷量如果条件允许RTC唤醒周期可以加长到2秒整机平均电流还能再往下压。对不带显示的物联网节点场景这个优势会进一步放大。6.2 采样模式对自热的影响PJ85718DM这类芯片在连续转换模式下内部会持续工作芯片自身温度会比环境略高。我实测连续转换和单次转换两种模式下本地通道读数可以相差大约0.2℃。对恒温控制来说0.2℃不是可以忽视的小数尤其HVAC目标温度精度通常在0.5℃之内。因此我在软件里采用“按需转换”MCU唤醒后写一次单次转换命令等待转换完成标志置位读出温度后立刻关闭转换。这样传感器90%以上的时间处于空闲状态自热被压到最低本地读数的可信度也提高不少。远程通道同样受益因为芯片内部差分测量电路的零点漂移会随时间变小。6.3 报警唤醒的红利把PJ85718DM的ALERT引脚接到STM32L152RE的外部中断输入温度越限时可以直接把MCU从停止模式唤醒而不是依赖主控定期醒来轮询是否越限。这个设计让“正常状态少干活、异常状态立刻响应”成为现实。需要注意报警唤醒后程序要在中断服务里正确读走报警状态并清除标志否则ALERT引脚会一直保持有效MCU会被反复唤醒整机电流会异常偏大。我调试时碰到过一次这个问题线上跑了一天功耗正常日志却显示唤醒次数每分钟上百次最后定位到就是清除寄存器顺序写错了。7. 复盘几个最有价值的坑与解决办法7.1 二极管接反远程读数直接掉到-40℃远程通道的正负接反时芯片大概率会读出一个非常低的固定值。排查思路是先确认本地通道正常再查远程通道的原始寄存器值如果异常拿起万用表二极管档去量D/D-两端确定二极管方向。原理图上标注极性只是第一步PCB封装也必须看清丝印焊接返修和样品手工焊都很容易弄反。调试早期就把方向标记做好能省掉大量时间。7.2 I2C上拉电阻导致的偶发通信故障前面提到过10kΩ上拉在长线多设备场景下会导致上升沿太缓。排查这类问题有个高效方法不要只看能不能通信而是用示波器观察SCL的上升沿时间。如果上升沿超过时钟周期的20%以上通信随时可能出问题。降到4.7kΩ后上升沿变锐利速率恢复100kHz依然稳定。这个经验对所有多设备I2C总线都适用。7.3 远程走线穿越强电区域读数波动明显有一版PCB把风管传感器走线安排在继电器旁边实际运行中继电器吸合和断开瞬间远程温度读数波动接近0.8℃。处理方案做了三件事走线改到板边并远离继电器区域、传感器双绞线外层增加屏蔽并接地、D/D-之间在芯片端并联10nF电容。最终波动压到0.1℃以内。HVAC设备强电干扰确实比想象中猛布局阶段一定不要把模拟走线和高频或继电器驱动线并行。7.4 断电重启后报警标志残留报警标志残留会直接表现为ALERT脚一直拉低MCU被频繁唤醒。解决办法是在初始化流程中先读取状态寄存器把上一次残留的报警标志读掉并写清除指令再写入阈值。这一步看起来不起眼但直接影响整机待机电流和用户体验。所有用到报警中断的项目都应该把“清残留标志”写进上电初始化例程不要只清一次就完事。整个项目做完我对“本地加远程”双通道测温方案的看法有了很大变化。最大的收益其实不是省了一颗传感器而是让板内温度和远端被测对象温度在同一个芯片、同一套校准逻辑下完成天然避开跨芯片偏差对齐的问题。远程二极管的布置方式也确实灵活风管、盘管、电机外壳这些位置都能用一对细线加小元件解决不用为每个测点准备完整传感器模组。最后再分享一个小经验调试这类系统时从第一天起就把每次读到的寄存器原始值记录下来而不是只记换算后的温度值。一旦后面怀疑标定和校准有问题原始寄存器数据是唯一可以追溯的依据只留温度结果很多时候根本查不出是哪一步出了问题。希望这篇梳理能帮你少踩几个坑。