首页 / 资讯中心 / 文章详情

HVAC双通道温度监测:基于PIC18F65K40与PJ85718DM的实践

HVAC双通道温度监测:基于PIC18F65K40与PJ85718DM的实践 ★ FEATURED ARTICLE
嵌入式项目里凡是涉及“本地温度”和“远程温度”同时监测的八成都是 HVAC 控制器、机房设备或工业整机这类场景。最近做的一个温控器项目我用 PIC18F65K40 做整机主控传感器方面选了一颗 PJ85718DM 本地/远程双通道温度芯片两路温度都通过 I2C 上报主控只负责显示、风机和告警联动。跟传统 NTC 方案比这套组合最直观的价值是一个芯片同时量“自己身上的温度”和“贴在远处目标上的二极管温度”信号走数字总线不用每个探头单独做调理和校准。下面从选型思路、硬件接法、固件流程到现场调试按我实际做的顺序展开适合做 HVAC 温控器、嵌入式整机热管理和远程温度监测的朋友参考。1. 项目定位与方案选型思路1.1 本地与远程温度到底测的是什么很多第一次接触温度采集的朋友会卡在一个概念上本地温度和远程温度到底分别指什么。简单说本地温度指的是传感器芯片自己所在位置的温度通常就是 PCB 板面或传感器邻近空气的环境温度远程温度则是指传感器芯片通过外部接口隔着一段线缆去测量的目标点温度。在 HVAC 场景里本地温度可以放在控制器的回风口、风道内或者面板附近远程温度则经常用来测压缩机壳体、冷凝器盘管、电机绕组或者散热器表面。嵌入式整机里本地温度通常代表主控板板温远程温度则延伸到功率管、接口芯片、电源模块这类发热核心旁边。远程通道的物理原理值得多说两句它并不是在远端放另一个完整的传感器芯片而是放一个普通的小信号三极管把基极和集电极短接后当作一个二极管来用。PJ85718DM 内部给这个外接 PN 结提供恒定电流激励通过测量正向压降随温度的变化来反推温度值。硅二极管正向压降大约按 -2mV/°C 变化温度越高压降越低差值经过芯片内部高精度 ADC 处理后就能得到远端温度读数。因为这个原理只需要两根线远程探头的体积可以做得很小贴装也方便。这类双通道芯片对项目最大的吸引力在于你不需要为每个测温点单独设计信号调理电路。如果按传统做法一个 NTC 热敏电阻就要配一个分压电阻网络、一路 ADC、一组查表校准数据探头多了之后不仅布板面积大长线传输时还容易引入压降误差和噪声。而本地加远程两路测温合成在一个芯片里统一走数字总线输出现场维护和量产一致性都会好很多。1.2 为什么是 PJ85718DM 而不是一堆 NTC选 PJ85718DM 而不是直接堆 NTC我当时的判断有几个。第一是精度和一致性像这类带数字输出的集成传感器出厂前已经做过校正本地通道精度能做到 ±1°C 到 ±2°C 的水平远程通道在正确校准后也差不多在这个范围而 NTC 的离散性和 B 值偏差会导致每台机器都需要单独校准产线压力很大。第二是接口简单PJ85718DM 走 I2C/SMBus 协议一片主控板上可以挂多个同型号芯片地址引脚拨一拨就能区分总线电容允许范围内随便扩展。第三是抗干扰能力和布板友好度。远程通道只有差分正负两根走线双绞或者屏蔽处理一下拉个两三米问题不大如果换成模拟热敏电阻长距离传输线缆电阻、接头接触电阻、电源地噪声全都会叠加进测量结果现场排查起来非常头疼。当然NTC 的优势是成本低一个探头可能只要几毛钱所以在只测一个点、精度要求不高、距离又近的情况下用 NTC 完全合理。但凡是遇到“既要测板卡自身、又要测远端关键器件”这类双点需求集成温度传感芯片的综合成本反而更低因为它省掉了 MCU 的 ADC 资源、校准工时和故障率。还有一点不能忽略就是远程通道用的是外接二极管 PN 结普通三极管比如 2N3904、2N3906 很容易买到探头成本很低而且不同批次一致性比取一个具体温度传感器做探针好管控。整个项目最终保留一路 NTC 通道作为冗余备份是从“数字为主、模拟兜底”的稳妥思路出发的这也是我在实际项目里的常用做法。1.3 PIC18F65K40 在这套方案里的角色PIC18F65K40 是一颗 8 位中高端单片机在这个项目里它承担的角色不是“只读温度”而是整个温控器的大脑。它要管显示、按键、风机 PWM、继电器动作、上下位机通信还要通过 I2C 定期从 PJ85718DM 采集温度。选它首先因为内部资源够用64KB 程序存储、4KB 左右的数据存储器还有自带 EEPROM固件做到中等规模不需要额外挂存储芯片。其次它的外设集成度比较高多个 MSSP 模块可以同时跑 I2C 和 SPI多个 EUSART 也能满足后续加 RS485 或无线模块的扩展需求。更关键的是它的核心独立外设比如可配置逻辑单元 CLC、数控振荡器 NCO、波形发生器 CWG 这些模块可以在不占用 CPU 的情况下生成风机调速所需的基础波形或者把几个保护信号用硬件逻辑直接组合。这样一来温度采集、PID 控制、故障封锁这些任务在代码层面就不会挤在一起实时性反而更容易保证。对 HVAC 这类“采样周期几百毫秒、控制动作不需要纳秒级响应”的应用来说这颗 MCU 的算力绰绰有余功耗和成本也能压得住。我特意没有选更高端的 32 位平台不是因为它不好而是杀鸡不用牛刀。8 位 MCU 的寄存器直接操作方式在这种固定功能的小系统里更直观开发环境稳定量产多年后的供货风险也相对可控。如果后续项目要接触摸屏、跑复杂协议栈再往上升级也不冲突因为 I2C 总线和传感器型号完全可以沿用主控换掉就行。2. 硬件电路与引脚分配从样板到能跑2.1 主控最小系统与 I2C 引脚怎么安排PIC18F65K40 的最小系统没什么花哨重点是把电源、去耦、复位和时钟这几件事做扎实。供电我用的是 3.3V主控和传感器统一供电省去电平转换。电源入口放一个 10uF 钽电容加一个 0.1uF 陶瓷电容并联两个电容尽量靠近 MCU 电源引脚数字电路去耦的法则是大电容负责储能小电容负责滤高频两者配合才能把电源纹波压住。复位脚做简单处理10k 电阻上拉到电源同时并在一个 0.1uF 电容到地防止现场干扰误复位。I2C 引脚分配比较简单把 MSSP 模块对应的 SCL 和 SDA 两脚接出来各对地接 47pF 左右的滤波电容再各接一个上拉电阻到 3.3V。上拉阻值的选择和总线频率、挂载设备数有关100kHz 工况下用 4.7k 比较稳。如果以后要跑 400kHz 或挂的从机变多总线电容会上升需要把上拉电阻降到 2.2k 甚至 1k但这个也不是越小越好太小的上拉会让信号边沿太陡产生振铃反而影响可靠性。外部显示模块、按键、继电器控制引脚按照主控的端口复用表挑不冲突的引脚分配即可注意把模拟功能引脚留给可能用到的 ADC 通道。2.2 PJ85718DM 的外围电路和远端探针接法PJ85718DM 的外围电路非常精简电源脚和地之间放一个 0.1uF 电容尽量贴近芯片。地址脚 A0、A1 直接接 GND对应的从机地址就是 0x48也就是二进制 1001000 开头那一段。SDA、SCL 和主控挂在同一条 I2C 总线上上拉电阻共用即可。对于这颗芯片比较需要花心思的是远程探头那两脚 D 和 D-。远端三极管按“基极和集电极短接作为 D 端发射极作为 D- 端”来接极性反了的话读数会偏差很大甚至直接报错这一点在产线装配时要特别强调。远程探头走线建议使用双绞线或者带屏蔽层的两芯线屏蔽层单端接地。为了滤除高频干扰可以在主控板侧的 D 和 D- 之间并联一个 100pF 到 1nF 的电容具体容值以数据手册给出的最大允许值为准太大会让远端二极管激励电流建立过程变慢导致温度读数偏大。探头末端的三极管可以不做任何额外电路直接用热缩管包住贴在测量面上或者用导热胶固定到散热器表面保证热接触即可。连接器我用的是 2P 端子方便现场更换探头。一个容易被忽略的细节是远程探针引线的电容效应。有些项目为了美观把导线扎得很长、很密导线的分布电容一旦变大读数会出现明显跳动。处理办法是控制线长、减少并行走线必要时把滤波电容的容值调小用软件多次采样平均来对抗随机噪声。硬件上做好 D、D- 的等长和靠近软件上再叠加滤波双管齐下现场表现才会稳定。2.3 样板布线在 HVAC 屏柜里的避坑经验HVAC 设备里最不缺的就是强电和感性负载压缩机、风机、接触器哪一个动作起来都能在空间里砸出不小的电磁干扰。PJ85718DM 的远程探头线如果跟这些动力线平行走太长即使有屏蔽层也很难完全隔离。真实项目里我踩过一次坑把探头线沿着一条 220V 风机电缆穿同一根线槽走了约一米结果风机启动瞬间温度读数直接跳了五六度。后来把探头线单独走管并远离动力线至少 10 厘米读数才恢复正常。PCB 布局上要注意传感芯片的位置。如果你想测的“本地温度”是环境温度就别把芯片放在 MCU、电源芯片或者继电器正下方否则你测到的其实是这些发热元件的温度。反过来如果你想监控 PCB 表面热点那本地通道就应该尽量靠近热点放。这个矛盾在项目初期必须想清楚因为一旦做成产品位置就固定了。给用户测量环境温度时我会把主控板和传感器板做成两块传感器板通过排针装在通风位置这样本地温度代表环境而不是代表板温。另外I2C 总线本身也要注意抗干扰。总线走线尽量短不要和继电器驱动线、PWM 信号线平行。如果项目里继电器动作频繁建议在继电器线圈两端加续流二极管触点端加 RC 吸收。这些看起来是常识但很多开发者在实验室用杜邦线调通了一到现场就发现问题往往就是差在这些细节上。3. 固件实现I2C 读取与温度运算3.1 MSSP 初始化时钟计算这一步最容易被忽略PIC18F65K40 的 MSSP 模块在 I2C 主模式下的初始化关键参数就是波特率寄存器。计算公式是 I2C 时钟等于系统时钟 Fosc 除以 4 再除以SSPxADD 加 1反过来算就是SSPxADD Fosc / (4 × 目标频率) - 1。我用内部振荡器 16MHz目标 I2C 频率 100kHz算出来等于 16,000,000 / 400,000 - 1结果是 39。这个计算不难但经常看到有人直接抄例程里的值换了主频忘了改波特率然后示波器一看 SCL 频率完全不对甚至从机不响应。初始化代码的大致形式如下具体寄存器宏名按开发环境里的头文件为准。// 16MHz 主频I2C 100kHz 主模式 // SSP1ADD 16MHz / (4 * 100kHz) - 1 39 SSP1STAT 0x00; SSP1CON1 0x08; // I2C master mode SSP1CON1bits.SSPEN 1; // 使能 MSSP SSP1ADD 39; // 波特率 // 别忘了把 SCL、SDA 对应引脚的中断/模拟功能关掉 // ANSEL 相关位清 0方向寄存器设置为输入每次读取温度寄存器的完整事务是先发送起始位然后发送从机地址加写位把要读的寄存器地址写进去接着重新发送起始位再发送从机地址加读位连续读取两个字节后结束。写成驱动函数就是下面这样这个函数返回成功或者失败上层不用关心底层时序。uint8_t i2c_read_reg(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len) { uint8_t i; i2c_start(); if (i2c_write(addr 1 | 0) I2C_NACK) return I2C_FAIL; if (i2c_write(reg) I2C_NACK) return I2C_FAIL; i2c_start(); // repeat start if (i2c_write(addr 1 | 1) I2C_NACK) return I2C_FAIL; for (i 0; i len; i) { if (i len - 1) buf[i] i2c_read(1); // ACK else buf[i] i2c_read(0); // NACK } i2c_stop(); return I2C_OK; }这里有个细节重复起始位不能省略。很多初学 I2C 的开发者以为读完寄存器地址后可以直接读数据但在标准 I2C 读流程里读操作必须重新发起起始地址要带上读位。如果少了这一步部分从机虽然也能读出数据但是不符合规范遇到要求严格的 SMBus 从机就会超时或者返回错误。3.2 温度寄存器格式与整数/浮点换算PJ85718DM 这类芯片的温度寄存器一般分为高字节和低字节温度值以二进制补码形式存放分辨率常见的是 0.25°C 或者 0.0625°C。本地温度通常是 8 位整数加若干位小数远端温度精度更高可能是 9 到 12 位。读取的时候不光要取高字节还要把低字节中的高位小数位拼进来。换算公式如果分辨率是 0.25°C可以简化成高字节乘以 1 再加上低位小数位占的权重分辨率 0.0625°C 则直接对原始 12 位值乘以 0.0625 即可。实际固件里我不建议直接使用浮点运算MCU 算浮点虽然能跑但代码体积和耗时都会增加。更妥当的做法是直接用整数表示。比如把换算系数拆成整数部分和小数部分温度保放大 256 倍读到的原始值乘以 16就得到 1/16°C 的分辨率显示时通过取模把整数和小数拆开。这样既照顾了显示精度又避免了浮点库带来的开销。我项目中采用的平滑滤波是简单的滑动平均对最近的 4 到 8 次采样进行求和再平均这样对探头的随机噪声抑制效果比较好同时又不会让温度响应显得太迟钝。值得注意的是补码格式的负温度处理很容易写错。假如远端探头处在零下环境寄存器高字节最高位为 1直接无符号乘系数会得到一个大正数。正确的做法是先判断符号位如果为负对原始值取反加一得到补码的绝对值再转换成带符号的放大值。这个边界条件在暖通应用里可能用不到但冷库、冷柜项目一定会遇到提前留好接口不会错。3.3 报警阈值、ALERT 中断与数据有效性校验本地和远程两路温度都要设置上限保护我把高温限值写在传感器内部的限值寄存器里这样一旦超过阈值芯片的 ALERT 引脚就会拉低直接触发主控的外部中断。中断里做的不是立即去读温度而是先置一个报警标志主循环再定时去读取状态寄存器和温度值这样做能避免中断里执行 I2C 事务带来的复杂性和阻塞风险。阈值具体写多少要看应用HVAC 场景本地温度我通常写到 85°C远程探头根据目标器件的耐温范围写比如功率管锁到 100°C电机的绕组写 120°C 左右实际值要结合器件规格书。数据有效性校验是我强烈建议在固件里加的一步。现场长时间运行后I2C 偶尔会出现一次异常也许是电磁干扰也许是主从机时序对不上。如果没有校验机制一个错误读数可能被当成真实温度轻则显示跳动重则触发误报警甚至关闭压缩机。我采用的办法很简单每次读取成功后再连续读两遍状态寄存器如果在规定时间内从机一直没有应答就判为通信故障保留上一次正常值并累计故障计数连续故障超过 3 次才调用故障处理函数。报警功能我做成“连续超限 N 次才触发”的防抖逻辑避免温度在阈值附近抖动引起继电器反复吸合。从传感器状态寄存器里读到超限标志还要结合当前温度是否回落超过一定回差再清除报警这种类似硬件比较器迟滞的处理方式比单纯拿温度值和阈值比较要可靠得多。毕竟现场不是实验室任何没有防抖的阈值判断早晚会在某个冬夜或某个用户投诉电话里暴露问题。4. HVAC 控制器与嵌入式整机的工程结合4.1 一个典型 HVAC 温控器怎么把这些串起来把这个方案放进真实的 HVAC 温控器整体结构就非常清晰了。主控 PIC18F65K40 上电后先从 EEPROM 读取用户设定温度、运行模式、历史报警等参数然后初始化 I2C、PWM 和其他外设。主循环每 500ms 通过 I2C 读一次 PJ85718DM得到本地回风温度和压缩机壳体或电机表面温度配合目标温度做 PID 运算输出控制风机转速和加热/制冷执行器。传感器送回的本地温度作为回风温度参与温控闭环远程温度则主要做故障诊断一旦超过保护阈值立刻封锁输出并显示故障代码。这个架构里有一个比较实用的细节EEPROM 存参数。PIC18F65K40 自带 EEPROM 是我非常喜欢的一点不需要外挂掉电不丢失。用户设定的目标温度、温度校准偏移、风机最低转速这些参数在每次修改后写入 EEPROM上电时读取。代码上注意不要频繁写 EEPROM因为虽然写次数远大于 Flash但也没有无限寿命合理的做法是按下“确认”后写一次不要在运行过程中每个周期都在写。除了常规温控外我还加了一个“传感器失效进入安全模式”的逻辑。如果 I2C 读取连续多次失败或者温度值明显超出物理范围比如低于 -50°C 或高于 150°C控制器不会立刻停机而是按照预设的安全输出运行比如保持风机最低转速运转同时点亮故障灯。这样做的好处是在传感器故障时系统不会突然停止换气或突然停止加热避免把整个房间的温度环境搞到一个更危险的状态。这个逻辑来源于实际工程里惨痛的经验教训早期版本曾因为一个探头接触不良导致现场整套机组停机客户意见很大。4.2 嵌入式整机多点测温与热保护拿下 HVAC 场景这套组合在嵌入式整机里同样能打。典型的使用场景是主控板上放一片 PJ85718DM 测板温远程探头贴到 CPU/GPU 散热器、电源开关管或者电池组上。当远程温度接近器件极限时主控可以动态降低工作频率、关闭高功耗外设或者提醒系统进行降载处理。由于温度数据是数字格式主控可以直接算出温升速率比单纯看绝对温度更能提前发现散热系统恶化比如风扇堵转、导热硅脂老化。嵌入式场景里还有一个优势是布线灵活。板卡与板卡之间通过连接器和排线连接时模拟温度信号容易受地弹和串扰影响而 I2C 系统只要保证总线电容在合理范围内传感器放在另一块板上也没问题。但要注意的是如果跨板距离超过 30 厘米总线上的电容会明显增大这时候要么降低 I2C 速率要么在远端板卡上再加一级缓冲器。这种情况我在实际项目里遇到过最后是在中间加了电平/缓冲芯片解决同时把速率从 400kHz 降到 100kHz系统稳定下来。热保护的动作要做成分级处理而不是一刀切。比如温度到达 85°C 时先报警90°C 时风扇提速95°C 时降频100°C 才强制关闭设备。分级处理的好处是既保护了硬件又不会因为瞬时波动导致设备频繁关机用户体验好很多。这些阈值和动作策略我都会写到一张配置表里方便后期针对不同机型调整不需要为每款产品重新编译固件。4.3 把温度数据送出去UART/RS485 小经验大多数 HVAC 控制器和嵌入式设备都需要把温度上传到上位机或者楼宇自控系统。PIC18F65K40 的 EUSART 在这里就派上用场了我用 Modbus 协议或者简单的自定义协议周期性地把本地温度、远程温度、状态标志、故障码组帧发送。因为数据直接就是数字量组帧非常简单上位机收到的就是干净的温度数值不需要做二次标定。做通信时有一个很常见的问题看门狗和通信阻塞。很多人把 Modbus 处理写成一个阻塞函数在主循环里等待从机回复或者等待整帧接收一旦对方没有应答主循环卡死看门狗复位设备重启现场表现为“运行一段时间后自己重启”。正确的做法是把 UART 收发做成状态机或者至少把 WDT 喂狗操作放在协议解析函数之外独立位置确保无论通信是否正常主循环都能周期喂狗。我通常的做法是通信处理放在主循环的一个非阻塞状态机里超时自动放弃本次上报。此外如果项目有多台设备组网我会把每一台设备的温度数据加上设备地址和 CRC 校验。这样上位机不仅可以实时显示每一路温度还能记录历史曲线。温度趋势数据对判断设备健康度非常有价值比如远程探头的温度曲线在一周内缓慢上升很可能就是散热系统积灰或制冷剂不足的前兆这些都是在把温度数据数字化之后才能获得的额外收益。5. 常见问题排查与现场调试实录5.1 读不到 I2C 设备一张排查速查表现场调试阶段遇到最多的问题就是 I2C 读不到设备症状五花八门根因往往很集中。我自己总结了一张速查表遇到问题先对照排查能省下不少示波器时间。症状可能原因处理办法SCL 完全没有时钟MSSP 未使能、波特率寄存器错误、主频配置错检查 SSP1ADD 计算值先确认系统时钟频率SCL 有波形但 SDA 无 ACK从机地址错误、地址脚接法不对核对 A0/A1 和总线地址示波器抓地址帧能 ACK 但读回全是 0x00传感器电源没起来、寄存器地址错测量供电先读状态或版本寄存器验证通信能 ACK 但读回全是 0xFF上拉电阻过大、总线电容大、速度太高降低 I2C 速率或减小上拉电阻读数随机跳变电源噪声、探头线未屏蔽、滤波电容缺失检查远程探头走线加强电源滤波排查的顺序建议是先看供电再看时钟然后看地址最后看数据和波形。很多问题其实是供电或者引脚复用引起的比如 SCL/SDA 引脚同时被配置成模拟输入内部模拟电路会把数字信号拉偏导致从机完全没反应。遇到这种情况直接看数据手册的 ANSEL 寄存器把那几个引脚的数字功能打开问题立刻消失。另一个容易忽略的是复位问题。PIC18F65K40 掉电重启后I2C 外设默认是关闭状态如果固件里没有重新初始化 MSSP从机自然收不到任何时钟。常规做法是在初始化函数里显式执行 SSPEN 置位并且延时几个毫秒后再操作总线给电源和从机上电稳定留出时间。5.2 远端温度读数不准的根因分析远程温度读数不准第一反应经常是怀疑传感器坏了但大多数情况是探头安装或者电路细节出了问题。我遇到过一种典型情况远程温度比实际温度高了好几度排查后发现是 D 和 D- 接反了。不少三极管的封装引脚顺序并不统一装配工人按图索骥的时候很容易把发射极和集电极搞反。这种问题在产线上一旦出现就是批量故障解决办法是在测试工装上做两个方向的自动判断或者在生产指导书里用实物照片标注。另一种情况是使用了错误的探针器件。远程温度传感器本质上依赖三极管 PN 结的特性但并不是随便一个二极管都能获得准确读数。我之前做过一个实验把一个 LED 当探针接到 D/D-读数偏差非常大后来换小信号三极管才正常。原因在于不同 PN 结的寄生电阻和理想因子不一样传感器内部用于计算温度的参数是按照普通小信号三极管模型标定的。所以探头器件一定要选数据手册推荐的型号范围量产阶段不要随意更换供应商否则每批都要重新验证。滤波电容的取值也需要留意。为了抗干扰给 D/D- 并联一只 10nF 电容结果 400kHz 转换周期下读数明显偏大因为电容太大导致激励电流的建立时间不够采样到的压降值落在了错误的曲线上。把电容降到 1nF 并做了软件平均后读数恢复稳定。这个教训说明硬件上的滤波措施对模拟测量通道是有副作用的必须在稳定性和精度之间取平衡。5.3 实测中最值得记住的几条避坑经验最后分享几条我在这个项目里总结的实操经验每一条都是真金白银踩出来的。第一上电后不要立刻读温度先读状态和配置寄存器确认通信链路是通的再做后续操作。这样可以避免把“传感器没准备好”和“温度异常”混为一谈调试时能节省大量时间。第二温度采样周期不建议太快。PJ85718DM 这类芯片一次转换需要几十毫秒500ms 的采样周期对 HVAC 完全够用太快反而让数据抖动更大。第三把温度显示小数位控制在一到两位即可不要为了追求精度把用户界面搞得花里胡哨实际系统里控制精度更多取决于探头位置和热设计而不是显示分辨率。第四量产校准一定要做两点校正。零点和 50°C 左右的温漂系数分别写入校准偏移而不是只做一个简单的加减偏置。远程通道的探头批量更换后至少抽检几台确认一致性。第五I2C 驱动一定要加超时恢复。现场设备运行半年一年后偶尔一次总线被干扰卡死是完全可能的如果没有超时机制只能断电重启。加上超时恢复和自动重新初始化后这个项目到现在跑了一年多没有再出现过需要人工干预的情况。我在实际项目里的体会是硬件方案决定这套系统能采集到多少精度而固件里的异常处理、现场探头安装工艺和装配规范才决定这套系统能在恶劣环境中稳定运行多久。PJ85718DM 与 PIC18F65K40 的组合算不上惊艳但它把本地和远程温度监测这个最常见的需求用最稳妥的方式落地了。如果你也正在做类似的控制系统建议先花一点时间把探头位置、线缆走向和故障降级逻辑想清楚再做固件功能这个顺序会让项目顺利很多。
阅读完成 · 觉得有帮助?
咨询建站