资讯动态

基于PJ85718DM与PIC18F85J10的HVAC多点温度监测系统设计

发布时间:2026/10/22 12:20:54 来源:尧图企业网站定制
做 HVAC 项目时温度测点是最绕不开的部分。我常用 PJ85718DM 这颗单总线数字温度传感器搭配 PIC18F85J10 单片机实现嵌入式的本地与远程温度监测板子守着本地回风温度风管末端和室外的测量点也能一并收进来。这篇记录这套硬件和代码方案适合正在做 HVAC 控制板或工业采集模块的朋友参考。实际项目里的温度监测不是“读一个温度”那么简单。控制策略要本地回风温度维护人员要远程看送风温度和室外温度传感器分散在风管、机组、外墙有的地方离主控板几十米。所以设计一开始就要想清楚哪些数据在本地闭环哪些数据要送到中控室传感器用模拟量还是数字量总线拉多远才稳定。下面按我实际的做法拆开讲。1. 项目整体设计思路先搞清楚要测哪些温度1.1 HVAC 项目里的温度测点到底难在哪HVAC 系统里温度是控制和监测共用的基础参量。夏天要盯回风温度判断制冷量冬天要看送风温度防止吹冷风还要留意室外温度做节能补偿。这些测点分布很零散回风温度在主控柜附近或者回风口送风温度在风管深处室外温度在机组外墙。对嵌入式系统来说最麻烦的是“不同位置、不同距离、不同环境”都要求稳定可靠。拿我参与过的模拟项目来说主控柜在机房一端风管末端传感器在 40 米开外的吊顶里。如果每个测点都拉独立模拟信号布线成本高还容易受变频器和压缩机启停干扰。所以项目一开始就得做减法把测点按“本地”和“远程”分类本地测点就近接入主控板远程测点共用一条总线拉过去数据汇总后统一处理。1.2 为什么选 PJ85718DM 这种数字温度传感器很多人习惯用 NTC 热敏电阻加 ADC 读温度这在单个测点、短距离内没问题但多点远程测温就不太划算。NTC 需要分压电阻、需要逐点标定线长一点压降就变ADC 引脚也不够用。PJ85718DM 这类单总线数字温度传感器把这些问题绕过去了测温电路直接做在传感器内部输出已经是数字量一根数据线就能挂多个测点。这颗传感器兼容常见的单总线温度协议DS18B20 那一套测温范围 -55°C 到 125°C常规范围精度 ±0.5°C每个传感器出厂带 64 位唯一 ROM 序列号天然适合多点挂载。价格也比较友好批量采购比同类的带通信接口芯片更便宜。对 HVAC 这种测点不少、成本敏感的板子来说PJ85718DM 是性价比很高的选择。对比项NTC MCU ADCPJ85718DM 单总线输出模拟电压需 ADC 校准数字信号直接读数多点扩展每点一路 ADC/引脚一根总线挂多个点长线传输容易受线阻和干扰影响数字信号抗干扰更好每点成本器件便宜但调试贵略高但省开发时间标定工作逐点标定出厂已校准1.3 为什么选 PIC18F85J10 做主控温度采集只是 HVAC 控制器的一部分工作。主控还要跑控制逻辑、驱动继电器、操作 LCD、和上位机通信所以 MCU 不能只有一根传感器总线。PIC18F85J10 属于中端 8 位 MCU3.3V 工作外设比较齐两个 EUSART、SPI/I2C、ADC、多个定时器和比较器都有80 引脚封装也留足了扩展空间不会做到一半发现引脚不够。选它还有一个实际原因和系统里其他模块的接口电压能对齐。PJ85718DM 工作电压是 3.0V 到 5.5VPIC18F85J10 工作在 3.3V两者直接接逻辑电平没问题RS485 收发器、OLED/LCD 模块大多也兼容 3.3V整板就可以统一供电减少电平转换电路。如果选 5V 的 MCU反而要单独处理 3.3V 外设的兼容问题。1.4 整体架构本地和远程温度到底怎么接这套系统的架构并不复杂一条 1-Wire 总线上挂若干个 PJ85718DM本地传感器直接焊在主控板上或者就近接线远程传感器沿风管/外墙布线到远端PIC18F85J10 作为总线主机周期性轮询所有传感器把读取到的温度保存在内部结构体里本地 LCD 显示现场数据另一路 UART 接 485 收发器用 Modbus RTU 协议把数据发给中控室或上位机。这里“本地”和“远程”是相对主控位置区分的但对 MCU 来说都是同一个单总线网络。传感器多点共用一根数据线关键在于总线驱动能力和布线质量。短距离时一根线上挂七八颗传感器很轻松拉远了就要在电源、上拉电阻、屏蔽和接地上下功夫这部分放在硬件章节细说。2. 硬件设计从引脚定义到现场布线2.1 先看清楚 PJ85718DM 的引脚和总线特性PJ85718DM 是三脚封装引脚功能是 VDD、DQ 和 GND和常见的 DS18B20 一致。VDD 接电源正极GND 接地DQ 是数据线。DQ 内部是开漏输出意思是传感器只能主动把总线拉低不能主动把总线拉到高电平。要让总线在空闲时回到高电平必须在外部接一个上拉电阻到 VDD通常是 4.7kΩ。你可以把它想象成一扇只能往下拉的卷帘门想让它回弹上去得靠外面的弹簧这个弹簧就是上拉电阻。上拉电阻的取值要看总线长度和挂载数量。短距离、单颗传感器用 4.7kΩ 没问题总线拉到 20 米以上尤其远程传感器在吊顶里我习惯换成 2.2kΩ让上升沿更陡减少时序误判。挂载数量多时也一样4 颗以上可以降到 2.2kΩ。但上拉电阻不是越小越好太小会让低电平下拉电流过大传感器可能拉不动所以别低于 1kΩ。另一个关键是供电方式。PJ85718DM 支持寄生供电也就是只用两根线利用 DQ 线上的高电平给内部电容充电省一根电源线。但 HVAC 现场我强烈不建议用寄生供电远程供电线缺失会带来压降波动传感器偶发复位温度读数就莫名跳变。老老实实三线制VDD、GND、DQ 一起拉过去电源单独走一对双绞线稳定压倒一切。2.2 PIC18F85J10 接口电路和引脚分配主控板供电建议先做一级 5V 输入再用 LDO 降到 3.3V 给 MCU、传感器和通信芯片。PIC18F85J10 的电源引脚要靠近放置 0.1uF 的去耦电容供电入口放一个大容量电解电容比如 100uF 或 220uF能吸收压缩机启停造成的电压跌落。MCU 的 MCLR 复位脚接一个 10kΩ 上拉电阻到 3.3V对地并联 100nF 电容增强抗干扰能力。引脚分配上我把本地传感器总线放在 RB0远程传感器总线放在 RB1这样代码里两条总线的读函数可以复用互不干扰。如果只布一条总线也可以把本地和远程传感器都挂上去用 ROM 地址区分位置但我更喜欢分开因为本地传感器距离短上拉电阻可以大一点远程总线独立调整参数排查问题也方便。串口方面UART1 接 485 收发器用于中控通信UART2 留作调试日志输出。485 收发器部分用一颗常见的通用芯片即可RO 接 MCU 的 RXDI 接 MCU 的 TXRE/DE 合起来接一个普通 IO 口控制方向。发送数据前把方向脚拉高发送完再拉低。在总线末端不需要终端电阻时别乱加多机连接时只在最远端接 120Ω 终端电阻中间节点不接。2.3 远程传感器布线的三个防护要点远程线最容易出问题的不是传感器本身而是线材和接口。第一线材选型要规范。1-Wire 总线建议用带屏蔽的双绞线DQ、GND 走一对VDD 走另外一根屏蔽层只在主控板端单点接地。别用普通平行软线拉着走几十米平行线之间的电容大会把信号波形磨圆时序就直接错误。第二总线和传感器入口要加保护。在主控板总线入口串联一个 100Ω 电阻限制浪涌电流对地加 TVS 二极管吸收感应过压传感器端子用环氧树脂或者热缩管密封。室外传感器最好装防辐射罩避免太阳直接晒到探头导致读数偏高风管内的传感器要用带引线的插入式探头保证测点位于气流中心不要贴在管壁上。第三跨区域布设注意地电位。如果远程传感器跨了不同配电区域两地“地”之间可能有电压差直接单点接地可能形成地环路。这种情况下RS485 测建议用隔离型收发器或者至少保证屏蔽层只在主控端接地。温度传感器如果跨区域拉线距离特别长除了三线制供电还可以在远端就近取电减少压降影响。3. 软件实现单总线驱动、多点轮询与远程上报3.1 单总线时序让 MCU 按规矩拉电平单总线协议的所有通信都是主机发起PIC18F85J10 作为主机每次通信从复位脉冲开始。主机先把总线拉低 480us 以上然后释放总线等待 60us 左右读取存在脉冲如果总线上有传感器传感器会把总线拉低 60us 到 240us 作为应答。这一步是后续所有操作的前提。读写每一位也有固定时序。写 0 时隙是主机拉低总线 60us写 1 时隙则是拉低很短时间1us 到 15us然后释放总线。读时隙由主机先拉低总线 1us 到 15us然后释放随后采样电平传感器如果在这一位想返回 0就会把总线拉低。因为时序窗口只有几十微秒执行这段代码时最好关闭中断避免定时器中断或其他外设中断插入破坏了时序。我在主循环里会用一个临界区保护函数包裹整个单总线读写过程。下面是一段简化的单总线读写代码框架寄存器名请按你的实际编译环境和引脚定义调整#define OW_DQ_IN() (PORTBbits.RB1) /* 远程总线 */ #define OW_DQ_SET_LOW() (LATBbits.LATB1 0) #define OW_DQ_SET_HIGH() (LATBbits.LATB1 1) static void ow_write_bit(uint8_t bit) { if (bit) { OW_DQ_SET_LOW(); delay_us(6); OW_DQ_SET_HIGH(); delay_us(64); } else { OW_DQ_SET_LOW(); delay_us(60); OW_DQ_SET_HIGH(); delay_us(10); } } static uint8_t ow_read_bit(void) { uint8_t val; OW_DQ_SET_LOW(); delay_us(6); OW_DQ_SET_HIGH(); delay_us(9); val OW_DQ_IN(); delay_us(55); return val; }写字节和读字节就是把这个位操作循环 8 次先写低位。有了字节读写再做复位、发送 ROM 命令、发送功能命令就顺理成章了。3.2 温度转换和暂存器读取读取 PJ85718DM 温度的固定流程是复位发送跳过 ROM 命令 0xCC单设备和广播场景或匹配 ROM 命令 0x55多设备按地址读取然后发送启动温度转换命令 0x44转换结束后再复位发送读暂存器命令 0xBE依次读取 9 个字节。前两个字节是温度 LSB 和 MSB第三到第八字节是报警和配置寄存器最后一个字节是 CRC 校验。启动转换之后要注意等待时间。PJ85718DM 默认 12 位分辨率转换时间典型值是 750ms。如果发完转换命令立刻去读读到的往往是暂存器里的旧数据甚至电源刚上电的默认值。很多“第一次读出来 85°C”的问题就是这么来的因为上电后暂存器默认值温度部分正好是 0x0550换算过来就是 85°C。读到 9 字节后一定要做 CRC 校验。单总线数据在长线上传输时偶尔一位错误很常见尤其是 HVAC 现场有变频器干扰的时候。CRC 校验用的多项式是 X^8 X^5 X^4 1初值为 0。如果 CRC 不对这次读数直接丢弃不要拿去参加控制计算。CRC 代码可以用查表法也可以逐位算下面是一个逐位实现uint8_t ow_crc8(const uint8_t *data, uint8_t len) { uint8_t crc 0; for (uint8_t i 0; i len; i) { uint8_t byte data[i]; for (uint8_t j 0; j 8; j) { uint8_t mix (crc ^ byte) 0x01; crc 1; if (mix) crc ^ 0x8C; byte 1; } } return crc; }温度值换算很简单。把 LSB 和 MSB 拼成一个 16 位有符号数乘以 0.0625 就是实际摄氏温度。举个例子如果读到 0x0191高字节是 0x01低字节是 0x91合并后是 0x0191也就是 401401 乘以 0.0625 等于 25.0625°C。负数情况类似符号位在高字节最高位按有符号数处理即可。3.3 本地和远程多点的轮询调度多点监测时千万不要一颗一颗地“启动转换、等 750ms、读数据”那样挂 4 颗传感器要 3 秒控制没压力但维护体验很差。正确做法是先发一条广播转换命令让总线上所有传感器同时开始转换然后该干嘛干嘛等 750ms 到了再逐个用匹配 ROM 命令读取每个传感器的暂存器。整个周期从 N 倍 750ms 缩短成“750ms N 个读取时间”。我在主程序里建了一个时间片调度结构每 100ms 切一次控制逻辑优先级高温度采集放在低优先级。每次调度检查“上次广播转换是否已经等了 750ms 以上”到了才进入读取阶段读取完所有点后再发下一轮广播转换。这样温度刷新周期稳定在 1 秒左右而 MCU 不会因为等待转换而卡住其他任务。ROM 地址的管理也很重要。项目初期可以用跳过 ROM 命令单点测试正式固件里应该在系统启动时扫描总线把检测到的所有传感器 ROM 地址存成数组。扫描算法就是逐个位搜索网上有很多现成的 1-Wire ROM 搜索例程篇幅关系不展开但建议做两层冗余扫描到的地址要连续采集两次一致才算有效避免上电瞬间总线不稳导致的假地址。本地传感器和远程传感器我建议分开管理本地传感器固定接在 RB0远程传感器在 RB1两者在数据结构里用节点编号区分中控上报时同时包含两个区域的数据运维人员一眼就能对比室内外温度。如果只用一条总线靠 ROM 地址区分也行就是上拉电阻和布线要同时照顾短距离和长距离定位问题会麻烦一点。3.4 把数据送给中控Modbus RTU 上报PIC18F85J10 作为从站中控室上位机作为主站使用 Modbus RTU 是最稳妥的。温度值先放大 10 倍存成整数比如 25.4°C 存成 254放入保持寄存器地址 0x0000 和 0x0001一个放本地温度一个放远程温度。主站发 03 功能码读保持寄存器从站收到后返回寄存器数据和 CRC16 校验。实现上UART1 收完一帧后先判断地址是否匹配再校验 CRC16解析功能码。03 功能码的响应帧格式是从站地址、功能码、字节数、数据字节、CRC16 低字节、CRC16 高字节。下面是个简化框架/* 收到主站请求并校验通过后 */ txbuf[0] slave_addr; txbuf[1] 0x03; txbuf[2] 0x04; /* 返回2个寄存器共4字节 */ txbuf[3] (temp_local 8) 0xFF; txbuf[4] (temp_local) 0xFF; txbuf[5] (temp_remote 8) 0xFF; txbuf[6] (temp_remote) 0xFF; crc16 calc_crc16(txbuf, 7); txbuf[7] crc16 0xFF; txbuf[8] (crc16 8) 0xFF; UART1_StartSend(txbuf, 9);485 通信的方向控制记得要提前拉高发送完最后一个字节后再拉低。有个小坑UART 发送是中断还是阻塞模式如果发送完成只判断 TXIF 标志可能最后一个字节还没真正移出移位寄存器就把方向脚拉低了导致尾部字节丢失。稳妥的做法是判断 TRMT 标志或者加一个小延时确认发送完全结束再切换方向。4. 现场常见的坑和排查方法4.1 读数一直是 85°C怎么回事85°C 这个现象我见过不少十有八九是“读到了上电默认值”。PJ85718DM 上电后暂存器没经过温度转换默认温度值就是 0x0550换算成十进制就是 85。出现这个值优先检查启动转换命令有没有发出去、等待时间够不够 750ms、读暂存器之前有没有重新复位。如果程序确认逻辑没问题再用示波器看总线波形。重点看复位脉冲后的存在脉冲是否存在如果存在脉冲正常再量启动转换命令的波形是否被干扰打断。HVAC 现场压缩机一启动电源会被拉低MCU 可能复位过温度采集流程就从半中间打断了。这种情况下除了加强电源还可以在每次读暂存器前重新发一次启动转换提高容错。4.2 总线读出来全是 FF 或 00读出来全是 0xFF最直接的原因是 DQ 线悬空。线断了、端子松了、传感器没焊好、上拉电阻没焊都会让 MCU 引脚读到空闲高电平 FF。读出来全是 0x00 则是总线被拉低常见于 DQ 对 GND 短路或者某个传感器损坏把总线一直钳在低电平。判断方法是万用表量 DQ 静态电压正常应该在 3.3V 左右如果接近 0V拔掉所有传感器再量还低就是短路或上拉问题恢复正常就是某个传感器害的。症状可能原因排查顺序全部 0xFFDQ 开路/上拉缺失量静态电压、查端子、查线全部 0x00DQ 对地短路/传感器损坏断开传感器逐个排除时而读到温度时而 FF接触不良/线缆过长摇动线束、换 2.2kΩ 上拉CRC 频繁错误干扰/电源不稳屏蔽层接地、加大电容、重试4.3 多传感器轮询时不时少一个总线挂 3、4 颗传感器平时正常偶尔某一次轮询少读了一个点这种问题最磨人。一个很容易忽略的原因是上拉电阻和总线电容不匹配。远程线很长时总线电容偏大如果上拉电阻也大上升沿会变慢超过时序窗口就读取失败。把远程总线那路上拉电阻从 4.7kΩ 换到 2.2kΩ多数情况能解决。另一种情况是同一个 ROM 地址出现在两个位置。采购时如果混用了同一批次传感器就可能出现地址重复主机匹配 ROM 时会同时收到两个从机响应数据冲突看不出来。解决方法是上电扫描时把发现的所有 ROM 地址打印出来逐颗传感器单独触发 Reading 确认物理位置把重复地址的传感器换掉。我一般会在固件里保留一个“地址自检”功能长按面板按键就进入简单实用。4.4 现场电磁干扰和门限复位HVAC 现场干扰源很多压缩机启动瞬间电流大、变频器谐波、接触器动作火花。表现为 MCU 频繁复位、温度读数跳变、485 通信超时。软件上要加看门狗并让温度采集模块在 CRC 校验失败后直接丢弃本轮数据不要用坏数据覆盖好数据连续三次失败才上报故障。温度控制算法里也可以采三次取中值滤掉尖刺干扰。硬件上主控板电源入口要加共模电感和滤波电容485 总线用屏蔽双绞线1-Wire 总线入口记得接 TVS。还有一个被我忽略过的问题传感器探头靠近水管长期潮湿导致端子氧化接触电阻变大也会报温度漂移。工艺上给端子涂三防漆传感器引线出口做密封环境温度高湿度大的点位尽量选不锈钢铠装探头省得后期反复检修。做这套系统我最深的体会是温度监测的坑很少出在“器件选错”大部分出在“总线物理层没伺候好”。PJ85718DM 和 PIC18F85J10 这对组合只要把上拉电阻、供电、屏蔽接地这三件事做扎实软件按时序和 CRC 来写跑起来相当省心。以后再做类似的多点温度采集我大概率还是这个思路先规划测点距离再定总线和保护而不是上来就写代码。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑