做嵌入式和HVAC控制器的朋友,应该都躲不过温度监测这件事。开发阶段调程序要盯着温度,量产之后现场也要盯温度,尤其是那种主控板和传感器节点不在同一个位置的场景。我这次要分享的是一个双测温点方案,核心就是 PJ85718DM 数字温度传感器加 PIC18F57K42 主控:本地温度用 I2C 直接读,远程温度通过 RS485 总线从远端节点拿,一套固件同时管理两路温度数据。这个方案既能用在嵌入式数据采集板上,也能直接搬到暖通空调(HVAC)控制箱里,比如监测回风温度、出风温度、压缩机附近管温。文章会把器件选型、通信架构、代码实现、告警逻辑和调试坑都过一遍,想搭一个稳定可靠的“本地+远程”测温系统的朋友可以参考着做。
1. 项目概述与需求拆解
1.1 为什么本地和远程测温不能只做一路
很多设备在设计温度监测时有一个惯性思维:板子上放一个传感器,读到温度就算完事。但实际场景里,一个系统往往有两个甚至多个关键温度点,只测一路很容易漏掉真正的问题。
举两个例子。先说嵌入式设备柜:主控板上的 MCU、电源模块、驱动芯片都会发热,你需要在控制盒内部测一个“本地温度”,用来判断控制器本身有没有过温、散热风扇有没有失效。但设备柜里还有另一个温度点,比如机柜后部、电缆沟、发热源附近,这些地方离主控板很远,如果只用板载传感器去推断,误差会很大。
HVAC 系统更是典型。一套空调系统有室内回风温度、蒸发器出风温度、室外冷凝器温度、压缩机排气管温度等多个点。控制器装在室内机或者室外机的电控盒里,但真正的温度监控点在风道和铜管路上。PCB 上的传感器只能代表电控盒内部环境温度,代表不了风道里的真实回风温度。所以“本地温度”和“远程温度”必须分开采集,再统一汇总到主控做温差判断和过温保护。
1.2 从标题拆出来的三件事
第一件事是本地温度采集。传感器要放在主控板上或者电控盒内部,和 MCU 之间距离短,接口越简单越好,I2C 是最稳的选择。
第二件事是远程温度采集。远程节点可能在几米甚至几十米外,中间要经过强电线路、压缩机启停干扰、风道震动,这一类场景需要抗干扰能力强的串行总线,RS485 或者基于 RS485 的 Modbus RTU 是最常见做法。
第三件事是统一管理。两路温度不是各读各的,而是要在主控里完成换算、滤波、告警和联动控制。比如本地温度和远程温度温差突然变大,大概率是风机皮带断了或者风道堵了;本地温度超过阈值就要降频或者断电保护。这套逻辑要放在同一个固件里处理。
这三件事决定了器件选型和系统架构:主控用 PIC18F57K42,本地传感器用 PJ85718DM,远程节点采用“从站 MCU + 同型号传感器”结构,通过 RS485 长线传输。
2. 关键器件选型与特性分析
2.1 PJ85718DM 数字温度传感器
PJ85718DM 是一颗 I2C 接口的数字温度传感器,和常见的 LM75A、TMP275 这类芯片定位类似,板级测温非常合适。
先从接口说起。它走 I2C 总线,两根线就能挂到主控上,SDA 和 SCL 各拉一颗上拉电阻即可。I2C 是漏极开路结构,总线速率通常工作在标准模式 100kHz 或快速模式 400kHz,对板级短距离通信来说完全够用。芯片还提供地址配置引脚,通过外部上下拉设置地址,这样一条 I2C 总线可以挂多个传感器,做多点板内测温时很方便。
ADC 分辨率做到 12 位,温度数据以补码形式放在两个寄存器里。对应的最小量化步长是 0.0625°C,也就是说 21°C 对应的寄存器值是 336,也就是 0x1500。这个精度对 HVAC 和嵌入式设备监控足够了,因为温度本身的惯性很大,0.06°C 级别的分辨率完全能满足控制逻辑判断。
芯片还有报警输出引脚,可以配置超温阈值和故障队列长度,温度超过设定值后把引脚拉低,用来直接触发 MCU 外部中断,或者接一个 LED、蜂鸣器做硬件告警。这颗传感器还支持连续转换和单次转换两种模式,单次转换适合低功耗应用,平时让传感器休眠,需要读温度时再触发一次转换。
PJ85718DM 的具体寄存器偏移值和默认上电状态,不同批次的芯片会有些许差别,调试前先对照实际器件的数据手册确认,避免把配置寄存器地址搞错。
2.2 PIC18F57K42 主控芯片的选型理由
PIC18F57K42 是 8 位 MCU,在温度监测这类中低速嵌入式任务里属于“杀鸡用牛刀”都不为过的配置,但正是这种外设冗余让方案省了很多事。
这颗芯片有多组通信外设,I2C/SPI 硬件模块和多个 UART 是并存的。这就意味着本地传感器走 I2C,远程通信走 UART 转 RS485,不需要软件模拟协议,更不需要频繁在 I2C 和 UART 之间抢引脚资源。硬件模块处理协议时序,CPU 只负责把数据搬进搬出,固件写起来省心很多。
它还带了内部温度指示器,可以粗略测量芯片结温。这个功能在诊断阶段特别好用:如果 I2C 传感器读回来的本地温度一直偏高,可以用内部温度指示器对比一下,判断是不是芯片自身发热影响了板级温度判断。
外设方面还有一个很实用的功能是可配置逻辑单元(CLC),内部温度传感器的报警引脚可以和 CLC 配合,直接在硬件层面把温度报警转换成中断信号,不需要软件轮询。这个设计在做 HVAC 控制器时很有价值,因为主控一旦进入正常循环,软件轮询可能会有几百毫秒的延迟,而硬件中断能在微秒级响应过温事件。
供电范围宽、独立 NVM 存储区可以保存校准偏移量,这些细节对批量生产很友好。你可以在出厂前给每个板子写入一个温度校准偏移值,让软件读取后自动补偿,降低传感器个体差异带来的精度影响。
2.3 为什么不用 NTC 加 ADC 的老方案
很多老工程师会习惯性用 NTC 热敏电阻配 ADC 测温,成本确实低,电路上也只需一颗电阻分压。但如果你同时要测本地和远程两个点,NTC 方案会带来一堆麻烦。
NTC 是非线性的。25°C 附近还好,到了高温区和低温区,电阻变化率会明显变化,必须做查表或者拟合计算。更麻烦的是 NTC 的互换性,不同批次同型号的 NTC,阻值和 B 值都有偏差,温度误差通常在 ±1°C 到 ±3°C 之间,批量生产时想要更高的精度,就得逐颗校准,产线成本直接上来。
远程测温时,NTC 的问题会更突出。传感器放在远端,信号线拉长之后,线阻会引入误差。比如 20 米长的一根普通导线,线阻大概有 2 到 4 欧姆,虽然分压电路上可以补偿一部分,但温度一变,这个误差也在变,很难修正。NTC 的测量电流还会在长线上形成压降,导致 ADC 读数偏移,这就更头疼了。
PJ85718DM 这类数字传感器把模数转换和校准都做在了芯片内部,输出就是可复现的数字量,抗干扰能力比模拟信号强得多,远程采集时不需要考虑线缆对模拟信号的衰减问题,这就是为什么新型设计越来越倾向于数字传感器直接上总线。
3. 系统架构与通信方案设计
3.1 整体拓扑:I2C 管本地,RS485 管远程
系统拓扑并不复杂,主控板上有两块区域:本地传感器直接通过 I2C 挂在 MCU 附近,远程节点通过 RS485 总线连接。
本地回路走 I2C 的原因很简单,距离近,通信稳定,初始化也快。I2C 需要 MCU 主动发起通信,传感器是从机,MCU 是主机,地址固定,时序简单,非常适合板级传感器读取。本地 PJ85718DM 就放在主控板边缘,远离大功率电感和大电流走线,避免 PCB 局部热点影响读数。
远程回路走 RS485 的原因也很直接:I2C 不适合长距离传输。I2C 是漏极开路结构,总线电容一大,信号上升沿就变缓,超过几米后非常容易误码。RS485 是差分信号,A/B 两线互为参考,抗共模干扰能力强,标准收发器在 9600 波特率下最远可以延伸到千米级。对 HVAC 系统来说,从电控盒到风道传感器节点的距离通常只有几米到几十米,RS485 余量非常足。
所以整体结构就是:本地温度走 I2C 短距直连,远程温度走 RS485 长线转发,主控通过轮询机制统一管理两路数据。最后一层是上位机或者人机界面,通过本地 UART 或者组网接口把温度数据上报。
3.2 远程从站节点怎么搭
远程从站节点需要单独做一块小板,结构相当于一个“传感器代理”。主控和远端传感器之间如果直接拉 I2C 线,信号完整性无法保证,所以需要一个从站 MCU 在远端把 I2C 传感器的数据读回来,再打包成标准协议通过 RS485 发回主控。
从站 MCU 可以用同样型号的 PIC18F57K42,好处是固件框架可以复用。从站的软件任务很单一:上电初始化 I2C,读取远端 PJ85718DM 温度,把换算好的温度值放到一个保持寄存器里,然后等待主控的 Modbus RTU 请求,收到请求就把数据回传。
从站还需要处理传感器断线异常。比如远端传感器因为线缆脱落或者接头氧化读不到数据时,从站要在保持寄存器里写入一个无效温度值,比如 0x7FFF,主控收到后判断为传感器故障,而不是当作真实温度参与控制逻辑。这一步非常重要,否则传感器断线后主控会被一个假温度带偏。
从站供电可以用 24VDC 转 5V 的模块,和 RS485 总线一起构成完整的远距离采集链路。如果距离特别远,远端从站可以通过隔离 DC-DC 模块将数字地与模拟地隔离,避免地环路噪声。
3.3 Modbus RTU 协议子集设计
远程通信协议选择 Modbus RTU 是经验之举。Modbus RTU 帧结构简单,CRC16 校验可靠,业界支持工具多,HVAC 和工业控制现场大量在用,后期要接入上位机组态软件或者触摸屏也非常方便。
本方案只用到两个功能码。读保持寄存器(03H)用来读取远程温度数据,写单个寄存器(06H)用来配置远程从站的报警阈值或者从站地址。帧格式如下:
- 地址码:1 字节,从站地址,主站配置为 1 到 247,广播地址 0 不参与温度回传
- 功能码:1 字节,03H 或者 06H
- 数据区:寄存器起始地址、寄存器数量、寄存器数据
- CRC16:低字节在前,高字节在后
主站轮询默认周期是 1000ms,9600 波特率,8 数据位,无校验,1 停止位。这个配置兼顾了稳定性和响应速度。HVAC 系统的温度变化很慢,1 秒级的采样周期已经足够,不需要把总线跑得飞快。
从站地址规划要提前想清楚。现场可能有多个远程节点:1 号从站对应回风温度节点,2 号从站对应出风温度节点,3 号从站对应冷凝器温度节点。这样主控读取时只需要轮询 1 到 3 号地址,每个地址返回两字节温度数据和一个状态字节,一帧下来最大 20 字节左右,9600 波特率下耗时约 20 毫秒,轮询三个节点花不到 60 毫秒,余量很大。
4. 核心实现:硬件连接与代码配置
4.1 硬件连接表与供电细节
先列硬件连接明细。PIC18F57K42 主控的引脚较多,具体引脚功能以实际配置为准,以下是一套常见连接方式:
| 信号 | PJ85718DM | PIC18F57K42 主控 | 说明 |
|---|---|---|---|
| VDD | 3.3V | 3.3V | 传感器电源,加 0.1uF 去耦电容 |
| GND | GND | GND | 共地 |
| SDA | SDA | I2C SDA 引脚 | 接 4.7k 上拉电阻到 3.3V |
| SCL | SCL | I2C SCL 引脚 | 接 4.7k 上拉电阻到 3.3V |
| A0 / A1 | GND 或 VDD | - | 配置 I2C 从机地址 |
| ALERT | 接 LED/主控输入 | - | 超温中断输出 |
RS485 部分,主控的 UART TX 和 RX 分别接到 RS485 收发器的 DI 和 RO 引脚,方向控制引脚接 MCU 的一个普通 GPIO。A/B 线接到远程从站对应的 A/B 端子上,总线两个末端各接一个 120 欧姆终端电阻,这一点新手很容易漏掉。终端电阻的作用是匹配线路阻抗,减少信号反射,距离超过 10 米时效果非常明显。
电源部分特别提醒:远程从站电源不要和主控电源直接长距离并联,会因为压降造成上电时序混乱。建议主控板提供隔离的 24V 给远程总线,从站板上再做本地 DC-DC 转换。传感器电源用 LDO 或者低纹波 DC-DC 都行,关键是纹波不要超过 50mV,数字传感器虽比模拟方案抗噪,但电源太脏同样会导致读数异常。
4.2 本地温度读取代码
本地 PJ85718DM 的读取流程是典型的 I2C 传感器操作:先写指针寄存器指向温度寄存器,再发起读操作,连续读两个字节,组合成 16 位数据,右移四位得到实际分辨率数据,再乘以 0.0625 得到摄氏温度。
MPLAB X IDE 配合 XC8 编译器,如果用 MCC 初始化外设,I2C1_Read、I2C1_Write 这些函数会生成好,直接调用即可。核心代码大概是:
// 读取 PJ85718DM 温度寄存器,返回 16 位原始值 uint16_t pj_read_temp_raw(void) { uint8_t buf[2]; // 写入指针寄存器地址,指向温度寄存器 I2C1_Start(); I2C1_Write(PJ_ADDR_W); // 器件地址 + 写 I2C1_Write(PJ_TEMP_REG); // 温度寄存器地址 I2C1_Stop(); // 重新发起读操作 I2C1_Start(); I2C1_Write(PJ_ADDR_R); // 器件地址 + 读 buf[0] = I2C1_Read(); // 高字节 buf[1] = I2C1_Read(); // 低字节 I2C1_AckNot(); // 最后一字节回 NACK I2C1_Stop(); return ((uint16_t)buf[0] << 8) | (uint16_t)buf[1]; } // 原始值转温度值,支持负数 float pj_calc_temp(uint16_t raw) { int16_t val = (int16_t)raw; val = val >> 4; // 算术右移保留符号位 return (float)val * 0.0625f; }有些芯片的寄存器布局可能是低字节在前,或者温度寄存器地址不同,这里要根据数据手册做调整。读取之后建议加一个简单的软件滤波,比如连续采样五次去掉最大最小值,再取平均,能有效过滤瞬间毛刺。
4.3 远程温度读取代码
远程 Modbus RTU 读取的关键是 CRC16 计算和超时处理。CRC16 可以用查表法,STM32 上可以用硬件 CRC,PIC18F57K42 没有硬件 CRC 模块,用位运算即可,计算量不大,波特率 9600 下完全来得及。
// 标准 Modbus CRC16 计算 uint16_t modbus_crc16(uint8_t *data, uint8_t len) { uint16_t crc = 0xFFFF; for (uint8_t i = 0; i < len; i++) { crc ^= data[i]; for (uint8_t j = 0; j < 8; j++) { if (crc & 0x0001) { crc = (crc >> 1) ^ 0xA001; } else { crc >>= 1; } } } return crc; }主站读取远程节点的温度,流程就是拼帧、发帧、切换方向、等待接收、校验 CRC。方向切换是这个环节最大的坑。RS485 是半双工通信,发送和接收共用一个方向控制引脚,发送完后必须延时一段时间再切换回接收,否则最后一个字节可能还没发完就切到接收,导致对方收不全数据。
按 9600 波特率计算,1 字节约 1ms,保险起见发完帧后延时 3ms 再拉低方向引脚。接收超时设置为 50ms,如果主控在这个时间内没收到完整帧或者 CRC 校验失败,就记录一次通信错误,连续错误三次后判定远程从站离线,并置位故障标志位。
uint8_t modbus_read_temp(uint8_t slave_addr, float *temp) { uint8_t tx_buf[8]; uint16_t crc; // 03H 读保持寄存器,起始地址 0x0000,读取 1 个寄存器 tx_buf[0] = slave_addr; tx_buf[1] = 0x03; tx_buf[2] = 0x00; tx_buf[3] = 0x00; tx_buf[4] = 0x00; tx_buf[5] = 0x01; crc = modbus_crc16(tx_buf, 6); tx_buf[6] = crc & 0xFF; // 低字节在前 tx_buf[7] = (crc >> 8) & 0xFF; // 发送并切换到接收,等待从站应答 RS485_DIR_TX(); UART1_Write(tx_buf, 8); delay_ms(3); RS485_DIR_RX(); if (modbus_wait_response((uint8_t *)rx_buf, 50)) { // 检查地址、功能码和 CRC if (rx_buf[0] == slave_addr && rx_buf[1] == 0x03) { uint16_t raw = ((uint16_t)rx_buf[3] << 8) | rx_buf[4]; if (raw != 0x7FFF) { *temp = pj_calc_temp(raw); return 0; // 成功 } } } return 1; // 失败 }从站那边,收到 03H 请求后,把温度寄存器中的 16 位数据放到响应帧的数据区里,回送时同样要加上 CRC16。如果读到的温度传感器数据无效,就返回 0x7FFF 这个特殊标志。
4.4 主循环与轮询策略
主循环不用写得很复杂,关键是把任务按周期分配好。本地温度变化慢,远程温度变化也慢,不需要高优先级实时抢占。
我习惯的做法是设一个 1ms 的系统 tick,然后主循环里做任务调度。每 200ms 读一次本地温度,每 1000ms 轮询一次远程从站,每 500ms 刷新一次告警判断。读取结果放在全局变量里,告警逻辑读取这些全局变量做判断。
这样做的原因是让通信任务和控制任务解耦。I2C 读取过程中如果耗时较长,可以先把数据放到 RAM 里,主循环再统一处理;RS485 轮询是阻塞式的,如果刚好在本地 I2C 读取过程中切换,可能会造成总线冲突,所以用时间片把两类通信错开。实测下来,200ms 和 1000ms 的周期互相错开,不会发生总线争抢。
初始化顺序也很重要。上电后先配置系统时钟,然后初始化端口,再初始化 I2C 和 UART,最后初始化 PJ85718DM 的配置寄存器。传感器初始化时要把报警阈值、转换分辨率、连续转换模式都写一遍,不能依赖芯片的默认值,因为不同型号上电默认值可能不一样,贸然用默认值容易在后期踩坑。
5. 温度换算与告警逻辑设计
5.1 温度换算里的坑
PJ85718DM 这类 12 位数字传感器的换算并不难,但细节上有两个坑值得单独说。
第一个坑是符号位。温度寄存器里的数据是补码格式,正温度时高字节最高位为 0,负温度时最高位为 1。换算成温度时,不能简单地把两个字节拼起来乘一个比例系数,必须先用 int16_t 类型接收原始值,再做算术右移,保证符号位在右移过程中被保留。
举个例子,21°C 对应的 12 位数据是 336,也就是 0x150,在寄存器和左对齐后读回的是 0x1500。换算流程是:0x1500 >> 4 = 0x150 = 336,336 * 0.0625 = 21°C。负温度比如 -32°C,对应的 12 位数据是 -512,补码是 0xFE00。读出后,int16_t 类型右移四位得到 0x0FE0,按无符号处理就是 4064,再乘 0.0625 会得到 254°C,显然是错的。必须用有符号右移,让符号位扩展,得到 -512,再乘 0.0625 才是 -32°C。
第二个坑是分辨率位。12 位 ADC 的数据在寄存器里通常是左对齐的,低四位是无效位。如果直接把两个字节合并成 16 位就乘以 0.0625,会出现 16 倍的误差。正确做法是先右移四位再乘 0.0625,或者直接把右移后的整数当作 0.0625°C 的倍数来计算。
还有一个容易忽略的点:远程从站返回的数据经过 Modbus 帧传输后,主站收到的也是原始寄存器值,同样要按上面的换算流程处理,不能只对本地传感器做换算,对远程回来直接套整数,否则远程温度误差会非常大。
5.2 告警和温差判断逻辑
温度数据拿来之后,真正有用的是告警逻辑和联动控制。这一层每个项目需求不同,我写一个适配嵌入式和 HVAC 场景的通用框架。
先设三个基础阈值:低温告警、高温告警、温差告警。HVAC 回风温度一般设在 10°C 到 40°C 之间;嵌入式板卡附近温度一般不超过 70°C,超过 85°C 基本可以判定散热异常。这些阈值要根据实际场景预设,最好支持通过 Modbus 写寄存器在线修改。
温差告警是 HVAC 里很有价值的判据。正常情况下,蒸发器出风温度和回风温度差大约在 8°C 到 15°C,如果出风温度忽然接近回风温度,说明蒸发器结霜或者风量不足。用本地传感器(回风温度)和远程传感器(出风温度)的差值来做判断,比单看任何一路温度都更直观。嵌入式场景里,如果主控板本地温度不高,但远程传感器温度异常升高,说明远端散热路径出问题,本地测温是看不出来的。
告警输出要加软件去抖。温度传感器读值偶尔会有毛刺,可能是因为电源波动或者通信瞬间干扰。我在逻辑里做了连续三次采样都超阈值才触发的设计,也就是“去抖计数器”。每读一次温度,超过阈值计数加一,低于阈值计数清零,计数达到三就置位告警标志。这样可以避免单次偶发读值导致误报警,也不会让告警在临界温度附近反复跳动。
告警处理动作分两级:一级是本地 LED 指示和蜂鸣器提示,二级是关断外设或者执行强制保护。HVAC 场景里,如果远程出风温度超温柔和,先降风机转速;如果连续超温达到硬安全阈值,直接切断压缩机继电器。嵌入式场景里,如果主板温度超过 85°C,及时降频,超过 95°C 就关机保护。执行动作要做成独立函数,方便在不同项目里裁剪。
6. 常见问题与排查技巧实录
6.1 I2C 读不到温度数据
I2C 读不到数据的现象,我这个项目里出现过一次,原因是传感器地址配错了。PJ85718DM 通过 A0/A1 引脚配置地址,如果地址引脚悬空,芯片内部上拉或者下拉的不确定性会导致地址漂移。解决办法是地址引脚必须接明确的高或低电平,不能悬空。我建议 A0/A1 直接通过 10k 电阻接 GND 或 VDD,然后上电后用 I2C 扫描工具把实际地址读出来,再回填到代码里。
另一个常见原因是 I2C 上拉电阻阻值不对。上拉电阻太小,总线灌电流过大;上拉电阻太大,总线上升沿太慢,高速模式下容易出错。3.3V 供电下用 4.7k 比较稳,5V 供电可以换 10k。如果总线上挂的设备多,上拉电阻可以适当降低到 2.2k,保证信号边沿速度。
还有一种容易被忽略的情况:传感器电源引脚上的去耦电容太大,比如直接并了 10uF 电解电容,电源上电瞬间充电电流过大,会导致芯片锁死,表现为 I2C 无应答。正确做法是 0.1uF 陶瓷电容并一个 1uF 到 10uF 电容,但电容耐压和 ESR 要符合规格,不要盲目加大。
6.2 RS485 通信超时或收到乱码
RS485 明明是差分信号,正常情况下抗干扰能力很强,但出现通信乱码时,优先检查方向引脚切换时序。发送完成后没等最后一个字节发完就切换接收,从站收到的帧会缺尾巴,主站自然等不到应答。调试时用示波器抓方向引脚和 A/B 差分波形,能清楚看到切换点和数据结束点的关系。我在代码里加了一个简单的字节发送完成中断,确认发送移位寄存器完全清空后再切方向,问题立刻消失。
第二个高发点是终端电阻没加或者加多了。RS485 总线两端各一个 120 欧姆终端电阻是标配。如果只在主站端加了一个,远程端没加,信号反射会让波形振铃,短距离测试没事,长距离就跑不稳定。如果加了两个以上,总线负载过重,收发器力度不够,也会误码。用万用表量 A/B 之间电阻,正常情况应在 60 欧姆左右,这个可以作为快速检查手段。
第三个问题是共地。RS485 是差分传输,但两个节点的逻辑地之间如果压差太大,超过收发器共模输入范围,照样通信失败。隔离型收发器是终极方案,不过普通场景下把两个节点的 GND 用一根线连接起来,通常就能解决。
6.3 温度读数跳变、偏移
温度读数跳变,先怀疑电源纹波,不要直接改软件滤波。手持万用表或示波器量传感器 VDD 引脚,纹波超过 100mV 时,给传感器供电串一颗 10~100 欧姆电阻,再并一颗 10uF 电容,形成简单的 π 型滤波,通常能明显改善。
温度偏移则是安装问题居多。传感器贴近大功率器件或者变压器,读到的温度自然比环境温度高几度。不要试图用软件偏移去硬拉,而是要把传感器放在真正代表“被测对象温度”的位置。PCB 布局时让传感器远离发热区,如果需要测环境温度,传感器不要靠近散热器出风口,否则读到的只是散热气流温度而不是环境温度。
传感器探头和线缆如果经过强电线路旁边,数字信号的翻转也会被感应干扰。这种干扰肉眼看不出来,但温度数据会随机跳动。处理方式是把传感器走线和强电线路分开,不要平行布线,实在绕不开就用屏蔽线,并保证屏蔽层单端接地。
6.4 配置丢失与批量校准
PJ85718DM 这类数字传感器的配置寄存器在上电后往往会恢复默认值,如果你在代码里靠“上一次写入”保持配置,断电重启后配置就丢了。所以初始化函数必须每次都把分辨率、报警阈值、连续转换模式完整写一遍,不能只写一次。
量产校准方面,建议在每块板子出厂前做一次温度校准。用一个恒温槽或者干脆用一杯温水加一个标准温度计做参考,读出传感器温度和标准温度计的差值,把偏差值写入 PIC18F57K42 的 NVM 区域。软件读温度时,先读 NVM 里的偏移值,再叠加到换算结果上。这样做的好处是传感器本身的个体偏差可以在产线端补偿,进一步提高整机温度精度,避免同一批板子温度一致性差的问题。
最后再分享一个我自己实践下来的经验:这种“本地 I2C + 远程 Modbus RTU”的双测温结构,调试时不要一上来就全部上。先只接本地传感器,确认 I2C 读到的温度正常;再接一个远程从站,手动通过串口助手模拟主站帧,确认从站返回数据的 CRC 正确;最后才把主站、从站、上位机全部连通。这样一步步拆开,任何一个环节出问题都能快速定位。这个方案我做下来整体很稳,在 HVAC 控制箱和嵌入式采集板上都验证过,扩展多个远程节点也很容易,多加几个从站地址就行。