搞温度监测的朋友应该都有体会:本地测温容易,难的是把温度数据可靠地送到远端;远程通信能打通,但现场安装环境复杂,精度和稳定性又容易翻车。我最近基于PJ85718DM数字温度传感器和STM32F767ZG微控制器,做了一套同时覆盖本地与远程温度监测的系统,用在嵌入式设备舱和HVAC管道测点场景。这篇文章就把整个项目的设计思路、硬件连接、固件关键代码、调试数据和踩坑经验完整拆开讲,适合正在做环境监控、设备温度采集或者暖通控制项目的开发者参考。
1. 项目拆解与方案选型
1.1 标题背后的真实需求
“本地与远程温度监测”这句话看起来简单,但拆开之后是两类完全不同的需求。
本地监测,指的是在设备现场直接读取温度、查看状态、触发告警。比如HVAC系统的送风管道、回水管道、机房空调出风口,运维人员需要就地看到温度数值,判断系统是否正常运行。嵌入式设备舱也一样,控制柜里元器件发热、柜内环境温度变化,都需要实时监控。本地侧的核心要求很直接:读数准、响应快、能直观显示,最好还能在超温时第一时间报警。
远程监测,则是把温度数据通过网络传到监控中心或者云平台,供管理人员远程查看和记录。HVAC场景里,一栋楼的空调机房可能分散在几十个楼层,运维不可能每个机房都跑一遍,远程汇总才是效率所在。嵌入式设备舱则在部署上更分散,可能分布在户外、地下室、远端站点,无人值守,温度数据必须主动上报。远程侧的核心要求是:链路稳定、数据传输可靠、断线能恢复、数据不丢。
两条线叠在一起,项目就变成了一个典型的边缘采集节点:本地负责高精度采集和就地展示,远程负责将数据安全送达。这需要单一MCU同时兼顾传感驱动、数据处理、本地交互和网络通信,所以主控选型不能太弱。
1.2 为什么是PJ85718DM加STM32F767ZG
先说传感器选型。
HVAC和嵌入式温度监测的测量对象温度跨度不大,基本在-40℃到+125℃范围内,但对绝对精度有要求:HVAC节能计算、能效评估都需要准确的温度差,嵌入式设备则靠温度判断热保护策略,误差大了可能误触发保护或者漏报警。
我最早试过NTC热敏电阻方案,优点是便宜、电路简单,但NTC的B值一致性差,需要逐点校准,而且在-20℃以下和+80℃以上线性度明显变差,批量生产时每路都标定非常痛苦。也试过模拟输出的集成温度传感器,但这需要MCU的ADC精度足够高,还要做好基准电压的温漂补偿,实际精度很难稳定做到±0.5℃以内。
PJ85718DM是我后来换上的数字温度传感器,内置高精度ADC,通过I2C接口直接输出数字温度值,测量精度标称±0.3℃,分辨率0.01℃,完全覆盖HVAC和嵌入式设备舱的精度需求。最关键的是它的上电时序和抗干扰能力做了加强——在工业现场电缆较长、电磁环境复杂的条件下,读数依然稳定,这比模拟方案省心太多。
再说主控选型。
STM32F767ZG是Cortex-M7内核,主频216MHz,带1MB Flash和512KB RAM,这个性能做温度采集简直是杀鸡用牛刀,但项目不只是采个温度——它还要跑本地显示、阈值告警、通信协议栈、断线重连和数据补发。M7内核跑起来非常从容,以后想扩展更多测点或者加算法模型也不至于推倒重来。
更重要的是外设配置。PJ85718DM走I2C,接一片没问题;但项目实际接了6路温度传感器,分布在不同的管道和机柜位置,I2C总线长度和地址数量都受限。好在STM32F767ZG给了3个I2C外设和4个SPI,还可以扩展I2C多路复用器,我把传感器分成两组挂在不同I2C总线上,降低了总线负载,地址冲突也好处理。
远程通信方面,这颗MCU原生带以太网MAC控制器,配合外部PHY芯片即可跑100M以太网,走MQTT或Modbus TCP都能轻松胜任。如果现场不方便拉网线,它也有多个USART可以接4G模块或者LoRa模块。可以说,从本地采集到远程上报,一颗芯片全部搞定,板子面积和BOM成本都控制在合理的范围。
2. 硬件架构与关键模块设计
2.1 系统总体架构
整套系统按功能划分为三层:采集层、控制层、远程层。
采集层由6路PJ85718DM构成,分布在HVAC管道测点和嵌入式机柜的关键发热部位。每路传感器用屏蔽双绞线引出,线长最长约8米。控制层以STM32F767ZG作为核心,负责定时轮询所有传感器、做温度校准、驱动LCD显示屏、判断超温阈值、通过RS485和以太网向外发送数据。远程层包括RS485总线上挂接的现场触摸屏,以及以太网上连的MQTT服务器,监控中心通过上位机软件实时查看所有测点温度和历史曲线。
这个三层结构的好处是职责清晰:传感器只管测,MCU只管算和传,远程平台只管看和存。哪怕远程网络瘫痪,本地显示和报警照常工作,不会因为网络故障而丧失监控能力。
2.2 PJ85718DM的接口与接线设计
PJ85718DM我使用的封装是SOT-23-6,引脚不多:电源、地、SCL、SDA,外加一个地址选择引脚AD0和一根可选的报警输出引脚ALR。
电源电压范围2.7V到5.5V,我统一用3.3V供电,和STM32F767ZG的IO电平直接兼容,不需要电平转换。芯片在3.3V下的典型功耗只有几十微安,即使6路传感器同时工作,对系统总功耗的影响也微乎其微。
地址配置:AD0引脚拉低时I2C设备地址是0x48,拉高时是0x49。所以一组I2C总线上最多可挂两个器件。项目有6路传感器,我把它们分成三组,用两个I2C外设接口,各接3路传感器——每路总线上最多两个器件地址,实际3路就需要处理。这里我做了个小设计:I2C1总线上直接挂2路(地址0x48和0x49),剩下的4路通过两块I2C多路复用器接到I2C2总线上,每个复用器通道再接1路。虽然结构复杂了一点,但每条总线的负载都控制在合理范围,信号质量有保障。
接线时需要注意几点:
- 电源和地线尽量用双绞线,SCL和SDA也要配地对,减少磁场干扰。
- I2C上拉电阻我选了2.2kΩ,在400kHz速率下8米线长的上升沿依然满足时序要求。
- 每个传感器靠近电源引脚处加100nF去耦电容,长线接入端并一个TVS管到地,防止静电和浪涌打坏芯片。
- ALR报警输出引脚接回MCU的GPIO,并加10kΩ上拉。这样传感器自身检测到超温时,即使MCU正在忙于通信,也能通过外部中断及时响应。
2.3 STM32F767ZG核心板设计
主控板我按最小系统加功能模块的思路来画:
时钟部分,用25MHz无源晶振作为HSE,配合内部PLL倍频到216MHz。STM32F767ZG的VDD和VDDA之间做常规磁珠隔离,模拟电源单独供电,保证ADC相关电路不受数字噪声影响。实际上温度数据是数字接口读进来的,ADC只用于监测板载电源电压,但隔离一下仍然值得——供电质量影响整个板的稳定性。
调试接口留了标准的SWD四线,再加UART1做日志输出。我习惯把调试日志和业务数据分开,业务数据走RS485和以太网,日志走独立串口,出问题时用逻辑分析仪直接抓,不会互相干扰。
外设分配如下:
- I2C1、I2C2:分别连接直接传感器和多路复用器后的传感器通道。
- 两路UART:一路接RS485收发器,跑Modbus RTU从站协议;另一路备用,后续可接4G模块。
- 以太网:SPI3接口连接外部PHY芯片,跑LWIP协议栈,走MQTT。
- 一组GPIO控制继电器:当任意测点温度超过设定阈值时,继电器动作,触发声光报警器。
- LCD屏采用SPI接口,刷新率不需要太高,重点是把6路温度和报警状态一目了然展示出来。
PCB布局上的一个经验:数字电路和传感器接线端子尽量分布在板子两侧,避免高速信号和低速传感器线交叉。我的板子左边是电源和传感器输入,右边是以太网口和RS485口,中间是MCU,实测下来传感器读数受到的干扰明显小于最初的紧凑布局版本。
3. 固件开发与核心代码实现
3.1 开发环境与工程搭建
固件开发基于HAL库,IDE用的是主流的ARM开发环境,调试器配了ST-Link。工程结构上按模块划分:bsp(板级驱动)、drv(传感器驱动)、app(业务逻辑)、net(网络协议栈)、sys(系统配置)。
初始化顺序很重要,我踩过一次坑:一开始先初始化I2C再初始化以太网,结果LWIP协议栈起不来,查了半天发现是ETH的GPIO和I2C1的引脚有冲突。后来把所有外设引脚分配列成一张总表,逐一比对确认没有复用冲突之后,才解决了问题。这里也给个建议:画板子之前先把全部功能模块的引脚分配表整理出来,哪些引脚被哪个外设占用,哪些引脚有默认功能,必须清清楚楚,否则后期软件阶段会非常痛苦。
3.2 传感器驱动与温度转换
PJ85718DM的寄存器结构是标准配置寄存器加2字节温度数据寄存器。初始化时先读ID寄存器确认设备在线,然后配置分辨率、单次还是连续转换模式。
HVAC场景中温度变化相对缓慢,我采用单次转换模式,每500ms轮询一次所有通道。这个周期对HVAC和机柜监测都足够了,省电又降低总线占用。如果后续需要快速响应报警,可以改成连续转换模式并启用ALR引脚的外部中断。
核心读取逻辑:
float read_temperature(uint8_t bus_id, uint8_t dev_addr) { uint8_t reg = 0x00; uint8_t data[2] = {0}; i2c_start(bus_id, dev_addr, I2C_WRITE); i2c_write_byte(bus_id, reg); i2c_stop(bus_id); i2c_start(bus_id, dev_addr, I2C_READ); data[0] = i2c_read_byte(bus_id, ACK); data[1] = i2c_read_byte(bus_id, NACK); i2c_stop(bus_id); int16_t raw = (data[0] << 8) | data[1]; return raw * 0.01f; }这里要注意一个有符号数处理的坑:PJ85718DM的高字节是符号位,温度值在零下时raw是一个负数。如果把高字节直接左移8位赋给int16_t,编译器会做正确的符号扩展,但我第一次用的是uint16_t临时变量,导致零下温度全部变成65535附近的大正数,校准了半天才反应过来。温度转换务必将原始数据强制转换为int16_t再做乘法。
3.3 温度校准与数据处理
即使传感器标称精度很高,批量安装和长线传输仍然会引入细微偏差。除了传感器自身误差,还有线缆电阻、连接器接触电阻、PCB走线差异等。所以我做了两级校准。
第一级是单点偏移校准:在0℃冰水混合物中让传感器稳定15分钟后读取实际输出,计算偏移量并保存到Flash。第二级是两点增益校准:再取一个50℃的恒温源,计算出增益系数。最终温度计算:
float calibrated_temp(float raw_temp) { return (raw_temp - offset) * gain; }对于HVAC这种测量范围集中在-10℃到60℃的场景,两点校准完全够用。实测下来,校准后整条链路的误差可以控制在±0.15℃以内。不要迷信传感器标称精度,系统级的误差是累加的,增益校准能显著提升多通道之间的一致性。
数据处理上还加了滑动平均滤波。窗口取了8次采样,对应4秒的时间常数,既能抑制瞬间干扰,又不会让报警响应太迟钝。滤波代码很轻量:
#define FILTER_WINDOW 8 float filter_push(float window[], uint8_t *idx, float new_val) { window[(*idx)++] = new_val; if (*idx >= FILTER_WINDOW) *idx = 0; float sum = 0; for (uint8_t i = 0; i < FILTER_WINDOW; i++) { sum += window[i]; } return sum / FILTER_WINDOW; }这里我故意没有做剔除异常值的处理,因为PJ85718DM本身稳定性很好,偶尔出现的异常值会被滑动平均平滑掉,如果再加中值剔除,反而会让真实温度变化被过渡平滑,影响报警响应速度。
3.4 本地显示与超温告警
LCD屏显示6个通道的实时温度、通道名称、报警状态。刷新频率设计为1秒,因为半秒轮询一次数据,1秒刷新显示不会感觉到卡顿,也避免了SPI刷屏占用MCU太多时间。
告警逻辑分两级:预警和报警。预警阈值默认设50℃,报警阈值设60℃,均可在上位机远程修改,也可以在现场通过按键调整。两级告警的好处是可以提前发现温度爬升趋势,给运维留出响应时间。
告警处理有个细节:单个通道超温后,程序只发一次报警事件,带上通道号和温度值,而不是一直重复发同一状态。避免网络被重复报警消息刷爆,也让监控端能清楚区分新事件和重复状态。
3.5 远程上报实现
远程通信我做了两套链路并行的方案:
第一套是Modbus RTU从站协议,通过RS485接到现场触摸屏和本地监控终端。STM32F767ZG作为从站,地址设为1,功能码支持读保持寄存器。6路温度打包成12个模拟量寄存器,监控终端直接轮询读取。这套方案适合已有现场总线的工业环境,不依赖IP网络,非常可靠。
第二套是以太网MQTT链路,STM32F767ZG作为客户端连接MQTT服务器,以固定Topic上报数据,payload用轻量的JSON格式,如:
{"device":"AHU-01","points":[{"ch":1,"t":23.45},{"ch":2,"t":24.12}]}MQTT链路做了两个关键处理。一个是心跳保活:每30秒发心跳包,60秒没收到服务器响应就判定链路异常,主动重连。另一个是数据补发:本地搞了一个环形缓冲区,容量为3000条记录,当网络断线超过5分钟时,历史数据会按时间戳批量补发到服务器,保证远程记录不出现长时间缺口。
协议栈方面直接集成了现成的LWIP和MQTT客户端库,把TCP连接管理、重连策略、JSON打包等工作交给上层应用,底层协议栈是成熟代码,稳定性反而更好。
4. 系统调试与实测数据
4.1 硬件调试步骤
拿到第一批打样的板子,我没有直接上全套外设,而是按“电源-核心-传感器-通信”的顺序逐步调试。
先焊电源部分,用万用表确认3.3V、2.5V等各路电压正常,量一下静态电流没有异常。然后只焊STM32F767ZG最小系统,用SWD连接调试器,写一个最简单的LED闪烁程序,确认时钟、Flash、启动流程正常。
第三步才接入传感器。用一个通道测试,把PJ85718DM焊到转接板上,用杜邦线连到开发板的I2C1接口。先不装6路,只验证单路通信时序,用逻辑分析仪抓I2C波形,确认通信正常、数据寄存器读取值符合预期。
确认单路正常后再焊接全部6路传感器和通信模块。此时如果出现问题,就能快速定位是硬件还是软件的问题,避免一上来就一大摊子东西分不清责任。
4.2 温度测量精度对比
为了验证系统的实际精度,我用标准的工业水银温度计做参照,同时在恒温箱里做了3组温度点对比测试。恒温箱设定值分别为0℃、25℃、50℃,稳定30分钟后记录系统读数。
在0℃点,6路通道的实测偏差在-0.08℃到+0.12℃之间,在校准前这个偏差范围是-0.21℃到+0.18℃。在25℃点,偏差在-0.06℃到+0.09℃,表现最好。在50℃点,偏差在-0.12℃到+0.14℃,相比低温度段略大,这与传感器在高温段线性度微变有关,但仍在±0.3℃标称范围内。
6路通道之间的最大温差也就是不同通道之间的读数差,校准后控制在0.15℃以内。这对HVAC的温差测量非常关键——很多时候用户其实不关心绝对温度到底是多少,而是关心温差。比如换热器两侧温差、送风回风温差,如果两个通道的系统偏差不一致,温差数值就不可信了。双点校准把通道间的一致性做上来了,这是整个项目交付时用户最满意的一点。
4.3 远程通信稳定性测试
远程链路在真实的HVAC机房环境里测试了48小时。机房内有变频器、电机、继电器等干扰源,以太网线和RS485线都走现场原有线槽。
Modbus RTU链路表现很稳定,48小时内触摸屏轮询读取10,000多次,没有出现一次通信超时。RS485走的是屏蔽双绞线,屏蔽层单端接地,终端电阻按标准并接在总线的物理末端,这些细节做到位之后,现场干扰基本不影响通信。
MQTT链路48小时内断线重连了3次,每次都在5秒内恢复,原因是现场网络有短暂的设备重启。断线期间产生的数据都从本地缓冲区补发了,服务器侧记录的时间序列连续无缺口。数据上报的延时平均在200ms以内,对于温度这类缓变量,这个延迟完全不是问题。
5. 踩坑记录与排查手册
5.1 温度读数异常跳变
现象:某天现场反馈,3号测点偶尔出现温度从25℃直接跳到80℃,再跳回来。
排查过程:用逻辑分析仪抓I2C波形,发现跳变前总线上出现了一个不完整的波形——SCL只有6个时钟周期,SDA却在第3个时钟就变了电平。初步判断是干扰导致的通信错位。
进一步检查发现,3号传感器所在的线缆经过一段靠近强电电缆的线槽,虽然用了屏蔽双绞线,但屏蔽层在现场被剪断没有接地。这件事暴露了安装规范的重要性:屏蔽层必须单端接地,且接地端在现场控制柜侧。
解决措施:把屏蔽层重新接地,同时I2C频率从400kHz降到100kHz,并将SCL和SDA各加了一个33pF的滤波电容,把信号边沿变缓一些以增强抗干扰能力。之后连续测试一周,没有再出现跳变。
5.2 上电后部分传感器I2C通信失败
现象:板子断电重开后,偶尔有一两个传感器无法应答。
排查过程:一开始怀疑是传感器损坏,换新后同样出现。后来发现每次失败的都是挂在I2C多路复用器后面的通道,复用器的使能时间不够长,MCU按键之后立即发起I2C通信,通道还没来得及打开。
解决措施:在切换复用器通道后加入5ms延时,再启动I2C传输。同时在软件初始化流程里增加了全通道的在线检测,发现无应答的通道会单独重试3次。这个问题本质是时序竞争,硬件没问题,但在固件里被忽略了。
5.3 远程MQTT频繁掉线
现象:部署到现场后,MQTT连接每隔几分钟就断开。
排查过程:抓包看到服务器发送了心跳超时断开。原来我把WiFi模块和以太网PHY放在了同一个供电支路上,WiFi发射瞬间拉低了以太网PHY的电源电压,导致PHY芯片偶发复位。
解决措施:给以太网PHY供电路径增加独立的LC滤波,WiFi模块改用单独的电源轨,两者在物理布局上也拉开了距离。调整后连续运行72小时,掉线次数降为0。
5.4 HVAC场景中的冷凝水问题
现象:在空调冷水管道的测点,传感器外壳出现凝露,温度读数在凝露后开始缓慢漂移。
排查过程:不是因为电气问题,而是外壳密封失效。水汽渗入传感器封装后,改变了散热路径,导致测温偏差。
解决措施:换用带IP67防护等级的传感器探头,安装时探头朝上,线缆走线形成“滴水弯”,冷凝水沿线的方向滴落而不进入探头。这件事提醒我,HVAC环境里防水防潮和防雷防干扰一样重要。
6. 经验扩展与后续优化思路
这块硬件的性能其实还有不少富余,我已经在考虑两个方向的扩展。
一个是增加测点类型。现在6路传感器都是湿度温度一体方案中的温度部分,后续可以在同一套主控下接入管道压力、流量的变送器,通过RS485或者模拟量输入把更多过程参数汇聚到同一个节点,形成真正的多功能现场采集站。
另一个是边缘计算。STM32F767ZG的M7内核性能足够跑轻量级的异常预测算法,比如基于温度变化率来判断风机轴承是否开始磨损,或者根据温差趋势预测过滤器堵塞时间。这样远程平台收到的就不只是原始数据,还有设备健康状态,对HVAC的预测性维护会更有价值。
能耗方面也可以优化。当前板子一直保持全速运行,实际上在工作模式之间加一个轻量级的低功耗调度,让MCU在两次轮询之间进入Sleep模式,整机功耗可以降到目前的30%以下。对于使用太阳能供电的嵌入式设备舱节点,这个优化会非常实用。
最后再分享一个体会:温度监测项目看着简单,但真正交付时,用户最在意的不是你能采集多少数据,而是数据可不可信、链路稳不稳、维护易不易。把精度校准、抗干扰、断线补发这些“看不见的细节”做扎实,系统才真正可用。这套方案目前已经在两个现场稳定运行了几个月,验证了从本地到远程的完整闭环,后续我也会持续把新的调试经验补充进来。