☰
单总线传感器实现HVAC本地与远程多点测温的完整方案
2026/10/22 6:40:27 网站建设 项目流程

做HVAC控制器的朋友应该都有体会,板子上最容易出问题的不是继电器,不是电源,反而是看起来人畜无害的温度传感器。回风温度放在控制板上测倒还好,室外盘管、新风管道那几路探头一拉就是十米二十米,走线还要贴着变频器,读数要么跳变、要么干脆掉线。我之前在某个项目里就是用PJ85718DM搭配PIC18F46K40把这套本地加远程的温度监测一次搞定:板内一颗PJ85718DM当作本地测温点,远端再挂两三颗,全部走一条单总线,主控用PIC18F46K40统一轮询,距离跑过20米,读数稳定。这篇就把从硬件电路到固件调度的完整做法拆开讲一遍,适合正在做HVAC控制器、小型嵌入式数据采集或者想用单总线传感器做多点测温的开发者参考。

1. 项目需求与总体方案设计

1.1 本地与远程温度到底差在哪

先说场景。HVAC领域典型的温度监控至少要覆盖三个位置:机组自己所在控制柜附近的回风温度,这算本地;压缩机排气管或室外盘管温度,离主控板可能只有几米,算近端远程;新风风管末端的送风温度,布线可能横跨整个吊顶,算真正的远程。在嵌入式设备里也类似:机柜进风口温度、机柜出风口温度、机房远端冷通道温度。这些点位的物理距离不一样,导线的电阻和分布电容不一样,暴露在现场干扰下的程度也完全不一样。所以标题里把“本地”和“远程”并列,不是文字游戏,而是设计上必须考虑的两套约束:本地点位通常可以做成板上直接贴装或板边连接,线路短、电平干净、调试容易;远程点位则要过接插件、穿线管、走强电桥架附近,线缆长度对信号质量的影响必须摆到桌面上算。

远程测温的方案其实不少:传统做法是Pt100铂电阻加变送器转4-20mA电流环,模拟量精度高、抗干扰强,但每路都要单独拉线,MCU侧还要配ADC和精密电阻;另一种是使用单总线数字温度传感器,一根数据线上就能并联多颗,每颗有独立ID,本地和远程共用一条总线,成本和布线量都小很多。PJ85718DM走的正是后一条路线,这也是我最终选它的核心理由:方案可以用一套驱动同时覆盖本地和远程,硬件上不增加接口数量。

1.2 器件选型思路:PJ85718DM与PIC18F46K40凭什么合适

先看传感器侧。PJ85718DM这种单总线数字温度传感器,典型配置是12位温度分辨率,测温范围覆盖-55℃到+125℃,这个范围对HVAC来说绰绰有余——正常空调工况大概在-20℃到+85℃之间,留出的余量足够应对排气温度过高这类故障检测。它内部带唯一64位ROM序列号,意味着同一根总线上挂多颗传感器时,主控可以通过序列号精确点名,不需要额外片选引脚。

然后是主控侧。PIC18F46K40是一颗40引脚级别、最高主频64MHz的8位MCU,Flash资源和RAM在同类里算宽裕,尤其重要的几个点:内置高精度内部振荡器,不需要外部晶振就能跑稳定,省掉两个引脚;ADC通道数量足够,除了数字温度传感器之外还能留几个通道给压力传感器、湿度传感器或者电位器输入;低功耗表现好,HVAC设备虽然通常不缺电,但设备处于待机状态时如果能把电流降到微安级,对安规和能效考核都有好处。还有一个信息量很大的地方:它的IO口翻转速度很快,做单总线这种需要微秒级时序的协议时,用普通GPIO模拟完全没问题。

顺便说一句,PIC18系列开发环境对新手也算友好,标准IDE里直接有代码配置工具,可以图形化生成初始化代码,再手写业务逻辑。我在项目里的做法是:外设初始化交给配置工具,传感器驱动和轮询调度自己手写,这样既省时间,又不会遇到自动生成代码看不懂的尴尬。

1.3 总体架构与数据流

整个系统的结构并不复杂:

  • 一颗或几颗PJ85718DM作为本地温度节点,直接布置在主控板上,测量机箱内温度或回风温度;
  • 再通过同一个单总线接口向外延伸,经过接插件和屏蔽双绞线,连接风管或室外的远程温度节点;
  • 单总线数据线上拉电阻放在主控板这一端,每个远端节点旁边加ESD保护;
  • PIC18F46K40通过软件轮询方式,每隔一段时间依次发出温度转换指令、读取所有节点暂存器,得到一组温度值;
  • 读取结果换算成摄氏度后,一部分用于本地控制逻辑(比如判断是否结霜、是否超温),另一部分通过显示接口或通信接口(串口、RS485)上报给上层控制器。

这样做的优点:本地和远程共用一个物理接口,驱动代码只写一遍;传感器节点越多,反而越能体现单总线的优势,因为每增加一个点只增加一颗传感器和一小段线,不增加MCU引脚。缺点也客观存在:单总线的通信时序对实时性要求高,在长线场景下如果线缆质量和布局不好,调试起来会比较费劲。这个弊端不是劝退理由,只要在硬件层面把该做的防护和线材选择做到位,后面固件就不会太难。

2. 硬件设计:从引脚规划到长线抗干扰

2.1 MCU最小系统与电源设计

先搭主控最小系统。PIC18F46K40的外围电路非常简洁,我用的是内部振荡器模式,没有接外部晶振。电源方案上,我选择了5V系统:主控和传感器共用5V,因为HVAC控制板里现成的稳压源往往就是5V,传感器在5V供电下的转换速度和读取时序余量也更好。MCU电源脚和模拟电源脚各放一组0.1uF陶瓷电容加10uF电解电容的组合,地平面统一铺在底层,传感器返回的GND在主控板这一点汇集以后接到电源地。这样做的原因是避免多个远端传感器的地线电流在PCB上形成环路,造成ADC或者逻辑电平被“地弹”干扰。

复位方面,PIC18F46K40内部有上电复位和欠压复位,我把欠压检测电压配置成4.25V左右,电网波动、掉电重启时MCU不会进入中间状态。这不是硬件上多花了什么东西,只是软件配置里勾一项,但对HVAC这种要长期无人运行的设备,少一次死机就等于少一次售后。

2.2 本地传感器接口电路

本地节点我直接放在主控板边缘,靠近进风口或者接线端子。电路极其简单:PJ85718DM的VDD接5V,GND接地,DQ数据线接到MCU的一个普通IO口上,IO口配置为开漏输出模式,然后在总线上挂一颗上拉电阻到5V。上拉电阻的取值要算一下:单总线空闲状态靠上拉电阻维持在逻辑高,传感器和MCU通过拉低总线来发信号。如果上拉电阻太大,比如10kΩ,总线分布电容会把上升沿拖慢,时序调到极限时会卡在“读1”和“读0”的临界区;如果太小,比如1kΩ,总线驱动能力和功耗又受影响。我在短距离(板内1米以内)时用4.7kΩ,实测时序非常从容。本地节点和MCU之间不需要额外滤波,因为距离短、干扰源少,一个0.1uF退耦电容放在传感器电源脚旁边就足够了。

这里有一个很多人忽略的细节:即使“本地”节点也要用同一个标准的数据线接线端子,不要图省事直接把传感器焊在PCB走线中间。原因有两个,一是生产时传感器损坏方便更换,二是本地节点往往用于校准参考,把它做成独立节点可以避免焊接温度对传感器造成不可逆漂移。做温度产品的应该都有体会,一个传感器经历过回流焊以后,低温段的读数和出厂校准值往往对不上。

2.3 远程传感器长线部署与保护

远程才是这套方案真正藏坑的地方。我的典型做法是:数据线和电源地各用一根双绞线里的一对,线材选用屏蔽双绞线,屏蔽层在主机端单点接地;远程节点最多挂3颗,总距离控制在25米以内。为什么选双绞线而不是平行线?因为HVAC设备附近的电磁干扰主要来自变频器、接触器和压缩机的启停,双绞线可以把每一个绞距内感应到的噪声电压自动抵消掉一大部分,这个效果在物理层面是免费的抗干扰红利。

电源也要单独处理。PJ85718DM可以容忍3.0V到5.5V的供电电压,长线时如果和主控共用一个5V,线缆压降会导致远端传感器供电偏低。25米双绞线的环阻按0.1Ω/m估算,一来一回大概50米导体,电阻约5Ω;单颗传感器工作时峰值电流大约1.5mA,三颗同时转换时接近5mA,线上的压降只有25mV左右,完全在容忍范围内。真正需要担心的是电压瞬变:压缩机启动瞬间,变频器在动力线上的dv/dt会通过分布电容耦合到信号线,处理办法是远程节点入口处加TVS管,对地并一个小电容滤除共模高频分量。具体参数我不锁死,选结电容低、钳位电压在6V左右、响应时间在纳秒级别的TVS即可,频率高的单总线协议对结电容敏感,结电容越大,信号边沿越缓。

还有一条经验:远程传感器的VDD不要和DQ分两条独立线走,而是让VDD、DQ、GND三根线走在一根屏蔽双绞线里,VDD和GND作为一对,DQ单独一根。这样做的理由是让信号回流的面积最小化,降低环路天线效应。如果只拉两根线,传感器使用寄生供电,虽然省一根线,但在长线场景下寄生电容使得传感器供电纹波大,转换结果容易不稳定,我不建议在HVAC这种电磁环境里用寄生供电。

3. 固件实现:驱动代码与轮询调度

3.1 单总线时序基础

软件层面核心就是单总线的GPIO模拟。三个基本时序:复位脉冲、写时隙、读时隙。这里先讲清楚一个关键认知:单总线这么慢的协议为什么反而和“时序”较真?因为它靠总线上的“拉低时间长短”来表达信息。MCU必须先拉低总线至少480us,释放并等待传感器拉低约60-240us作为存在脉冲,完成复位。写1时,MCU拉低总线1us到15us(我习惯用6us),然后释放;写0,则拉低整个时隙的60us以上。读时序则要求MCU拉低1us后立刻释放,并在采样窗口内读取电平。PIC18F46K40的IO口翻转时间在几十纳秒级别,距离时序要求留出了极大余量,这也是用它做模拟单总线很舒服的原因。

实现上我建议用延时函数配合开关中断的方式。单总线的时序窗口虽然不苛刻,但在读写过程中还是尽量关掉中断,否则一个定时器中断服务程序跑几十微秒,就可能把读时序的采样点挤出去。实测下来,读取一颗传感器全部数据的过程中,关中断时间总共不到几毫秒,对系统实时性几乎无影响。

3.2 驱动代码关键片段

以下是我在项目里用的驱动骨架,删掉了和硬件平台绑定的寄存器细节,保留逻辑主线:

// 复位单总线,返回1表示检测到设备 uint8_t ow_reset(void) { DQ_OUT = 0; // 配置为输出并拉低 delay_us(480); // 复位脉冲 DQ_IN = 1; // 释放总线,转为输入 delay_us(60); // 等待设备低电平出现窗口 uint8_t presence = (DQ_READ == 0); delay_us(420); // 等待存在脉冲结束 return presence; } // 写一位 void ow_write_bit(uint8_t bit) { DQ_OUT = 0; if (bit) { delay_us(6); DQ_IN = 1; delay_us(64); } else { delay_us(60); DQ_IN = 1; delay_us(10); } } // 读一位 uint8_t ow_read_bit(void) { DQ_OUT = 0; delay_us(1); DQ_IN = 1; delay_us(5); // 在采样窗口读取 uint8_t bit = DQ_READ; delay_us(60); return bit; }

延时函数用定时器或者_nop()汇编都行,关键是编译器优化不能把延时优化掉,我一般用不透明的延时函数,传入毫秒或微秒参数,编译时不会被识别为纯函数裁剪。写字节、读字节就是按位循环,不再赘述。

读PJ85718DM温度数据的完整流程是这样:

  1. 复位,读是否存在;
  2. 发送ROM匹配命令,后跟目标节点的64位序列号;
  3. 发送温度转换命令(0x44),告诉这颗传感器开始采样;
  4. 等待转换完成,12位分辨率下典型转换时间约750ms;
  5. 再次复位;
  6. 跳过ROM或匹配ROM,发送读暂存器命令;
  7. 连续读取两个字节的温度数据,第9个字节是CRC,可以做校验。

第2步的ROM匹配很重要。同一个总线上挂多颗传感器时,跳过ROM会把所有传感器同时唤醒,它们会在总线上“打架”。所以我的轮询代码里缓存一个节点表,记录了每颗传感器的序列号和安装位置(本地/远程),每次操作都走匹配ROM路径。读取暂存器后我用CRC校验,一旦校验失败就丢弃本次数据而不是直接使用,这是防止远程线路噪声污染数据的关键手段。

3.3 本地与远程节点的轮询调度

轮询调度逻辑看起来简单,做扎实了不容易。我用的策略是:每1秒执行一轮完整采集,一轮采集的时间预算为:每颗传感器的转换等待时间按750ms估算,但注意这些时间是串行的还是并行的,可以优化——先向所有节点发送转换命令,再统一等待750ms,之后再逐个读取数据。这样无论挂多少颗传感器,一轮采集的耗时都约等于最大转换时间加读取时间,而不是“节点数乘以转换时间”。

具体流程:

  1. 复位,跳过ROM,广播温度转换命令,让所有节点同时开始转换;
  2. MCU进入等待状态,这750ms里可以干别的事(处理显示、通信、按键),用一个标志位表示“正在转换”;
  3. 转换结束后,遍历节点表,逐一复位、匹配ROM、读取温度数据和CRC;
  4. 读到的温度做合法性判断(比如超出-55℃到+125℃的范围就认为异常);
  5. 更新显示和通信接口的数据缓存,清零错误计数;
  6. 如果某节点连续3次读取超时或CRC错误,在状态字里标记该节点离线,并且不阻塞其他节点的采集。

这种广播转换加串行读取的模式,在8位MCU上非常实用。有一年我做项目时试着每颗传感器单独转换单独读取,三颗传感器轮询一轮要2.5秒,用户体感上温度刷新明显变慢;改成广播转换以后,刷新周期缩短到1秒左右,而且总线占用时间反而变少了,因为读取数据的时间比转换时间小一个数量级。

3.4 用PIC18F46K40外设降低CPU开销

PIC18F46K40和其他普通8位MCU的一个不同点,是它带了一批所谓“核心独立外设”。在单总线这种场合,最有用的其实是那两个可配置逻辑模块(CLC)。我做过一个优化:用CLC把复位脉冲的480us定时和IO自动翻转组合起来,通过硬件定时产生复位脉冲,MCU发出一句触发命令后就不需要一条一条延时指令了。

不过说实话,对于只挂三五个节点的应用,CPU算力完全够用,CLC优化属于锦上添花。我更看重的是MCU内部的看门狗和欠压复位模块:看门狗超时时间我配置成2秒,正常工作时每轮采集结束喂一次;如果传感器总线被干扰导致程序卡在某个延时里,看门狗能在一秒多以后把MCU拉回来,这个兜底对现场无人值守的设备意义非常大。在嵌入式场景里,温度监测往往是“数据最后一道防线”,主控可以重启,但温度数据不能长期缺失,所以一个有看门狗兜底的采集循环比任何代码优化都值钱。

4. 标定、调试与常见问题排查

4.1 温度误差来源与软件修正

PJ85718DM这种传感器出厂误差通常在±0.5℃级别,对HVAC控制来说已经够用。但实际工程里还会引入两类额外误差:一是传感器安装位置造成的测量误差,比如远程探头的护套探头里如果没涂导热硅脂,风管里的空气不流通时,读数可能比真实温度滞后好几度;二是长线压降和地电位差异带来的误差,这个问题在PJ85718DM上是真实存在的。我发现当远端节点和主控板之间有较长地线时,传感器读到的VDD和主控的GND之间存在零点几伏的动态偏差,反映到温度数据上就是读数整体偏移。

软件修正的办法有两种。简单做法是本地加一个高精度参考温度计,在0℃和50℃附近做两点校正,得到偏移量和增益系数,写入Flash保存,每轮读取后做一次线性修正。复杂一点的做法是在每颗传感器旁边加一个已知阻值的参考电阻测地线压降,实时补偿,但对HVAC来说没必要。我的经验是:先把安装工艺做好,再谈软件修正。很多“传感器不准”的问题其实是安装位置选得不对,温度梯度大、气流不充分、和热源距离太近,这些就算传感器再准也白搭。

4.2 实测过程中的三种典型故障

项目里第一次上电,我就遇到了经典三连。第一种:远程传感器可以识别,但读数周期性跳变,波形上表现为每隔几秒出现一次毛刺。排查到是远端传感器供电线在三线接线端子上松动,接触电阻忽大忽小。把端子压紧、打胶固定后问题消失。这种故障的隐蔽性在于:单总线数据线上偶尔一个毛刺,CRC校验很容易拦住,但如果毛刺出现在传感器转换过程中,转换结果就会整体偏移,而且不报错。

第二种:压缩机启动瞬间,远程温度读数出现-127℃这种极端值。这是典型的动力线干扰耦合,共模噪声把单总线拉到了逻辑误判区。我在远程节点入口加TVS和小电容后,极端读数基本消失。如果还不能解,就把屏蔽层从“两端接地”(当时施工队图省事,把屏蔽层在两端都接了地)改成“主机端单点接地”,噪声电流就不会通过屏蔽层形成环路。

第三种:距离超过25米后,总线电平无法拉低到有效低电平。这里要算一下线缆电容。双绞线的线间电容大约50pF/m,25米就是1250pF,再加上三颗传感器的输入电容,总线总电容轻松超过1.5nF。单片机的开漏输出可能拉不低,或者说拉低速度不够快。这个问题的对策是适当降低上拉电阻,我用2.2kΩ替换4.7kΩ,上升沿明显变利落。注意不能无限减小上拉,否则低电平灌电流太大,会触发IO口的电流限制。

4.3 问题排查速查表

现象优先检查顺序常见根因解决办法
完全检测不到设备总线电压、上拉电阻、接线顺序DQ线虚接、上拉电阻缺失万用表量DQ空闲电平,确认上拉到5V
识别到ID但读数固定一个值不变传感器供电、接线端子远端VDD断开量传感器引脚电压,确认3.0V以上
读数周期性跳变松动端子、供电压降、屏蔽接地接触电阻、地线环路压紧端子、屏蔽层单点接地
干扰时出现极端值TVS、滤波电容、屏蔽变频器共模干扰增加防护器件、双绞线走线远离动力线
长距离后无法通信上拉电阻、线缆电容总线电容过大上拉从4.7kΩ降到2.2kΩ
两节点互相干扰ROM匹配逻辑广播命令时节点同时应答严格用64位序列号匹配后读取

这套表格基本就是我在现场排查时的“检查清单”。还有个经验:不要在温度传感器总线上使用“飞线”临时测试,飞线没有双绞,绕线电感更大,很多噪声问题在测试台上测不出来,一接现场就现原形。测试阶段就要尽可能还原现场线长和走线环境。

一点个人体会。现在回看这个项目,PJ85718DM和PIC18F46K40这套组合最让我满意的不是某一项性能指标,而是把“本地加远程、一条总线、一套驱动”这种工程优雅感做到了。单总线技术本身并不新,但配合有丰富内部外设和宽裕处理能力的现代8位MCU,依然能在HVAC和嵌入式温度监测这类成本敏感、可靠性要求高的场景里长期服役。如果你的传感器数量超过6个,记得把总线拆成两路分担电容,或者干脆加一颗总线驱动器;如果现场走线要跨楼层,那就不是单总线能管好的事了,直接上RS485网络会更稳。但就大多数控制柜级别的应用来说,照着上面的硬件布局和固件轮询思路做,踩坑概率会小很多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询