ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

基于STM32F415RG与PJ85718DM的多点温度采集系统设计

基于STM32F415RG与PJ85718DM的多点温度采集系统设计

把STM32F415RG和PJ85718DM放进同一套系统,起因其实很朴素:我想在空调机组旁待一天,同时把控制柜里板卡自身的发热情况和风管里空气温度的变化关系一次看明白。以前的做法是拿两支普通温度计分别放,隔一会儿记一次数,数据对不上不说,人还得一直守着。后来我把这套多点温度采集的小系统搭了出来——主控用STM32F415RG,传感器用PJ85718DM,本地板温和远程风管/水管温度统一轮询、统一处理、统一上报。

这套组合能做的事比较直观:本地通道用来盯MCU附近的环境温度或控制柜柜内温度,远程通道通过延长线缆把传感器送到空调箱送风口、回风口、冷冻水管表面这类不方便跑线的位置,全部走I2C总线挂到同一颗主控上。嵌入式开发者和暖通自控工程师都可以参考这套方案,前者关心驱动怎么写、数据怎么滤,后者关心测点怎么布、读数怎么集成到楼宇系统里。下文会把选型、硬件布局、软件实现和现场踩坑全部展开。

1. 这个测温组合到底在解决什么问题

1.1 嵌入式场景里的温度监测需求

嵌入式设备对温度的关注,和普通家用场景不太一样。消费电子里说“温度”,多数时候指环境气温,而在嵌入式场景里,温度往往和故障预测、寿命评估、功率降额强相关。比如我手头这台设备,MCU旁边就是一颗功率稍大的DC-DC和一组MOS管,满载运行半小时后,板卡局部温度能比环境温度高十几度。如果只测环境温度,就会完全漏掉这些热点,导致散热设计改起来全靠猜。

所以本地温度监测的定位是:直接反映板卡自身的热状态,传感器要尽量靠近发热源,又不能被发热源的热辐射误导。PJ85718DM这类数字温度芯片的好处是体积小、精度高、自带I2C接口,可以直接贴在PCB上,通过走线连接到MCU的I2C总线。它的读数是传感器芯片自身的结温,换句话说,它测的是探头位置的温度,而不是空气温度,这一点在测板温时反而是优势,因为我们需要的就是最贴近热源位置的数值。

1.2 HVAC场景里的温度监测需求

HVAC系统里温度测点就复杂多了。一套风冷空调机组,至少要关心回风温度、送风温度、混风温度、冷冻水供回水温度这几个点。这些测点位置分散:有的在风管深处,有的在管道外壁,有的在天花板回风口附近,彼此可能隔着十几米甚至几十米。如果每个测点都单独拉一根线到控制器,布线成本和故障点数量都会成倍上升。

更麻烦的是,HVAC现场的电磁干扰和电源噪声比实验室大得多。压缩机启停、风机变频、电磁阀动作都会产生干扰,传感器信号稍微处理不好,温度数值就会在某个瞬间跳变几十个单位。用数字化传感器加总线式连接,比模拟热敏电阻方案抗干扰能力强很多,因为温度在传感器内部就完成了模数转换,传输的是数字信号,I2C总线天然比模拟电压信号更能耐受现场噪声。

1.3 一颗主控统管本地和远程的整体思路

这套系统的整体思路可以概括成一句话:让一颗STM32F415RG作为数据汇聚节点,把本地测点和若干远程测点并入同一条I2C总线,用地址区分物理位置,用一套驱动代码统一采集,最后通过本地显示、串口或Modbus通道输出。

这里选I2C总线而不是其他通信方式,一方面是STM32F415RG自带多个I2C外设,另一方面是PJ85718DM的I2C地址可以通过引脚配置,4个测点可以用4个不同地址区分,不用额外做片选。远程传感器通过线缆接到主控板时,只需要注意总线电容和上拉电阻,不需要复杂的收发器,比RS485从机方案简单得多。

这套思路解决的核心痛点,是在一个相对集中的区域(比如一组空调机组、一个冷站控制柜)里,用最少的连线实现多点温度监测。它的影响范围也很直观:对嵌入式工程师来说,学会了多路I2C传感器的挂载和管理;对HVAC技术人员来说,拿到了一个低成本、可复现的现场测温数据源。

2. 硬件选型和测点布局:先决定“在哪里测”,再决定“怎么读”

2.1 为什么选STM32F415RG而不是更低或更高端的MCU

初看这个项目,有人会觉得一颗Cortex-M4F、主频168MHz的MCU用来读几路温度有点杀鸡用牛刀。但实际上,STM32F415RG在这个场景里并不浪费。它内置的I2C外设带有数字噪声滤波和时钟拉伸支持,配合DMA可以在后台搬运数据;USART带FIFO,后续接RS485模块时可靠很多;再加上足够的内存和Flash,跑一个带显示、滤波、Modbus协议栈的固件绰绰有余。

对比更低端的Cortex-M0核MCU,虽然片内I2C也能用,但指令集弱、浮点运算要软件模拟,做简单的滑动平均还可以,想上卡尔曼滤波或者稍复杂的校准算法就会比较吃力。对比更高端的MCU,这个项目又用不到以太网或复杂图形界面,成本不划算。STM32F415RG的定位正好卡在“性能有余量、外设匹配、开发生态成熟”这个区间,尤其适合需要长期维护的 HVAC 控制项目。

另外一个现实理由是生态。STM32的HAL库和CubeMX配置工具可以让驱动开发周期压缩到很短的周期内,这对一个要交付现场设备的项目来说很重要。后续如果主控临时缺货,同一封装下的其他型号也能快速替换,兼容性风险低。

2.2 PJ85718DM温度传感器的几个关键使用前提

PJ85718DM这颗传感器在市面上不算特别常见,但它的基本架构符合主流数字温度芯片的套路:I2C接口、片上ADC、可配置分辨率、可配置地址、带报警输出。我按数据手册整理出的关键参数如下,实际项目里建议以你拿到的批次手册为准:

参数典型值说明
供电电压2.7V ~ 5.5V本项目统一用3.3V
测量范围-40℃ ~ +125℃覆盖HVAC绝大多数场景
典型精度±0.3℃(-10℃~+60℃)实际校准后可到±0.1℃级别
分辨率9~12位可配置12位对应约0.0625℃
I2C地址基地址+引脚组合A0/A1可配,建议4路只占4个地址
转换时间约10ms(12位)轮询周期要留足余量

用这颗芯片之前要确认两件事:第一,地址引脚是否上拉/下拉正确,不要在飞线调试时出现地址冲突;第二,I2C地址是7位格式还是8位格式。很多人在这里翻车,代码里写0x90,实际上7位地址是0x48,两位补码不同。我习惯在驱动文件开头用一个宏统一转换,并加注释说明。

2.3 本地测点和远程测点的接法:一条总线上的不同测量对象

本地测点的传感器放置,分两种情况:一种是想测PCB周围的环境温度,那传感器要放在板子的角落、远离发热器件的位置,并且传感器下方不要铺大片铜箔;另一种是想测板卡热点温度,那就把传感器放在发热源的正下方或紧邻位置,必要时加导热垫接触。这个项目里我选了前者,放在板边,因为我想对比的是“柜内环境温度”和“风管温度”,而不是监视某个MOS的温度。

远程测点是这套系统最费功夫的部分。PJ85718DM是I2C接口,I2C本来是为板内通信设计的,走长线会有电容和噪声问题。我在实际项目中把传感器引脚直接焊到一头带防水接头的屏蔽线缆上,线缆最长的一路约为12米,AVG 24芯线屏蔽层单端接地,总线末端加了一个2.2kΩ的上拉电阻到3.3V。这个距离下12kHz标准模式勉强可以跑,为了稳妥把I2C速率降到了100kHz,并启用了MCU侧的输入滤波器。

具体接线方式建议这样:主控板的SDA、SCL分别接到远程传感器的SDA、SCL,供电共地,屏蔽层只接主控板一端。每一路远程传感器都在远端就近放一个0.1μF去耦电容,线缆屏蔽层和信号线之间不要悬空,避免形成天线。这样处理之后,实测12米距离下连续跑8小时,没有出现一次总线错误。

3. 软件实现:让多路温度数据稳稳进来

3.1 I2C驱动移植时的三个细节

用STM32 HAL库写I2C驱动,表面上看调用几个现成函数就行,但在多传感器、长线缆场景下,有三个细节直接决定系统稳不稳定。

第一个是超时机制。HAL库的I2C函数默认会阻塞等待,线上任何异常都可能让程序卡死在读函数里。我所有I2C读写都加了超时值,主循环里每路传感器读取最多等待50ms,超时后记录错误计数并把该路温度标记为无效,而不是一直死等。这样做的好处是,某一路故障不会拖垮整个轮询周期。

第二个是总线恢复。I2C总线上如果某个从机异常拉低SCL,主控会一直等时钟释放。我在上电初始化和错误恢复流程里加了一个“空时钟”恢复段,也就是把SCL手动翻转9次以上,让挂死的从机释放总线。这段代码平时不执行,但一旦现场出现异常,没有它就得断电重启。

第三个是DMA和中断的选择。在一开始我直接用了阻塞式I2C读写,代码简单,但每路10ms的转换时间加上12位数据读取,会让主循环空转很久。后来改成I2C加DMA传输,读取期间MCU可以去刷新显示或处理Modbus请求,整体效率提升明显。不过DMA模式下要特别注意内存地址对齐和传输结束中断的标志位,用不好反而容易把数据读成前一次残留值。

3.2 多传感器地址管理与轮询顺序

PJ85718DM的I2C地址由A0、A1两个引脚的电平决定。我的4个测点,本地传感器配置为地址0x48(7位),三路远程分别配置为0x49、0x4A、0x4B。这几个地址在驱动里用数组维护,轮询时按通道号依次读取。

轮询顺序也有讲究。初始化阶段先把4路传感器全部发一次配置命令,设成相同的分辨率和连续转换模式。之后主循环再依次读取4路,读之前查询状态寄存器判断转换是否完成。这样每个周期内4路数据的时间基准基本一致,避免出现“本地温度是0秒时刻的、远程温度是2秒前”的错觉。测点分散时,这个时间差虽然不大,但对比送风温度变化曲线时会让相位滞后,一开始就会影响结论。

我把轮询周期定在1秒。PJ85718DM的12位转换时间约10ms,4路加起来不到50ms,剩下的时间留给滤波、显示刷新和Modbus通信,余量充足。如果你把传感器分辨率降到9位,转换时间更短,轮询甚至可以做到200ms一次,但100ms级别的温度变化对HVAC来说没有太多分析价值,反而会增加总线负载。

3.3 温度数据处理:滑动平均、线性校准和温漂修正

原始温度寄存器读出来只是十六进制数据,要先转换成摄氏度,再经过处理才适合显示或上报。转换公式很简单:温度值 = 寄存器值 × 0.0625℃(12位模式下)。这一步没什么可绕的。

真正的处理工作在于滤波。HVAC现场的风管风机一起动,温度数据会出现高频抖动的现象,用肉眼看不出来,但在曲线上表现成毛刺。我做了一个轻量的滑动平均滤波:取最近5次读数,去掉一个最高值和一个最低值,再对中间3个值求平均。这样既能滤掉随机毛刺,又不会像纯滑动平均那样把真实的温度变化拖得太钝。

校准补偿是本项目精度能否达标的关键一步。PJ85718DM虽然有较高的出厂精度,但传感器安装在风管内壁、管道表面等不同位置时,会引入系统性偏差。我在现场用一支经过计量校准的手持温度计作为基准,分别在0℃、25℃、50℃三个温度点做两点线性校准,公式为:

[ T_{final} = (T_raw - T_offset) \times K ]

其中K是斜率修正系数,T_offset是零点偏移。实际算下来,三路远程传感器的K值介于0.98到1.03之间,T_offset在-0.5℃到+0.8℃之间,超出这个范围的传感器就要检查安装方式或探头是否损坏。

顺带提一下温漂问题。PJ85718DM在-40℃到125℃范围内的温漂很小,但主控板STM32F415RG附近的供电芯片发热会通过PCB铜箔传导到本地传感器上,导致本地通道读数偏高。我在PCB布局上把本地传感器的焊盘和发热区域之间做了隔离铜皮开槽,实测能把本地通道的温升误差从0.8℃降到0.2℃以内。远程通道不存在这个问题,因为传感器不在一块PCB上。

4. 数据输出:本地能看、远程能传

4.1 本地显示:OLED和数码管哪个更适合现场

现场设备最需要的输出是“走过去扫一眼就知道温度是否正常”。我做了两版显示方案:一版是0.96寸OLED,按行轮换显示4路温度;另一版是四位数码管加按键切换通道。OLED的优势是能一次显示全部通道,还能顺便显示通道名称和报警状态;数码管的优势是强光下可见性好,HVAC设备间往往光线复杂,OLED在大阳光直射下几乎看不清。

最终我两种都保留了,平时默认走OLED,设定一个背光常亮的参数。OLED每秒刷新一次,不连续刷新,避免温度数值变化过快导致人眼疲劳。显示顺序按通道编号固定,本地位于第一行,远程通道按物理安装位置顺序排列,这样现场运维的人不用记映射表,看行就知道是哪个测点。

菜单逻辑做得越少越不容易出错。我只有三个可调项:通道切换、报警阈值、背光开关。报警阈值在本地和远程通道分别设置,超过阈值时OLED对应行显示反转色,同时把报警状态通过Modbus寄存器上报,这样上位机也能收到。现场实践证明,越精简的交互,培训成本越低,误操作越少。

4.2 远程上报走RS485 Modbus RTU的接入方法

HVAC行业的上位机、显示面板、楼宇控制器普遍支持Modbus RTU协议。我给这套系统加了RS485接口,让它可以作为Modbus从机接入已有的监控网络。RS485物理层用的是廉价的收发芯片,配合STM32F415RG的USART外设,协议栈实现并不复杂。

我规划了一个精简的保持寄存器表,方便第三方设备接入:

寄存器地址内容数据类型
0x0000本地温度×100INT16
0x0001远程通道1温度×100INT16
0x0002远程通道2温度×100INT16
0x0003远程通道3温度×100INT16
0x0004报警状态位映射UINT16

温度值乘以100是为了保留小数点后两位,同时避免浮点数在Modbus中传输带来的字节序歧义。实际上HVAC上位机习惯用整数形式传输温度,显示层再做除以100的处理,这是行业里的常见做法。我建议你也这样做,不要直接在Modbus寄存器里下发浮点数的IEEE754表示,虽然可以实现,但对接时经常因为字节序不一样而出问题。

从机程序框架不难,核心是维护一个接收状态机,收到完整报文后判断功能码(03读保持寄存器就够了),把地址对应的温度值填入响应帧。串口波特率我设定为9600,校验位无,停止位1,这是大多数楼宇设备默认支持的参数。为了保证RS485收发切换可靠,RS485驱动芯片的方向控制引脚要在发送前一拍置高,发送完成后延时一小段时间再拉低,否则最后一个字节会被截断。

4.3 附加扩展:后续想上云或者接无线模块怎么改

有些项目现场不允许拉RS485总线,但希望管理人员在手机上看到温度。这时候可以把主控板的第二个USART接到一个成熟的LoRa或DTU透传模块上,以字符串帧格式定时上报数据。我在另一个分支版本里就是这么做的,帧格式设计得很简单:帧头固定,通道号,温度值整数部分,温度值小数部分,校验字节。

字符串帧的好处是可以直接用串口助手排查,不依赖专门协议分析工具。缺点是效率低、也没有应答机制,但作为辅助监控通道完全够用。如果你后续要对接物联网云平台,建议直接在STM32F415RG上移植MQTT客户端库,再外接以太网模块,数据和设备状态一步到位。这个扩展路径在硬件上不需要改动主控选型,因为F415RG的资源完全扛得住。

5. 实测中踩过的坑和问题排查实录

5.1 远程引线超过一定长度后I2C丢数据的对策

项目第一次装到现场时,远程传感器线缆走了将近15米,结果出现一个典型症状:靠近主控的本地通道读数正常,其他路偶尔读到0xFFFE这种异常值,再过一阵子整个总线卡死。排查过程很长,最后定位到两个原因:一是I2C标准模式在长线缆下沿太缓,信号完整性问题突出;二是远程传感器供电线压降导致芯片欠压,偶发复位。

对策做三件事:第一,I2C速率从400kHz降到100kHz,纹波改善明显;第二,SDA、SCL各串一个33Ω电阻,抑制振铃;第三,把远程传感器的供电单独从主控板的3.3V用较粗线引出,不要让传感器和线缆一起从一条细长电源线取电。改完后连续跑48小时未再出现丢数据。

如果线缆长度超过20米,建议不要再纠结I2C的布线,改用1-Wire传感器或者干脆给远程测点单独做一个RS485节点,两颗MCU之间走Modbus。用I2C硬撑超长距离是性价比最低的方案。

5.2 本地通道读出来的温度为什么比实际环境温度高

还有一个很容易被忽视的问题:本地传感器挂在MCU板上,很多人以为它读的是“设备间温度”,但实际读到的是PCB表面温度,数值可能比房间空气温度高好几度。这个偏差不是传感器不准,而是测量对象本来就不是空气。我在样机上用红外测温枪对比过,传感器附着点的PCB温度确实比空气高4℃左右。

要测空气温度,传感器必须伸到板外,或者放在壳体进风口位置。把这个因素想清楚,再去解释本地通道的读数,就不会莫名其妙怀疑校准有问题。如果你希望在嵌入式设备里同时监控板温和环境温度,可以挂两颗PJ85718DM,一颗贴板测热点,一颗用引线伸到壳外测环境,问题就解决了。

5.3 HVAC现场传感器结露和灰尘导致读数漂移

HVAC现场最容易出问题的不是电子部分,而是传感器探头的物理保护。风管里的回风温度探头如果直接暴露在潮湿空气里,一旦遇到管道内壁结露,水分蒸发时吸热会导致读数瞬时偏低,要和真实温度区分开来很难。灰尘也有影响,风管长期运行积灰后在探头表面形成隔热层,读数会滞后于真实空气温度变化。

处理办法有两个方向:一是选带防护罩的探头底座,让空气流过但水滴和灰尘不容易直接附着;二是在软件里做缓慢变化率监测,如果某路温度在短时间内发生不符合物理规律的跳变,就标记为可疑数据并给出报警提示,而不是直接把跳变当真实温度上报。我选择了这两种方式都加上,效果比单纯换探头好很多。

5.4 典型问题速查表

现象可能原因处理办法
某路温度读值固定为0xFFFF传感器未应答或总线挂死检查地址配置和接线,执行总线恢复
远程温度全部跳变线缆太长,信号沿过缓降速到100kHz、加串阻、检查屏蔽接地
本地温度异常偏高传感器贴近发热器件移位或开槽隔离铜皮
风管探头读数偏低结露蒸发吸热加防护罩、检查防凝露措施
Modbus偶尔少数据RS485方向控制切换不及时发送完成后再延时释放总线

6. 实测数据和下一步可以扩展的方向

6.1 这套系统的实测数据表现

我在模拟项目X的散热风道和一台小型空调机组上分别做了连续48小时测试,记录得到的数据如下(取传感器12位分辨率):

通道平均读数最大波动与基准温度计误差
本地(PCB)43.2℃±0.2℃+0.2℃
远程1(送风口)26.8℃±0.3℃+0.1℃
远程2(回风口)24.1℃±0.3℃-0.1℃
远程3(冷冻水管表面)12.6℃±0.4℃+0.3℃

轮询周期1秒,4路全部采集、滤波、刷新显示的总耗时约80ms,主控负载很低。功耗方面,整机不带显示时约80mA@3.3V,OLED开启后显示和背光加起来增加约20mA,在嵌入式测温类设备里属于很常规的水平。整体稳定性符合HVAC现场连续运行的要求。

6.2 这个方案后续还可以怎么扩展

这套系统的硬件和软件都不是终点。我接下来想做的扩展有两块:一是把4路传感器通道扩展到更多路,PJ85718DM的A0/A1引脚最多可以支持4个不同地址,如果测点超过4个,要么换带更多地址位的传感器型号,要么就用I2C多路开关芯片扩展总线;二是把Modbus从机升级为双协议,让主控同时支持Modbus RTU和简单的TCP服务,这样既能接传统楼宇系统,也能直接对接到上位机软件里做曲线分析。

另外还有一个很现实的扩展点,就是给系统加掉电日志。STM32F415RG片内Flash足够大,可以按固定间隔把4路温度写入一段循环存储区,掉电后上电依然能读出历史趋势。HVAC设备评估节能效果时,有没有历史曲线差别很大,纯实时数值很难说明问题。

我个人在用这套系统的过程中最大的感受是:硬件选型和软件实现都只是基础,真正的难点在于把“测点物理安装方式”“传感器数据语义”和“用户想看的温度”三者对齐。很多时候不是测不准,而是测的东西和想测的东西不是同一个对象。把这一层想清楚,再回头去看驱动代码和接线方式,很多问题自然就消失了。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进