ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

基于PJ85718DM与PIC18F47K42的本地及远程温度监测方案

基于PJ85718DM与PIC18F47K42的本地及远程温度监测方案 1. 从一颗温度传感器说起为什么本地与远程双路监测值得单独做嵌入式温度监测这件事看起来简单真做起来坑不少。我最早接触温度采集是在一个环境监控项目里当时用一颗数字温度传感器直接挂在主控的I2C总线上本地温度读得挺准但一旦要把探头拉到几米外的设备舱或者风管里读数就开始飘有时候跳变两三度有时候干脆通信失败。后来才明白本地温度监测和远程温度监测本质上解决的是两类完全不同的问题硬件选型、总线拓扑、软件滤波策略都得分开对待。这篇要聊的就是围绕一颗PJ85718DM温度传感器和一颗PIC18F47K42单片机怎么把本地温度和远程温度同时监测起来并且让这套方案能同时适配嵌入式设备内部的环境监控和暖通空调HVAC场景下的温度采集。PJ85718DM是一颗支持本地测温加远程二极管测温的传感器件PIC18F47K42则是Microchip家PIC18系列里外设比较全的一颗8位MCU带I2C、带多路ADC、带比较器做温度采集和逻辑控制绰绰有余。先说清楚这套方案能干什么。本地温度监测指的是传感器自身所在位置的温度比如PCB板级温度、机箱内部环境温度远程温度监测指的是通过外接一个二极管接法的三极管或者专用远程温度二极管把温度探头延伸到几米甚至十几米外的地方去测。HVAC场景里控制板往往装在电控箱里但真正要测的是风管温度、回风温度、盘管温度这些测点离控制板很远这就是远程测温的典型需求。嵌入式场景里比如一块工控主板既要知道板子自己热不热又要知道外部某个功率器件或者电池组的温度同样是本地加远程的组合。适合谁看这篇内容如果你正在做温度采集相关的嵌入式开发或者在做HVAC控制器的方案选型又或者你手上有PIC18系列的板子想跑通温度监测这篇的实操细节和踩坑经验应该能帮上忙。我会把硬件连接、寄存器配置、温度换算、远程二极管校准、滤波策略、故障排查这些环节都拆开讲尽量让新手能照着做老手能拿去避坑。2. PJ85718DM的本地与远程测温机制拆解2.1 本地测温通道的工作原理与精度边界PJ85718DM的本地温度通道核心是一个片上温度敏感元件通常是利用半导体PN结的电压随温度变化的特性来实现测温。芯片内部会把这个电压转换成数字量再通过I2C接口读出来。本地通道的好处是响应快、不需要外部元件、一致性比较好但它的精度受限于芯片自身的工艺偏差和封装热阻。实际用下来本地通道的绝对精度大概在正负1到2摄氏度这个量级分辨率可以做到0.0625摄氏度甚至更细。这里有个容易忽略的点分辨率不等于精度。你能读到0.0625度的变化不代表你的绝对温度值就准到0.0625度。很多新手看到读数小数点后四位就以为测温很准其实那只是量化精度真正的误差要看芯片手册里的精度指标。本地测温还有一个坑是自热效应。芯片自身功耗会让结温略高于环境温度尤其是在供电电压偏高、采样频率很快的时候。我实测过如果连续高速采样不做间隔本地读数会比实际环境温度高0.3到0.5度。解决办法是降低采样频率或者在固件里做自热补偿。对于大多数环境监控场景这个偏差可以接受但如果你做的是高精度恒温控制就得把这一项算进去。2.2 远程二极管测温的物理基础与布线要求远程测温通道的原理是让芯片去测量一个外部二极管接法三极管的基极-发射极电压。这个电压和温度呈线性关系芯片通过交替注入两个不同电流测出两个VBE的差值再换算出温度。这种方法的优势是探头可以做得非常小响应快而且可以拉远。但远程测温对布线非常敏感。我踩过最典型的坑是探头线用普通排线拉了五米读数一直偏高且不稳定。后来换成双绞线加屏蔽层问题立刻缓解。原因是远程测温本质上是在测微伏级的电压差任何串入的噪声、线阻、寄生电容都会影响结果。所以远程二极管的走线要尽量短、尽量成对、尽量远离功率开关节点。另外远程二极管必须用芯片推荐的型号或者符合二极管接法的三极管比如常见的MMBT3904这类。如果你随便拿一个三极管把集电极和基极短接当二极管用大多数情况下也能工作但温度系数可能和芯片预期的不一致导致读数系统性偏移。这个偏移可以通过校准寄存器修正但前提是你得知道偏了多少。2.3 本地与远程通道的采样时序与数据就绪判断PJ85718DM内部是轮流采样本地和远程通道的转换速率可以配置。这里有个实操细节如果你读得太快可能读到的是上一次转换的结果或者数据还没就绪。正确的做法是读状态寄存器确认对应通道的数据就绪标志置位了再去读温度寄存器。我见过有人用固定延时来等转换完成比如延时100毫秒再读。这种做法在常温下没问题但如果你改了转换速率配置延时就不准了。更稳的方式是轮询状态位或者用ALERT引脚做中断触发。PIC18F47K42有外部中断引脚可以把传感器的ALERT输出接上去温度超限时直接进中断主循环不用一直轮询效率高很多。采样时序还有一个要注意的是通道切换后的稳定时间。本地通道和远程通道切换时内部模拟前端需要一点时间稳定。如果你配置的转换速率太快通道间可能会互相干扰。我的经验是对于HVAC这种温度变化本来就慢的场景转换速率设成1赫兹到4赫兹足够了没必要追求高速采样反而容易引入噪声。3. PIC18F47K42侧的I2C驱动与温度数据处理3.1 硬件I2C初始化时钟、上拉与地址确认PIC18F47K42的I2C外设配置起来不算复杂但有几个参数必须算对。首先是时钟频率标准模式100kHz快速模式400kHz。PJ85718DM一般支持到400kHz所以你可以用快速模式。时钟频率由SSPADD寄存器决定计算公式是SSPADD (Fosc / (4 * Fscl)) - 1。假设你的MCU跑16MHz想要400kHz的I2C时钟那SSPADD就是(16000000 / (4 * 400000)) - 1 9。这个值要算准算错了通信直接失败。上拉电阻的选择也常被忽略。I2C总线是开漏输出必须有上拉。常见取值是4.7kΩ但如果总线电容大、走线长4.7k可能太小导致上升沿不够陡或者太大导致上升太慢。我的经验是短距离板内通信用4.7k没问题如果传感器在另一块板上、排线较长可以降到2.2k试试。但注意上拉电阻越小总线低电平时的灌电流越大要确认器件能承受。地址确认这一步新手最容易卡住。PJ85718DM的I2C地址通常由地址引脚的电平决定可以配置成多个地址之一。你必须先确认硬件上地址引脚接的是高还是低然后在代码里用对应的7位地址。我建议第一次调试时先用I2C扫描程序把所有地址扫一遍确认传感器实际响应的地址再写死到代码里。这个习惯能省掉很多“为什么读不到数据”的排查时间。3.2 温度寄存器读取与定点数换算PJ85718DM的温度寄存器一般是16位高字节是整数部分低字节是小数部分分辨率通常是0.0625度也就是低字节的高4位有效。读取时先读高字节再读低字节或者用连续读的方式一次读两个字节。注意有些器件在读取过程中会锁存数据保证高低字节来自同一次转换这个特性要利用好。换算成实际温度时如果是正温度直接把高字节当作有符号整数低字节的高4位乘以0.0625加起来就是温度值。如果是负温度高字节是补码形式需要先转成有符号数再算。我见过有人忘了处理负温度结果冬天室外测出来是两百多度就是因为把补码当无符号数读了。用定点数处理可以避免浮点运算的开销。比如把温度放大16倍存成整数0.0625度正好对应1个LSB。这样温度值就是一个整数比较、显示、传输都方便。需要显示的时候再除以16得到整数部分取余得到小数部分。PIC18F47K42是8位机浮点运算很慢能用定点就别用浮点。3.3 远程通道的校准寄存器配置与偏移修正远程通道的校准是这套方案里最需要耐心的部分。理想情况下远程二极管在25度时的VBE对应一个标准值但实际器件的工艺偏差会导致读数偏移。PJ85718DM通常提供一个偏移校准寄存器你可以写入一个修正值来补偿。校准的方法是让远程二极管处于一个已知的、稳定的温度环境比如冰水混合物0度或者恒温槽25度读取未校准的温度值和实际温度的差值就是偏移量。然后根据芯片手册里偏移寄存器的步进大小算出要写入的修正值。比如偏移寄存器每LSB代表0.0625度你测出来偏高1.5度那就写入-241.5 / 0.0625 24。这里有个经验校准要在最终产品的实际布线条件下做。如果你在实验台上用短线校准好了装到现场换成五米长的探头线偏移可能又变了。因为线阻和寄生参数会影响测量结果。所以校准最好在整机装配完成后、用实际探头线进行。如果现场条件不允许至少要在实验室里用和现场同规格、同长度的线来校准。4. 本地与远程温度监测在HVAC与嵌入式场景的落地差异4.1 HVAC风管测温远程通道的响应速度与滤波取舍HVAC场景里远程探头通常贴在风管外壁或者插入风管内部测的是空气温度或者盘管表面温度。空气温度变化本来就慢所以采样速率不用高但滤波要做足。我一般会在固件里做一个滑动平均滤波窗口大小取8到16个采样点。窗口太小读数跳窗口太大响应滞后影响控制效果。这里有个取舍如果你做的是送风温度控制响应滞后会导致控制超调如果你做的是回风温度监测滞后一点无所谓。我的做法是分两路处理控制用的那一路用较小的滤波窗口比如4点监测用的那一路用较大的窗口比如16点。这样既保证控制响应又保证显示稳定。还有一个HVAC特有的问题是探头结露。风管里湿度高的时候探头表面可能凝结水珠导致读数突然偏向环境温度或者直接短路。硬件上可以做防潮处理软件上可以加一个变化率限制如果相邻两次采样温差超过某个阈值比如2度就认为是异常跳变丢弃这次数据用上一次的值代替。这个策略能有效过滤结露和干扰引起的野值。4.2 嵌入式板级测温本地通道的自热补偿与布局建议嵌入式板级测温本地通道测的是板子周围的空气温度或者板面温度。如果你把传感器放在发热元件旁边读数会明显偏高。布局时要注意远离稳压器、功率电感、功率MOS这些热源至少留出1厘米以上的间距有条件的话在传感器下方做开窗或者挖槽减少通过PCB铜箔传过来的热量。自热补偿的做法是在固件里根据采样频率和供电电压估算一个自热偏移量从读数里减掉。这个偏移量可以通过实验测定让板子在已知环境温度下稳定运行记录传感器读数和实际环境温度的差值这个差值就是自热加布局误差的综合偏移。然后在固件里做固定补偿。虽然不够精确但对于大多数监控场景够用了。如果要做更精确的板级测温可以考虑让传感器间歇工作平时处于关断或者低功耗模式需要测量时唤醒快速采一次然后继续休眠。这样自热效应可以降到最低。PIC18F47K42本身也支持低功耗模式整个系统可以做成周期唤醒采集平均功耗做得很低。4.3 双通道数据融合与告警阈值设定本地和远程两路温度都拿到之后怎么用是个问题。最简单的做法是分别显示、分别告警。但实际场景里有时候需要看两者的差值。比如嵌入式设备里如果本地温度和远程温度差得很多可能说明远程探头脱落了或者本地散热出了问题。我一般会设三个告警本地超上限、远程超上限、两者差值超限。阈值设定要留回差不然温度在阈值附近波动时会频繁告警。比如上限设60度回差设2度那就是超过60度告警降到58度以下才解除告警。这个回差在HVAC控制里尤其重要能避免执行机构频繁启停。数据融合方面如果两路测的是同一个热源的不同位置可以取加权平均。权重根据你更信任哪一路来定。如果两路测的是完全不同的对象那就各管各的不要混在一起。我见过有人把本地和远程温度直接平均结果远程探头测的是室外温度本地测的是机箱温度平均出来的值没有任何物理意义。5. 调试过程中最容易卡住的几个环节5.1 I2C通信失败的分层排查法I2C不通是最高频的问题。我的排查顺序是先确认供电和地再确认上拉电阻再确认地址最后看时序。供电不对芯片根本不工作地上有噪声通信会时好时坏上拉缺失或者阻值不对波形根本拉不起来地址错了从机不响应时序不对比如时钟太快或者建立保持时间不够数据会错。用示波器看波形是最直接的。正常I2C的SDA和SCL应该是干净的方法上升沿有弧度但不至于太慢。如果看到SCL被拉低不放可能是从机在等待什么条件或者总线死锁了。总线死锁的解决办法是在SCL上多发几个时钟脉冲让从机释放SDA。PIC18F47K42的I2C外设有超时机制可以配置成检测到总线异常时自动复位。还有一个隐蔽的坑是电平不匹配。如果传感器供电是3.3V而MCU是5V直接连可能烧传感器或者通信不稳定。必须确认两边电平兼容必要时加电平转换。现在很多传感器支持宽电压但一定要看手册确认。5.2 远程读数跳变从布线到寄存器逐项定位远程读数跳变原因可能有很多。我的排查链路是先看跳变幅度和频率如果跳变幅度大且无规律多半是干扰或者接触不良如果跳变有规律比如和某个开关动作同步那是耦合干扰如果读数缓慢漂移可能是自热或者环境变化。接触不良是常见原因。远程二极管通常是通过接插件连出去的接插件氧化或者松动会导致接触电阻变化直接影响测量。我遇到过好几次重新插拔一下接插件读数就稳了。所以如果现场出现莫名其妙的跳变先检查接插件。寄存器配置错误也会导致跳变。比如转换速率设得太快通道间串扰或者滤波配置没开原始数据直接输出。PJ85718DM一般有数字滤波选项可以配置成多次转换取平均。把滤波打开跳变会明显改善。5.3 温度换算出负值或超大值的典型原因读到负值或者超大值基本是数据格式处理错了。前面说过温度寄存器的高字节是有符号数负温度是补码。如果你用无符号方式读负温度就会变成很大的正数。解决办法是在代码里把高字节声明为有符号类型或者手动做补码转换。另一个原因是高低字节读取不同步。如果你先读高字节然后处理了一会儿再读低字节中间可能发生了一次新的转换导致高低字节来自不同次采样。解决办法是用连续读或者利用器件的锁存机制。有些器件在读高字节时会锁存低字节读低字节时锁存高字节这种设计就是为了保证一致性。还有一种情况是I2C读回来的数据全是0xFF或者0x00这通常意味着通信根本没成功读到的只是总线空闲电平。这时候不要急着算温度先确认通信是否正常。可以读一下器件ID寄存器如果有的话确认能读到正确的ID再往下做。6. 把这套方案做稳的几个工程习惯6.1 上电自检与传感器在线检测产品化的时候上电自检很重要。我的做法是上电后先读一次传感器ID或者状态寄存器确认器件在线然后读一次本地和远程温度确认读数在合理范围内比如负40到正125度之间如果任何一项不通过就置一个故障标志让上层知道传感器有问题。传感器在线检测还可以做成周期性的。比如每隔一段时间读一次状态寄存器如果连续多次读失败就判定传感器掉线。这个机制在HVAC场景里很有用因为探头线可能被老鼠咬断或者接插件被振动松脱。早点发现故障比等到控制失效再排查要好得多。6.2 采样周期与功耗的平衡电池供电的嵌入式设备功耗是硬指标。温度采集本身耗电不多但如果你让MCU一直醒着轮询功耗就上去了。合理的做法是让MCU大部分时间休眠用定时器周期唤醒唤醒后快速采一次温度处理完继续休眠。PIC18F47K42的休眠电流很低配合传感器的关断模式整体平均功耗可以做到微安级。采样周期的选择要看应用。环境温度监测一分钟采一次都嫌多设备内部温度监控可能一秒一次HVAC控制取决于控制周期一般几秒一次。不要盲目追求高采样率够用就行采样越频繁功耗越高噪声也越大。6.3 固件层面的异常恢复与看门狗配合I2C总线有可能死锁传感器有可能无响应这些异常如果不处理固件可能卡死。我的做法是在I2C读写函数里加超时如果超过一定时间还没完成就复位I2C外设重新初始化。同时开看门狗如果主循环卡住看门狗直接复位整个系统。看门狗的时间要设得比正常循环时间长但比你能接受的最长故障时间长。比如正常循环100毫秒看门狗设500毫秒这样偶发的长延时不会误触发但真卡死了也能及时恢复。喂狗的位置要放在主循环里不要放在中断里否则主循环卡死而中断还在跑看门狗就失效了。温度数据的异常恢复也值得做。如果连续几次读到超范围的值可以判定传感器异常切换到备用策略比如用上一次的有效值或者用本地温度代替远程温度。这样即使远程探头出问题系统还能降级运行不至于完全失控。7. 从这套方案延伸出去还能做什么PJ85718DM加PIC18F47K42这个组合做温度监测只是基础。PIC18F47K42本身带多路ADC和比较器你可以把温度数据和其他模拟量比如湿度、压力、电流一起采集做成一个多参数监控节点。I2C总线上还可以挂其他传感器扩展性不错。如果要做温度控制PIC18F47K42的PWM外设可以直接驱动加热或者制冷执行机构。把温度采集和控制逻辑放在同一颗MCU里省掉一颗控制器成本更低。控制算法可以用简单的位式控制或者PID8位机跑PID虽然吃力但温度这种慢过程用定点数实现PID完全可行。再往上层走可以加通信接口把温度数据传到上位机或者云端。PIC18F47K42有EUSART可以接无线模块或者有线收发器。这样一套本地加远程的温度监测系统就能融入更大的监控网络里。我在实际项目里就是这么做的底层用PIC18做采集和控制上层通过串口或者无线把数据汇总整体架构清晰维护也方便。最后分享一个我在实际布线中总结的小经验远程二极管的走线如果能和地线成对绞合抗干扰效果比单独走两根线好很多。如果条件允许用带屏蔽层的双绞线屏蔽层单端接地能进一步抑制共模干扰。这个细节在实验室里可能看不出差别但到了现场尤其是HVAC这种有变频器、接触器的环境差别非常明显。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进