1. 从一颗温度传感器说起为什么HVAC系统需要双通道测温做嵌入式暖通空调控制这行十几年我见过太多项目在温度采集环节翻车。不是传感器选型不对就是本地和远程测温的架构没设计好导致整机联调时数据飘得没法看。这次要聊的这套方案核心是用PJ85718DM这颗I2C接口的远程二极管温度传感器配合PIC32MX470F512H这颗带浮点运算单元的32位MCU搭建一套能同时监测本地板载温度和远程目标温度的采集系统。标题里说的本地与远程指的就是这两路温度通道——本地测的是控制板自身的环境温度远程测的是通过二极管接法比如三极管接成二极管贴在发热源或风道里的目标点温度。为什么HVAC场景特别需要这种双通道架构因为暖通空调的控制器通常装在一个金属或塑料壳里壳内温度受MCU自身发热、电源模块发热影响跟真实回风温度能差出5到10摄氏度。如果只测本地压缩机启停逻辑就会误判。而远程通道可以把测温点延伸到蒸发器翅片、出风口或者回风管道里拿到真正有控制价值的那一路温度。PJ85718DM这类远程二极管传感器就是干这个的——它本身是个低功耗的本地远程双通道温度采集芯片通过I2C把两路数据交给MCU。PIC32MX470F512H在这套方案里的角色很明确它要跑温度采集驱动、做数据滤波、执行HVAC控制算法比如PID调节风机和压缩机还要处理本地显示和远程通信。这颗MCU有512KB Flash、128KB RAM带硬件I2C外设主频能到120MHz还有单精度浮点单元跑温度补偿和滤波算法绰绰有余。选它不是因为性能过剩而是HVAC控制器往往还要兼做Modbus从站、驱动段码屏或者点阵屏算力留余量是刚需。这篇文章适合谁看如果你正在做嵌入式温度采集、HVAC控制器开发或者单纯想搞明白远程二极管测温到底怎么落地那接下来的内容会从芯片原理、硬件连接、I2C驱动、温度换算、滤波策略到实测避坑一层层拆开讲。我不打算只给寄存器配置表而是把每个选择背后的理由说清楚——为什么用二极管测温而不是热敏电阻为什么I2C走线要这么处理为什么温度换算里那个0.0625的系数不能随便改。2. PJ85718DM的测温原理远程二极管到底在测什么2.1 本地通道与远程通道的物理差异PJ85718DM内部有两个测温通道。本地通道用的是芯片自身的衬底温度传感器本质是一个与绝对温度成正比PTAT的电流源经过内部ADC量化后输出数字值。这个通道测的是芯片引脚附近的PCB温度精度通常在±1摄氏度以内分辨率可以做到0.0625摄氏度。它的响应速度很快因为热源就在芯片内部但缺点也很明显——它测的是芯片自己的温度不是环境温度。如果MCU和传感器靠得近MCU的发热会直接串进来。远程通道则完全不同。它通过两个引脚通常标为D和D-驱动一个外部二极管接法的三极管比如常见的MMBT3904或者2N3904把基极和集电极短接用发射结作为测温二极管。PJ85718DM会轮流注入两个不同大小的电流比如10微安和100微安然后测量二极管上的正向压降差。这个压降差与绝对温度成正比公式是ΔVBE (kT/q) × ln(N)其中k是玻尔兹曼常数T是绝对温度q是电子电荷N是两个电流的比值。芯片内部把这个ΔVBE量化成数字温度值。这里有个关键点远程通道测的是二极管结温不是环境温度。所以二极管必须和被测物体有良好的热接触。在HVAC应用里通常会把三极管贴在风道壁、换热器翅片或者回风管上用导热硅脂或者导热胶固定再用引线接到控制板。引线长度可能到几十厘米甚至一米这就引入了走线电阻和噪声问题后面会专门讲怎么处理。2.2 为什么不用热敏电阻或者数字温度芯片很多人会问测温度用NTC热敏电阻或者DS18B20这类数字温度芯片不香吗便宜、简单、资料多。但在HVAC场景下远程二极管方案有几个不可替代的优势。第一是多点测温的扩展性。一颗PJ85718DM可以接一个远程二极管但同系列的芯片有的能接多个。更关键的是二极管测温的物理原理决定了它适合做点测——把一个小三极管贴在任何需要测温的位置用双绞线引回来就行。NTC虽然也能引线但它的阻值随温度变化是非线性的长线电阻会直接叠加到测量结果上补偿起来很麻烦。而二极管测温测的是压差线电阻在两条电流路径上基本抵消对长线更友好。第二是自热效应。NTC需要流过电流才能测阻值这个电流会让NTC自身发热在静止空气里可能引入0.5到1摄氏度的误差。二极管测温的电流只有微安级自热可以忽略。第三是与MCU的接口简洁度。PJ85718DM直接输出数字温度值I2C接口MCU不需要额外的ADC或者分压电路。而NTC需要MCU的ADC通道还要处理参考电压漂移和分压电阻精度问题。在PIC32MX470F512H这种带硬件I2C的MCU上接PJ85718DM只需要两根线加两个上拉电阻PCB布局非常干净。当然远程二极管方案也不是没缺点。它需要额外的三极管和走线成本比一颗NTC高一点二极管的一致性不如理想中的好不同批次的ΔVBE会有微小差异需要软件校准长线引入的噪声需要滤波处理。但在HVAC这种对可靠性要求高、测温点分散的场景里这些代价是值得的。2.3 PJ85718DM的关键寄存器与配置逻辑PJ85718DM的寄存器不多但每个都有明确的用途。我按实际使用顺序列一下寄存器地址名称功能典型配置0x00本地温度值只读高字节低字节读取后组合成16位0x01远程温度值只读高字节低字节读取后组合成16位0x09配置寄存器设置分辨率、关断模式等0x6012位分辨率0x0A转换速率设置每秒转换次数0x044次/秒0x0B远程温度偏移校准远程通道误差根据实测填写0x0C本地温度偏移校准本地通道误差通常保持00x0D远程温度上限超限报警阈值根据HVAC逻辑设定0x0E远程温度下限超限报警阈值根据HVAC逻辑设定配置寄存器0x09的位定义需要特别注意。bit6和bit5决定分辨率00是9位0.5摄氏度01是10位0.25摄氏度10是11位0.125摄氏度11是12位0.0625摄氏度。我一般用12位因为HVAC控制对温度精度要求通常在0.5摄氏度以内12位分辨率留足了余量。bit0是关断控制写1进入低功耗模式写0正常转换。转换速率寄存器0x0A决定芯片多久更新一次温度值。HVAC系统的热惯性很大温度变化通常以分钟计所以4次/秒值0x04完全够用。设太快只会增加功耗和I2C总线负载没有实际收益。如果做快速响应的出风口测温可以设到8次/秒但再高就没必要了。远程温度偏移寄存器0x0B是校准的关键。由于二极管批次差异和走线影响远程通道读数可能和实际温度有1到3摄氏度的偏差。校准方法很简单把二极管放在已知温度的恒温槽或者冰水混合物里读取远程温度值计算偏差把这个偏差以0.0625摄氏度为步进写入偏移寄存器。注意这个寄存器是8位有符号数范围是-128到127对应-8到7.9375摄氏度。3. 硬件连接从原理图到PCB的实操细节3.1 PIC32MX470F512H的I2C外设配置PIC32MX470F512H有两个I2C模块我一般用I2C1接温度传感器I2C2留给EEPROM或者显示模块。I2C1的SDA和SCL引脚需要配置为开漏输出外部接4.7kΩ上拉电阻到3.3V。上拉电阻的取值有讲究太小会增加总线电容充电电流太大则上升沿变缓导致通信失败。在标准模式100kHz下4.7kΩ是经过验证的稳妥值如果走快速模式400kHz可以降到2.2kΩ。但HVAC控制板的I2C总线通常不长100kHz足够所以4.7kΩ配100kHz是黄金组合。PIC32MX470F512H的I2C配置步骤大致如下先关掉I2C模块设置I2CxCON寄存器的ON位为0然后配置I2CxBRG寄存器设置波特率计算公式是I2CxBRG (FSCL / (2 × FSCL)) - 2其中FSCL是外设总线时钟频率。假设外设总线是60MHz目标SCL是100kHz那么I2CxBRG (60,000,000 / (2 × 100,000)) - 2 298。实际写入298即可。接着使能I2C模块设置ON位为1等待一段时间让总线稳定。这里有个容易踩的坑PIC32的I2C模块在使能后需要等待至少一个SCL周期才能开始发送起始条件。我见过有人在使能后立刻发START结果第一个字节丢失。稳妥的做法是使能后延时1毫秒或者轮询I2CxSTAT寄存器的IDLE位确认总线空闲再操作。3.2 远程二极管的选型与布线远程测温二极管我推荐用MMBT3904SOT-23封装便宜好买一致性也不错。接线方式是基极和集电极短接发射极接D-基极-集电极节点接D。这样形成一个PN结正向压降约0.6V温度系数约-2mV/摄氏度。PJ85718DM内部会自动处理电流切换和压差测量外部不需要额外元件。布线是远程测温最容易出问题的地方。D和D-必须走双绞线或者平行等长线并且尽量远离高压开关节点、继电器驱动线和PWM功率线。HVAC控制板上有风机驱动和压缩机继电器这些线上的dv/dt噪声很容易耦合到测温线上。我一般会在D和D-之间并联一个100pF到1nF的陶瓷电容靠近PJ85718DM引脚放置用来滤除高频噪声。注意电容不能太大否则会拖慢电流切换的建立时间导致压差测量不准。100pF是经过实测的稳妥值。如果测温线长度超过30厘米建议在D和D-上各串一个100Ω电阻靠近传感器端放置。这两个电阻和输入电容构成低通滤波进一步抑制噪声。但电阻不能太大否则会分压导致压差信号衰减。100Ω在微安级电流下压降只有0.01mV完全可以忽略。还有一个细节远程二极管的三极管本体要尽量小热容小才能快速响应温度变化。但太小又容易被PCB上的其他热源影响。我的经验是把三极管放在一个独立的热岛上——周围挖空铜皮只留细走线连接这样它测的就是目标点的温度而不是PCB的温度。如果测的是风道温度可以用导热胶把三极管粘在风道壁上引线用耐温的硅胶线。3.3 电源与去耦的实战经验PJ85718DM的供电范围是2.7V到5.5V和PIC32MX470F512H的3.3V系统可以直接对接。但电源质量直接影响温度读数稳定性。我实测过如果PJ85718DM的VDD上有50mV的纹波本地温度读数会跳动±0.25摄氏度。所以去耦电容不能省在VDD引脚附近放一个0.1μF陶瓷电容再并一个10μF钽电容或者MLCC。0.1μF负责高频10μF负责低频两个配合才能把电源噪声压下去。如果控制板上还有继电器或者可控硅它们的开关噪声会通过电源串到传感器上。这种情况下建议给PJ85718DM单独走一条电源线从LDO输出端直接拉过来不要和功率器件共用一段铜皮。LDO的选择也有讲究PSRR电源抑制比至少要在40dB以上否则输入端的纹波会直接透传到输出。我用过某款PSRR只有20dB的LDO结果温度读数每隔几秒就跳一次换成高PSRR的型号后立刻稳定。4. 固件实现从I2C读写到温度换算的完整链路4.1 I2C底层驱动的编写要点在PIC32MX470F512H上写I2C驱动我习惯用中断方式而不是轮询因为温度采集是周期性的轮询会浪费CPU时间。但中断方式需要处理好状态机的切换。一个典型的I2C写操作流程是发START - 发从机地址写位 - 等ACK - 发寄存器地址 - 等ACK - 发数据 - 等ACK - 发STOP。读操作则是发START - 发从机地址写位 - 等ACK - 发寄存器地址 - 等ACK - 发RESTART - 发从机地址读位 - 等ACK - 读数据 - 发NACK - 发STOP。PIC32的I2C中断标志位有多个START、STOP、ACK、NACK、数据接收等。我一般用一个状态变量记录当前步骤在中断里根据状态和标志位决定下一步动作。这里有个坑PIC32的I2C模块在发送RESTART时如果前一个操作没有完全结束RESTART会失败。所以每次操作后要检查I2CxSTAT寄存器的TRSTAT位确认发送器空闲再继续。另一个坑是ACK超时。如果从机没有响应I2C模块会一直等下去。我一般加一个超时计数器在中断里累加超过一定次数就复位I2C模块重新初始化。HVAC系统要求高可靠性这种保护机制不能省。4.2 温度值的读取与换算PJ85718DM的温度寄存器是16位高字节是整数部分低字节是小数部分。但低字节只有高4位有效低4位保留。所以读取后要这样组合uint8_t temp_high i2c_read_byte(PJ85718DM_ADDR, 0x00); uint8_t temp_low i2c_read_byte(PJ85718DM_ADDR, 0x01); int16_t raw_temp (temp_high 8) | (temp_low 0xF0); float temperature raw_temp / 256.0;注意这里除以256.0而不是除以16.0。因为12位分辨率下最低位代表0.0625摄氏度而16位组合后低4位是0所以实际有效位是12位除以256得到的就是摄氏度值。我见过有人除以16结果温度高了16倍查了半天才发现是换算系数错了。对于负温度PJ85718DM输出的是二进制补码。比如-0.0625摄氏度对应0xFFF0。在C语言里用int16_t接收后直接除以256.0就能得到正确的负值不需要额外处理。但要注意如果温度低于-64摄氏度高字节的符号位会扩展这时候要确保int16_t的转换是正确的。远程温度读取同理只是寄存器地址换成0x01。读取后可以加上偏移寄存器0x0B的值做校准。偏移寄存器的值也是二进制补码8位有符号步进0.0625摄氏度。所以最终远程温度是int8_t offset i2c_read_byte(PJ85718DM_ADDR, 0x0B); float remote_temp raw_remote / 256.0 offset * 0.0625;4.3 温度滤波为什么滑动平均不够用HVAC系统的温度信号有两个特点一是变化慢二是噪声大。变化慢意味着可以用低通滤波噪声大意味着需要滤除高频干扰。很多人第一反应是用滑动平均比如取最近10次采样的平均值。但滑动平均有两个问题一是需要存储历史数据占用RAM二是对突发噪声的抑制不够如果某次采样被干扰跳变平均值会被拉偏。我推荐用一阶IIR低通滤波公式是filtered filtered * (1 - alpha) new_sample * alpha。alpha是滤波系数取值在0到1之间。alpha越小滤波越强但响应越慢。对于HVAC温度采集alpha取0.1到0.2比较合适。以4次/秒的采样率计算alpha0.1时时间常数约2.5秒既能滤掉噪声又不会让温度响应太迟钝。PIC32MX470F512H有硬件浮点单元跑这个滤波公式只需要几个时钟周期完全不影响其他任务。但要注意浮点运算的精度问题。如果filtered和new_sample都是float累加多次后可能会有微小误差。我一般用double做滤波变量最后再转float输出这样精度更稳。还有一个进阶技巧自适应滤波。当温度变化率超过某个阈值时临时增大alpha让系统快速响应当温度稳定时减小alpha增强滤波。这在HVAC里很有用比如压缩机刚启动时温度快速变化需要快速跟踪稳定后需要平滑读数。实现方法是计算当前采样和上一次滤波值的差值如果差值大于0.5摄氏度alpha设为0.5否则alpha设为0.1。5. 实测中的坑与排查链路5.1 远程温度读数偏高10摄氏度的根因有一次调试本地温度读数正常远程温度却比实际高了10摄氏度。用万用表测二极管压降发现只有0.3V正常应该是0.6V左右。这说明二极管没有正常导通可能是接反了或者损坏了。检查原理图发现D和D-接反了。PJ85718DM的D应该接二极管的阳极基极-集电极节点D-接阴极发射极。接反后内部电流源无法正常注入测到的压差就不对。把线调过来后远程温度恢复正常。这个坑的教训是远程二极管的极性不能凭感觉一定要对照数据手册的引脚定义。MMBT3904的SOT-23封装1脚是基极2脚是发射极3脚是集电极。基极和集电极短接后接D发射极接D-。如果用的是其他型号引脚定义可能不同必须查手册。5.2 I2C通信间歇性失败的排查过程另一个项目里I2C通信每隔几分钟就失败一次温度读数变成0或者乱码。用示波器抓SDA和SCL波形发现SCL在某个时刻被拉低后一直没有释放。这是典型的I2C总线死锁——从机在某个状态下把SCL拉低等待主机发时钟但主机以为总线空闲不再发时钟双方僵持。解决方法是加总线恢复机制。在I2C初始化时先检查SCL和SDA是否都为高。如果SCL被拉低就手动切换SCL引脚为GPIO输出发送9个时钟脉冲让从机释放总线。然后发一个STOP条件复位I2C模块。这个机制在PIC32上实现起来不难但很多人会忽略。HVAC系统要求长期无人值守运行这种保护必须加。还有一个原因是上拉电阻太大。原来用的是10kΩ在总线电容较大的情况下上升沿太慢从机可能误判。换成4.7kΩ后问题消失。所以上拉电阻的取值要根据总线电容和通信速率来算不能随便抓一个就用。5.3 电源噪声导致温度跳变的解决前面提到过电源噪声的影响这里展开讲一个实际案例。某控制板用开关电源供电PJ85718DM的VDD上测得约80mV的纹波频率是开关频率的2倍。温度读数每隔几秒跳变一次幅度约0.5摄氏度。一开始以为是滤波不够把alpha降到0.05跳变幅度减小但仍有0.2摄氏度。后来用频谱分析发现噪声频率在100kHz左右正好是开关电源的二次谐波。在VDD引脚上并了一个1μF的MLCC后纹波降到20mV温度跳变消失。所以去耦电容不仅要放还要放对位置和容值。0.1μF对高频有效但对100kHz这个频段1μF更合适。我现在的做法是0.1μF和1μF并联覆盖更宽的频率范围。6. 把温度用起来HVAC控制逻辑中的双通道策略6.1 本地温度补偿远程温度的算法在HVAC控制器里本地温度和远程温度不是孤立的。本地温度可以用来补偿远程温度因为远程二极管的走线可能经过温度梯度区域。一个简单的补偿方法是如果本地温度和远程温度的差值超过某个阈值比如3摄氏度说明远程通道可能受到走线影响可以用本地温度做参考来修正。但更常见的做法是双通道融合。比如控制目标是回风温度远程二极管测的是回风管道温度本地测的是控制板温度。如果控制板装在回风管道附近本地温度可以作为回风温度的粗略估计。融合公式可以是T_control 0.7 * T_remote 0.3 * T_local。这样即使远程通道暂时失效本地通道也能提供降级运行的能力。PIC32MX470F512H的浮点单元让这种融合计算变得很简单。我一般把融合逻辑放在1秒周期的任务里和温度采集任务分开避免相互阻塞。6.2 超限报警与保护逻辑PJ85718DM有远程温度上下限寄存器可以硬件触发报警。但硬件报警的阈值是固定的不够灵活。我一般用软件报警在MCU里设定阈值每次采集后比较超限就置标志位。软件报警的好处是可以做迟滞——比如上限设60摄氏度但只有降到55摄氏度以下才清除报警避免在阈值附近反复触发。在HVAC逻辑里远程温度超限通常意味着换热器过热或者风道堵塞。这时候应该先降压缩机频率再关压缩机最后停风机。这个顺序很重要直接关风机会导致换热器热量积聚可能触发高压保护。本地温度超限则通常意味着控制板环境温度过高可能是机柜散热不良应该先降载运行再报警提示维护。6.3 低功耗模式下的温度监测HVAC控制器有时需要待机运行比如夜间或者无人时段。这时候可以把PIC32MX470F512H切到低功耗模式但温度监测不能停。PJ85718DM本身支持关断模式电流可以降到几微安。但关断后就不转换了所以不能完全关。我的做法是把转换速率降到1次/秒MCU在两次转换之间进入休眠用I2C转换完成中断唤醒。PIC32MX470F512H的休眠电流在几十微安级别加上PJ85718DM的几百微安整体待机功耗可以控制在1毫安以内。对于电池供电或者能量收集的HVAC传感器节点这个功耗水平是可以接受的。唤醒后读取温度如果超过报警阈值就唤醒主控做进一步处理如果正常继续休眠。这样既保证了监测的连续性又最大限度地降低了功耗。7. 从原型到量产校准与一致性处理7.1 远程通道的批量校准方法原型阶段可以手动校准每个板子但量产时不可能逐个校准。我的做法是在生产线上用恒温槽做单点校准。把所有板子放在25摄氏度的恒温槽里读取远程温度值计算与25摄氏度的偏差把这个偏差写入每块板的EEPROM。MCU启动时从EEPROM读取偏差加到远程温度读数上。这个方法的假设是偏差在温度范围内是线性的。实际上二极管测温的偏差主要是由串联电阻和电流源失配引起的在-20到80摄氏度范围内基本是常数偏移所以单点校准足够。如果要求更高精度可以做两点校准比如0摄氏度和50摄氏度用线性插值计算偏差。校准用的恒温槽精度要在±0.1摄氏度以内否则校准本身就不准。我见过用冰水混合物校准的理论上0摄氏度但实际冰水混合物在稳定前可能偏差0.5摄氏度以上不适合做批量校准。7.2 本地通道的精度验证本地通道测的是芯片自身温度精度主要取决于芯片的出厂校准。PJ85718DM的本地通道精度在25摄氏度时是±1摄氏度在全温范围内是±2摄氏度。对于HVAC控制来说这个精度够用因为本地温度只是参考不是控制目标。但如果要做精确的环境温度监测本地通道就需要校准。校准方法是把整块板子放在恒温箱里设置几个温度点比如10、25、40摄氏度读取本地温度值和恒温箱的设定值比较计算偏差。如果偏差是常数写入本地偏移寄存器如果偏差随温度变化就需要在固件里做分段补偿。我实测过几批PJ85718DM本地通道的一致性很好偏差都在±0.5摄氏度以内基本不需要校准。但远程通道的一致性就差一些不同批次的二极管和走线差异会导致±2摄氏度的偏差所以远程通道的校准是必须的。7.3 长期漂移与维护策略任何温度传感器都会随时间漂移。二极管测温的漂移主要来自二极管本身的老化和走线电阻的变化。在HVAC这种长期运行的环境里漂移可能导致控制精度下降。我的策略是在固件里记录每次上电时的远程温度读数和上次上电时的读数比较。如果差值超过1摄氏度就认为可能发生了漂移触发自检提示。同时如果系统有参考温度源比如另一个独立的温度传感器可以定期比对自动修正偏移。对于关键应用我建议每两年做一次现场校准。校准不需要拆机只需要把标准温度计放在测温点旁边读取两者差值通过维护接口更新偏移值即可。这个操作在HVAC系统的年度维护里顺便就能做成本很低。8. 一些零散但值钱的经验PJ85718DM的I2C地址是固定的7位地址0x4C写和0x4D读。如果总线上有多个同型号芯片就需要用I2C多路复用器或者选带地址选择引脚的型号。我在一个多区域HVAC项目里用过8颗PJ85718DM就是通过I2C多路复用器分时切换的。切换后要等至少100微秒再发START让总线稳定。温度寄存器的读取顺序也有讲究。PJ85718DM在读取高字节后会锁存低字节所以要先读高字节再读低字节。如果顺序反了低字节可能是上一次转换的结果导致温度值错乱。这个细节数据手册里有写但很容易被忽略。还有PJ85718DM的转换速率寄存器和配置寄存器在修改后需要等一个转换周期才能生效。如果改完立刻读温度读到的还是旧配置下的结果。我一般改完配置后延时200毫秒再读确保新配置生效。最后说一个关于PCB布局的细节PJ85718DM尽量靠近MCU放置I2C走线越短越好。如果实在要拉长就用屏蔽线或者双绞线并且远离功率器件。远程二极管的走线同理而且D和D-要尽量靠近不要分开走否则会形成环路拾取噪声。这套方案我在多个HVAC项目里用过从家用空调控制器到商用新风系统稳定性都很好。核心就是三点硬件上把电源和走线处理好固件上把滤波和校准做扎实逻辑上把双通道融合和报警策略设计清楚。剩下的就是根据具体项目调参数了。