嵌入式HVAC双通道温度采集:PJ85718DM+PIC18F86J55
发布时间:2026/10/22 12:11:48 锦皓数字建站

搞过嵌入式温控的人应该都有这种经历单体测试的时候一切正常把板子装进柜子、接好风管之后温度读数就开始和你做对。柜内 PCB 附近明明已经热得烫手面板上显示却还是 25℃ 上下送风口实际温度逼近 45℃控制器还在那儿慢悠悠地跑。问题就出在只测了一个点而且很多时候测的还是芯片自己周围那点空气。这个项目要解决的正是这件事用 PJ85718DM 这颗数字温度传感器做本地温度采集再配合 PIC18F86J55 单片机完成远程温度通道的读取、换算、滤波和上报在嵌入式系统里同时拿到“电路板附近温度”和“远端被测点温度”两个关键数值。对 HVAC 应用来说这两个温度分别对应设备安全和环境控制质量——本地温度决定散热风扇要不要提速远程温度决定加热或制冷设备该投入多少功率。这篇文章会把这套方案从头拆到尾硬件上怎么接、固件里怎么读、实测中哪些坑最容易踩、以及我后来在产线上调整过的校准方法。适合正在做温控器、风机盘管、风管温度监测、或任何“既要管自己别烤坏、又要管远端环境”的嵌入式开发者参考。硬件和固件都有一点基础的读者可以完整复现纯小白也能跟着理解每一步在干什么。1. HVAC 温控场景里为什么必须同时盯住“本地”和“远程”两个温度先别急着看芯片把需求理清楚。很多人以为“测温度”就是找一颗传感器往板子上一贴、读出数字就完事到 HVAC 现场就会碰壁。因为 HVAC 系统里的温度不是一个点而是好几个性质完全不同的点。1.1 本地温度和远程温度在物理上根本不是一回事本地温度指的是传感器所在 PCB 附近的温度。它由这几个因素共同决定板子上功率器件MOSFET、LDO、IGBT的发热、散热风扇形成的局部气流、机柜外壳的辐射和热传导。它本质上反映的是“设备自身热不热”和用户体验的环境温度没有直接关系。远程温度指的是离主控板几厘米到几十米之外的那个被测点的温度比如风管里的送风温度、房间回风口温度、水管表面温度、室外机进风温度。这个量和主控板之间隔着导线、接插件、甚至隔着一段总线信号的干扰、压降、接触电阻都会叠加上去。这两者的物理特性差异很大。本地温度热惯性小紧贴热源时响应很快适合做保护逻辑远程温度热惯性大但它是环境控制的真正依据。如果只拿到其中一个控制策略就会缺一条腿只测本地远端烧到 60℃ 你都不知道只测远程板子已经过温了还傻乎乎全速制热。1.2 典型场景拆解机柜、风管、风机盘管我在实际项目里遇到过几类典型需求大家可以对照自己的场景。第一类是大功率设备柜。柜里变频器、开关电源、控制板叠在一起本地温度必须实时监测用来调速散热风扇或触发降额远程温度测的是柜子进风口或出风口的空气温度用来判断柜内整体散热是否有效。这类系统最怕“局部热点”和“整体换热失效”同时发生两个温度点缺一个都不好排查。第二类是风机盘管和中央空调末端。控制板常常藏在吊顶里的接线盒中本地温度用来防止控制板烧损远程温度探头伸到回风口或者送风管内用于决定风机转速和冷热水阀开度。这时候远程探头的线可能要走一两米穿过金属风管、强电线路对传感器接口的抗干扰能力要求很高。第三类是空气处理机组AHU里的多点监测。除了机房本地的控制器温度还要采集新风温度、混合段温度、表冷器盘管温度。盘管温度经常用二极管或热敏电阻远距离测量距离长、环境恶劣正好是这套本地远程方案的用武之地。这些场景的共同点是什么测温点分散、距离不一、环境电磁噪声高、温度范围宽。用一个方案把它们都覆盖掉比给每个点单独设计一套电路要省事得多。1.3 整体框架数据是怎么从传感器流到上位机的本项目的系统框架可以用一条数据流说清楚本地温度由 PJ85718DM 的数字传感器部分直接测量得到的是一个数字量通过 I2C 总线传给 PIC18F86J55 单片机。远程温度则有两条路线一条是 PJ85718DM 的远程二极管通道专门接一颗远端的三极管传感器用 ΔVbe 方法算出远端温度另一条是 PIC18F86J55 的 ADC 通道接 NTC 热敏电阻作为备份或扩展。所有数据在单片机里完成滤波、校准、阈值判断之后通过 UART 或 USB 上报给上位机、触摸屏或楼宇控制系统。PJ85718DM 在链路里的角色是“把温度翻译成数字”的感知层PIC18F86J55 的角色是“搬运、计算、对外通信”的处理层。感知层贴近被测对象处理层贴近人机接口两者各干各的活职责很清晰。2. 器件分工与选型逻辑PJ85718DM 感知温度PIC18F86J55 处理数据选型这件事我向来主张先想清楚“谁干什么”再去看数据手册选具体型号。这两颗芯片的分工恰好是一个很典型的感知/处理分离架构。2.1 PJ85718DM把温度翻译成数字量的传感器PJ85718DM 在我的项目里是温度采集的核心。它属于数字温度传感器这一类器件和常见的 I2C/SMBus 接口温度传感器是同一路数片内集成测温前端对外提供数字寄存器接口不需要信号调理电路读数直接就是温度值。它最实用的地方是同时支持本地和远程两条测温链路。本地链路测的是芯片自身的结温精度通常在 ±1℃ 左右响应很快远程链路则通过一个专用输入引脚接远端二极管或三极管利用 ΔVbe 原理测远端结温这个通道的精度和本地差不多测量范围也覆盖了 HVAC 需要的 -40℃ 到 125℃ 区间。接口方面它走 I2C 兼容总线有两线通信、多器件挂载、地址引脚可配这些常规能力。配置寄存器里可以设测量分辨率、转换模式连续转换或单次触发、报警阈值和故障队列。对 HVAC 这种长期无人值守的场合单次触发模式特别有用平时让器件休眠需要读数时再唤醒功耗和自热都能压下来。我习惯把 PJ85718DM 的度数看成 12 位来看待最低位对应的温度分辨率在 0.0625℃ 左右这个精度对空调和风机控制来说完全够用甚至有点富裕。要注意的是不同批次和不同封装的器件绝对精度会有细微差别所以量产前最好做一次批量校准而不能只信数据手册。2.2 PIC18F86J55负责搬运、计算和通信的中枢PIC18F86J55 是 8 位 MCU 里性能比较靠前的一档选它不是因为跑得快而是因为它的外围资源刚好覆盖这套系统的所有需求。首先是通信接口。PIC18F86J55 内置了 I2C 外设可以直接和 PJ85718DM 对接不需要软件模拟总线同时带 UART 和 USB 功能既能通过串口连调试工具也能接 USB 转串口做上位机通信。HVAC 项目里上位机协议五花八门有的用 Modbus有的用自定义帧但这些都建立在可靠的串口物理层上MCU 的 UART 够稳比什么都重要。其次是模拟通道。PIC18F86J55 带 ADC可以读 NTC 热敏电阻或者 4-20mA 变送器的电压信号这在现场扩展传感器数量时很关键。我接 NTC 做备份测温点没有占用 PJ85718DM 的远程通道相当于给自己留了余量。资源容量上这一级别的 MCU 的 Flash 足够装下温度换算、滤波算法、协议解析和几组报警逻辑不会出现写一半没空间的窘况。更重要的是它支持宽工作电压和较宽的温度范围这在柜内高温环境里是硬指标。很多低成本 MCU 在 70℃ 就开始性能飘移做 HVAC 控制器必须留足温度裕量。2.3 为什么是“两颗芯片”而不是用一颗全包有人会问不少 MCU 内部自带温度传感器为什么还要外挂一颗 PJ85718DM我也这么想过后来被现实教育了。MCU 内部温度传感器的主要问题是“测不准也测不巧”。它测的是芯片自己的结温和 PCB 表面温度、空气温度都有偏差而且出厂不校准个体差异可能到 ±5℃更重要的是芯片的发热会自我污染读数负载一重温度就虚高。用它做“芯片有没有烧掉”的粗略判断还可以做 HVAC 控制就太粗糙了。PJ85718DM 是独立的数字传感器放在 PCB 上离热源较远的位置或者通过连线放到机箱内壁能测到真正需要关注的那个温度点。它的误差来源可控可以做产线校准还能通过远程二极管通道把测量点延伸到风管里去。感知和处理分离意味着传感器可以放到你想测的地方MCU 可以放到方便走线和接插的地方板上布局的灵活性一下就大了。3. 硬件连接细节供电、I2C 链路和远程传感器的走线这一节直接给可以照抄的硬件方案。画原理图之前先啰嗦一句温度传感器是模拟量链路绕不开“电源干净、走线合理、共地可靠”这三个基本功。数字接口再方便电源和地没弄好读出来的数据照样是废的。3.1 供电与去耦先把电源搞干净PJ85718DM 和 PIC18F86J55 我用同一个 3.3V 电源轨供电这是最省事的做法两个器件都兼容。但“同一个轨”不等于“直接并在一起”电源纹波会通过地弹和耦合影响 ADC 和温度读数。我的做法是两级去耦在电源入口放一个 1µF 的陶瓷电容做低频储能在每个器件电源引脚旁边再放一个 0.1µF 的电容做高频去耦电容尽量贴近器件引脚。PIC18F86J55 的 ADC 参考电压脚如果单独引出我会在参考电压引脚处额外放一个 0.1µF 电容并且用一根独立的走线从电源源头引过来不走大电流路径。温度传感器对电源纹波的敏感度超出很多人想象数字输出的器件也一样内部模拟前端对参考电源的干净程度有要求。供电顺序上有个小细节PJC85718DM 的上电时序只要满足“先有电源、再通信”就行没有 MCU 那么讲究但如果电源和 I2C 上拉接的是不同电压轨就需要检查上拉电阻接在哪一侧避免传感器通过 I2C 引脚反向供电。3.2 I2C 链路的搭建上拉电阻、地址和时序PJ85718DM 通过 I2C 和 PIC18F86J55 通信硬件连接大概是这个样子信号传感器端MCU 端说明SDAPJ85718DM SDAPIC18F86J55 的 I2C SDA 引脚双向数据线SCLPJ85718DM SCLPIC18F86J55 的 I2C SCL 引脚时钟线地址线A0/A1接 GND 或 VDD配置从机地址电源VDD3.3V器件供电地GNDGND单点共地SDA 和 SCL 必须各自接一个上拉电阻阻值我常用 4.7kΩ总线长度不长、通信速率 100kHz 时很稳如果升到 400kHz可以换成 2.2kΩ。总线电容大、走线长的情况下上拉电阻太小会拉不出低电平太大会导致上升沿变缓具体取值最好用示波器看一眼边沿。PIC18F86J55 的硬件 I2C 外设初始化为主机模式后软件上只需要几个函数启动、发送地址、读字节、发 ACK/NACK、停止。这里强调一个经验第一次通信前给传感器一个稳定的延时上电复位时间不要 MCU 刚复位就立刻访问 I2C 总线否则传感器还没准备好通信就会失败一次。这只是个小问题但会导致开机第一帧数据异常。3.3 远程传感器接法用三极管而不是“温度探头”远程温度通道是这套方案里最需要认真对待的部分。PJ85718DM 的远程测温原理是向外部半导体结注入特定电流测量结压降随温度的变化。实际工程里最合适的传感元件是一颗小信号三极管比如 MMBT3904把集电极和基极短接发射极接传感器等效成一个二极管。为什么要用三极管而不是普通二极管因为三极管的 Vbe 曲线在宽温度范围内更接近理想方程远程测温芯片的设计基准通常就是针对这类三极管校准的。如果换成普通整流二极管温度偏差可能到好几度。接法上我总结过三个要点。第一远端三极管和传感器之间用双绞线连接尽量用屏蔽线且屏蔽层单端接地第二走线长度控制在 1 米以内做高精度测量超过 2 米就要考虑在固件里做线阻补偿第三双绞线不要和 220V 强电或 PWM 驱动线平行走至少拉开 5cm 以上否则高频噪声会被测温前端捕捉读数抖动。我踩过的最大坑是接插件接触电阻。远端探头如果做成可插拔结构端子氧化或者接触不到位等效于在测温结上串了一个几十欧姆的电阻会让读数整体偏高。这个问题在后面的实测记录里还会详细说。3.4 可选扩展NTC ADC 通道的做法PJ85718DM 的远程通道用掉之后如果还想加测温点PIC18F86J55 自带的 ADC 就可以接 NTC。我用 10kΩ 的 NTC 热敏电阻B 值 3435 或者 3950 的都行接法很简单NTC 一端接 GND另一端接 ADC 引脚同时 ADC 引脚通过一个 10kΩ 精密电阻接到 3.3V形成一个分压器。ADC 引脚处加一个 100nF 电容滤掉高频噪声采样时再在固件里做多次采样取平均。NTC 的绝对精度不如三极管远程测温但胜在便宜、采购容易、走线不做严格屏蔽也能用非常适合做“大概知道温度就行”的辅助测点。如果你只需要一个远程点更推荐直接走 PJ85718DM 的远程二极管通道。4. 固件流程从读取寄存器到输出稳定温度值硬件焊好只是开始真正的功夫在固件。这一节把初始化、读取、换算、滤波、校准和上报完整过一遍代码是面向 PIC18F86J55 写 C 的风格直接套你自己的工程骨架就行。4.1 初始化顺序外设先起传感器最后碰固件初始化的顺序我排得比较死顺序错了会吃到莫名其妙的 bug。第一步是配置 PIC18F86J55 的时钟、引脚复用和 I2C 外设把 I2C 波特率设在 100kHz第二步延时 50ms 左右等电源稳定第三步配置串口方便随时打调试日志第四步才去读取 PJ85718DM 的器件 ID 或者状态寄存器确认传感器已经进入正常状态。初始化传感器时把配置寄存器设置为单次转换模式分辨率设 12 位然后触发一次转换读取结果。确认通信正常后再进入正式的循环逻辑。这种“先探测、再使用”的方式比上来就盲目读数据要稳妥得多。void sensor_init(void) { I2C_Init(100000); // 100kHz 主机模式 delay_ms(50); // 等电源和总线稳定 uint8_t cfg 0x00; sensor_write(REG_CONFIG, cfg); // 连续转换、12位分辨率 delay_ms(5); sensor_read(REG_CONFIG, cfg, 1); if ((cfg 0x80) 0) { // 配置写不进去先查上拉和地址 } }4.2 读取与换算从原始寄存器到真实温度PJ85718DM 的温度数据存在两个寄存器里高位和低位。读取方法是先发寄存器地址再连续读两个字节。需要注意符号位因为温度可能是负的12 位数据读出来要自己做符号扩展否则 -5℃ 会变成 4075℃ 这种荒唐值。int16_t read_temperature(void) { uint8_t buf[2]; sensor_read(REG_TEMP_MSB, buf, 2); int16_t raw (buf[0] 8) | buf[1]; int16_t adc12 raw 4; // 低4位是扩展位丢弃 if (adc12 0x0800) { adc12 | 0xF000; // 12位转16位有符号数 } return adc12; // 单位为 0.0625℃ } float temp_c read_temperature() * 0.0625f;远程通道的读取流程类似只是寄存器地址不同。要么直接读远程温度寄存器要么通过状态寄存器先确认远程转换完成再读避免读到上一次的数据。连续转换模式下最稳妥的做法是读两次取第二次的结果因为第一次可能正好在转换边界上高低字节跨了两次采样。NTC 通道的换算我用 B 参数公式ADC 取 12 位模式float read_ntc_temp(uint16_t adc, float r_fixed, float b_value) { if (adc 0) return -40.0f; if (adc 4095) return 125.0f; float ratio (float)adc / (4096.0f - (float)adc); // Rntc Ratio * Rfixed float r_ntc r_fixed * ratio; // 25℃ 参考温度 298.15KR25 10k float t_k 1.0f / (1.0f / 298.15f 1.0f / b_value * logf(r_ntc / 10000.0f)); return t_k - 273.15f; }注意这个公式只在 NTC 接地、固定电阻接电源的接法下成立。如果反过来公式里的 ratio 要取倒数这个错误我见过不止一次。4.3 滤波、去尖峰和校准让数据不再乱跳原始温度数据直接上报波形会很难看。HVAC 现场有风机启停、压缩机切换、变频器辐射这些干扰会在温度数据上叠加尖峰。我最常用的组合是“中值滤波 滑动平均”两层中值滤波去掉明显跳变的异常点滑动平均把剩余的高频抖动抹平。具体来说连续采集 5 个样本取中值作为一次有效采样再用最近 8 次有效采样做滑动平均输出。这个组合的延迟很小响应速度仍然够控制使用。PWM 控制的变频风扇产生的 EMI 尖峰很厉害单靠一层 8 次平均会把尖峰“拉宽”变成持续好几秒的偏置中值滤波能更干净地剔除。校准是 HVAC 项目最容易忽略的一步。我采用两点校准用恒温槽或者用一个已经校准过的参考温度计在 0℃ 和 50℃ 各记录一组实际读数和期望读数然后算偏移和斜率校正温度 (实测温度 - 校准点1实测) × (点2期望 - 点1期望) / (点2实测 - 点1实测) 点1期望这个公式对 PJ85718DM 和 NTC 都适用。只要把这两个系数存在 PIC18F86J55 的 Flash 里量产时每台设备校准一次整批设备的温度一致性就能从 ±3℃ 收敛到 ±1℃ 以内。4.4 上报协议简单、带校验、别偷懒和上位机的通信我用 UART 115200 波特率8 数据位、无校验、1 停止位。协议格式没有用字符串 CSV因为字符串解析在 MCU 上太浪费。我定义了一个极简二进制帧字节内容说明00xAA帧头10x55帧头2长度数据区长度3数据区本地温度、远程温度、NTC 温度、状态位末位校验和前面所有字节累加取低 8 位MCU 每 100ms 发一帧上位机缺帧也不怕因为下一帧马上就到。校验和虽然简单但能挡住绝大多数单字节错误。UART 的发送我放在定时中断的服务函数里主循环只负责更新数据缓存避免长时间关中断导致传感器读取被卡住。温度数据先乘以 100 存成整数再打包省掉浮点传输的各种麻烦。5. 实测数据与踩坑记录最容易翻车的六个细节方案跑起来之后真正的考验才开始。下面六条是我在这个项目和其他同类项目里真实踩过的每一条都有明确的排查路径和解决办法。5.1 远程读数整体偏高 0.8℃根源是走线电阻第一个版本焊完远程通道读出来比实际温度稳定高 0.8℃ 左右。不是偶发是每次都高。我一度怀疑是传感器芯片的问题换了三颗样片都一样。后来查了远程测温原理才发现测温芯片向远端三极管注入恒定电流测量的是“芯片引脚到三极管结”这一整条回路的压降。双绞线本身有电阻接触端子和 PCB 走线也有电阻这些电阻上的压降叠进了测温结的压降里表现出来就是温度偏高。线越长、越细偏高越明显。解决办法有两个一是设计阶段就把走线做短做粗二是让 sensor 工作在更低的注入电流档位。如果必须在固件里补偿我建议按实际线阻做一次单点校正在 25℃ 恒温下记录偏差然后做一个线性修正系数。千万不要直接用“减 0.8℃”这种死值因为误差不是恒定不变的。5.2 I2C 总线偶尔锁死加超时恢复运行几天后出现了偶发的“数据卡住”现象表现在本地温度长时间不变重启后恢复。排查到最后是 I2C 总线被某个异常时序挂住了——SDA 被拉低时钟不再翻转主设备一直在等一个永远不会来的响应。恢复手段是在 MCU 里实现一个 I2C 超时检测每次启动传输前先检查 SDA 是否异常为低如果是就把 I2C 引脚切换成 GPIO 模式手动翻转 SCL 9 个周期让挂在总线上的从设备恢复空闲状态再切回硬件 I2C 模式。这个“9 个时钟脉冲”的恢复技巧是从 I2C 规范里来的几乎所有从设备都会在 9 个时钟后释放总线。加上这个逻辑之后再没出现过长期锁死。5.3 开机第一帧读到“异常值”是未就绪读取设备上电后的第一帧数据出现过 -40℃ 和 85℃ 这种极端值但第二帧开始就正常了。初看像是传感器坏了实际是 MCU 复位速度比传感器快传感器还没有完成第一次转换MCU 就去读寄存器读到的要么是全 0 要么是全 1换算出来自然离谱。解决方法是读数据前先检查状态寄存器里的“转换完成”位或者强制等待一个转换周期再加上第一节里说的初始化延时。对 HVAC 设备来说上电多等 100ms 完全无所谓但这一百多毫秒能省掉很多误报。5.4 本地温度读数反复横跳被开关电源污染本地温度在 ±2℃ 范围内来回抖持续不断。用示波器查看 PJ85718DM 的电源引脚发现纹波有 80mV 左右来自板上的 DC-DC 开关电源开关频率正好落在测温前端的采样时间段里。整改方案就是 3.1 节说的两级去耦。我把 0.1µF 电容挪到传感器电源引脚 3mm 以内再把传感器供电改成一截窄走线从主电容处引出起到一点电源滤波的作用。纹波降到 20mV 以下后读数稳定在 ±0.3℃ 以内。数字传感器不代表不怕电源噪声参考模拟前端的敏感度来对待它才是正确心态。5.5 远端插座氧化导致读数“断崖式跳变”有一台设备用了可插拔的远端探头运行三个月后开始出现间歇性读数突跳——从正常温度瞬间跳到 70℃ 以上过几秒又自己恢复。我用万用表量端子接触电阻发现从最初的 10mΩ 涨到了 1Ω 以上镀层已经氧化。这个问题的工程意义是远程测温接口必须用镀金触点或者直接使探头焊接连线不走接插件。如果结构上必须可插拔至少要在固件里加“变化率限制”相邻两次温度跳变超过 5℃ 就判定为异常改用上次有效值并在状态位里标记探头故障。这样即使接触不良系统也不会做出疯狂的风机调速动作。5.6 一次典型的双通道对照结果把以上问题都处理完以后我做了 24 小时连续记录取值对比是这样数据项参考温度计PJ85718DM 本地通道远程二极管通道NTC 通道均值25.1℃25.3℃25.2℃25.6℃最大偏差/0.3℃0.4℃0.9℃波动范围±0.1℃±0.3℃±0.4℃±0.8℃本地和远程通道都能做到 ±0.5℃ 以内NTC 备用通道因为传感器本身的精度限制稍差一些但做辅助判断够用。这个结果对大多数 HVAC 控制场景来说已经相当宽裕了。最后再分享一个我自己的习惯所有温度传感器不管带不带数字接口第一版 PCB 出来之后都不要直接信任出厂标定。先找一个稳定的温度源做一次全量校准把校准系数固化在设备里再放出去跑。传感器是模拟器件批量之间一定有偏差这一步省掉后续售后调温问题会成倍增加。基于这套方案做产品我的体会是硬件上把走线和电源处理好固件里把滤波和超时做扎实温度监测就不会再是系统中让你夜里被叫醒的那部分。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。