1. 从一颗温度传感器说起:为什么本地与远程双路监测在 HVAC 场景里绕不开
做嵌入式 HVAC 控制板的人都有一个共识:温度采样看起来简单,真正落地到设备上却处处是坑。板子自身的发热、传感器走线的长度、现场电磁环境的复杂度,都会让一个"读个温度"的需求变成需要认真设计的子系统。这次我拿到的项目标题是"通过 PJ85718DM 与 PIC18F47Q10,监测嵌入式和 HVAC 应用中的本地与远程温度",核心就是用一颗远程温度传感器配合一颗 8 位单片机,同时把"本地板载温度"和"远端被测点温度"两路数据采回来。
先说清楚这套组合各自扮演什么角色。PIC18F47Q10 是一颗带 10 位 ADC、多路 UART/SPI/I2C 外设的 8 位单片机,属于那种资源够用、成本可控、开发资料齐全的通用控制芯片,在暖通空调、家电控制、工业小节点里非常常见。PJ85718DM 则是一颗远程温度传感器,它的价值在于把感温元件从主控板上"挪出去"——通过外部连接把远端的热敏探头接到芯片上,芯片内部完成激励、采样和数字化,再通过数字接口把温度值交给主控。这样一来,主控板可以放在机箱里,探头却可以贴在出风口、回风口、水管表面或者房间任意位置。
为什么非要"本地 + 远程"两路一起做?因为 HVAC 设备真正关心的从来不只是"某个点多少度"。举几个实际场景你就明白了:空调控制器需要知道回风温度来决定压缩机启停,同时还要知道主控板自身的温度来判断是否需要降额保护;新风系统要比较室内探头和室外探头的温差来决定风阀开度;热泵热水器要监测水箱温度和环境温度来算加热效率。这些场景里,本地温度负责"自检和保护",远程温度负责"控制目标",两者缺一不可。
这篇文章面向的是正在做类似方案、或者准备选型的嵌入式工程师。我会把选型逻辑、硬件连接、软件采样流程、校准方法、抗干扰处理、常见故障排查都讲透,尽量给出可以直接抄作业的配置和代码思路。哪怕你之前没接触过远程温度传感器,看完也能明白它和普通板载传感器的本质区别在哪里。
2. PJ85718DM 与 PIC18F47Q10 的分工逻辑:为什么不是随便挑两颗芯片凑一起
2.1 远程温度传感器到底解决了什么板载传感器解决不了的问题
很多人第一反应是:测温嘛,板子上焊一颗数字温度芯片不就行了,何必搞远程。这个想法在小家电上没问题,但在 HVAC 里会立刻撞墙。板载传感器测的是"芯片自己周围的温度",而芯片周围恰恰是整块板子最热、最脏、最不具代表性的地方。开关电源的发热、继电器动作的干扰、MCU 自身的功耗,都会让板载读数比真实环境高出好几度。
远程温度传感器的思路完全不同。它把敏感的模拟前端留在芯片里,把"感温点"通过一对走线延伸到物理上远离主控的位置。PJ85718DM 这类器件通常支持外接热敏电阻或者二极管型感温元件,芯片内部用恒流源激励、用高精度 ADC 采样,再经过内部算法换算成温度。关键收益有三个:第一,感温点可以放到真正需要测量的地方;第二,模拟小信号在芯片内部处理,走线上传输的是数字量或者抗干扰能力更强的信号;第三,一颗芯片往往能接多路远程通道,省掉多路独立的板载传感器。
注意:远程不等于无线。这里的"远程"指的是感温元件与主控芯片物理分离,靠有线连接,和通信距离上的"远程"是两回事。选型时别被字面意思带偏。
2.2 PIC18F47Q10 在这套方案里承担的三重职责
PIC18F47Q10 不是单纯来"读个数"的。在这类 HVAC 控制板里,它通常同时干三件事。第一是数据采集与融合:通过 I2C 或 SPI 从 PJ85718DM 读取远程温度,同时用自己内部的 ADC 或者另一路传感器读本地温度,把两路数据做时间对齐和滤波。第二是控制决策:根据温度数据驱动继电器、可控硅、风机或者通信模块,比如温差超过阈值就开阀、本地过温就降频。第三是通信与上报:把温度数据打包,通过 UART 或者总线接口送到上位机、显示面板或者云端网关。
这三重职责决定了选型时的几个硬指标。ADC 分辨率要够,10 位在大多数 HVAC 场景够用,但如果要做 0.1 度级别的精细控制,就得考虑外部 ADC 或者选更高分辨率的型号。通信外设要全,I2C 接传感器、UART 接上位机、最好再留一路 SPI 备用。GPIO 数量要能覆盖继电器驱动、按键、指示灯。PIC18F47Q10 在这些维度上属于"刚好够用且留有余量"的选择,这也是它在同类方案里出镜率高的原因。
2.3 两路温度数据的采样节奏怎么定
本地和远程两路温度的采样节奏不能拍脑袋定。远程通道因为走线长、感温元件有热惯性,响应速度天然比本地慢;本地通道虽然快,但容易受板子自身发热的瞬时波动影响。我的做法是让两路用不同的采样周期,再在软件层做融合。
具体来说,远程通道每 500ms 采一次,连续采 4 次做滑动平均,等效更新率 2 秒一次,这样能压掉走线耦合进来的工频干扰。本地通道每 100ms 采一次,用一阶低通滤波,时间常数设在 1 秒左右,既能跟上真实温度变化,又能滤掉开关电源带来的高频抖动。两路数据在控制逻辑里使用时,各自带一个"数据有效"标志位,任何一路连续多次读取失败就置无效,避免用坏数据去做控制决策。
| 通道 | 采样周期 | 滤波方式 | 等效更新率 | 主要用途 |
|---|---|---|---|---|
| 远程(PJ85718DM) | 500ms | 4 点滑动平均 | 约 2s | 控制目标温度 |
| 本地(MCU 内部/板载) | 100ms | 一阶低通,τ≈1s | 约 1s | 自检与过温保护 |
这张表看着简单,但每一条都是踩过坑之后定下来的。早期我把两路都设成 100ms 采样,结果远程通道因为走线干扰,读数一直在跳,控制逻辑跟着抽风,风机频繁启停。后来把远程采样放慢加平均,问题立刻缓解。
3. 硬件连接与信号完整性:远程通道最容易翻车的地方
3.1 PJ85718DM 的外围电路该怎么搭
远程温度传感器的外围电路不复杂,但细节决定成败。典型接法是这样:芯片的远程通道引脚接一对走线到外部感温元件,走线尽量等长、靠近、成对布线;电源引脚旁边放 100nF 加 1uF 的去耦电容,位置要贴近芯片;数字接口(I2C 的话是 SDA/SCL)各拉一个 4.7k 上拉到主控电源。如果芯片有独立的参考电压引脚,参考源要干净,最好单独走线,不要和数字电源混在一起。
这里有个容易被忽略的点:远程通道的走线如果太长,会引入寄生电容和串联电阻,影响激励电流的建立时间。我的经验是走线超过 30cm 就要考虑加屏蔽或者用双绞线,超过 1 米基本就得在软件里延长建立时间,等信号稳定后再采样。PJ85718DM 这类芯片一般允许配置转换时间,把转换时间调长一点,给寄生参数留出裕量,读数会稳很多。
3.2 本地温度到底用 MCU 内部传感器还是外挂一颗
PIC18F47Q10 内部有温度指示模块,能粗略读出芯片结温,但它的绝对精度一般,适合做"过温保护"这种只需要相对变化的场景,不适合做精确测量。如果你要的本地温度是"板子附近的环境温度",我建议外挂一颗数字温度芯片,通过同一路 I2C 挂在总线上,和 PJ85718DM 共用 SDA/SCL,用不同地址区分。
这样做的代价是多一颗物料和一点布板空间,收益是本地温度有了独立且可校准的测量点。实际项目里我倾向于外挂,因为内部传感器受 MCU 自身功耗影响太大,负载一变读数就飘,做保护阈值判断时很难定一个稳定的门限。
3.3 I2C 总线上挂多颗器件时的地址冲突与速率取舍
PJ85718DM 加一颗本地温度芯片,再加可能的 EEPROM 或者显示驱动,I2C 总线上很容易挂到四五颗器件。地址冲突是第一道坎,选型阶段就要把各器件的地址选项列出来,确保没有重叠。第二道坎是速率:标准模式 100kHz、快速模式 400kHz,挂的器件越多、走线越长,就越要往低速靠。
我的做法是默认跑 100kHz,只有在确认总线电容小、器件都支持的情况下才上 400kHz。原因很实在:HVAC 板子上继电器、风机、压缩机这些负载动作时会产生强干扰,I2C 速率越高越容易被干扰打成误码。100kHz 虽然慢,但配合重试机制,稳定性明显更好。总线电容要控制在 400pF 以内,超了就得减小上拉电阻或者加总线缓冲器。
提示:上拉电阻不是越小越好。阻值太小会增加器件灌电流负担,太大又会让上升沿变缓。4.7k 是 3.3V 系统的常用值,5V 系统可以用 2.2k 到 4.7k,具体要结合总线电容算上升时间。
4. 固件实现:从寄存器配置到温度换算的完整链路
4.1 初始化顺序为什么不能随便调
上电初始化有个固定顺序,调换了就容易出玄学问题。我的顺序是:先配时钟和电源,确保 MCU 和外设供电稳定;再配 GPIO 方向,把 I2C 引脚设成开漏或者复用功能;然后初始化 I2C 外设,设定速率和从机地址;接着给传感器留一段上电稳定时间,通常 10ms 到 50ms,等内部参考建立;最后才开始第一次读取。
这段稳定时间很多人会省掉,结果就是上电后头几次读数全是 0 或者满量程,过一会儿才正常。传感器内部的模拟前端需要时间建立工作点,省这几十毫秒换来的是不可靠的启动行为,不划算。
// 初始化顺序示意(伪代码,具体寄存器名以器件手册为准) void system_init(void) { clock_init(); // 配置系统时钟 gpio_init(); // 配置 I2C 引脚为复用开漏 i2c_init(100000); // I2C 100kHz delay_ms(50); // 等待传感器上电稳定 sensor_config(); // 配置 PJ85718DM 转换时间、通道等 local_sensor_config(); // 配置本地温度芯片 }4.2 读取远程温度的时序与超时处理
读取远程温度不是发一个命令就完事。典型流程是:发起转换命令,等待转换完成(可以轮询状态位,也可以等固定时间),然后读取结果寄存器,最后把原始值换算成温度。每一步都要有超时保护,I2C 操作尤其如此,总线被拉死的情况在现场并不罕见。
我习惯给每个 I2C 操作设一个 10ms 的超时,超时就复位 I2C 外设重新初始化。连续三次失败就把该通道标记为无效,上报故障码,而不是让程序卡死在那里。这个机制在实验室里可能一年都用不上,但在现场能救你一命。
int read_remote_temp(float *out) { uint8_t raw[2]; if (i2c_write(REMOTE_ADDR, CMD_START, 1) != OK) return ERR; delay_ms(convert_time_ms); // 等转换完成 if (i2c_read(REMOTE_ADDR, REG_TEMP, raw, 2) != OK) return ERR; *out = raw_to_celsius(raw); // 换算 return OK; }4.3 原始值到摄氏度的换算与校准偏移
远程温度传感器的原始输出通常是定点数,比如 12 位或 16 位表示,需要按手册给的公式换算。换算本身不难,难的是校准。每颗传感器、每个探头、每块板子都有个体差异,出厂不做校准的话,几度的偏差很常见。
我的校准方法是两点校准:在已知的低温点和高温点各测一次,记录原始值,算出斜率和截距,把这两个系数存到 EEPROM 里,运行时用它们做线性修正。低温点用冰水混合物(0 度附近),高温点用恒温槽或者沸水(注意海拔对沸点的影响)。校准一次之后,同一批板子的偏差能压到 0.5 度以内。
| 校准项 | 方法 | 存储位置 | 修正方式 |
|---|---|---|---|
| 远程通道斜率 | 两点法计算 | EEPROM | 原始值乘斜率 |
| 远程通道截距 | 两点法计算 | EEPROM | 加偏移量 |
| 本地通道偏移 | 单点比对 | EEPROM | 加固定偏移 |
4.4 本地与远程数据的融合与有效性判断
两路数据采回来之后不能直接用,要先做有效性判断。判断依据包括:读数是否在物理合理范围内(比如 -40 到 125 度之外直接判无效)、连续多次读数变化是否超过合理速率(温度不可能一秒跳 20 度)、I2C 通信是否成功。任何一条不满足就置无效标志。
融合逻辑上,控制决策优先用远程温度,因为它是控制目标;本地温度作为约束条件,比如本地超过 85 度就强制降额或者停机,不管远程温度是多少。这种"主控 + 保护"的双层结构,比单纯用一路温度要稳健得多。
5. 抗干扰与现场稳定性:实验室能跑不代表现场能用
5.1 继电器和风机动作时的读数抖动怎么压
HVAC 板子上最大的干扰源就是继电器和风机。继电器吸合瞬间的浪涌、风机换向时的反电动势,都会通过电源和地耦合进模拟前端。表现就是温度读数在负载动作时突然跳几度,然后慢慢恢复。
压制手段分硬件和软件两层。硬件上,继电器线圈两端加续流二极管,触点两端加 RC 吸收,强电和弱电分区布线,模拟地和数字地单点连接。软件上,在检测到继电器动作后的 200ms 内,暂停温度采样或者把这段时间的读数标记为可疑,不参与控制决策。我实测过,加了这两层之后,负载动作引起的读数抖动从 3 到 5 度压到了 0.5 度以内。
5.2 长走线引入的工频干扰与屏蔽处理
远程探头走线一长,50Hz 工频干扰就来了。表现是读数以 50Hz 或者 100Hz 的节奏小幅波动。对付它有两个办法:一是走线用双绞线,让干扰在两根线上共模出现,被差分输入抑制掉;二是软件上让采样周期和工频周期错开,或者用整数个工频周期做平均,把工频整周期抵消掉。
我一般两个都用。双绞线成本增加有限,效果立竿见影;软件平均则是在采样率允许的前提下顺手做的事。如果探头走线必须经过强电区域,那就得考虑屏蔽线,屏蔽层单端接地,接在控制板这一侧。
5.3 上电自检与故障上报机制
现场设备最怕的是"坏了但不说"。温度通道失效如果不上报,控制逻辑可能拿着错误数据一直跑,后果比直接停机更严重。所以上电自检和运行期故障上报必须做。
上电自检包括:I2C 总线扫描,确认传感器在线;读一次传感器 ID 寄存器,确认型号匹配;读一次温度,确认在合理范围。运行期则持续监控通信成功率和读数合理性,连续失败或者读数越界就置故障标志,通过通信接口上报,同时让控制逻辑进入安全模式。
注意:故障上报要有防抖。偶发的一次通信失败不应该立刻报故障,连续多次失败才报,避免误报把维护人员折腾得团团转。
6. 调试与排错实录:几个真实踩过的坑
6.1 读数一直偏高:原来是板子自身发热在作怪
早期调试时发现本地温度总比环境温度高 8 到 10 度,换了传感器也没用。后来用热成像一看,MCU 和电源芯片周围就是热点,传感器离得太近。把本地传感器挪到板边、远离发热源,再在软件里加一个基于负载状态的补偿系数,偏差才降到 2 度以内。这个坑告诉我们:本地温度测的是"传感器所在位置的温度",布板位置比传感器精度更重要。
6.2 I2C 通信偶发失败:上拉电阻和总线电容的账要算清
有一批板子 I2C 通信时好时坏,换芯片、换固件都没用。最后量了总线波形,发现上升沿太缓,原因是走线长、挂的器件多,总线电容超了 400pF,而用的上拉电阻偏大。把上拉从 10k 换成 4.7k,波形立刻变陡,通信稳定。这件事让我养成了一个习惯:每次布完 I2C 总线,都估算一下总线电容,别等出问题再回头查。
6.3 远程通道读数跳变:转换时间设太短的代价
远程通道刚跑起来时读数一直在跳,平均也压不住。查手册发现转换时间设的是最小值,而走线有几十厘米,寄生电容让信号还没建立好就开始采样了。把转换时间调大一档,读数立刻稳了。这个参数很多人不看,默认用最小值,结果就是远程通道永远不稳。
6.4 温度换算结果不对:定点数的符号位陷阱
有一次换算出来的温度在零下时完全不对,零上正常。查了半天发现是原始数据是带符号的定点数,我按无符号处理了,负温度全变成了大正数。处理这类数据一定要先确认符号位和补码格式,别想当然。
| 故障现象 | 根本原因 | 解决手段 |
|---|---|---|
| 本地读数偏高 | 传感器靠近发热源 | 挪位置 + 软件补偿 |
| I2C 偶发失败 | 总线电容超限 | 减小上拉电阻 |
| 远程读数跳变 | 转换时间过短 | 增大转换时间 |
| 负温度换算错误 | 符号位处理错误 | 按补码解析 |
7. 这套方案还能怎么扩展
把本地和远程两路温度跑通之后,扩展方向其实很多。最直接的是增加远程通道数量,PJ85718DM 这类芯片往往支持多路,一颗芯片就能覆盖多个测点,省掉重复的板载传感器。再进一步是把温度数据接入通信总线,做成标准的上报格式,方便接入楼宇自控系统或者云端平台。
另一个方向是做更聪明的控制策略。有了本地和远程两路数据,可以做温差控制、变化率控制、甚至简单的预测控制。比如根据回风温度的变化率提前调整压缩机频率,比等到温度到位再动作要平滑得多。这些策略的前提都是温度数据足够稳、足够准,所以前面讲的采样、滤波、校准、抗干扰,每一步都不能省。
我在实际项目里的体会是:温度监测这套东西,硬件选型占三成,软件处理占三成,剩下四成全在细节——布板、走线、校准、故障处理。把这些细节做扎实,方案才能在现场站得住。