
去年在做一个暖通空调的嵌入式控制单元时碰到了那个经典的老问题既要看主板附近的设备腔内温度又要看风道远端、冷却水管或室外机附近的温度。如果用多个传感器分别采集校准基准不一致、线缆数量跟着翻倍、故障点也多了一大堆如果只用一个传感器测“平均温度”又根本满足不了温差控制的逻辑需求。后来我把方案收敛到 PJ85718DM 这颗双通道数字温度传感器配上 PIC32MX695F512L 做主控一次解决了本地温度与远程温度的同步监测问题顺带把远程上报通道也打通了。这篇文章就是那次落地过程的完整复盘。内容涉及硬件接线、PIC32 下的 I2C 读取、温度标定、HVAC 现场的干扰处理以及最后通过以太网做远程数据上报的思路。如果你想在嵌入式设备里同时监测本机环境和远端探头温度或者正在选 MCU 方案、调温度采样精度这篇应该能给你省不少弯路。1. “本地远程”温度监测到底在测什么1.1 两种温度的来源标题里“本地与远程温度”这几个字在不同项目里的含义差别很大。我这次做的是 HVAC 设备上的温度监测本地温度指的是控制板所在电气腔内温度也就是 PJ85718DM 芯片内部测温点感知到的环境温度远程温度指的则是通过外部感温探头引到风道、回风口、冷水管或室外的温度。PJ85718DM 这颗芯片内部自带一个本地温度传感单元同时还有一个外部测温通道可以接一颗二极管结构的探头到设备远端。也就是说一颗芯片同时输出两个独立的温度值不用再为远程测点单独拉一路传感器电源和信号线。这个特性在 HVAC 控制器里非常实用因为设备的电气腔和风道往往隔着几米线束远程探头只靠两根细线就能把温度数据传回来。1.2 HVAC 为什么需要“看两个点”空调箱或者热泵机组运行的时候要判断是否需要制热、制冷、除湿或旁通靠的是各个测点的温差和变化趋势。比如判断蒸发器是否结霜要对比管道表面温度和空气温度判断过滤器是否堵塞要对比送风温度和回风温度。如果只测设备内部温度风机停转、风道堵塞这类工况根本看不出来。这就是为什么“测两个点”远比“多测几遍一个点”重要。PIC32MX695F512L 作为主控通过 I2C 总线反复读取 PJ85718DM 的两个温度寄存器再把本地温度和远程温度一起放进控制逻辑。硬件上无需增加额外的传感器节点软件上也只需处理一颗芯片的寄存器维护成本低很多。1.3 为什么用 PIC32MX695F512L 这颗芯片选主控的时候其实列过几个候选8 位机、Cortex-M0、还有 PIC32MX695F512L。最终定这颗 32 位 MCU 主要是三个原因。第一它有两组独立的 I2C 外设一颗 PJ85718DM 挂在 I2C1 上另一路 I2C 还可以兼顾 EEPROM 或显示屏互不干扰第二片内 Flash 有 512KBRAM 也不小跑 TCP/IP 协议栈和温度采集任务不会捉襟见肘第三它在工业温度范围内工作稳定HVAC 设备夏天 60°C 的电气腔里用起来不会像消费级芯片那样参数飘得离谱。低功耗和高性能未必能兼得但 PJ85718DM 本身功耗很低整体系统功耗主要取决于 MCU。用 PIC32 做控制可以保证后期扩展逻辑和协议栈时有足够余量。2. PJ85718DM 的通道结构、接线方式与硬件设计注意事项2.1 本地通道和远程通道共同工作PJ85718DM 的本地测温单元在芯片内部靠近芯片表面反映的是 PCB 附近空气温度和板卡自身发热的综合结果。远程测温通道则通过引脚引出连接一个外部探头。探头通常是一只二极管结构的温敏器件温度变化时正向导通压降跟着变化芯片内部通过电流激励和 ADC 采集把这个压降转换还原成温度。我第一次用这种远端二极管探头时还不太放心总怕线长会有衰减。实际测试下来普通两线制探头线长做到 2 米以内完全没问题只要线材屏蔽和供电处理好数据稳定得反而比某些热敏电阻方案更好。远程通道的测温范围比本地通道大不少适合放到 HVAC 风道里测低温回风或高温盘管。2.2 硬件接线的三个关键细节硬件接线这里有一张参考连接表是我在样机上验证过的接法信号PJ85718DM引脚PIC32MX695F512L引脚说明VCCVDD3.3V建议 100nF10µF 去耦GNDGNDGND单点接地SCLSCLI2C1 SCL4.7kΩ 上拉到3.3VSDASDAI2C1 SDA4.7kΩ 上拉到3.3VREMOTED--用双绞线接远端探头正极REMOTE-D---用双绞线接远端探头负极SCL 和 SDA 的上拉电阻一定要接在 MCU 电源侧不能接在传感器电源侧。否则 MCU 已经上电、传感器还没供电时I2C 线上会出现从 MCU 到传感器 VDD 的漏电流路径把传感器半唤醒。这也是很多板子“时而能读、时而读不到”的隐藏原因。远端探头的两根线最好采用双绞线形式并且远离变频器功率线。我在这套样机上试过普通平行线线长 1.5 米时读数偶尔会跳 0.5°C换成双绞线并加上一个 2.2nF 的差分滤波电容后跳变彻底消失。2.3 电气腔与探头的隔离处理HVAC 现场最麻烦的不是传感器的精度而是地电位差。风道里的探头往往和压缩机、风机共地而控制板的信号地又和功率地连在一起。如果控制板地和探头远端地之间存在压差远程通道读数就会莫名其妙偏移。这次设计中我在探头负极与控制板地之间不加直接连接让 PJ85718DM 依靠双线差分方式测量压差从源头避免地环路。如果板子空间允许还可以在 VDD 和 GND 之间加一个共模电感进一步抑制共模干扰对 ADC 的影响。3. PIC32MX695F512L 的软件配置与读取流程3.1 采样周期和主循环的设计温度采集看着简单但 HVAC 控制里不能一味追求“越频繁越好”。本地温度和风道温度都存在热惯性1 秒采一次已经能满足 90% 的控制需求。如果每 10ms 就去读一次 I2C反而会把总线占用满影响其他传感器和对显示屏的刷新。我最终把温度采样放在一个 1Hz 的软件定时中断标志位里。主循环检测到标志位置位后才发起 I2C 读取。读取完成后通过队列发给控制任务。这样温度数据和 PID 周期天然对齐调试时也容易复盘。3.2 I2C 寄存器读写时序与代码示例PJ85718DM 的读取流程通常分两步先写配置寄存器选择要读的通道再从对应的数据寄存器读取 16 位温度原始值。以下代码是实际项目中精简出来的关键函数基本反映了 PIC32MX695F512L 操作 I2C 的套路。#define PJ85718DM_ADDR 0x4C #define REG_LOCAL_TEMP_HI 0x01 #define REG_REMOTE_TEMP_HI 0x02 #define REG_CONFIG 0x09 uint8_t i2c_read_reg(uint8_t addr, uint8_t reg) { uint8_t val 0; // start i2c_start(); // 7-bit地址写位 i2c_send_byte((addr 1) | 0); i2c_send_byte(reg); i2c_restart(); // 7-bit地址读位 i2c_send_byte((addr 1) | 1); val i2c_read_byte(0); // 带NACK i2c_stop(); return val; } uint16_t read_temperature(uint8_t reg_hi) { uint16_t raw; raw ((uint16_t)i2c_read_reg(PJ85718DM_ADDR, reg_hi) 8); raw | i2c_read_reg(PJ85718DM_ADDR, reg_hi 1); return raw; }这里需要提醒一下PIC32 的 I2C 外设在作为主机发送完最后一个字节后必须手动产生 Stop 条件。很多人读回全是 0xFF 就是在 restart 和 stop 顺序上出了问题。另外某些版本的外设库中I2C_ReadByte会自动返回 ACK 状态最后一个字节要改成 NACK 应答否则传感器会认为主机还要继续读下一帧数据就错位了。3.3 温度原始值到工程值的换算PJ85718DM 温度寄存器里的数值通常是 16 位带符号数分辨率可以做到 0.0625°C 或更细。拿到 raw 值后本地和远程通道的换算公式略有不同但基础逻辑都是先判断符号位再乘分辨率。float reg_to_celsius(uint16_t raw, float resolution) { int16_t signed_raw; // 先转换为有符号类型再由编译器做扩展 signed_raw (int16_t)raw; return signed_raw * resolution; }需要注意本地通道的偏移和远程通道的偏移并不一样。PJ85718DM 的数据手册一般会分别给出两个通道的 offset 校准值。如果硬件在远程通道接了不同规格的二极管探头还需要根据二极管型号的 ideality factor理想系数做一次比例修正。HVAC 系统里常见的探头是 2N3904 或同类小信号管它们的系数不完全相同直接用默认值会引入 1°C 到 2°C 的偏差。4. HVAC 现场的标定、误差来源与抗干扰经验4.1 零点与满度标定刚把板子装回样机时远程温度和标准水银温度计差了大约 1.3°C本地通道只差了 0.2°C。排查了一圈发现是远程通道的二极管探头压降偏大导致的不是芯片问题。解决办法是标定。我取 0°C 冰水混合物和 60°C 恒温槽两个点记录远程通道的原始读数然后用线性插值修正。修正系数直接写进设备的校准区每次开机读 EEPROM 加载。这样下来两个通道在 0°C 到 70°C 范围内都能稳定在 ±0.3°C 以内。标定的具体步骤很简单把探头放到已知温度环境中等待 10 分钟让热平衡建立然后读取 PJ85718DM 的原始值。注意不要刚放入就采样传感器自身的热时间常数加上探头外壳的导热延迟至少要等读数稳定两次变化小于 0.05°C 才算有效。这一步如果省了后面所有控制逻辑都会跟着飘。4.2 探头热阻和风道风速对读数的影响HVAC 风道温度测量有一个绕不开的问题风道里的空气流速很高时探头表面不会真正达到空气温度。实测 2m/s 风速下裸露二极管探头与静止空气环境的读数差异能到 0.8°C。这是因为探头自身的对流换热系数有限而热辐射和热传导又把周围管道壁温带进去了。应对策略是在探头外面加一个薄壁金属护套并让护套与空气流有足够接触面积。护套会稍微增大热惯性但换来的是更稳定的读数。控制程序里再对远程温度做一阶低通滤波时间常数设为 5 秒到 10 秒既不会让控制反应迟钝也能过滤掉风机启停时造成的波动。4.3 电源地和信号地的处理我在这套系统里吃过一次大亏主控板、风机驱动和 PJ85718DM 共用同一个开关电源风机启动瞬间远程温度读数会突然从 25°C 跳到 35°C过两秒又回落。用示波器看传感器 VDD 上叠加了接近 200mV 的尖峰远超数据手册允许范围。后来做了三件事才解决。一是 PJ85718DM 的供电通过一颗小功率 LDO 单独供给不再直接接系统 3.3V二是把去耦电容从 100nF 加到 4.7µF并在 D/D- 之间加了一颗 10nF 电容三是把传感器和主控之间的 I2C 线改为 10cm 以内的短走线远离功率电感的辐射路径。处理后风机启停期间的读数抖动降到了 0.1°C 以内。5. 远程上报通道PIC32MX695F512L 的以太网与 Modbus TCP 简化实现5.1 远程温度不只是“探头远程”还要“数据远程”标题里还有一个“远程”是容易被忽略的数据远程上传。PIC32MX695F512L 自带以太网控制器这是它比普通单片机更适合 HVAC 场景的原因之一。现场设备把本地温度和远程温度计算出来后通过以太网打包交给上位机或云网关运维人员不用跑到设备跟前就能看到实时数据。以太网在 HVAC 控制器里最常见的方式是跑 Modbus TCP。相比自定义 UDP 协议Modbus TCP 的优势是通用调试工具多、上位机组态软件直接支持。PIC32 的资源可以支撑一个轻量级的 TCP 服务器每次收到主站的查询请求后把温度寄存器映射到保持寄存器地址即可。5.2 数据帧组装与状态机Modbus TCP 的报文结构并不复杂。我实现时只保留了读保持寄存器这个功能码足够覆盖温度上报场景。核心是把 PJ85718DM 获取的温度值换算成 0.01°C 单位的有符号数再放到响应缓冲区里。uint16_t temp_fixed (uint16_t)(celsius * 100 0.5f); // 构造响应帧 resp_frame[0] transaction_id_hi; resp_frame[1] transaction_id_lo; resp_frame[2] 0x00; resp_frame[3] 0x00; resp_frame[4] 0x00; resp_frame[5] 0x06; // 后续字节数 resp_frame[6] slave_id; resp_frame[7] 0x03; // 功能码 resp_frame[8] 0x02; // 2个保持寄存器 resp_frame[9] (uint8_t)(temp_fixed 8); resp_frame[10] (uint8_t)(temp_fixed 0xFF); // 第二个寄存器类似...状态机分成监听、接收、解析、响应四个状态。PIC32 的 TCP 处理如果放在主循环里一定要控制单次处理时间否则长时间 PING 没人管连接会假死。我把每个 TCP Socket 都设了 60 秒超时回收机制防止异常断连占住连接池。5.3 断线重连与掉电保持HVAC 现场的网络没想象中那么可靠。交换机重启、网线被老鼠咬断、维护人员误拔网线这些都可能让连接断掉。我做了两个保险一是 TCP 服务器端把被动连接改成主动重连加被动监听并存二是在检测到连接断开后把最近 30 分钟的温度历史存进片内 Flash 的一小块区域恢复连接后再补传。掉电保持这块要特别小心 Flash 擦写次数。温度数据每秒一组几分钟就能把扇区写穿。所以实际实现是每 5 分钟写入一次并且用双缓冲区交替写写坏一个还能从另一个恢复。对于 HVAC 设备的运维5 分钟粒度足够判断设备是否异常。6. 实际调试中遇到的三个典型问题与排查链路6.1 远程温度在 100°C 附近乱跳最后查出来是接线端子样机装好后远程通道读数偶尔会直接跳到 100°C 以上持续一两秒又恢复正常。一开始怀疑是传感器损坏换了一颗新的还是同样现象。后来用示波器测 D 和 D- 两脚的电压发现探头的连接端子稍微一晃动差分电压就出现瞬间中断。PJ85718DM 对远程通道的故障检测开关被触发把故障值当作测温结果输出。排查链路是先排除软件配置错误再用示波器观察引脚波形最后把接线端子压接处重新冷压并固定线缆问题消失。教训是远程探头线缆尽量使用焊接或专用压接头不要让裸露铜线在端子排里悬空。6.2 I2C 总线读回全是 0xFFSCL 被某个设备拉低另一块实验板在上电后PIC32 读 PJ85718DM 的寄存器全部返回 0xFF。这通常是 I2C 总线 ACK 异常。我用逻辑分析仪看总线SCL 和 SDA 的波形在地址阶段还有活动但器件没有返回 ACK。逐个排查时发现总线上的另一个外设EEPROM地址和 PJ85718DM 存在冲突。把 PJ85718DM 的地址线跳线从高电平改到低电平后总线恢复正常。如果你遇到的不是地址冲突还有可能是 SDA 上拉电阻太小导致低电平无法被拉低通信时读到的全为 1。I2C 总线上的每个器件都要有唯一地址这条规则在原型阶段最容易忽略。6.3 变频器干扰导致周期性跳变样机最终测试时系统旁边多了一台变频器。只要变频器启动PJ85718DM 的本地温度读数每隔 200ms 左右就有一次 0.3°C 的跳变。用示波器抓 VDD 波形能看到明显的周期性纹波频率正好是变频器载波频率。解决方式除了前面提到的独立 LDO 和去耦电容软件上也做了一个中值滤波每次取连续 5 个采样值去掉最大值和最小值取中间 3 个的平均作为最终温度。这个办法对周期性干扰很有效而且不牺牲温度控制的响应速度。中值滤波窗口不能太大否则会滤掉真实温度变化5 点窗口在 HVAC 场景里已经够用。如果未来再扩展这套系统我会把 PJ85718DM 的远程通道接到冷却水进出口两端通过温差判断换热器效率。本地温度则继续作为机柜过温保护输入。两个通道的数据各自独立主控里的控制逻辑却能同时使用它们这才是“监测本地与远程温度”最舒服的落地方式。到那时候也会先把变送器输出端加上一级 RC 滤波让现场调试不用再靠运气解决问题。