PIC18F57K42与PJ85718DM的HVAC温度采集与抗干扰设计
发布时间:2026/10/22 1:08:07 锦皓数字建站

做 HVAC 控制和嵌入式设备的朋友应该都有过类似的折腾经历一个系统里既要盯主控板上那一路温度又要在十几米外的风管、盘管、回风口再放上几个测温点而且这两类温度还不能简单混为一谈。我最近完成的某一个控制器项目就是围绕 PIC18F57K42 这颗 MCU 和 PJ85718DM 温度前端来统一处理本地与远程温度监测覆盖嵌入式设备自身的过热保护以及 HVAC 场景里的送风、回风、盘管温度采集。这篇文章会把硬件接线、固件配置、校准方法和现场干扰处理完整串一遍适合正在做环境控制器、风机盘管控制器、空气处理机组控制器的工程师参考。需要先说明的是PJ85718DM 从应用定位来看属于数字温度测量前端常见实现是内部带隙测温核加上数字比较器通过 I2C 这类接口直接输出温度数据和报警状态。这类器件最大的价值是把模拟量就地数字化信号抗耦合噪声的能力远强于长距离走模拟信号这也是我在远程测点上坚持用它而不是直接拉 NTC 线的原因。1. 这个组合解决的是 HVAC 与嵌入式里最容易被低估的两类测温需求1.1 本地温度保护的是主控板与功率器件本地温度测点在控制器上承担的角色和远程测点完全是两回事。你现在打开任意一台风机盘管控制器或者空气处理机组控制器的电路板能看到 MCU、电源 DCDC、通信芯片有时还有 BLDC 风机的预驱和功率管这些都是实打实的发热源。如果温度超过器件规格轻则运行不稳定重则烧板。所以本地测温的第一目标不是舒适性而是保护。在 PIC18F57K42 所在的主控板上我通常会在以下位置预留测温点电源芯片附近、功率管或预驱附近、主控芯片封装附近。每个测温点关注的对象不一样对应的保护动作也不同。功率管附近温度高了可以先降 PWM 频率或减小占空比电源芯片附近温度继续上升就说明散热或负载有问题主控附近温度异常多半是机箱风道堵了或环境温度超标。这里容易犯的错是把本地传感器设计成只测一个板温然后靠经验漂移估算功率器件温度。实际上功率器件温度变化很快和板温之间可能差出 20~30 摄氏度尤其在风机启动和负载突变瞬间。我在另一个项目里就吃过这个亏板温传感器放在主控附近功率管已经到 100 摄氏度了主控周围还在 55 摄氏度等到报警触发器件寿命已经受到影响。1.2 远程温度才是控制环路的真实反馈远程温度测点是 HVAC 控制系统真正依赖的控制反馈。回风温度决定室内负荷估算送风温度用来判定系统有没有满足设定需求盘管温度则是除霜、防冻和冷媒过热度判断的关键输入。这些测点离主控板少则半米多则十几米而且分布在风道、水管的物理边界上。我接触过的 HVAC 项目里最典型的一组测点是回风温度 送风温度 盘管温度。回风温度代表空间内实际空气状态送风温度反映处理后的空气状态两者差值可以看出空调系统有没有在正常做工。盘管温度则是制冷制热循环里变化最灵敏的信号结霜、防冻保护都得靠它。有一个工程问题是很多新手不太注意的盘管温度和空气温度之间的响应速度差异非常大。盘管表面温度在压缩机启动后几十秒就会掉下来但送风温度可能要几分钟才稳定。如果你把两类温度同时拿去参与同一套控制逻辑又用了相同的滤波时间常数系统会出现剧烈的振荡。正确做法是给不同测点配不同的滤波系数和采样周期盘管温度这种快变量采样周期可以到 200ms 左右空气温度 1s 左右即可。1.3 为什么是 PIC18F57K42 与 PJ85718DM 搭档PIC18F57K42 是 PIC18 增强型系列里的实用选择工作电压范围宽温度等级符合工业需求外设比较全ADCC 带计算功能、MSSP 支持 I2C/SPI、UART、DMA、可配置逻辑单元 CLC、PWM 生成器 COG/CWG 都有。这意味着它既能接模拟 NTC 做本地测温也能通过 I2C 总线挂多片数字温度传感器做远程测温一套固件里同时管理两类测温架构完全可行。PJ85718DM 这类数字温度前端我相中的是两点。第一数据就地数字化抗干扰强。远程测点的走线大概率要经过强电区域模拟小信号会被变频器、接触器干扰得一塌糊涂数字信号只要保证电平不被严重破坏就行。第二多个传感器可以挂同一总线上主控通过地址区分测点不用为每个远程传感器单独铺线到主控的 ADC 引脚省下来的 IO 和 PCB 面积很可观。当然这个组合也有一个必须先认清的短板I2C 总线不适合直接做超远距离传输。这个问题我在第二章会专门展开因为它不是靠调整软件就能解决的必须在硬件设计阶段就处理掉。2. 硬件链路设计远端传感器不是插根线就能跑2.1 传感器地址与上拉电阻先给每路测温点分配好身份在同一组系统里我会安排两个甚至三个 PJ85718DM 测点比如主控板上一个作为本地温度风管盘管各一个作为远程温度。它们挂在同一条 I2C 总线上靠地址区分。这种数字传感器通常都有地址配置引脚三根引脚可以组合出多个地址实际项目中先把地址规划好再画原理图能省掉后面不少麻烦。地址规划这件事看起来简单踩过坑才明白它的重要性。我有一次做样机调试两个传感器地址配置完全相同结果读到的数据一会儿是主板温度一会儿是盘管温度控制逻辑完全混乱查了整整半天。后来在 PCB 上把地址引脚的接法做成可配置通过 0 欧电阻或者跳线帽选择地址基础型号固定用默认地址升级型号再换地址生产阶段就很少出错了。I2C 上拉电阻也是容易被忽略的细节。总线上拉电阻的取值要综合考虑总线上挂了多少器件、走线多长、通讯速率多高。上拉太小低电平拉不下去信号被压住上拉太大高电平上升沿太慢高速时就出错。一般做法是先估算总线电容再选 4.7k 或 2.2k。如果远程线缆比较长总线电容增加我会把上拉电阻调小一些但不能小于驱动能力允许的范围。此外传感器的电源不能直接扔给一片式供电就完事。远程传感器所在的线缆如果比较长有可能会被雷击浪涌或设备启停的电压跌落干扰我在每个传感器电源引脚旁边都放了 100nF 和 1uF 两个电容距离超过 3 米的测点还在传感器板上加了一个小功率 LDO。这样传感器的供电噪声降下来读数的稳定性明显提升。2.2 远程线缆的电气边界电容、屏蔽与总线缓冲我见过不少工程师拿到 I2C 数字传感器后直接把传感器甩到 10 米外的管道上结果通讯时好时坏最后归结为芯片不稳定。实际上 I2C 标准规定总线电容通常不能超过 400pF普通线缆每米分布电容就有 50 到 150pF算上传感器和主控输入电容10 米线早就超限了。信号在这种环境下边沿变形通讯失败是迟早的事。要解决远程数字测温的 I2C 总线问题有几种成熟路线。第一是降速把总线从 400kHz 降到 100kHz 甚至 50kHz有一定缓解作用但不治本距离稍微一长仍然会偶发错误。第二是加总线缓冲器这类芯片能把 I2C 总线电容隔离成两段主控侧保持短走线低电容远程侧线缆电容只要缓冲器能驱动就行适合几十米内的应用。第三是干脆不用 I2C 做远程传输改成 RS485 加带远程通讯功能的温度模块或者用电流输出型测温模块逻辑上更稳但硬件成本和复杂度都上去了。我做这类设计的时候习惯设一个分界线传感器距主控板 1 米以内直接 I2C1 到 5 米降速加总线缓冲器超过 5 米就认真考虑 RS485 或 4-20mA 的模块方案。这个分界值不是拍脑袋定的而是多次实测后得到的经验。远程线缆我一般用屏蔽双绞线屏蔽层单端接地并且规定远程线缆必须和动力线分层走线、不要共用线槽。光这一点就能解决掉现场一半以上的偶发通讯故障。2.3 本地测点的热设计与 ADC 参考选择本地测点如果只用数字传感器那就简单很多。但我通常还会留一路 NTC 作为冗余或者做快速响应的板温监测PIC18F57K42 的 ADCC 模块用来采集 NTC 分压信号。这里先讲一个热设计上的要点本地温度传感器不要贴在 PCB 边缘也不要直接放在大铜箔散热区中央这些位置的温度和主控感知到的实际环境温度差距很大。传感器放在需要保护的功率器件附近但要留一点距离避免热源直接辐射导致读数腰斩。NTC 分压电阻的选型直接决定测温量程和精度。我习惯用 10k 的 NTC配 10k 精密电阻做分压工作电流小自热效应可以忽略。分压电阻的精度建议选 1% 甚至更高因为电阻本身的温漂会直接叠加到测温误差里。如果项目预算允许ADC 参考电压用内部固定参考电压 FVR 而不是直接用 VDD可以避免供电电压波动时产生读数偏移。PIC18F57K42 的 ADCC 支持多个参考源选择我在实际项目里把 FVR 配置成固定参考电压后续校准的工作量小了不少。ADC 参考电压的选择其实藏着一个小坑如果参考源电压噪声大所有通道的转换结果都会跟着抖。即便传感器本身很准ADC 结果也会像心电图一样上下跳。因此硬件设计上参考源的去耦电容不能省而且要高精度低温漂的电容。固件上再配合 ADCC 的硬件均值功能才能拿到稳定的原始值。3. PIC18F57K42 侧固件让采集尽量不占主循环3.1 ADCC 计算模块自动扫描、累加平均、阈值比较PIC18F57K42 的 ADCC 计算功能是我比较喜欢的一个外设特性它可以在后台自动完成多次采样累加平均而且能在结果超过阈值的时候直接产生中断。这意味着温度采集不需要 CPU 全程盯着采集任务完全可以后台化。以本地 NTC 通道为例我会把 ADCC 配置成 12 位分辨率开启自动采样功能在每次转换完成后自动重新触发下一次转换并且按照设定的次数累加。内部累加单元把多次转换结果加起来再取平均得到的值已经被硬件滤了一遍主循环不用每毫秒去服务 ADC 中断。阈值比较功能还可以用来做温度越限报警配置一个高阈值当完成后的结果超过阈值时ADCC 模块自动产生中断主控快速进入过热保护逻辑。我先给一段配置思路的示意识别代码实际寄存器名以 PIC18F57K42 数据手册为准// ADCC 初始化示意12位分辨率内部FVR参考自动累加平均 ADCON0 0x00; // 关闭ADCC进入配置阶段 ADCON1 0b10000000; // 结果右对齐累加平均使能 ADCON2 0x02; // 采样保持配置时钟分频 ADREF 0b00110000; // 正参考选择 FVR ADACQL 0x1F; // 采样时间设置保证NTC信号稳定 // 选择模拟通道并启动自动转换 ADCHS 0x01; // 通道1本地NTC ADCON0 | 0x80; // 开启ADCC模块这段配置的核心思路就是把 NTC 的阻值变化尽量平滑、稳定地变成可用的原始数据。ADCC 的自动转换可以在后台持续运行转换完成后如果要读取结果直接读取结果寄存器即可代码非常简单。还有一个值得用的点是 DMA。PIC18F57K42 支持 DMA 把 ADC 结果直接搬到 RAM 变量里不需要 CPU 写读取动作。如果项目里面有多个模拟量要采集比如 NTC 温湿度、压力传感器、电流采样DMA 加 ADCC 的组合可以把 CPU 负载压得很低留更多时间给控制算法和通讯处理。3.2 I2C 状态机轮询把远程读数做成不阻塞的后台任务远程数字传感器的读取不能写成阻塞式轮询。如果你的主循环在 I2C 总线等待应答时卡住几百微秒对控制周期的影响可能不大但传感器数量一多、通讯偶尔出错需要重试时阻塞时间会不断叠加。另一个项目里用阻塞读写挂了三路传感器结果其中一路线缆接触不良时整个系统的控制周期被拖慢压缩机保护都差点失效。正确的做法是用定时器驱动一个状态机每个时间片只处理一条总线上的一次通讯步骤。比如每 10ms 触发一次调度主控按顺序处理发送传感器地址、写命令、等转换完成、读数据。单路操作没有完成就退出状态机等下一个时间片继续。这样即使一路通讯卡住主循环永远不会被阻塞。我这里给出一个简洁的读取流程示意typedef enum { SEN_WRITE_ADDR, SEN_WRITE_REG, SEN_READ_DATA, SEN_DONE, SEN_ERROR } sensor_step_t; void sensor_poll(void) { switch (sensor_state) { case SEN_WRITE_ADDR: // 发启动位和传感器地址写温度寄存器 status i2c_master_write_byte(dev_addr); break; case SEN_WRITE_REG: // 写寄存器地址和/或触发转换 break; case SEN_READ_DATA: // 读两个字节组装成温度值并做完整性校验 break; case SEN_DONE: // 存入滤波缓冲区切换下一路传感器 break; case SEN_ERROR: // 记录错误计数值不把异常数据写入变量 break; } }这里最容易被新手忽略的一点是当 I2C 通讯出现 NACK 或者超时时绝对不要把旧数据清掉或者直接填入一个 FFFF 之类的异常值。我会让上一次有效温度值继续保留同时给该测点的故障计数加一。只有连续多次失败才真正认定这个传感器离线。否则现场一次短暂的干扰脉冲就会让控制系统把温度当成几十度的异常值参与运算后果可能比传感器离线还严重。3.3 滤波、超限报警与故障后的 fail-safe 策略温度数据进入控制逻辑之前滤波是必须做的一步。即使是数字传感器远程线缆经过强电区域后偶尔也会读到跳变的毛刺。如果不过滤直接送到 PID 或保护逻辑里很容易让执行机构来回动作。一阶低通滤波是性价比最高的做法公式是y (x - y) / NN 根据采样周期和系统时间常数来定。对空气温度这类慢变量N 可以取大一点让响应平缓盘管温度这类快变量N 取小一点让保护逻辑能及时响应。还有一个更实用的方法是滑动中值滤波把最近 5 次读数排序取中值能非常干净地去掉单点毛刺代价是内存多一点。超限报警要分优先级。HVAC 里的盘管防冻属于安全级别一旦盘管温度低于阈值必须立即执行防冻动作或者停机警告。回风温度传感器失效则是一个运行质量问题系统可以不立即停机但要把控制模式切换到安全默认值比如按设定容量运行并报警。不同测点的 fail-safe 策略一定要提前设计好不能在故障发生时才临时决定。我在这类系统里配置了三级故障状态传感器正常、传感器可疑、传感器离线。可疑状态是连续 3 次读取异常这时继续使用上一次有效值但提高巡检频率离线状态是连续 10 次读取异常此时切换安全模式并上报故障码。这样既能容忍瞬间干扰又不会让传感器彻底失效时系统毫无察觉。4. 从寄存器读数到可信温度校准、实测与 HVAC 干扰4.1 多点校准把传感器偏差和安装误差拆开看数字温度传感器一般出厂前做过校准但具体到某一颗器件、某一种安装方式仍然会有偏差。更关键的是安装误差比如传感器套管里没填导热硅脂、探头和被测表面之间有空气缝隙都可能造成几摄氏度的误差。因此在系统联调阶段校准不是可选项。我做校准的方法是先建一个目标温度表覆盖这个测点在真实工况里的范围。以 HVAC 应用为例通常会校准 0 摄氏度盘管防冻点附近、25 摄氏度环境温度附近、50 摄氏度送风或排风高温点。使用恒温槽或者干体炉设定稳定温度把传感器放进去等读数稳定后记录当前计算出的显示温度和标准温度之间的偏差。对数字传感器来说偏移校准通常就是写入一个 offset 参数。但如果跨三个点校完发现偏差不是恒定的即是线性度问题这时不能只做零点偏移。常用的做法是线性两点校准算出增益和偏移固件里calib_temp raw_temp * A B。如果三个点之间的残余误差还很大就得怀疑探头安装方式或者传感器本身选型是否正确而不是继续加高阶曲线拟合否则会把安装问题的责任混淆掉。4.2 强电场合下的远程读数问题从实测数据看对策HVAC 设备现场是出了名的干扰密集场所接触器吸合、压缩机堵转、变频器 PWM 输出每一个动作都会通过电源线、动力线向周围辐射噪声。远程温度线缆如果和动力线平行走线几米线上感应出的共模电压会直接打进 I2C 总线导致读数跳变甚至通讯失败。我在实际项目中做过一次对比测试。远程传感器经 3 米屏蔽双绞线连接主控附近开启一台变频风机。刚开始总线速率设在 400kHz持续几分钟后就会出现偶发 NACK读回来的温度偶尔跳到 127 度。把速率降到 100kHz 之后连续运行半小时没有报错。后来又把线缆改成从动力线另一侧单独走线槽速率恢复到 200kHz 也没再出现过通讯错误。这说明干扰问题往往是物理布局和电气速率共同作用的结果单靠软件改哪一头都只能缓解不能根治。远程传感器的供电也要重点处理。干扰最容易从供电线进来我会在远程传感器板上放一个 LDO 或 LC 滤波在电源引脚附近放 TVS 管。对于高可靠场合传感器供电还可以单独用一路受控电源出现故障时主控可以断开传感器电源复位它比单纯发送总线 reset 命令更有效。关于干扰防护我最想提醒的一点是远程线缆屏蔽层接地的位置不能乱接。一般做法是屏蔽层单端接地也就是靠近主控一端接地传感器端不接地避免形成地环路。如果你把两端都接地屏蔽层里反而会有工频环流干扰更严重。现场排查过几次通讯异常最后发现就是屏蔽层两端接地引起的。5. 这套方案落地时值得注意的经验5.1 从原型到样机的几个典型坑原型阶段大家喜欢用杜邦线接传感器距离短、环境干净什么问题都没有。一到样机线缆变长、走线靠近动力线、现场环境温升一上来问题集中爆发。我见过最典型的几个坑列出来供参考。第一个坑是 I2C 上拉电阻重复。有的传感器评估板上自带 4.7k 上拉主控板上又放了一组两块一接上拉电阻并联后总阻值太低导致总线低电平都拉不下去通讯更不稳定。我现在的习惯是原理图评审时明确只有主控板放上拉电阻传感器子板不加上拉或者通过跳线决定是否安装。第二个坑是地址冲突。多个远程传感器如果型号相同又没配地址数据会串位。这个问题如果放在现场才发现拆设备改跳线的成本非常高所以我在固件里加了传感器地址自检上电后逐个读取传感器 ID 和地址发现重复就报错并拒绝进入运行模式。第三个坑是异常温度值参与控制。有一次现场报告空调系统明明很热还在不停制冷查到最后发现是回风温度传感器线缆接头松动偶发读到 5 摄氏度控制逻辑认为室内过冷就继续制冷。后来我在所有温度进入控制逻辑前加了一道合法性检查超过合理范围直接拒绝并走 fail-safe 分支类似问题彻底不再出现。5.2 把温度数据用起来从采集到风机与加热控制温度监测如果只是把结果显示在界面上价值很有限。在 HVAC 控制器里温度数据的尽头是风机转速、压缩机启停、加热器 PWM 输出这些执行动作。PIC18F57K42 的 COG/CWG 模块可以生成互补 PWM用来驱动半桥或全桥把温度控制映射到变频风机非常自然。我做了一个比较通用的温度到 PWM 映射采样回风温度与设定温度得到偏差经过温度 PID 计算后输出占空比给 COG。温度变化慢控制周期设在 500ms 到 1sPWM 频率放在 20kHz 左右避开人耳可听范围。温度环的输出再级联到风机转速环实现无级调速。这个架构里有一个容易犯的问题把温度环的控制周期和 PWM 周期混淆。温度环周期长没问题但 PWM 周期必须足够快才能让风机平滑转动。两者是独立的定时器资源不能放在同一个中断里处理。PIC18F57K42 的定时器资源足够多完全可以把温度环、通讯轮询、PWM 再生分成三个不同的时间片。5.3 固件架构上给传感器换型留好退路不同项目对传感器精度的要求不一样有的用普通数字温度传感器就够有的需要更高精度型号有的现场就认 NTC 加 AD 的模拟方案。固件架构上如果不做抽象产品换代时驱动逻辑要重写一大片。我现在的习惯是在固件里定义统一的测点接口比如sensor_read(point_id, temperature)、sensor_status(point_id)外部控制逻辑完全不感知底层是 I2C 数字传感器还是 ADCC 采集 NTC。底层驱动做成两套通过一个配置表把每个测点映射到不同的驱动实现。这样以后想换传感器型号只需要新增一个驱动文件改配置表控制逻辑完全不用动。另外校准参数、传感器地址、滤波系数这类参数不要写死在代码里而是放在数据存储区生产时通过串口或工装写入。这样同一套固件可以支持不同器件的微调现场替换传感器也不必重新烧录程序。我最初把传感器地址直接定义成宏后来发现每片板的地址要单独区分只能频繁改宏重编译浪费了很多时间现在统一改成运行配置管理。最后再分享一个我反复用到的技巧在校验台上给同一测点做校准后把校准日期、校准人员、校准系数一并存回去现场维护时可以直接读出传感器的校准历史。这套做法花不了多少工作量但能把现场排查时间压缩一大截。温度链路看起来只是读寄存器-算温度两件事真正让它稳定的往往是你在这个链路上做过多少预防性的设计。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。