ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

嵌入式双点测温方案:PJ85718DM与PIC18F86J16实战解析

嵌入式双点测温方案:PJ85718DM与PIC18F86J16实战解析

干嵌入式这行,迟早都会碰上测温需求:控制器得知道自己这块板子热不热,还得知道远端的风道、风盘、水管里现在是多少度。本地和远程两个温度点,听起来简单,真做起来坑不少。几年前我在一套 HVAC 控制器上用过 PJ85718DM 配 PIC18F86J16 的方案,到现在还觉得这套搭配非常适合这类场景,尤其是对可靠性和成本都敏感的嵌入式产品。

PJ85718DM 是一颗带本地和远程测温通道的数字温度传感器,PIC18F86J16 则是 80 引脚的 8 位单片机,两者通过 I2C 连接,单片机上跑采集、滤波和 PWM 风扇控制逻辑,再把结果通过串口上报给上位机。这套方案既能测控制板自身的板温,又能通过远端二极管探头测风管或回水温度,测温误差控制在 ±1℃ 以内,BOM 成本又不高,非常适合暖通控制器、嵌入式机箱、变频驱动这类产品参考。这篇文章就完整拆一遍:为什么这么搭配、硬件怎么接、固件怎么写、实际调试中踩过哪些坑。

1. 方案思路:一处测温远不够,本地远端要分开测

1.1 本地温度和远程温度分别指什么

把标题拆开看,“本地温度”指的是传感器所在的电路板附近温度,也就是控制器自身的环境温度;“远程温度”指的是通过两根导线引出、放到被测目标上去测的温度。在 HVAC 系统里,这个远程探头通常贴在风管壁、盘管回水管、换热器进出口或者机柜散热风道上。

为什么要分两个点?因为控制逻辑里这两个温度承担的任务完全不同。本地温度用来做热保护:芯片自己过温了就算远程温度正常,也得降频或报警。远程温度用来做闭环控制:目标点冷热超限,就要加大风机转速、开大电动阀、启动压缩机。

以前有同事偷懒,只用一个 NTC 贴在 PCB 上,又当板温又当风管温度用,结果控制器放在电控箱里时,箱体内外温差七八度,控制效果完全对不上。测温点选错了,后面控制算法再怎么调都是白搭。

1.2 分立测温方案和集成测温方案怎么选

测温度有几种常见做法,我列个表对比一下:

方案测温原理优势劣势适合场景
NTC 热敏电阻 + ADC电阻随温度变化便宜、抗干扰好、传感器小非线性、需要标定、长线时引线电阻影响大板载单点测温
热电偶 + 冷端补偿热电效应测温范围宽、耐高温线性度差、需要冷端补偿、信号微弱高温工业现场
数字温度传感器(本地)片内半导体 PN 结直接出数字量、免标定只能测芯片附近温度、远离被测点板温和环境温度
数字温度传感器(本地+远程通道)本地 PN 结 + 远端三极管/二极管一个芯片测两点、远程探头轻、引线电阻可抵消探头需要二极管或三极管、布线要求高嵌入式/HVAC 双点测温

PJ85718DM 属于最后一种。它内部带一个本地测温单元,同时还有一路远程测温单元,用来测量外接的二极管连接型三极管的结电压差。原理上,三极管基极-发射极电压 Vbe 随温度近似线性变化,大约 -2mV/℃,芯片以两种不同电流激励,分别测出 Vbe,再用片上的数字逻辑算出温度。这样远端探头只需要一个几毛钱的小三极管,比拉一条 NTC 过去可靠得多。

1.3 为什么单片机选 PIC18F86J16

选这颗单片机是当时项目综合评估的结果,不是说别的 MCU 不行。PIC18F86J16 属于资源偏中高的 8 位机,80 引脚封装,Flash 容量和 RAM 对这类产品足够用,关键是外设齐全:硬件 I2C 模块可以直连 PJ85718DM,多个独立 PWM 输出可以直接驱动风扇调速,两个以上 UART 可以同时和触摸屏、上位机通信,还有比较器和中断引脚做告警联动。

还有一个实际原因:这类控制器经常放在电柜里,电源环境不干净,PIC18 的内核和外设抗干扰能力实测下来不错,复位和看门狗配置成熟稳定。做暖通产品讲究“放在那里十年不管”,选熟悉的、经过大量出货验证的型号,比追新品稳得多。

2. 器件拆解:看懂 PJ85718DM 的测温机制

2.1 PJ85718DM 的功能与寄存器逻辑

PJ85718DM 这类芯片做的是“把测温这件事尽量简单化”。它对外提供 I2C 从机接口,主机读几个寄存器就能拿到本地温度和远程温度。常见的寄存器布局大致包括:

  • 状态寄存器:放着测量忙标志、错误标志;
  • 本地温度高字节、低字节;
  • 远程温度高字节、低字节;
  • 配置寄存器:分辨率、测量模式、转换周期;
  • 高限/低限告警寄存器:超限自动拉低 ALERT 引脚。

不同批次的 85718 系列,寄存器具体偏移可能略有差异,以实际到手的数据手册为准。但道理都差不多:高字节是整数部分,低字节的高几位是小数部分,12 位分辨率下 LSB 等于 0.0625℃。读回来的是左对齐的补码数据,负数要自己转。

它的本地通道测量的是芯片自身附近的板温,远程通道则需要把探头的基极和发射极,也就是 BJT 的 e、b 端,甚至 b、c 短接后的 e-c 体二极管,接到芯片的两个专用引脚上。芯片会用固定电流去激励这个外部 PN 结,测量结压降,再推导出远端温度。

2.2 体温测量精度与分辨率的取舍

做温度监测,不是精度越高越好,而是“够用且稳定”最好。HVAC 的室内温度控制,±0.5℃ 已经能支撑较好的舒适度;风管温度和回水温度,±1℃ 完全够控制逻辑使用。PJ85718DM 本地通道做到 ±0.5℃ 左右,远程通道因为受探头本身一致性和布线影响,±1℃ 是合理预期。

分辨率方面我平常设置成 12 位,也就是 0.0625℃。有些工程师喜欢调到更高分辨率以求心理安慰,但这没有任何实际意义,反而增加转换时间和 I2C 读取频率的负担。数据的有效精度归根到底由传感器物理特性和噪声决定,分辨率只是显示层面的东西。

2.3 远程探头的接法:三极管还是二极管

远程通道的探头可以用二极管连接的 NPN 或 PNP 三极管,也可以用单独的二极管。我习惯用 NPN 小信号三极管,基极和集电极短接,只用到 e-b 结。因为三极管的 e-b 结构造更接近芯片设计时的校准模型,温度曲线好,一致性也更好。常见的管子型号不限于某一种,只要是低功耗小信号类型基本都行。

需要注意的是极性:接反了温度读数要么不变,要么直接显示负值,这一条后面排查时还会提到。

3. 硬件实现:从接线表到 PCB 布线的完整细节

3.1 引脚分配和最小系统接法

我这版硬件是 3.3V 供电,PJ85718DM 和 PIC18F86J16 共用一组 I2C 总线。引脚分配大概如下:

信号芯片引脚走线说明
SCLPIC 的 SCL 引脚 / 传感器 SCLI2C 时钟,4.7kΩ 上拉
SDAPIC 的 SDA 引脚 / 传感器 SDAI2C 数据,4.7kΩ 上拉
ALERTPIC 的外部中断引脚远程超限时拉低唤醒 MCU
远端探头 B/EPJ85718DM 的 D+/D- 引脚差分对走线,加地保护
风扇 PWMPIC 两个 PWM 输出低速风机信号,经三极管或驱动芯片

I2C 上拉电阻的选择要说明白:总线电容小时,4.7kΩ 是稳妥值;总线拉得长、挂多个从机,可以换成 2.2kΩ。上拉太大会导致上升沿变缓,在 I2C 高速模式下可能通信失败;上拉太小又会让低电平拉不高,功耗也偏大。3.3V 系统上我没有用过 10kΩ 以上,实测边缘不干净,后面固件层总是报超时。

电源上 PJ85718DM 的 VDD 加 0.1μF 陶瓷电容做退耦,且电容尽量靠近电源引脚。这属于老生常谈,但每次调试出诡异读数,检查退耦电容总能占一席之地。PIC18 的 MCLR 引脚接标准 RC 复位电路,同时留一个复位按键测试位置,量产时可不贴。

3.2 远端探头布线:决定远程测温成败的关键

远程测温对线长和布线的要求比很多人想象中高。PJ85718DM 施加给探头的激励电流只有微安到毫安级,测的是 mV 级电压差,所以 D+/D- 两根线非常容易被旁边的数字信号串扰。细节如下:

  • 两根探头线尽量平行靠近走,构成类似差分对,避免形成大环路面积;
  • 探头线下面铺地,让地平面做屏蔽,不要让他们跨过 PWM 输出或继电器控制线;
  • 板内探头线长度控制在 10cm 以内最佳,最长不超过 30cm,超过就要用屏蔽双绞线且金属编织层单端接地;
  • 如果探头需要出机箱,接口处加一个串联小电阻和一个对地电容,滤除高频噪声,具体阻容值以传感器手册建议为准。

我吃过一个亏:第一版板子把远程探头线从 PWM 风扇排线正下方穿过,风扇一开,远程温度读数抖动了 1.5℃。后来把探头线移到板边,远离 PWM 走线,并在传感器入口加 1nF 差模电容,读数才稳下来。这一条如果不想生产后返工,布线时就得当回事。

3.3 给 HVAC 环境的硬件增强

HVAC 控制柜里的干扰源很多:继电器吸合、接触器通断、大电机启停。为了不让远程测温数据在继电器动作瞬间发生跳变,建议在传感器供电上串一个小磁珠,再并联 10μF 到 47μF 的电解电容,形成简单的 π 型滤波。ALERT 信号也要加一个 10kΩ 上拉,因为大部分这类芯片的告警输出是开漏结构。开漏不加上拉,引脚电平悬空,中断会被随机触发或者干脆不触发。

另外,设计时给 I2C 的 SCL/SDA 加 33Ω 串联电阻,对于抑制过冲有帮助,成本几乎可以忽略。这些都不是数据手册里会催你做的事,但实测对 HVAC 这种恶劣电磁环境很有效。

4. 固件开发:I2C 采集、温度换算和联动控制

4.1 初始化代码:先把 I2C 模块和传感器配好

固件的第一步是初始化 PIC18F86J16 的 MSSP 模块,让它运行在 100kHz 或 400kHz 的 I2C 主模式下。PJ85718DM 这类低速传感器跑 100kHz 完全够用,400kHz 在走线不好时反而容易出错,我通常选 100kHz,稳定优先。

初始化之后,给传感器写配置寄存器,把分辨率设为 12 位并开启连续转换模式。配置的伪代码如下:

void temp_sensor_init(void) { // 配置 I2C 主模式,100 kHz i2c_master_init(100000); // 读取设备 ID 确认在线,0x00 寄存器等 if (temp_sensor_read_id() != EXPECTED_ID) { set_error_flag(ERROR_NO_SENSOR); return; } // 写配置寄存器:12 位分辨率,连续转换 temp_sensor_write_reg(REG_CONFIG, 0x60); }

初始化阶段读设备 ID 是我自己的习惯,不是手册强制要求。开门先确认器件在线,后面所有读取流程出问题时,至少能排除“传感器根本没焊上”这个低级原因。这个习惯帮我在产线阶段节省过大量排查时间。

4.2 读温度并换算成摄氏度

温度寄存器组在转换完成后可读,读回来的原始值是 12 位左对齐补码。换算代码大概长这样:

float pj85718_read_remote_celsius(void) { uint8_t msb = pj85718_read_reg(REG_RTEMP_MSB); uint8_t lsb = pj85718_read_reg(REG_RTEMP_LSB) & 0xF0; int16_t raw = (int16_t)((msb << 4) | (lsb >> 4)); // 12 位补码符号扩展 if (raw & 0x0800) { raw |= 0xF000; } return (float)raw * 0.0625f; }

这里有个细节要留意:低字节的规格通常是最低 4 位无效,必须掩掉。新工程师最容易犯的错误是直接(msb << 8) | lsb,导致温度值整整多了 16 倍,因为把无效位当成有效数据了。

本地温度的读取代码几乎一样,只是寄存器地址不同。读回来的负数要记得先做符号扩展,否则 0℃ 以下会显示成 400 多度,这个错我亲眼见过不止一次。

4.3 中位平均滤波:远程读数的最后一层防护

无论布线多小心,远程通道始终会带一点杂散噪声,特别是在继电器通断瞬间。固件层面我加了中位平均滤波:每 100ms 采样一次,取最近 5 个值丢掉最大最小再平均。这个办法同时兼顾了抗脉冲干扰和平滑响应,比单纯滑动平均更能抵抗突变值。

滤波之后,还有一个软件层面的保护:读取结果如果落不到合理范围,就视为无效。HVAC 场景我通常把有效范围限定在 -40℃ 到 +150℃,超出就抛弃当前值并连续报错 3 次后置故障标志。这样做的好处是,探头断开时不会以某个漂移值参与控制,系统会主动进入安全模式,把风机开到默认转速,而不是盲目全速或停机。

4.4 风扇曲线和告警联动逻辑

温度拿到手,最终要落到执行器上。HVAC 控制器的典型逻辑是:远程温度超过目标点时,风扇按比例调速;本地温度过高时,限制系统输出甚至告警停机。

我这里用了一组分段线性曲线控制 PWM 占空比:

uint8_t compute_fan_duty(float remote_temp) { // 20℃ 以下低速待机,40℃ 以上全速 if (remote_temp <= 20.0f) { return 30; // 基础通风 } else if (remote_temp >= 40.0f) { return 255; // 满速 } else { float ratio = (remote_temp - 20.0f) / 20.0f; return (uint8_t)(30 + ratio * (255 - 30)); } }

注意这里不能只做线性换算,必须留基础占空比。很多 HVAC 设备的风机在占空比过低时转不起来,或者虽然转了但风量几乎为零。基础 30 的占空比实测能保证大多数轴流风机稳定启动和运转,具体值要按你们实际风机标定。

告警方面,我把 PJ85718DM 的 ALERT 引脚下沿触发接到 PIC18 的外部中断。传感器内部设置上、下限和迟滞,温度越限就能自主拉低 ALERT,即使 MCU 正在忙别的任务,中断也能第一时间让系统进入保护流程。传感器自身带迟滞功能这一点非常重要,否则温度在临界点附近波动时,风扇会频繁变速,影响舒适度还损耗风机寿命。

4.5 远程上报:把两路温度送到上位机

“远程温度”除了传感器层面,还体现在整机通讯层面。我用 UART 按 Modbus RTU 协议把本地温度和远程温度打包发给上位机或触摸屏。数据帧很简单,读保持寄存器时返回两个 16 位温度值,单位 0.1℃,高字节在前。

固件里要注意一个细节:Modbus 的寄存器地址分配最好在设计初期就定好,并写进文档。我见过项目做了一半,第三版固件开始加寄存器,结果上位机、触摸屏、产测工具各自维护一份地址表,最后对不上,联调改了三天。把地址映射表当作接口规范管理,和管硬件原理图一样认真。

5. 现场排查:远程温度异常的常见原因和处理方法

5.1 现象、原因和解决方案速查表

实际调试中遇到过的远程温度异常,我整理成了排查表,每次遇到问题先对照一遍,比盲目改固件有效率得多。

现象可能原因排查和解决动作
远程温度始终不变且为负值探头二极管极性接反互换 D+/D- 连线或用万用表确认 PN 结方向
远程温度抖动超过 1℃探头线跨越高频 PWM 或继电器信号重新布线、加屏蔽、传感器入口加差模电容
远程温度贴近本地温度且不随探头位置变化探头引脚短路或传感器内通道未使能悬空测量 D+/D- 静态阻值,检查配置寄存器
I2C 偶发超时,重启后恢复上拉电阻偏大或总线上挂设备过多把上拉从 10kΩ 换到 4.7kΩ,检查是否总线电容过大
读到的温度整体偏高到不可能的范围寄存器低字节无效位没掩掉检查读取代码是否遗漏& 0xF0
0℃ 以下误显示为高温补码符号扩展缺失检查raw & 0x0800前的类型,确保用 int16_t
通电瞬间读数跳变一次传感器电源未稳定让系统延时 300ms 后再初始化 I2C 并读取

5.2 我被现场困住的一次经历

有一台样机在客户现场运行,远程温度每隔几分钟会突然跳到 110℃ 然后恢复。现场离实验室一千多公里,只能靠日志远程分析。从日志看不出规律,后来把事件和 IO 记录对齐,才发现每次跳变都发生在同一台水泵接触器吸合时刻。

根因是水泵通过接触器启停时,产生的浪涌耦合到远程探头线上,微伏级信号被干扰,个别采样值严重异常。中位平均滤波理论上能滤掉单次尖峰,但那次干扰持续了连续几个采样周期,滤不掉。最终解决是硬件上把探头线换成屏蔽双绞线,并在传感器 D+/D- 端加强了对地的共模电容。

这件事教会我一个道理:远程测温的可靠性,七分在硬件布线,三分在软件滤波。软件能兜底,但永远替代不了接线和布局上的功夫。

5.3 温度标定与批量一致性

HVAC 产品出货量大,每台设备的传感器标定不能靠人工。我的做法是:在产测工序对每台设备采集本地和远程两个温度,与标准仪器对比,软件计算偏移量,写入单片机的数据 EEPROM 里。这个偏移量在出厂前补进温度换算结果。

批量一致性问题上要特别注意远端探头的批次。不同批次的小三极管 Vbe 曲线会有细微偏差,换供应商或换批次时,要重新抽检在 0℃ 和 50℃ 两个点上的读数偏差,这个偏差如果不查,产线可能整批出现系统性偏高或偏低,到时候已经在客户现场出了问题,代价就大了。

6. 实测数据与调参心得

6.1 一组有代表性的实测数据

在实验室里,我用标准水浴锅校准远程探头,用环境箱校准本地通道,拿到的一组数据大概如下:

标准值本地读数远程读数偏差
0.0℃0.2℃0.4℃+0.2℃ / +0.4℃
25.0℃25.1℃24.8℃+0.1℃ / -0.2℃
50.0℃50.3℃49.7℃+0.3℃ / -0.3℃
75.0℃75.4℃75.2℃+0.4℃ / +0.2℃

这套数据说明硬件上偏差已经收紧。在此基础上,软件补偿了两个固定偏移量,基本能在全量程把误差控制到 ±0.5℃ 以内。对于 HVAC 应用,这个精度余量非常充足。

6.2 迟滞参数怎么设

告警阈值和迟滞的设置,我推荐一个经验值:上限拉高 2℃,下限放低 2℃。阈值的设置要和被控对象的温变速率匹配。风管温度变化快,迟滞设小一点,避免响应迟钝;回水温度变化慢,迟滞设 3℃ 问题也不大。

这个参数不要凭感觉敲,最好在实测温度波动曲线上直接量出来:把现场温度变化曲线打出来,看温度在目标值附近震荡的幅度,然后按“震荡幅度再加一半”去设迟滞。第一次做风机联动调速时,我没有设迟滞,结果风机声听着就像在打呼噜,一冲一冲的。补上 2℃ 迟滞后,声音平滑了很多。

6.3 后续扩展:这套测温框架能往哪走

这个方案的核心价值是“一个芯片覆盖板温和远端温度,数字接口对主机友好”。同样的框架,后续还能扩展方向包括:增加一路远程探头测冷凝水管温度、把本地通道换成测量芯片附近空气温度并加进气导流罩、把 I2C 改成多设备挂接读取分区温度等。

我自己后来的几个项目基本沿用了这套代码和硬件框架,只是换了单片机和传感器供货版本,核心逻辑一直没有重构。因为整套东西经过现场验证,改动越少越安全。这也是我希望这篇文章能带给你的价值:方案不一定最新,但可靠的结构、清晰的流程和踩坑记录,才是产品长期稳定运行的基础。

RELATED READING

延伸阅读

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