做HVAC控制器的朋友都清楚“测温度”这三个字看着简单实际上一旦牵扯到多点测量事情就琐碎得让人头大。我最近在弄一套本地/远端双通道温度监测模块主控用的PIC18F87J50传感器用的PJ85718DM专门解决HVAC里两类典型测点一类是控制器自己柜内温度、PCB板温这种“本地温度”另一类是送风管、回风管、冷冻水管表面这种离主板一两米甚至更远的“远端温度”。折腾下来整块板子用一颗传感器加一颗8位MCU就把两路温度同时拿下了还顺手留了RS-485上报和USB调试口。这篇文章把整个方案的选型理由、硬件接线、固件流程、校准方法和实测踩坑完整过一遍适合正在做HVAC控制器、楼宇自控或工业嵌入式温度采集的工程师参考。1. 这套测温组合盯的是HVAC现场的哪两类温点1.1 本地温度控制器自己的“体温”本地温度说起来不起眼但在HVAC现场很重要。控制器装进电柜之后柜内温度往往比车间环境高不少变频器、接触器线圈、DC-DC电源模块全都是热源。如果控制器自身过热轻则液晶屏老化加快、电解电容寿命缩短重则直接触发保护动作甚至误停机。我最初做原型时把本地传感器放在MCU旁边结果柜内环温只有28°C板面实测35°C本地读数就贴着35°C跑。这不是传感器不准而是板上热源把传感器所在的局部环境加热了。所以本地温度通道的真正意义是监测“控制器的热状态”而不是“车间气温”。有了这一路我可以根据板温做风扇调速、过热告警甚至粗略估算整机寿命。1.2 远端温度真正参与工艺控制的测点真正跟制冷/制热工艺挂钩的是远端测点。送风管里吹出来的是冷风还是热风、回风管吸回去多少度、冷冻水管表面结不结露、室外机进风温度多少这些数据直接参与PID调节、压缩机启停和防冻保护。PJ85718DM这类带远端通道的传感器做法跟常规数字温度传感器不太一样本地通道测芯片周围的环境温度远端通道通过一个外部二极管结来测探头端的温度。也就是说我只需要在远端探头里放一颗小信号三极管把基极和集电极短接成二极管就能把温度测量点从PCB表面“搬”到几十厘米甚至几米外的风管、水管上去。这也是“本地与远程温度”这个名字的由来。1.3 为什么双通道单芯片比两颗传感器划算一开始我也想过用两颗独立的数字温度传感器一颗在板上、一颗装远端探头。后来对比了一下发现双通道单芯片方案优势明显BOM少一颗器件的钱PCB少一个封装的位置I2C总线上少一个节点而且两路温度在同一个转换周期内完成采样天然同步不会出现“先是本地后是远端”的时间差。对HVAC这种需要本地和远端做温差判断的应用来说同步性很重要。当然代价也有远端探头不能直接买现成的NTC封装得自己定制传感器探头把三极管接成二极管形式封装进去这一点在方案规划阶段就要想清楚。2. 选型逻辑PJ85718DM和PIC18F87J50各自看中什么2.1 传感器的远端测温原理与选型要点选传感器之前得先搞明白远端通道是怎么测温的。PJ85718DM这类器件不是直接测电阻而是测二极管结电压随温度的变化芯片对连接在远端通道上的二极管先后灌两个不同电流常见的是10µA和100µA然后测两次Vbe的差值ΔVbe。理论关系是T ΔVbe / (η × (k/q) × ln(N))其中η是二极管的理想系数大约在1.0几k/q约等于86.7µV/KN是两个电流的比值。按N20、η1.004算大概每260µV的ΔVbe变化对应1K温度。正因为测的是电压差而不是绝对电压这种方案对环境温度、芯片自身温漂都不敏感精度能做上去。选型时除了双通道这个核心需求我主要看几点I2C地址是否可通过引脚配置、温度分辨率、精度等级、转换速率、远端通道的开短路检测、是否有ALERT输出引脚、供电电压和工业级温度范围。PJ85718DM在这几项上都能对上尤其是远端通道带开路/短路检测这对现场线缆连接可靠性非常重要。提醒一下具体到PJ85718DM某一批次的寄存器地址、位域定义、精度参数务必以你手上那版DataSheet为准。下面讲的流程是按这类双通道温度传感器的通用做法展开的拿到芯片后第一件事就是把寄存器一章通读一遍。2.2 主控选型PIC18F87J50为什么够用且好用选PIC18F87J50不是因为它性能多炸裂而是这个8位MCU在一个封装里把HVAC控制器最常用的外设备齐了。128KB Flash和约4KB SRAM跑温度采集逻辑加Modbus协议绰绰有余1KB EEPROM正好存校准系数和设备参数最高48MHz运行、16MIPS3.3V供电两个MSSP模块一路I2C挂温度传感器另一路还能挂外部EEPROM或者SPI显示屏两个EUSART一路走RS-485接上位机或楼宇管理系统另一路留作调试打印USB 2.0全速设备控制器可以做本地配置和数据导出10位ADC多通道留着接NTC备份或者干接点检测。工业级温度范围-40~85°C做HVAC控制器绰绰有余。很多人问这种应用为什么不上32位我的回答是HVAC控制逻辑为主不需要跑操作系统16MIPS做每秒几十次的温度采样和轮询式Modbus通信完全够用8位MCU开发快、价格稳定、工具链成熟供货周期也好把控。设备选型不是选参数最高的而是选刚刚好能覆盖需求并且留有余量的。2.3 和常见替代方案的取舍对比方案本地远端实现方式主要痛点NTC MCU内部ADC板载一颗NTC远端再拉一颗NTC线性化、分压电阻精度、自热、线阻、长期漂移逐台校准成本高两颗独立I2C数字传感器板载一颗远端探头一颗BOM增加、地址可能冲突、两路采样时间不同步一棵总线挂多颗单总线数字传感器多颗器件挂在一条单总线上时序要求苛刻、连线电容影响大、多节点管理和供电问题PJ85718DM双通道方案一颗芯片测本地远端二极管通道远端探头需要自行制作或采购手册细节要捂清楚对这个项目来说双通道方案的综合成本、精度和抗干扰能力最均衡所以我最终定了这条线。3. 硬件连接与布线远端精度在第一道关口3.1 供电、去耦和VCAP电容整个系统用3.3V单电源。如果前端是DC-DC输出建议后面再加一颗LDO温飘小纹波也干净。传感器供电我加了RC滤波10Ω串联电阻加0.1µF对地电容把数字IO耦合过来的毛刺滤一滤。MCU每个VDD/VSS对都要就近放0.1µF去耦电容不要为了省位置共用。这里有个非常容易漏的细节PIC18F87J50内部有稳压器VCAP管脚必须按手册接一颗电容典型值通常是10µF。这颗电容没焊或者虚焊MCU上电后电流偏大、程序就是不跑。我后面排查坑的时候第一个遇到的就是它后面专门讲。传感器SDA、SCL上拉电阻接到3.3V具体阻值按总线电容算下面小节细说。远端探头连接器附近要加TVS管防止现场线缆引入的静电和浪涌打坏传感器。3.2 I2C上拉电阻怎么算I2C上拉阻值不是拍脑袋选的。总线上升时间约等于2.2 × Rp × CbusCbus包括PCB走线电容约0.5~1pF/cm、传感器引脚的输入电容和MCU引脚电容。假设总线电容150pF用4.7k上拉上升时间约1.55µs100kHz标准模式要求上升时间在1µs以内这个配置就偏慢了。换成2.2k上拉上升时间约0.73µs余量就出来了。所以我的建议是HVAC控制板里走线不长、附近又有变频器这类干扰源直接用100kHz速率加2.2k上拉稳字当头。别为了数据手册上写着支持400kHz就硬上高速现场电柜里电缆一绕、电容一大400kHz的时序余量会被吃掉一大截偶发NACK和死锁就来了。3.3 远端二极管的接法与走线原则远端探头端的小信号三极管必须按二极管接法接基极和集电极短接发射极接传感器的D-。三极管型号选择上用常见的通用小信号三极管就好B极和C极短接后等效为一个PN结。有些传感器的远端通道也可以直接接二极管但三极管接法的一致性更好精度更高。走线方面远端测量线尽量用双绞线或者一左一右贴着地线走。绝对不要跟继电器线圈、PWM电机驱动线、压缩机启停线并行走长距离。非要并行的话加屏蔽层并且屏蔽层单端接地别两端都接地否则会形成地环流。信号线长短也很关键。30cm以内两线制没问题超过1米建议用四线开尔文接法用独立的导线承载电流和测量电压。原因在于远端测量靠的是两个电流之间的ΔVbe线阻会直接叠进去。简单估算如果两个电流分别是10µA和100µA差值是90µA线阻每增加1Ω等效温度误差就是90µV除以260µV/K大约0.35K。5米长0.15Ω/m的双绞线一去一回就是1.5Ω误差接近0.5K足够影响HVAC的温差判断了。如果你要拉几十米那就别硬拉二极管线了在探头端放一个小变送器转成RS-485或4-20mA再传回来比什么都靠谱。3.4 探头安装的现场细节风管里测温度探头插入深度至少要达到风管断面的三分之一否则测到的是贴壁的边界层温度不是主流区温度。探头要迎着气流方向固定牢靠开孔处做好密封防止漏风。水管表面测温度表面一定要清理干净涂导热硅脂再用金属卡箍压紧。最容易被忽略的一步是加保温棉如果不把探头和管壁的接触点整体包起来环境温度会沿着探头外壳漏进去测出来的“管壁温度”其实是管壁和环境温度的混合值。这些安装细节对精度的影响往往比芯片本身的误差大得多。4. 固件实现读时序、换算、滤波与失败处理4.1 一次完整的I2C读取流程温度采集的固件核心就是I2C读取。流程分四步发开始条件写器件地址加写位写寄存器指针然后发重复开始条件写器件地址加读位读温度和状态字节最后一个字节回NACK最后发停止条件。这里用重复开始而不用“停止-开始”的方式是因为有些传感器对断开后的连续访问很敏感重复开始最稳妥。代码骨架如下uint8_t i2c_read_reg(uint8_t dev_addr, uint8_t reg, uint8_t *data, uint8_t n) { if (I2C1_Start() ! I2C_OK) return I2C_ERR_BUS; I2C1_Write(dev_addr 1); // 器件地址 写位 I2C1_Write(reg); // 寄存器指针 I2C1_Restart(); I2C1_Write((dev_addr 1) | 1); // 器件地址 读位 for (uint8_t i 0; i n; i) data[i] I2C1_Read(i (n - 1) ? I2C_NACK : I2C_ACK); I2C1_Stop(); return I2C_OK; }读温度寄存器的调用方式uint8_t buf[2]; if (i2c_read_reg(TEMP_ADDR, REG_TEMP_LOCAL, buf, 2) I2C_OK) { int16_t raw ((int16_t)(int8_t)buf[0] 4) | (buf[1] 4); float degC raw * 0.0625f; }这段代码是按“12位数据左对齐存放在16位寄存器中”的常见布局写的如果你的器件是高字节只存整数、低字节高4位存小数右移量要相应调整。寄存器位域和分辨率务必以手册为准。4.2 补码换算与字节序的坑温度寄存器在负温下以补码存放这里有个非常典型的坑如果高字节是0xFE直接按无符号处理会变成254再乘分辨率就会得出一个正得离谱的温度。必须在移位之前把高字节转成int8_t让符号位正确扩展。举例buf[0]0x1Abuf[1]0x90按上面的公式raw(264)|9425乘0.0625就是26.5625°C。如果buf[0]0xFE先转换成-2再左移4位得到-32乘0.0625就是-2.0°C。很多刚上手的人在这里踩坑读负温时怎么都对不上。远端通道的读法和本地通道完全一样只是寄存器地址不同。注意有些芯片的远端温度寄存器在未配置时会返回默认值而不是实时测量值这一点我后面讲坑的时候会具体说。4.3 滤波策略与坏值上报HVAC现场温度信号本身变化不快但容易叠加干扰尖峰。我用的是“三取中值16次滑动平均”的组合先去掉毛刺再平滑输出。对控制环路输出滤波后的值但诊断用原始值这样即使滤波滞后一点也不影响故障判断。坏值处理更要命。远端二极管一旦开路或者短路读回来的温度会瞬间跳到异常值。我的做法是每轮读取都先看状态寄存器里的开短路标志有问题就直接让上层拿到错误码而不是继续用上一次的好值。因为在HVAC应用里拿旧值撑着会让PID误判可能导致压缩机持续运行或者防冻保护失效这是安全隐患。4.4 I2C超时与总线恢复再稳定的总线也有抽风的时候特别是电柜里变频器一启动近场辐射把SDA上抖出毛刺就会偶尔卡死。我在主循环里记录最近一次I2C成功的时间超过500ms就认为总线异常执行恢复流程void i2c_recover(void) { // SCL连续给9个脉冲让挂在总线上的从机释放时钟 GPIO_SCL 0; for (uint8_t i 0; i 9; i) { GPIO_SCL 1; delay_5us(); GPIO_SCL 0; delay_5us(); } I2C1_Init(); // 重新初始化主模式 }这个恢复函数要在主循环里调用不能在中断里做因为它依赖毫秒级延时。另外整个I2C通信尽量统一放在主循环的定时器里触发不要在PWM中断或者电机控制中断里去发I2C否则高优先级中断一嵌套时序就乱了。5. 校准与HVAC工况下容易忽略的误差源5.1 自热误差的识别与处理板载本地传感器必然受板上发热元件影响这个误差不是芯片能解决的。我习惯在第一次上电时做一次“静置测试”板子放在已知温度的恒温箱里通电但不加载任何外部负载等半小时看本地读数比箱温高多少。高出部分就是自热周边热源导致的固定偏差。这个偏差在软件里做一个负偏移补偿掉。但要注意固定偏移只在通风条件不变时成立。如果实际装在风道里气流会带走一部分热量同一块板子的自热偏移会变小。所以更稳妥的做法是把本地传感器放在气流入口附近并且只补偿那部分不受气流影响的基础自热。5.2 两点校准的完整步骤校准时我按下面几步走把整个测温模块放进冰水槽槽里放足量碎冰和水的混合物稳定10分钟记录本地和远端读数M1。把模块移到恒温箱设定60°C或你系统的主要工作温度附近稳定后记录读数M2。用精密温度计读参考值T1、T2参考温度计精度至少±0.1°C计算增益和偏移k(T2-T1)/(M2-M1)bT1-k×M1。把k、b存进PIC18F87J50的内置EEPROM开机加载后对原始读数做yk×xb修正。再用第三个点比如室温25°C验证修正后的误差。校准系数最好限制在±2°C以内的修正量如果算出来要修3°C以上别急着写补偿先回头查探头安装热阻和线阻大概率是系统问题而不是传感器问题。5.3 线阻与二极管理想系数的修正远端通道的线阻误差前面已经量化过大约每1Ω线阻引入0.35K的偏差。在软件里可以做一个固定补偿但前提是线缆长度固定。如果现场线缆长度不固定最好采购时把线长也固定下来比如统一用2米探头线这样补偿值就是确定的。另外一类误差来自二极管理想系数η。不同批次的二极管η会在1.0到1.02之间波动影响大约0.5~1K。有些传感器寄存器里提供了理想系数配置项出厂校准过的探头可以把这个系数写进去没有的话就在两点校准时一起吃掉这个误差。5.4 时间常数、气流和“系统误差”温度传感器还有一个躲不开的指标叫时间常数。风管里的气流速度快探头响应能到数十秒级别贴在水管表面的探头热阻大响应可能要好几分钟。这意味着校准时不能拿刚落稳的温度读数就做计算必须等探头和介质充分热平衡。还有个很容易翻车的点风管里测回来的温度跟水系统管壁温度两者的“热历史”完全不同。管壁探头如果不加保温环境温度变化会让读数跟着漂。所以我在现场一直坚持的规矩是固定好探头之后至少等5~10分钟热稳定再开机校准。别让工人一装上就催你调零那时候测出来的偏移跟实际工况对不上。6. 实测数据与现场踩坑记录6.1 一组有代表性的实测结果我把这套测温模块做了三个温度点的验证远端探头用2米双绞屏蔽线探头贴在恒温箱内的金属导热块上精密温度计做参考。校准点选在0°C和60°C验证点在室温25°C附近。基准温度校准前本地读数校准前远端读数校准后本地误差校准后远端误差0.0°C0.4°C0.9°C-0.1°C0.1°C25.0°C0.5°C0.7°C0.1°C-0.2°C60.0°C0.6°C0.8°C0.2°C0.3°C校准前远端整体偏高主要原因就是2米线缆的线路电阻和探头热阻。两点校准之后本地和远端误差都压到了±0.3°C以内满足HVAC通常要求的±0.5°C指标。6.2 踩过的三个具体坑第一个坑就是VCAP电容。样机第一次上电现象是MCU复位脚电平正常、晶振有波形、电源电压正常但程序就是不跑量功耗还偏高。排查了两小时最后翻手册看到内置稳压器需要对VCAP管脚接外部电容补上一颗10µF之后立刻恢复正常。这个坑太经典了用这颗MCU的朋友一定先把VCAP搞定。第二个坑是I2C偶发死锁。实验室样机上一切正常装进电柜靠近变频器走线之后温度读数偶尔变成0xFF或者读超时。最后把速率从400kHz降到100kHz、上拉改成2.2k、SDA和SCL各串33Ω电阻再加上9脉冲恢复函数之后连续通电一周没再死锁。我的结论是工业现场别迷信高速I2C。第三个坑是远端读数“跟着本地跑”。一开始我远端读回来的温度跟本地几乎一样我还以为探头没插好。后来查配置寄存器才发现芯片默认情况下远端通道处于关闭状态我初始化的时候没有把远端使能和转换模式配置到位读回来的只是默认填充值。按手册重新配置之后远端读数才真正反映探头端温度。6.3 排查速查表现象可能原因解决办法本地温度比柜内温度高3°C以上板上热源耦合、自热严重优化布局、加挡风板、补偿固定偏移远端读数随线缆长度明显漂移线路电阻引入ΔVbe误差四线开尔文接法或软件补偿线阻I2C偶发超时或读到0xFF上拉过大、总线电容大、速率过高换2.2k上拉、降到100kHz、串电阻、加总线恢复远端读数为固定值或跟着本地变远端通道未使能、二极管开路/短路检查配置寄存器、状态寄存器、探头接线MCU上电不工作且电流偏大VCAP电容缺失或容值不对按手册补接VCAP电容校准后温度仍然非线性偏差探头安装热阻大、气流不稳、参考点未平衡改善接触、包保温棉、延长热稳定时间6.4 如果要推向量产还得补几件事原型跑通只是第一步。真到量产我会再补三样东西一是一台简易自动校准工装用恒温槽加精密温度计对每块板子做两点校准把k、b烧进EEPROM二是把出厂抽检改成-20°C、25°C、60°C三点验证每台保留校准记录方便追溯三是在固件里加看门狗和上电自检确保传感器故障时控制器能安全退守到预设值而不是带着错误温度继续运行。最后聊点个人体会。这类测温模块真正决定精度的往往不在芯片而在安装和线缆。芯片手册里写的±0.5°C都是理想条件探头松松垮垮顶在金属管壁上、风管里半悬空、线缆沿着强电桥架绕一圈误差翻倍是常有的事。所以我做这类项目总是把校准接口、测温备份通道和探头安装余量留足固件里把坏值标志做得干净利落剩下的就是现场调试的耐心。这套双通道方案跑下来冷热源两路管温、柜内温度和送风温度都能稳定上报整体误差控制在±0.5°C以内对我这边的HVAC应用来说已经够用了。后面如果再把RS-485走Modbus和USB调试那部分单独整理出来我再写一篇续文。