☰
基于PJ85718DM与PIC18F86J10的HVAC本地远程温度监测系统设计
2026/10/22 17:01:33 网站建设 项目流程

我们做楼宇自控和HVAC设备改造的人,应该都有过这样的经历:现场控制柜里要测温度,十几米外的风管或者回风口也要测温度,中控室还想把这几个温度都收上去。之前用热敏电阻,得接分压电路、标定曲线,换一茬探头重新标一遍,调试周期长不说,温度稍有波动后台就开始误报。直到我换了 PJ85718DM 数字温度传感器和PIC18F86J10 主控芯片这套组合,本地测温和远程测温才真正变得省心。

这篇文章把我完整做过的模拟项目X 的细节整理出来,包括硬件选型思路、单总线驱动、Modbus RTU远程上报、以及现场踩过的坑。内容面向正在做嵌入式测温、HVAC控制器或者类似工业数据采集的朋友,不管是新手还是有经验的老手,应该都能从里面找到能直接用的东西。

1. 项目概述与整体设计思路

1.1 需求拆解:本地与远程温度监测

这个项目的需求听起来简单,其实就是测两个温度:一个装在控制柜里,叫“本地温度”,代表设备附近的环境温度;另一个装在风管远端或者室外机回风口,叫“远程温度”,代表实际工作位置的温度。但真正落地时有两个约束特别关键:

第一,现场没有Wi-Fi覆盖,中控室和现场柜之间只有一根预埋的屏蔽双绞线。第二,柜里有变频器、接触器、开关电源,电磁干扰非常大,蓝牙和无线方案基本不用考虑。

所以最终方案确定为:传感器采集温度,主控芯片做数据处理和协议转换,通过RS485总线把两个温度值送到中控室的组态软件。这个思路本质上就是前端采集加总线传输,和很多工业物联网项目是一样的架构,只不过把无线换成了更可靠的有线总线。

1.2 为什么选 PJ85718DM 和 PIC18F86J10

先看传感器。PJ85718DM 这个型号,很多人可能不熟,它本质上是一颗数字式温度传感器,内部已经把测温元件、模数转换、信号调理全做在一个小模块里。和NTC热敏电阻的逻辑不一样,它不需要我们再用ADC采样去算查表,直接通过单总线协议把温度值读出来,误差控制在±0.5℃以内。

当初选它有一个很现实的理由:工程现场的人手和仪器都不一定齐全,用NTC的话,每换一个探头你都得重新校正分压电阻,整个过程全看操作人员的细心程度。而用PJ85718DM这种数字传感器,插上就能读,换器件也不需要重新标定,后期维护量小很多。

再看主控。PIC18F86J10 是Microchip的8位单片机,但和很多人印象里那种“小芯片”不一样,它引脚多、Flash和RAM足够、外设丰富,片上就有多个UART、SPI、I2C,GPIO数量也够。这对于需要同时驱动温度传感器、按键、显示屏、RS485收发器的场景来说,非常合适。供电范围宽这一点也是加分项,HVAC柜里的电源波动比较大,它能在较宽的电压范围内稳定运行。

2. 硬件搭建与电路设计

2.1 温度采集电路:单总线接线要点

PJ85718DM 支持单总线接口,我实际用的就是这种接法,因为一根数据线加一根地线就能把远程探头拉到十几米外,现场布线压力最小。本地探头直接放在主控板上,和MCU的某个GPIO短距离连接;远程探头则通过屏蔽双绞线接到同一个单总线引脚上。

单总线的一个特点是同一根线上可以挂多个传感器,每个传感器出厂时有一个唯一序列号。主机先发ROM搜索命令,逐个识别出所有设备并保存序列号,然后再按序列号点名读取每个传感器的温度值。这个机制很像对讲机通话时的“点名应答”,一句话就是一个设备,绝不允许两个设备同时抢答。

硬件上有一个细节很容易被忽视:单总线的数据线必须接上拉电阻到电源,一般用4.7k欧姆。虽然PJ85718DM内部有一定上拉能力,但线上挂了两个探头、线长十几米时,分布电容不小,没有外部上拉电阻的话,电平翻转变慢,读写时序就不稳定,温度读数容易跳变。这个是我实测下来的经验,不是理论猜测。

2.2 RS485接口与供电设计

远程上报走的RS485总线,电路上我选用了带隔离的RS485收发模块。为什么一定要隔离?因为中控室和现场控制柜之间经常存在地电位差,雷击、电机起停的时候,共模电压可能跳到几十伏甚至更高。如果不做隔离,高压会直接窜到MCU的数字地,轻则数据乱码,重则主控板上芯片烧掉。

供电方面,现场是24V开关电源,我先把24V降到5V,再从5V一级LDO降到3.3V给MCU和传感器供电。3.3V这一侧我加了个100uF电解电容和多个100nF去耦电容,用来吸收变频器启动瞬间的电压跌落。另外数字地和模拟地在PCB上通过一个0欧姆电阻单点连接,这样RS485收发切换时的电流突变不会干扰温度采集的地参考平面。

整个硬件电路其实不复杂,但走线布局很讲究。单总线数据线尽量短,不要和RS485的A、B线平行走太长距离;远程探头的屏蔽层要在主控板单端接地,而不是两端都接地,否则会形成地环路电流,反而引入更大干扰。

3. 软件实现:驱动、滤波、协议全流程

3.1 单总线驱动的时序细节

单总线协议对时序要求很高,写驱动代码前,一定要拿示波器看几个关键波形,否则代码写出来也会有问题。初始化复位时,主机把数据线拉低至少480微秒再释放,传感器收到复位脉冲后会把线拉低60到240微秒,表示“我在这里”。这个过程是后续所有命令的前提,读不到存在脉冲就说明设备不在线上。

写一个bit分两种:写“0”是主机拉低总线60到120微秒;写“1”是主机拉低1到15微秒后立刻释放,让上拉把线拉高。读一个bit则是主机先拉低1到15微秒发起读时隙,然后释放总线,并在15微秒内采样电平,如果读到低电平就是0,高电平就是1。

我用的驱动框架大概是这样,XC8编译器下可以直接用:

#define DQ_PORT PORTCbits.RC0 #define DQ_TRIS TRISCbits.TRISC0 void delay_us(uint16_t us) { while (us--) { NOP(); NOP(); } } uint8_t ow_reset(void) { DQ_TRIS = 0; DQ_PORT = 0; delay_us(500); DQ_PORT = 1; delay_us(60); DQ_TRIS = 1; uint8_t presence = DQ_PORT; delay_us(420); return presence; // 返回0表示检测到设备 } uint8_t ow_read_bit(void) { DQ_TRIS = 0; DQ_PORT = 0; delay_us(2); DQ_PORT = 1; DQ_TRIS = 1; NOP(); uint8_t bit = DQ_PORT; delay_us(50); return bit; } void ow_write_bit(uint8_t bit) { DQ_TRIS = 0; DQ_PORT = 0; if (bit) { delay_us(8); DQ_PORT = 1; } else { delay_us(70); DQ_PORT = 1; } delay_us(20); }

读温度的流程是这样的:复位,发送跳过ROM命令0xCC,发送读暂存器命令0xBE,然后连续读取9个字节。前两个字节是温度值,第1字节是低字节,第2字节是高字节。把16位数据组合出来后,判断符号位,再乘以分辨率系数0.0625,得到的就是实际温度摄氏度。

3.2 滤波算法:滑动平均加变化率限制

单总线在工业现场偶尔会受干扰,读出来的值可能偶尔跳一下。我用的滤波方案是排序后取中间值加上变化率限制:连续采集5个原始温度值,排序后去掉最大值和最小值,剩下3个取平均。这个做法实现简单,效果也够HVAC这种低速温度采样场景用。

平均之后再做一个变化率限制:如果本次滤波结果和上一次结果偏差超过2.5℃,先不更新,连续3次都超限才认为真的发生温度突变。这样既能防偶发干扰,又不会掩盖真实的快速升温。HVAC系统温度变化本身就慢,风管温度一分钟也就变个零点几度,2.5℃的限制已经留了很大余量。

3.3 Modbus RTU远程上报协议实现

远程通信走了Modbus RTU,这是工业控制领域的老牌协议,中控室的组态软件、PLC大都能直接支持。实现时PIC18F86J10作为从站,地址设为1,波特率9600,8位数据位,1位停止位,无校验。我把本地温度放在保持寄存器地址0,远程温度放在地址1,中控室以2秒为周期读取这两个寄存器。

Modbus RTU的报文结构是:地址码1字节,功能码1字节,数据区若干字节,最后2字节是CRC16校验。03功能码是读保持寄存器,04功能码是读输入寄存器,我因为要读两个温度值,用03就够了。温度值统一放大10倍后放入16位寄存器,比如25.3℃就存成253,中控那边除以10就是真实温度,避免小数点和负号问题。

CRC16校验是Modbus协议里最重要的一段代码,逐位运算的实现如下:

uint16_t modbus_crc16(uint8_t *data, uint16_t len) { uint16_t crc = 0xFFFF; for (uint16_t i = 0; i < len; i++) { crc ^= data[i]; for (uint8_t j = 0; j < 8; j++) { if (crc & 1) { crc >>= 1; crc ^= 0xA001; } else { crc >>= 1; } } } return crc; }

收到主机请求后,先从UART接收缓冲区拼出完整报文,解析地址和功能码,计算CRC并对比,校验通过后再组装响应帧。响应帧格式是地址码、功能码、字节数、寄存器数据、CRC。这里要注意寄存器数据必须是先高字节后低字节,很多人第一次写Modbus从站会栽在这,数据顺序反了,中控读到的就是另外一个数。

4. 实操过程与现场调试记录

4.1 开发环境与工程配置

开发环境用的是MPLAB X IDE,编译器选XC8标准版。工程建立后,第一件事就是把芯片型号选对,然后配置时钟。HVAC主板上没有外部晶振,直接用内部振荡器,我通过配置字把系统时钟设为64MHz。

配置字我用的是这一行:

#pragma config OSC=INTIO67, WDT=OFF, LVP=OFF, BOREN=ON

这里几个选项说明一下:内部振荡器模式;看门狗关闭,避免程序长时间运行时意外复位;低电压编程关闭,防止引脚电平不稳时进入编程模式;欠压复位必须使能,HVAC现场电源抖动频繁,这个功能关系到系统能不能在电压跌落时安全复位。

工程配置好了之后,编译下载都正常。有一点要注意,PIC18F86J10的Flash空间相当充裕,但这个项目用到的Modbus协议栈和单总线驱动全部写完,整体代码量依然不大,所以空间完全不是问题,不用刻意优化。

4.2 分步上电调试顺序

我调试这个系统时,严格按“电源、时钟、串口、传感器、协议”的顺序来,每一步都确认没问题再走下一步。

第一步,烧录一个点灯程序,确认最小系统能跑。第二步,写一个UART自检程序,让MCU持续发送0x55,用USB转串口工具在电脑上确认能收到。第三步,初始化单总线驱动,把温度值直接打印到串口,用冰水混合物和沸水校验传感器的准确度,误差在±0.5℃以内才算过关。第四步,把远程探头用十几米双绞线接上,确认总线上两个传感器都能被识别。第五步,再加载Modbus协议,用中控软件测试读取。

这里特别提醒第四步:如果代码在一开始就用跳过ROM命令去读温度,而线上挂了两个传感器,两个设备会同时应答,读出来的数值完全是乱的。我第一次测试时就出现过温度读数固定在85℃的情况,后来加了ROM搜索流程,分别保存两个设备的序列号,问题立刻解决。

4.3 现场安装的细节处理

现场安装这块,看似简单,实际很影响数据准确性。远程探头放在风管上测量送风温度,必须要用导热胶贴合管道外壁,外面再包一层保温棉,不然它测到的其实是周围空气温度而不是风管表面温度。本地探头放在控制柜内,要远离变频器、变压器这类发热元件至少10厘米,否则测的是元器件温升而不是环境温度。

RS485的A、B线按照屏蔽双绞线正确接线,现场长度不到100米,我一开始没有加终端电阻。调试时发现偶发校验错误,用示波器看波形,发现上升沿有轻微振铃,于是在总线的远端设备侧加了一个120欧姆终端电阻,波形明显干净了,通信错误率也降到零。这里建议是,几十米的距离可以不接终端电阻,但超过100米或者现场干扰严重,两端都接120欧姆电阻更稳妥。

另一个施工细节是,RS485屏蔽层只在主控板一侧接地。如果两端都接地,电流会通过屏蔽层和大地形成环路,干扰反而更大。这是我多年做现场工程的一个习惯性选择,很多施工单位不注意这个,通信不稳定了找不到原因。

5. 常见问题与排查技巧

5.1 温度读数跳变和固定值异常

温度读数跳变,最常见原因是单总线引脚的上拉电阻缺失或阻值不合适。前面提过,长线情况下要用4.7k欧姆上拉,如果上拉太弱,线电容充电慢,读时序时不满足传感器要求,读出来的数据就会在正常值和-55℃之间来回跳。

另一个很隐蔽的问题是,有人在数据线上加了RC低通滤波电路。这种做法在普通数字信号采集上是好事,但在单总线协议上行不通,因为RC会拉长信号的上升沿和下降沿,时序窗口就变了。如果非要加滤波,电容不能超过100pF,而且最好在调试时对比加与不加的读数差异。

如果读到固定85℃,优先怀疑两个问题:一是单片机没检测到传感器,返回了默认值;二是跳过ROM命令同时触发了多个设备,总线冲突。先用示波器看复位脉冲后有没有存在脉冲,再用串口打印ROM搜索到的序列号,基本就能定位。

5.2 RS485通信超时和乱码

RS485通信不稳定时,第一件要排查的是收发切换时序。MCU发送完最后一个字节后,必须等移位寄存器完全移出数据并经过一个延时再切回接收状态,否则RS485收发器的发送使能关闭太快,最后一个CRC字节会被截断。我在发送完成中断里加了大概10个bit宽度的延时后再切换,问题就消失了。

第二件要排查的是波特率误差。PIC18F86J10用内部振荡器跑9600波特率,在没有精确校准前,误差可能超过3%。接收端的容错能力有限,误差大了就会偶发乱码。我在调试时先发连续0x55,用逻辑分析仪看实际波特率是否和配置值一致,偏差大就调整振荡器校准寄存器。

5.3 电源波动导致重启

柜里变频器和风机启停的瞬间,24V电源会有一个很大的跌落,稳压模块压差不够时,3.3V输出也会跟着塌下去,MCU就复位了。处理办法有三个:前级加大电解电容储能;后级加TVS管吸收尖峰;软件里使能欠压复位功能。

这三个措施加上后,我做过一个压力测试:手动连续启停继电器和风机几十次,设备都没有再复位,后台数据也没有出现中断。这里要提醒,不要只迷信稳压芯片的参数,实际工况下的动态负载是一块芯片能不能撑住的最关键考验。

6. 经验总结与扩展建议

6.1 技术选型的实际心得

回过头看这套方案,我觉得最核心的决策是用了数字传感器和成熟总线协议。PJ85718DM把温度测量从“模拟电路加查表”变成“数字通信”,省掉了现场标定环节;PIC18F86J10资源富余,开发起来不用抠门,逻辑清晰;Modbus RTU占的存储和带宽都很小,但对接能力很强,中控随便一个组态软件就能连上。

相比以前用NTC热敏电阻接ADC的做法,这套方案在可维护性上的优势太明显了。NTC换探头需要重新标定,数字传感器换一个就能直接用;NTC线路受线阻影响,单总线只要时序正确,线阻的影响就小很多。这也是我把这个项目做完后,强烈建议做HVAC测温的人尽快切换的原因。

6.2 多测温点和自动联动扩展

单总线允许一根线上挂多个传感器,所以这套硬件基本上不用改,软件扩展一下ROM搜索和寄存器映射,就能从两个测温点扩展到十几个测温点。每个温度点分配一个Modbus寄存器地址,中控读一次就能拿到全部数据。

更实用的扩展是加报警和联动控制:温度超过阈值时,MCU的GPIO直接驱动继电器,控制风机启停或者关断截止阀。这么做的好处是,即使中控室脱机了,现场设备仍能靠本地逻辑保护自身安全。冷藏库、机房、配电房这些场景,这个功能非常有必要。

我后续在模拟项目X上做过一次升级,增加了三路温度监测和两路过温报警,寄存器和GPIO都富余,代码结构也没动多少。整个过程让我意识到,这套方案的扩展成本很低,前期选对了型,后面做功能叠加就轻松很多。

6.3 一点个人经验

调试这种带总线通信的嵌入式系统,最忌讳的是“差不多就得了”。波形不稳要加强上拉,时序不满足要拿示波器量,数据偶发错乱要先查使能切换。把这些细节一个个较真地磨掉,系统自然就稳定了。那种“时好时坏”的现场问题,多半就是某个细节没到位。

如果你正在做类似的HVAC温度监测或嵌入式传感器采集项目,我建议直接参考这套硬件和软件架构起步,先把最简单的主链路打通,再加扩展功能。别一开始就想着把所有功能都堆上,一条成熟的主链路,比一堆花哨但不可靠的功能重要得多。

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

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

立即咨询