做HVAC控制器那阵子,我经常被客户追问:能不能同时测回风口温度和换热盘管温度?一开始觉得很简单,直到在冷库项目里用PJ85718DM搭配STM32L031C6做了一套本地与远程温度监测方案,才算把这件事彻底想明白。这颗传感器负责把测温点铺到线缆远端,这颗低功耗单片机负责在强电环境下稳定地把数据算出来。这篇文章我会把需求背景、选型逻辑、硬件接线、软件驱动、低功耗策略和实际踩过的坑全部理一遍,给正在做嵌入式温度采集或者HVAC控制器开发的读者一个可以照抄的参考。
PJ85718DM是单总线数字测温方案里很典型的一颗芯片,STM32L031C6则是ST的低功耗Cortex-M0+单片机。两者组合最舒服的地方在于:单总线只需要一根数据线就能挂多路探头,L031又恰好有足够的GPIO和低功耗模式来处理这种“平时睡、醒来看一眼温度继续睡”的活儿。接下来我从需求源头开始拆。
1. 从需求源头说起:本地与远程温度在什么场景下真正需要
1.1 暖通和制冷设备为什么要同时看两个温度点
很多非暖通背景的嵌入式工程师第一次听到“本地温度”和“远程温度”会觉得抽象。我举个实际例子:一台风冷热泵机组安装在屋顶,控制器盒子在室内配电箱里。回风温度探头装在风机入口附近,这是“本地”;而室外换热器盘管表面温度、压缩机回气管温度,装在几十米外的室外机上,这就是“远程”。
对于制冷系统而言,回风温度决定风机启停和档位,盘管温度决定除霜周期和化霜截止,压缩机回气温度则用来做保护。几个温度点缺一个,控制逻辑就是瞎猜。过去很多老设备用NTC热敏电阻拉长线,问题在于NTC的阻值变化是非线性的,线长之后分压误差会明显放大,而且每个探头都要单独占一路ADC通道加一路独立走线。
用单总线数字传感器替代NTC后,多探头可以共用一条总线,每个传感器自带64位ROM序列号,单片机通过寻址就能区分每一路温度。这正好覆盖“本地+远程”的物理需求:本地探头挂在总线短端,远程探头通过双绞线或屏蔽线拉到几十米外,程序逻辑上没有任何区别。
1.2 单总线拓扑是怎么做到“一根线读多个点”的
单总线通信的核心思想是把时钟和数据复用在同一条线上,所有传感器并联在这根数据线上。单片机通过严格的时序窗口向总线上发送命令,每个传感器靠内部的64位序列号来决定“这条命令是不是发给我的”。
一次典型的温度读取过程分三步:第一步单片机发起复位脉冲,把所有传感器从总线状态归零;第二步发ROM命令,比如读ROM或者按序列号匹配;第三步发功能命令,比如启动温度转换或者读暂存器。远程探头距离超过10米后,线缆电容会明显增大,所以在软件时序和硬件上拉阻值上都要做相应调整,这部分后面专门讲。
2. 器件选型背后的几个关键考量
2.1 PJ85718DM 为什么比 NTC 方案更适合这个项目
我在做方案对比时核心比过三种路线:NTC加ADC、I2C温度传感器、单总线数字传感器。NTC方案在低端设备里依然便宜,但精度靠校准,线长后误差大,ADC通道占用多。I2C传感器通信速度快,但地址冲突需要额外管理,而且I2C线缆的抗拉伸能力弱,不适合长距离布线。
PJ85718DM这类单总线传感器的主要优势是布线极端简单。一条数据线加一条地线就能把探头铺到设备各处,传感器内部已经把温度数字化,抗干扰能力远强于模拟电压传输。另一优势是多探头寻址能力,理论上一条总线可以挂几十个传感器,对HVAC设备这种“几个点位分散在不同位置”的场景来说非常合适。
需要说明的是,PJ85718DM的测温范围、分辨率和转换时间等详细参数要以你手上的数据手册为准。我在项目里用到的这颗芯片支持常见的9到12位分辨率配置,12位分辨率下测温精度足够温控系统使用,转换时间在数百毫秒量级,对暖通这种秒级响应的控制环路完全没有压力。
2.2 STM32L031C6 在强电环境里的底气哪里来的
HVAC设备的控制板通常和220V驱动电路放在同一个壳子里,这对应单片机选的抗干扰能力和宽压范围都提出了要求。STM32L031C6的工作电压范围覆盖1.65V到3.6V,在电源波动较大的工业环境里可以直接用3.3V LDO供电,再配合内部的多个时钟源和看门狗,运行稳定性在同类小封装MCU里是很能打的。
它的Cortex-M0+内核跑在32MHz,Flash有32KB,SRAM有8KB。我实际把单总线驱动、多个探头的ROM表、温控逻辑和一段简易的Modbus从站协议代码全放进去,Flash还剩下将近一半。对这个应用场景来说,资源没有浪费,也没有出现不够用的焦虑。
最重要的是低功耗能力。冷库和无人值守机房的设备经常需要掉电后继续记录温度曲线,或者靠电池维持一路温度报警。L031在睡眠模式下电流是微安级,唤醒后几十毫秒内就能完成一次温度采样并再次睡下。这在后面第5部分我会结合唤醒流程详细展开。
2.3 组合方案的整体功耗估算
我按最保守的方式算过一笔账:12位分辨率转换期间传感器电流约1.5mA,持续几百毫秒;单片机处于睡眠模式时整板电流大约4到8微安。假设每30秒唤醒一次读温度,每次唤醒加转换总耗时约1秒,平均电流估算公式为:
I_avg = (I_active × t_active + I_sleep × t_sleep) / T_total
带入数字大约等于(3.2mA × 1s + 6µA × 29s) / 30s,约等于110µA。一颗常见的18650电池容量约2500mAh,理论上能撑超过两年,实际由于电池自放电和温度传感器的静态电流,保守估计一年半以上没问题。这对于靠电池供电的冷链记录仪来说非常实用。
3. 最小系统的硬件设计和采暖/制冷现场的布线坑
3.1 最小系统怎么搭
STM32L031C6最小系统跟我做过的多数STM32开发板类似,芯片加上供电退耦、复位电路、SWD调试接口和一颗外部低速晶振(如果用RTC就需要)。由于L031内部有多个振荡器,单纯跑裸机Main Loop甚至可以不接外部晶振,这降低了故障率。PJ85718DM连接到任何一个GPIO即可,但建议选支持外部中断的引脚,后面做低功耗唤醒会方便一些。
数据线上接一颗上拉电阻到3.3V,这是单总线工作的必要配置。传感器那边的供电比较推荐外部供电方式,也就是VDD接3.3V,GND共地,数据线单独接回单片机。三个引脚:VDD、DQ、GND,千万别图省线用寄生供电,在长线场景下寄生供电非常容易出问题,后面讲坑的时候会细说。
3.2 上拉电阻与线缆长度到底怎么配
单总线上拉电阻的阻值要跟总线的线路电容匹配。短距离(1米以内)用4.7kΩ到10kΩ都没问题,但探头拉到20米以上时,线缆分布电容会拖慢数据线上的边沿,导致通信时序失败。我实测下来,20米左右的普通双绞线,上拉电阻降到2.2kΩ效果明显好转,30米以上建议1kΩ左右,具体电路还要看实际波形。
如果总线特别长、传感器数量又多,一个更稳妥的做法是在接近单片机的数据线上加一个单总线缓冲器,相当于用有源器件代替无源上拉,把总线电容和单片机引脚隔离开。如果不想额外加芯片,另一个土办法是选用屏蔽双绞线并把屏蔽层单端接地,线缆电容比普通线更低,抗变频器干扰能力也更好。
3.3 防静电和共地处理
HVAC现场经常会有静电放电和感应雷问题,尤其是室外机的传感器走线,几十米的线缆本身就是一根天线。我至少见过两起传感器被静电打坏的现场,现象是温度读数变成固定偏差或者总线直接被拉死。后来在数据线上加了TVS管钳位,同时保证所有传感器的屏蔽层在控制器端做单点接地,问题基本消停。
再强调共地问题。单总线传感器和单片机之间除了数据线,必须有一根可靠的GND线。有些安装工人会省地线,只拉数据线,结果数据线在实际中既当代又带回流路径,轻则通信不稳定,重则整个总线工作不正常。我的做法是每路远程探头都强制要求三线制并现场检查,别嫌麻烦。
4. 本地与远程温度读取的软件实现
4.1 单总线驱动的时序细节
单总线对时序精度有要求,但也没有很多人想象的那么苛刻。复位脉冲要求主机拉低至少480µs然后释放,传感器会在15到60µs后拉低总线给出存在脉冲。写时序时,写0是拉低60到120µs,写1是拉低1到15µs后释放。读时序则是主机拉低1到15µs后释放,然后在15µs内采样总线电平,因为传感器用“是否延长拉低”来表示0或1。
在代码实现上,最稳妥的方法是操作GPIO输出寄存器,直接刷BSRR/BRR寄存器,并在临界时序段关中断。我试过用HAL库函数来做位操作,延时函数又叠加了一层开销,长线之后时序余量不够,所以最终改成了寄存器级驱动加临界区保护。核心思想是用一个带参数的总线延时函数,配合DWT计数器实现微秒级延时,比单纯靠循环精度高得多。这部分代码框架大致如下:
uint8_t ow_reset(GPIO_TypeDef *port, uint32_t pin) { uint8_t presence = 0; OW_LOW(port, pin); delay_us(500); OW_RELEASE(port, pin); delay_us(60); presence = OW_READ(port, pin) ? 0 : 1; delay_us(240); return presence; } void ow_write_bit(GPIO_TypeDef *port, uint32_t pin, uint8_t bit) { if (bit) { OW_LOW(port, pin); delay_us(3); OW_RELEASE(port, pin); delay_us(55); } else { OW_LOW(port, pin); delay_us(60); OW_RELEASE(port, pin); delay_us(5); } }实测下来,这套时序在1米短线和30米长线上都能正常跑通,关键在于延时一致性。如果换成跑FreeRTOS的系统,必须在底层把这几个函数用临界区保护起来,不能被任务切换打断。
4.2 多探头轮询与掉线处理
本地和远程多路温度采集在软件上的核心是维护一张ROM表。首次上电时我调用搜索ROM命令枚举总线上的所有传感器,把64位序列号存进数组;之后每次轮询,用匹配ROM命令选中一个传感器,再发温度转换和读暂存器命令,逐个把温度数据取回来。
轮询间隔我设成2秒一次。单总线一次温度转换最长需要数百毫秒,所以正确的处理顺序是:先发一次广播的温度转换命令,让总线上所有传感器同时开始转换;等待转换完成;然后逐个匹配ROM读取各自的暂存器。这样总耗时远小于逐个传感器轮流转换,效率高很多。
掉线处理是实际项目中必须考虑的。远程探头被老鼠咬断线、接插件氧化、现场工人误拔线,都是真实发生过的故障。我在读取函数里做了三项检查:复位脉冲是否正常返回存在脉冲、读回的暂存器CRC是否匹配、温度值是否在合理范围内,比如-55到125度之外直接判无效。一旦连续多次无效,软件会把这个探头标记为Offline,同时往上位机报故障码,而不是显示一个离谱的温度值把控制逻辑带偏。
5. 低功耗睡眠唤醒与温度采样的配合节奏
5.1 睡眠模式的选择和唤醒源配置
STM32L031C6的睡眠模式要做到微安级,关键是把时钟系统切到低频或者干脆把主时钟关掉,让内核停住,所有未使用的外设时钟也全部关闭。项目里我用的是Stop模式,保留RTC低速时钟继续走时,设置一个秒级或分钟级的中断作为唤醒源。
唤醒流程上需要注意一个细节:从Stop模式唤醒到CPU全速运行,需要等待HSI和PLL重新稳定。L031的硬件会等待时钟稳定后再从中断返回,一般不需要额外软件延时,但如果唤醒后马上跑单总线复位时序,我会加一段几百微秒的等待,避免在时钟还没完全稳定时就采样。
5.2 唤醒后读温度的动作编排
我实际用的流程是:RTC中断唤醒,先读取当前传感器温度,把结果存到备份寄存器或者Flash缓存里,再判断当前温度是否越过报警阈值,越过了就额外拉高一个报警引脚,然后立刻重新进入Stop模式。整个过程从唤醒到重新睡下不到1.2秒,其中大头是单总线的转换等待。
这里有个优化点:PJ85718DM的转换是传感器自己完成的,单片机可以在发出转换命令后立即进入低功耗模式,等定时器或RTC再次唤醒后再来读结果。这样单片机在几百毫秒的转换等待期基本不耗电,真正实现了“指令发出后睡觉,醒来拿结果”的采温方式。不过要保证转换命令发出后传感器能在这段时间内保持供电状态,不能直接切掉传感器的电源。
6. 实测数据、踩坑记录和个人体会
6.1 不同线长和上拉阻值下的实测表现
我拿一盘50米的双绞线做了一组对比测试,用同一个传感器接不同长度的线缆,读取12位分辨率下的温度值,并用医用级测温仪做参考。结果见下表:
| 线缆长度 | 上拉电阻 | 通信结果 | 温度读数偏差 |
|---|---|---|---|
| 1米 | 4.7kΩ | 稳定 | 0°C |
| 10米 | 4.7kΩ | 稳定 | 0°C |
| 20米 | 4.7kΩ | 偶发CRC错误 | 0°C |
| 20米 | 2.2kΩ | 稳定 | 0°C |
| 30米 | 1kΩ | 稳定 | 0°C |
温度读数本身没有因线长出现系统性偏移,因为传感器内部已经把温度数字化了,线缆只影响通信可靠性,不影响精度。这也从另一个角度验证了选数字传感器的意义:模拟信号长距离传输的衰减和干扰问题在单总线链路里被大大弱化。
6.2 三个让我印象深刻的坑
第一是寄生供电的教训。样板阶段为了省一根线,把传感器设置在寄生供电模式,也就是只有VDD和GND两根线,由数据线给传感器储电。短距离测试没问题,一旦把远程探头实际装上,温度转换瞬间电流需求变大,传感器供电电压跌落,转换结果经常出现跳变或者干脆返回85摄氏度这个典型的电源供电不足错误值。后来全部改成外部供电三线制,问题一次性消失。
第二是读取时序过于靠后导致偶尔读错。长线情况下总线电容会让信号边沿变缓,如果在读时序的末尾才采样,正好采到传感器信号和线缆反射叠加的不确定区间。把采样点尽量前移,在读时序拉低释放后立即采样,错误率会明显下降。
第三个坑跟HVAC变频器有关。室外机附近有大功率变频器时,未加屏蔽的数据线在压缩机启动瞬间会出现长达几百毫秒的通信噪声,表现为传感器突然掉线或者CRC连续报错。我把传感器供电从开关电源改到线性稳压器供电,再配合屏蔽双绞线和TVS管,才算根治。电源噪声对远程探头的影响远比想象中大。
6.3 这类项目后面还能怎么扩展
监测做完之后,很自然的下一步是控制。STM32L031C6的8KB SRAM和32KB Flash足够塞下一套完整的PID或简单的开关量温控逻辑,加上一路PWM驱动风机或者四路继电器控制加热丝,整套方案就能从“监测”升级成“监测加控制”。
如果客户要远程查看温度数据,L031的USART可以外接一个RS485收发器跑Modbus RTU,温度数据和故障码就能直接并入楼宇自控系统。更复杂一点的无线化需求,用L031唤醒后通过串口唤醒一个低功耗LoRa模块上报数据,也是一条成熟路线。整体方案从传感器到主控到通信链路,延展性都很好。
做嵌入式和HVAC测温项目这两年,我的体会是方案好不好用,往往不是看器件多高级,而是看在现场连不连得通、稳不稳定。PJ85718DM加STM32L031C6这套组合,成本克制、接线简洁、代码量不大,又能实打实地把本地和远程温度都摆在工程师面前,对中小批量暖通控制设备和小型嵌入式测温系统来说,是一个相当舒服的出发点。